Mercurial > hg > ucis.core
comparison NaCl/crypto_hash/sha512.cs @ 72:b7d981ccd434
NaCl: improved sha512 implementation
author | Ivo Smits <Ivo@UCIS.nl> |
---|---|
date | Sat, 02 Nov 2013 15:59:51 +0100 |
parents | 7e9d1cfcc562 |
children |
comparison
equal
deleted
inserted
replaced
71:7e9d1cfcc562 | 72:b7d981ccd434 |
---|---|
1 using System; | 1 using System; |
2 | 2 |
3 namespace UCIS.NaCl.crypto_hash { | 3 namespace UCIS.NaCl.crypto_hash { |
4 public static class sha512 { | 4 public static class sha512 { |
5 public static int BYTES = 64; | 5 public static int BYTES = 64; |
6 | |
7 /* static Byte[] iv = new Byte[64] { | |
8 0x6a,0x09,0xe6,0x67,0xf3,0xbc,0xc9,0x08, | |
9 0xbb,0x67,0xae,0x85,0x84,0xca,0xa7,0x3b, | |
10 0x3c,0x6e,0xf3,0x72,0xfe,0x94,0xf8,0x2b, | |
11 0xa5,0x4f,0xf5,0x3a,0x5f,0x1d,0x36,0xf1, | |
12 0x51,0x0e,0x52,0x7f,0xad,0xe6,0x82,0xd1, | |
13 0x9b,0x05,0x68,0x8c,0x2b,0x3e,0x6c,0x1f, | |
14 0x1f,0x83,0xd9,0xab,0xfb,0x41,0xbd,0x6b, | |
15 0x5b,0xe0,0xcd,0x19,0x13,0x7e,0x21,0x79 | |
16 };*/ | |
17 | 6 |
18 public static unsafe void crypto_hash(Byte[] outv, Byte[] inv, int inlen) { | 7 public static unsafe void crypto_hash(Byte[] outv, Byte[] inv, int inlen) { |
19 if (outv.Length < 64) throw new ArgumentException("outv.Length < 64"); | 8 if (outv.Length < 64) throw new ArgumentException("outv.Length < 64"); |
20 if (inv.Length < inlen) throw new ArgumentException("inv.Length < inlen"); | 9 if (inv.Length < inlen) throw new ArgumentException("inv.Length < inlen"); |
21 fixed (Byte* outp = outv, inp = inv) crypto_hash(outp, inp, (UInt64)inlen); | 10 fixed (Byte* outp = outv, inp = inv) crypto_hash(outp, inp, (UInt64)inlen); |
22 } | 11 } |
23 public static unsafe void crypto_hash(Byte* outp, Byte* inp, UInt64 inlen) { | 12 public static unsafe void crypto_hash(Byte* outp, Byte* inp, UInt64 inlen) { |
24 // Byte[] h = new Byte[64]; | 13 sha512state state = new sha512state(); |
25 Byte[] padded = new Byte[256]; | 14 state.init(); |
26 UInt64 i; | 15 state.process(inp, (int)inlen); |
27 UInt64 bytes = inlen; | 16 state.finish(outp); |
28 Byte[] h = new Byte[64] { | 17 } |
29 0x6a,0x09,0xe6,0x67,0xf3,0xbc,0xc9,0x08, | |
30 0xbb,0x67,0xae,0x85,0x84,0xca,0xa7,0x3b, | |
31 0x3c,0x6e,0xf3,0x72,0xfe,0x94,0xf8,0x2b, | |
32 0xa5,0x4f,0xf5,0x3a,0x5f,0x1d,0x36,0xf1, | |
33 0x51,0x0e,0x52,0x7f,0xad,0xe6,0x82,0xd1, | |
34 0x9b,0x05,0x68,0x8c,0x2b,0x3e,0x6c,0x1f, | |
35 0x1f,0x83,0xd9,0xab,0xfb,0x41,0xbd,0x6b, | |
36 0x5b,0xe0,0xcd,0x19,0x13,0x7e,0x21,0x79 | |
37 }; | |
38 | 18 |
39 // for (i = 0; i < 64; ++i) h[i] = iv[i]; | 19 public unsafe struct sha512state { |
20 fixed UInt64 state[8]; | |
21 fixed Byte input[128]; | |
22 int offset; | |
23 int length; | |
40 | 24 |
41 fixed (Byte* hp = h) crypto_hashblocks.sha512.crypto_hashblocks(hp, inp, inlen); | 25 public unsafe void init() { |
42 inp += inlen; | 26 fixed (UInt64* s = state) { |
43 inlen &= 127; | 27 s[0] = 0x6a09e667f3bcc908; s[1] = 0xbb67ae8584caa73b; s[2] = 0x3c6ef372fe94f82b; s[3] = 0xa54ff53a5f1d36f1; |
44 inp -= inlen; | 28 s[4] = 0x510e527fade682d1; s[5] = 0x9b05688c2b3e6c1f; s[6] = 0x1f83d9abfb41bd6b; s[7] = 0x5be0cd19137e2179; |
45 | 29 } |
46 for (i = 0; i < inlen; ++i) padded[i] = inp[i]; | 30 offset = 0; |
47 padded[inlen] = 0x80; | 31 length = 0; |
48 | |
49 if (inlen < 112) { | |
50 for (i = inlen + 1; i < 119; ++i) padded[i] = 0; | |
51 padded[119] = (Byte)(bytes >> 61); | |
52 padded[120] = (Byte)(bytes >> 53); | |
53 padded[121] = (Byte)(bytes >> 45); | |
54 padded[122] = (Byte)(bytes >> 37); | |
55 padded[123] = (Byte)(bytes >> 29); | |
56 padded[124] = (Byte)(bytes >> 21); | |
57 padded[125] = (Byte)(bytes >> 13); | |
58 padded[126] = (Byte)(bytes >> 5); | |
59 padded[127] = (Byte)(bytes << 3); | |
60 fixed (Byte* hp = h, paddedp = padded) crypto_hashblocks.sha512.crypto_hashblocks(hp, paddedp, 128); | |
61 } else { | |
62 for (i = inlen + 1; i < 247; ++i) padded[i] = 0; | |
63 padded[247] = (Byte)(bytes >> 61); | |
64 padded[248] = (Byte)(bytes >> 53); | |
65 padded[249] = (Byte)(bytes >> 45); | |
66 padded[250] = (Byte)(bytes >> 37); | |
67 padded[251] = (Byte)(bytes >> 29); | |
68 padded[252] = (Byte)(bytes >> 21); | |
69 padded[253] = (Byte)(bytes >> 13); | |
70 padded[254] = (Byte)(bytes >> 5); | |
71 padded[255] = (Byte)(bytes << 3); | |
72 fixed (Byte* hp = h, paddedp = padded) crypto_hashblocks.sha512.crypto_hashblocks(hp, paddedp, 256); | |
73 } | 32 } |
74 | 33 public unsafe void process(Byte* inp, int inlen) { |
75 for (i = 0; i < 64; ++i) outp[i] = h[i]; | 34 fixed (sha512state* pthis = &this) { |
35 length += inlen; | |
36 if (offset > 0) { | |
37 int blen = 128 - offset; | |
38 if (blen > inlen) blen = inlen; | |
39 for (int i = 0; i < blen; i++) pthis->input[offset++] = *inp++; | |
40 inlen -= blen; | |
41 } | |
42 if (offset == 128) { | |
43 crypto_hashblocks.sha512.crypto_hashblocks(pthis->state, pthis->input, (UInt64)offset); | |
44 offset = 0; | |
45 } | |
46 if (inlen >= 128) { | |
47 crypto_hashblocks.sha512.crypto_hashblocks(pthis->state, inp, (UInt64)inlen); | |
48 inp += inlen; | |
49 inlen &= 127; | |
50 inp -= inlen; | |
51 } | |
52 if (inlen > 0) { | |
53 for (int i = 0; i < inlen; i++) pthis->input[offset++] = *inp++; | |
54 } | |
55 } | |
56 } | |
57 public unsafe void finish(Byte* outp) { | |
58 fixed (sha512state* s = &this) { | |
59 s->input[offset++] = 0x80; | |
60 if (offset > 112) { | |
61 for (int i = offset; i < 128; i++) s->input[i] = 0; | |
62 crypto_hashblocks.sha512.crypto_hashblocks(s->state, s->input, 128); | |
63 offset = 0; | |
64 } | |
65 for (int i = offset; i < 119; i++) s->input[i] = 0; | |
66 UInt64 bytes = (UInt64)length; | |
67 s->input[119] = (Byte)(bytes >> 61); | |
68 s->input[120] = (Byte)(bytes >> 53); | |
69 s->input[121] = (Byte)(bytes >> 45); | |
70 s->input[122] = (Byte)(bytes >> 37); | |
71 s->input[123] = (Byte)(bytes >> 29); | |
72 s->input[124] = (Byte)(bytes >> 21); | |
73 s->input[125] = (Byte)(bytes >> 13); | |
74 s->input[126] = (Byte)(bytes >> 5); | |
75 s->input[127] = (Byte)(bytes << 3); | |
76 crypto_hashblocks.sha512.crypto_hashblocks(s->state, s->input, 128); | |
77 crypto_hashblocks.sha512.crypto_hashblocks_state_pack(outp, s->state); | |
78 } | |
79 } | |
76 } | 80 } |
77 } | 81 } |
78 } | 82 } |