Mercurial > hg > ucis.core
comparison NaCl/crypto_onetimeauth/poly1305.cs @ 20:c873e3dd73fe
Added NaCl cryptography code
author | Ivo Smits <Ivo@UCIS.nl> |
---|---|
date | Mon, 15 Apr 2013 00:43:48 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
19:b9ef273964fd | 20:c873e3dd73fe |
---|---|
1 using System; | |
2 | |
3 namespace UCIS.NaCl.crypto_onetimeauth { | |
4 unsafe static class poly1305 { | |
5 static Boolean UseNativeFunctions = false; | |
6 static unsafe internal Boolean EnableNativeImplementation() { | |
7 UseNativeFunctions = false; | |
8 Byte* dummy = stackalloc Byte[32]; | |
9 try { | |
10 if (Native.crypto_onetimeauth_poly1305(dummy, dummy, 0, dummy) != 0) return false; | |
11 } catch (Exception) { | |
12 return false; | |
13 } | |
14 return UseNativeFunctions = true; | |
15 } | |
16 | |
17 const int CRYPTO_BYTES = 16; | |
18 const int CRYPTO_KEYBYTES = 32; | |
19 | |
20 //Never written to | |
21 static UInt32[] minusp = new UInt32[17] { 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252 }; | |
22 | |
23 public static int crypto_onetimeauth_verify(Byte* h, Byte* inv, UInt64 inlen, Byte* k) { | |
24 Byte* correct = stackalloc Byte[16]; | |
25 crypto_onetimeauth(correct, inv, inlen, k); | |
26 return crypto_verify._16.crypto_verify(h, correct); | |
27 } | |
28 | |
29 static void add(UInt32* h, UInt32* c) { //h[17], c[17] | |
30 UInt32 u = 0; | |
31 for (int j = 0; j < 17; ++j) { u += h[j] + c[j]; h[j] = u & 255; u >>= 8; } | |
32 } | |
33 | |
34 static void squeeze(UInt32* h) { //h[17] | |
35 UInt32 u = 0; | |
36 for (int j = 0; j < 16; ++j) { u += h[j]; h[j] = u & 255; u >>= 8; } | |
37 u += h[16]; h[16] = u & 3; | |
38 u = 5 * (u >> 2); | |
39 for (int j = 0; j < 16; ++j) { u += h[j]; h[j] = u & 255; u >>= 8; } | |
40 u += h[16]; h[16] = u; | |
41 } | |
42 | |
43 static void freeze(UInt32* h) { //h[17] | |
44 UInt32* horig = stackalloc UInt32[17]; | |
45 for (int j = 0; j < 17; ++j) horig[j] = h[j]; | |
46 fixed (uint* minuspp = minusp) add(h, minuspp); | |
47 UInt32 negative = (UInt32)(-(h[16] >> 7)); | |
48 for (int j = 0; j < 17; ++j) h[j] ^= negative & (horig[j] ^ h[j]); | |
49 } | |
50 | |
51 static void mulmod(UInt32* h, UInt32* r) { //h[17], r[17] | |
52 UInt32* hr = stackalloc UInt32[17]; | |
53 for (uint i = 0; i < 17; ++i) { | |
54 UInt32 u = 0; | |
55 for (uint j = i + 1; j < 17; ++j) u += h[j] * r[i + 17 - j]; | |
56 u *= 320; | |
57 for (uint j = 0; j <= i; ++j) u += h[j] * r[i - j]; | |
58 hr[i] = u; | |
59 } | |
60 for (int i = 0; i < 17; ++i) h[i] = hr[i]; | |
61 squeeze(h); | |
62 } | |
63 | |
64 public static void crypto_onetimeauth(Byte* outv, Byte* inv, UInt64 inlen, Byte* k) { | |
65 if (UseNativeFunctions) { | |
66 Native.crypto_onetimeauth_poly1305(outv, inv, inlen, k); | |
67 return; | |
68 } | |
69 | |
70 UInt32* r = stackalloc UInt32[17]; | |
71 UInt32* h = stackalloc UInt32[17]; | |
72 UInt32* c = stackalloc UInt32[17]; | |
73 | |
74 r[0] = k[0]; | |
75 r[1] = k[1]; | |
76 r[2] = k[2]; | |
77 r[3] = (UInt32)(k[3] & 15); | |
78 r[4] = (UInt32)(k[4] & 252); | |
79 r[5] = k[5]; | |
80 r[6] = k[6]; | |
81 r[7] = (UInt32)(k[7] & 15); | |
82 r[8] = (UInt32)(k[8] & 252); | |
83 r[9] = k[9]; | |
84 r[10] = k[10]; | |
85 r[11] = (UInt32)(k[11] & 15); | |
86 r[12] = (UInt32)(k[12] & 252); | |
87 r[13] = k[13]; | |
88 r[14] = k[14]; | |
89 r[15] = (UInt32)(k[15] & 15); | |
90 r[16] = 0; | |
91 | |
92 for (int j = 0; j < 17; ++j) h[j] = 0; | |
93 | |
94 while (inlen > 0) { | |
95 int m = (int)Math.Min(16, inlen); | |
96 for (int j = 0; j < m; ++j) c[j] = inv[j]; | |
97 c[m] = 1; | |
98 inv += m; | |
99 inlen -= (ulong)m; | |
100 for (int j = m + 1; j < 17; ++j) c[j] = 0; | |
101 add(h, c); | |
102 mulmod(h, r); | |
103 } | |
104 | |
105 freeze(h); | |
106 | |
107 for (int j = 0; j < 16; ++j) c[j] = k[j + 16]; | |
108 c[16] = 0; | |
109 add(h, c); | |
110 for (int j = 0; j < 16; ++j) outv[j] = (Byte)h[j]; | |
111 } | |
112 } | |
113 } |