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 }