Skip to content

Commit 704e4e3

Browse files
committed
Added Panama hash and unittest
1 parent c504511 commit 704e4e3

File tree

2 files changed

+374
-0
lines changed

2 files changed

+374
-0
lines changed

SharpHash.Tests/Crypto/PanamaTests.cs

+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
using SharpHash.Base;
2+
using SharpHash.Interfaces;
3+
using SharpHash.Utils;
4+
using SharpHash.Tests;
5+
using Microsoft.VisualStudio.TestTools.UnitTesting;
6+
using System.Text;
7+
8+
namespace SharpHash.Crypto.Tests
9+
{
10+
[TestClass]
11+
public class PanamaTests
12+
{
13+
protected IHash hash = HashFactory.Crypto.CreatePanama();
14+
15+
protected string ExpectedHashOfEmptyData = "AA0CC954D757D7AC7779CA3342334CA471ABD47D5952AC91ED837ECD5B16922B";
16+
protected string ExpectedHashOfDefaultData = "69A05A5A5DDB32F5589257458BBDD059FB30C4486C052D81029DDB2864E90813";
17+
protected string ExpectedHashOfOnetoNine = "3C83D2C9109DE4D1FA64833683A7C280591A7CFD8516769EA879E56A4AD39B99";
18+
protected string ExpectedHashOfabcde = "B064E5476A3F511105B75305FC2EC31578A6B200FB5084CF937C179F1C52A891";
19+
protected string ExpectedHashOfDefaultDataWithHMACWithLongKey = "93226A060B4A82D1D9FBEE6B78424F8E3E871BE7DA77A9D17D5C78D5F415E631";
20+
protected string ExpectedHashOfDefaultDataWithHMACWithShortKey = "3C15C9B7CDC77470BC02CA96711B66FAA976AC2044F6F177ABCA93B1442EA376";
21+
22+
[TestMethod]
23+
public void TestEmptyString()
24+
{
25+
TestHelper.TestActualAndExpectedData(TestConstants.EmptyData,
26+
ExpectedHashOfEmptyData, hash);
27+
}
28+
29+
[TestMethod]
30+
public void TestDefaultData()
31+
{
32+
TestHelper.TestActualAndExpectedData(TestConstants.DefaultData,
33+
ExpectedHashOfDefaultData, hash);
34+
}
35+
36+
[TestMethod]
37+
public void TestOnetoNine()
38+
{
39+
TestHelper.TestActualAndExpectedData(TestConstants.OnetoNine,
40+
ExpectedHashOfOnetoNine, hash);
41+
}
42+
43+
[TestMethod]
44+
public void TestBytesabcde()
45+
{
46+
TestHelper.TestActualAndExpectedData(TestConstants.Bytesabcde,
47+
ExpectedHashOfabcde, hash);
48+
}
49+
50+
[TestMethod]
51+
public void TestEmptyStream()
52+
{
53+
TestHelper.TestEmptyStream(ExpectedHashOfEmptyData, hash);
54+
}
55+
56+
[TestMethod]
57+
public void TestIncrementalHash()
58+
{
59+
TestHelper.TestIncrementalHash(TestConstants.DefaultData,
60+
ExpectedHashOfDefaultData, hash);
61+
}
62+
63+
[TestMethod]
64+
public void TestHashCloneIsCorrect()
65+
{
66+
TestHelper.TestHashCloneIsCorrect(hash);
67+
}
68+
69+
[TestMethod]
70+
public void TestHashCloneIsUnique()
71+
{
72+
TestHelper.TestHashCloneIsUnique(hash);
73+
}
74+
75+
[TestMethod]
76+
public void TestHMACWithDefaultDataAndLongKey()
77+
{
78+
IHMAC hmac = HashFactory.HMAC.CreateHMAC(hash);
79+
hmac.Key = Converters.ConvertStringToBytes(TestConstants.HMACLongStringKey,
80+
Encoding.UTF8);
81+
string ActualString = hmac.ComputeString(TestConstants.DefaultData,
82+
Encoding.UTF8).ToString();
83+
84+
Assert.AreEqual(ExpectedHashOfDefaultDataWithHMACWithLongKey, ActualString);
85+
}
86+
87+
[TestMethod]
88+
public void TestHMACWithDefaultDataAndShortKey()
89+
{
90+
IHMAC hmac = HashFactory.HMAC.CreateHMAC(hash);
91+
hmac.Key = Converters.ConvertStringToBytes(TestConstants.HMACShortStringKey,
92+
Encoding.UTF8);
93+
string ActualString = hmac.ComputeString(TestConstants.DefaultData,
94+
Encoding.UTF8).ToString();
95+
96+
Assert.AreEqual(ExpectedHashOfDefaultDataWithHMACWithShortKey, ActualString);
97+
}
98+
99+
[TestMethod]
100+
public void TestHMACCloneIsCorrect()
101+
{
102+
TestHelper.TestHMACCloneIsCorrect(hash);
103+
}
104+
105+
}
106+
107+
}

