20
|
1 ???using System; |
|
2 |
|
3 namespace UCIS.NaCl.crypto_stream { |
|
4 static unsafe class salsa20 { |
|
5 public const int KEYBYTES = 32; |
|
6 public const int NONCEBYTES = 8; |
|
7 |
|
8 static Byte[] sigma = new Byte[16] {(Byte)'e', (Byte)'x', (Byte)'p', (Byte)'a', //[16] = "expand 32-byte k"; |
|
9 (Byte)'n', (Byte)'d', (Byte)' ', (Byte)'3', |
|
10 (Byte)'2', (Byte)'-', (Byte)'b', (Byte)'y', |
|
11 (Byte)'t', (Byte)'e', (Byte)' ', (Byte)'k', }; |
|
12 |
|
13 public static void crypto_stream(Byte* c, int clen, Byte* n, Byte* k) { |
|
14 Byte[] inv = new Byte[16]; |
|
15 Byte[] block = new Byte[64]; |
|
16 if (clen == 0) return; |
|
17 |
|
18 for (int i = 0; i < 8; ++i) inv[i] = n[i]; |
|
19 for (int i = 8; i < 16; ++i) inv[i] = 0; |
|
20 |
|
21 while (clen >= 64) { |
|
22 fixed (Byte* invp = inv, sigmap = sigma) crypto_core.salsa20.crypto_core(c, invp, k, sigmap); |
|
23 |
|
24 UInt32 u = 1; |
|
25 for (int i = 8; i < 16; ++i) { |
|
26 u += inv[i]; |
|
27 inv[i] = (Byte)u; |
|
28 u >>= 8; |
|
29 } |
|
30 |
|
31 clen -= 64; |
|
32 c += 64; |
|
33 } |
|
34 |
|
35 if (clen != 0) { |
|
36 fixed (Byte* invp = inv, sigmap = sigma, blockp = block) crypto_core.salsa20.crypto_core(blockp, invp, k, sigmap); |
|
37 for (int i = 0; i < clen; ++i) c[i] = block[i]; |
|
38 } |
|
39 } |
|
40 |
|
41 public static void crypto_stream_xor(Byte* c, Byte* m, int mlen, Byte* n, Byte* k) { |
|
42 Byte[] inv = new Byte[16]; |
|
43 Byte[] block = new Byte[64]; |
|
44 if (mlen == 0) return; |
|
45 |
|
46 for (int i = 0; i < 8; ++i) inv[i] = n[i]; |
|
47 for (int i = 8; i < 16; ++i) inv[i] = 0; |
|
48 |
|
49 while (mlen >= 64) { |
|
50 fixed (Byte* invp = inv, sigmap = sigma, blockp = block) crypto_core.salsa20.crypto_core(blockp, invp, k, sigmap); |
|
51 for (int i = 0; i < 64; ++i) c[i] = (Byte)(m[i] ^ block[i]); |
|
52 |
|
53 UInt32 u = 1; |
|
54 for (int i = 8; i < 16; ++i) { |
|
55 u += inv[i]; |
|
56 inv[i] = (Byte)u; |
|
57 u >>= 8; |
|
58 } |
|
59 |
|
60 mlen -= 64; |
|
61 c += 64; |
|
62 m += 64; |
|
63 } |
|
64 |
|
65 if (mlen != 0) { |
|
66 fixed (Byte* invp = inv, sigmap = sigma, blockp = block) crypto_core.salsa20.crypto_core(blockp, invp, k, sigmap); |
|
67 for (int i = 0; i < mlen; ++i) c[i] = (Byte)(m[i] ^ block[i]); |
|
68 } |
|
69 } |
|
70 |
|
71 internal static void crypto_stream_xor_split(Byte* mcpad, int padbytes, Byte* c, Byte* m, int mlen, Byte* n, Byte* k) { |
|
72 Byte* inv = stackalloc Byte[16]; |
|
73 Byte* block = stackalloc Byte[64]; |
|
74 |
|
75 for (int i = 0; i < 8; ++i) inv[i] = n[i]; |
|
76 for (int i = 8; i < 16; ++i) inv[i] = 0; |
|
77 |
|
78 if (padbytes > 0) { |
|
79 if (padbytes > 64) throw new ArgumentOutOfRangeException("padbytes"); |
|
80 crypto_core.salsa20.crypto_core(block, inv, k, sigma); |
|
81 if (mcpad != null) for (int i = 0; i < padbytes; ++i) mcpad[i] ^= block[i]; |
|
82 if (mlen > 0) { |
|
83 int bleft = 64 - padbytes; |
|
84 if (bleft > mlen) bleft = mlen; |
|
85 for (int i = 0; i < bleft; ++i) c[i] = (Byte)(m[i] ^ block[i + padbytes]); |
|
86 c += bleft; |
|
87 m += bleft; |
|
88 mlen -= bleft; |
|
89 if (mlen >= 0) { |
|
90 UInt32 u = 1; |
|
91 for (int i = 8; i < 16; ++i) { |
|
92 u += inv[i]; |
|
93 inv[i] = (Byte)u; |
|
94 u >>= 8; |
|
95 } |
|
96 } |
|
97 } |
|
98 } |
|
99 |
|
100 while (mlen >= 64) { |
|
101 crypto_core.salsa20.crypto_core(block, inv, k, sigma); |
|
102 //for (int i = 0; i < 64; ++i) c[i] = (Byte)(m[i] ^ block[i]); |
|
103 for (int i = 0; i < 64; i += 4) *(int*)(c + i) = *(int*)(m + i) ^ *(int*)(block + i); |
|
104 |
|
105 UInt32 u = 1; |
|
106 for (int i = 8; i < 16; ++i) { |
|
107 u += inv[i]; |
|
108 inv[i] = (Byte)u; |
|
109 u >>= 8; |
|
110 } |
|
111 |
|
112 mlen -= 64; |
|
113 c += 64; |
|
114 m += 64; |
|
115 } |
|
116 |
|
117 if (mlen > 0) { |
|
118 crypto_core.salsa20.crypto_core(block, inv, k, sigma); |
|
119 for (int i = 0; i < mlen; ++i) c[i] = (Byte)(m[i] ^ block[i]); |
|
120 } |
|
121 } |
|
122 } |
|
123 } |