SharpHash/Crypto/Panama.cs

+267
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,267 @@
1+
using SharpHash.Base;
2+
using SharpHash.Interfaces;
3+
using SharpHash.Utils;
4+
using System;
5+
6+
namespace SharpHash.Crypto
7+
{
8+
internal sealed class Panama : BlockHash, ICryptoNotBuildIn, ITransformBlock
9+
{
10+
private UInt32[][] stages = null;
11+
private UInt32[] state, theta, gamma, pi, work_buffer;
12+
13+
private Int32 tap;
14+
15+
public Panama()
16+
: base(32, 32)
17+
{
18+
tap = 0;
19+
state = new UInt32[17];
20+
theta = new UInt32[17];
21+
gamma = new UInt32[17];
22+
pi = new UInt32[17];
23+
work_buffer = new UInt32[17];
24+
25+
Array.Resize(ref stages, 32);
26+
for (UInt32 i = 0; i < 32; i++)
27+
stages[i] = new UInt32[8];
28+
29+
} // end constructor
30+
31+
override public IHash Clone()
32+
{
33+
Panama HashInstance = new Panama();
34+
HashInstance.buffer = buffer.Clone();
35+
HashInstance.processed_bytes = processed_bytes;
36+
37+
HashInstance.tap = tap;
38+
39+
HashInstance.state = new UInt32[state.Length];
40+
Utils.Utils.memcopy(ref HashInstance.state, state, state.Length);
41+
42+
HashInstance.theta = new UInt32[theta.Length];
43+
Utils.Utils.memcopy(ref HashInstance.theta, theta, theta.Length);
44+
45+
HashInstance.gamma = new UInt32[gamma.Length];
46+
Utils.Utils.memcopy(ref HashInstance.gamma, gamma, gamma.Length);
47+
48+
HashInstance.pi = new UInt32[pi.Length];
49+
Utils.Utils.memcopy(ref HashInstance.pi, pi, pi.Length);
50+
51+
Array.Resize(ref stages, 32);
52+
for (UInt32 i = 0; i < 32; i++)
53+
Utils.Utils.memcopy(ref HashInstance.stages[i], stages[i], stages[i].Length);
54+
55+
HashInstance.BufferSize = BufferSize;
56+
57+
return HashInstance;
58+
} // end function Clone
59+
60+
override public unsafe void Initialize()
61+
{
62+
Utils.Utils.memset(ref state, 0);
63+
64+
for (Int32 i = 0; i < 32; i++)
65+
Utils.Utils.memset(ref stages[i], 0);
66+
67+
base.Initialize();
68+
} // end function Initialize
69+
70+
override protected unsafe byte[] GetResult()
71+
{
72+
byte[] result = new byte[8 * sizeof(UInt32)];
73+
74+
fixed (UInt32* statePtr = &state[9])
75+
{
76+
fixed (byte* resultPtr = result)
77+
{
78+
Converters.le32_copy((IntPtr)statePtr, 0, (IntPtr)resultPtr, 0,
79+
result.Length);
80+
}
81+
}
82+
83+
return result;
84+
} // end function GetResult
85+
86+
override protected unsafe void Finish()
87+
{
88+
Int32 tap4, tap16, tap25;
89+
90+
Int32 padding_size = 32 - (Int32)(processed_bytes & 31);
91+
92+
byte[] pad = new byte[padding_size];
93+
94+
pad[0] = 0x01;
95+
TransformBytes(pad, 0, padding_size);
96+
97+
UInt32[] theta = new UInt32[17];
98+
99+
fixed (UInt32* ptr_theta = theta)
100+
{
101+
for (Int32 i = 0; i < 32; i++)
102+
{
103+
tap4 = (tap + 4) & 0x1F;
104+
tap16 = (tap + 16) & 0x1F;
105+
106+
tap = (tap - 1) & 0x1F;
107+
tap25 = (tap + 25) & 0x1F;
108+
109+
GPT(ptr_theta);
110+
111+
stages[tap25][0] = stages[tap25][0] ^ stages[tap][2];
112+
stages[tap25][1] = stages[tap25][1] ^ stages[tap][3];
113+
stages[tap25][2] = stages[tap25][2] ^ stages[tap][4];
114+
stages[tap25][3] = stages[tap25][3] ^ stages[tap][5];
115+
stages[tap25][4] = stages[tap25][4] ^ stages[tap][6];
116+
stages[tap25][5] = stages[tap25][5] ^ stages[tap][7];
117+
stages[tap25][6] = stages[tap25][6] ^ stages[tap][0];
118+
stages[tap25][7] = stages[tap25][7] ^ stages[tap][1];
119+
stages[tap][0] = stages[tap][0] ^ state[1];
120+
stages[tap][1] = stages[tap][1] ^ state[2];
121+
stages[tap][2] = stages[tap][2] ^ state[3];
122+
stages[tap][3] = stages[tap][3] ^ state[4];
123+
stages[tap][4] = stages[tap][4] ^ state[5];
124+
stages[tap][5] = stages[tap][5] ^ state[6];
125+
stages[tap][6] = stages[tap][6] ^ state[7];
126+
stages[tap][7] = stages[tap][7] ^ state[8];
127+
128+
state[0] = theta[0] ^ 0x01;
129+
state[1] = theta[1] ^ stages[tap4][0];
130+
state[2] = theta[2] ^ stages[tap4][1];
131+
state[3] = theta[3] ^ stages[tap4][2];
132+
state[4] = theta[4] ^ stages[tap4][3];
133+
state[5] = theta[5] ^ stages[tap4][4];
134+
state[6] = theta[6] ^ stages[tap4][5];
135+
state[7] = theta[7] ^ stages[tap4][6];
136+
state[8] = theta[8] ^ stages[tap4][7];
137+
state[9] = theta[9] ^ stages[tap16][0];
138+
state[10] = theta[10] ^ stages[tap16][1];
139+
state[11] = theta[11] ^ stages[tap16][2];
140+
state[12] = theta[12] ^ stages[tap16][3];
141+
state[13] = theta[13] ^ stages[tap16][4];
142+
state[14] = theta[14] ^ stages[tap16][5];
143+
state[15] = theta[15] ^ stages[tap16][6];
144+
state[16] = theta[16] ^ stages[tap16][7];
145+
146+
} // end for
147+
}
148+
149+
} // end function Finish
150+
151+
override protected unsafe void TransformBlock(IntPtr a_data,
152+
Int32 a_data_length, Int32 a_index)
153+
{
154+
UInt32 tap16, tap25;
155+
156+
fixed (UInt32* thetaPtr = theta, workPtr = work_buffer)
157+
{
158+
Converters.le32_copy(a_data, a_index, (IntPtr)workPtr, 0, 32);
159+
160+
tap16 = (UInt32)((tap + 16) & 0x1F);
161+
162+
tap = (tap - 1) & 0x1F;
163+
tap25 = (UInt32)((tap + 25) & 0x1F);
164+
165+
GPT(thetaPtr);
166+
167+
stages[tap25][0] = stages[tap25][0] ^ stages[tap][2];
168+
stages[tap25][1] = stages[tap25][1] ^ stages[tap][3];
169+
stages[tap25][2] = stages[tap25][2] ^ stages[tap][4];
170+
stages[tap25][3] = stages[tap25][3] ^ stages[tap][5];
171+
stages[tap25][4] = stages[tap25][4] ^ stages[tap][6];
172+
stages[tap25][5] = stages[tap25][5] ^ stages[tap][7];
173+
stages[tap25][6] = stages[tap25][6] ^ stages[tap][0];
174+
stages[tap25][7] = stages[tap25][7] ^ stages[tap][1];
175+
stages[tap][0] = stages[tap][0] ^ work_buffer[0];
176+
stages[tap][1] = stages[tap][1] ^ work_buffer[1];
177+
stages[tap][2] = stages[tap][2] ^ work_buffer[2];
178+
stages[tap][3] = stages[tap][3] ^ work_buffer[3];
179+
stages[tap][4] = stages[tap][4] ^ work_buffer[4];
180+
stages[tap][5] = stages[tap][5] ^ work_buffer[5];
181+
stages[tap][6] = stages[tap][6] ^ work_buffer[6];
182+
stages[tap][7] = stages[tap][7] ^ work_buffer[7];
183+
184+
state[0] = theta[0] ^ 0x01;
185+
state[1] = theta[1] ^ work_buffer[0];
186+
state[2] = theta[2] ^ work_buffer[1];
187+
state[3] = theta[3] ^ work_buffer[2];
188+
state[4] = theta[4] ^ work_buffer[3];
189+
state[5] = theta[5] ^ work_buffer[4];
190+
state[6] = theta[6] ^ work_buffer[5];
191+
state[7] = theta[7] ^ work_buffer[6];
192+
state[8] = theta[8] ^ work_buffer[7];
193+
state[9] = theta[9] ^ stages[tap16][0];
194+
state[10] = theta[10] ^ stages[tap16][1];
195+
state[11] = theta[11] ^ stages[tap16][2];
196+
state[12] = theta[12] ^ stages[tap16][3];
197+
state[13] = theta[13] ^ stages[tap16][4];
198+
state[14] = theta[14] ^ stages[tap16][5];
199+
state[15] = theta[15] ^ stages[tap16][6];
200+
state[16] = theta[16] ^ stages[tap16][7];
201+
202+
203+
Utils.Utils.memset(ref work_buffer, 0);
204+
}
205+
206+
} // end function TransformBlock
207+
208+
private unsafe void GPT(UInt32* a_theta)
209+
{
210+
gamma[0] = state[0] ^ (state[1] | ~state[2]);
211+
gamma[1] = state[1] ^ (state[2] | ~state[3]);
212+
gamma[2] = state[2] ^ (state[3] | ~state[4]);
213+
gamma[3] = state[3] ^ (state[4] | ~state[5]);
214+
gamma[4] = state[4] ^ (state[5] | ~state[6]);
215+
gamma[5] = state[5] ^ (state[6] | ~state[7]);
216+
gamma[6] = state[6] ^ (state[7] | ~state[8]);
217+
gamma[7] = state[7] ^ (state[8] | ~state[9]);
218+
gamma[8] = state[8] ^ (state[9] | ~state[10]);
219+
gamma[9] = state[9] ^ (state[10] | ~state[11]);
220+
gamma[10] = state[10] ^ (state[11] | ~state[12]);
221+
gamma[11] = state[11] ^ (state[12] | ~state[13]);
222+
gamma[12] = state[12] ^ (state[13] | ~state[14]);
223+
gamma[13] = state[13] ^ (state[14] | ~state[15]);
224+
gamma[14] = state[14] ^ (state[15] | ~state[16]);
225+
gamma[15] = state[15] ^ (state[16] | ~state[0]);
226+
gamma[16] = state[16] ^ (state[0] | ~state[1]);
227+
228+
pi[0] = gamma[0];
229+
pi[1] = Bits.RotateLeft32(gamma[7], 1);
230+
pi[2] = Bits.RotateLeft32(gamma[14], 3);
231+
pi[3] = Bits.RotateLeft32(gamma[4], 6);
232+
pi[4] = Bits.RotateLeft32(gamma[11], 10);
233+
pi[5] = Bits.RotateLeft32(gamma[1], 15);
234+
pi[6] = Bits.RotateLeft32(gamma[8], 21);
235+
pi[7] = Bits.RotateLeft32(gamma[15], 28);
236+
pi[8] = Bits.RotateLeft32(gamma[5], 4);
237+
pi[9] = Bits.RotateLeft32(gamma[12], 13);
238+
pi[10] = Bits.RotateLeft32(gamma[2], 23);
239+
pi[11] = Bits.RotateLeft32(gamma[9], 2);
240+
pi[12] = Bits.RotateLeft32(gamma[16], 14);
241+
pi[13] = Bits.RotateLeft32(gamma[6], 27);
242+
pi[14] = Bits.RotateLeft32(gamma[13], 9);
243+
pi[15] = Bits.RotateLeft32(gamma[3], 24);
244+
pi[16] = Bits.RotateLeft32(gamma[10], 8);
245+
246+
a_theta[0] = pi[0] ^ pi[1] ^ pi[4];
247+
a_theta[1] = pi[1] ^ pi[2] ^ pi[5];
248+
a_theta[2] = pi[2] ^ pi[3] ^ pi[6];
249+
a_theta[3] = pi[3] ^ pi[4] ^ pi[7];
250+
a_theta[4] = pi[4] ^ pi[5] ^ pi[8];
251+
a_theta[5] = pi[5] ^ pi[6] ^ pi[9];
252+
a_theta[6] = pi[6] ^ pi[7] ^ pi[10];
253+
a_theta[7] = pi[7] ^ pi[8] ^ pi[11];
254+
a_theta[8] = pi[8] ^ pi[9] ^ pi[12];
255+
a_theta[9] = pi[9] ^ pi[10] ^ pi[13];
256+
a_theta[10] = pi[10] ^ pi[11] ^ pi[14];
257+
a_theta[11] = pi[11] ^ pi[12] ^ pi[15];
258+
a_theta[12] = pi[12] ^ pi[13] ^ pi[16];
259+
a_theta[13] = pi[13] ^ pi[14] ^ pi[0];
260+
a_theta[14] = pi[14] ^ pi[15] ^ pi[1];
261+
a_theta[15] = pi[15] ^ pi[16] ^ pi[2];
262+
a_theta[16] = pi[16] ^ pi[0] ^ pi[3];
263+
} // end function GPT
264+
265+
} // end class Panama
266+
267+
}

0 commit comments

Comments
 (0)