0bf4ac4218287175a86d3966d8334d96eabc3a3d
[NovacoinLibrary.git] / Novacoin / ScryptHash256.cs
1 \feff/**
2  *
3  * This program is free software: you can redistribute it and/or modify
4  * it under the terms of the GNU Affero General Public License as
5  * published by the Free Software Foundation, either version 3 of the
6  * License, or (at your option) any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU Affero General Public License for more details.
12  *
13  * You should have received a copy of the GNU Affero General Public License
14  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15  */
16
17 using System;
18 using System.Collections.Generic;
19 using System.Linq;
20
21 namespace Novacoin
22 {
23     /// <summary>
24     /// Representation of scrypt hash
25     /// </summary>
26     public class ScryptHash256 : Hash
27     {
28         // 32 bytes
29         public override int hashSize
30         {
31             get { return 32; }
32         }
33
34         public ScryptHash256() : base() { }
35         public ScryptHash256(byte[] bytes, int offset = 0) : base(bytes, offset) { }
36         public ScryptHash256(IEnumerable<byte> bytes, int skip = 0) : base(bytes, skip) { }
37         public ScryptHash256(ScryptHash256 h) : base(h) { }
38
39         /// <summary>
40         /// Calculate scrypt hash and return new instance of ScryptHash256 class
41         /// </summary>
42         /// <param name="inputBytes">Byte sequence to hash</param>
43         /// <returns>Hashing result instance</returns>
44         public static ScryptHash256 Compute256(IEnumerable<byte> inputBytes)
45         {
46             var V = new uint[(131072 + 63) / sizeof(uint)];
47
48             var dataBytes = inputBytes.ToArray();
49             var keyBytes1 = CryptoUtils.PBKDF2_Sha256(128, dataBytes, dataBytes, 1);
50             var X = Interop.ToUInt32Array(keyBytes1);
51
52             for (var i = 0; i < 1024; i++)
53             {
54                 Array.Copy(X, 0, V, i * 32, 32);
55
56                 xor_salsa8(ref X, 0, ref X, 16);
57                 xor_salsa8(ref X, 16, ref X, 0);
58             }
59             for (var i = 0; i < 1024; i++)
60             {
61                 var j = 32 * (X[16] & 1023);
62                 for (var k = 0; k < 32; k++)
63                 {
64                     X[k] ^= V[j + k];
65                 }
66                 xor_salsa8(ref X, 0, ref X, 16);
67                 xor_salsa8(ref X, 16, ref X, 0);
68             }
69
70             var xBytes = Interop.LEBytes(X);
71             var keyBytes2 = CryptoUtils.PBKDF2_Sha256(32, dataBytes, xBytes, 1);
72
73             return new ScryptHash256(keyBytes2);
74         }
75
76         private static void xor_salsa8(ref uint[] B, int indexB, ref uint[] Bx, int indexBx)
77         {
78             uint x00, x01, x02, x03, x04, x05, x06, x07, x08, x09, x10, x11, x12, x13, x14, x15;
79             byte i;
80
81             x00 = (B[indexB + 0] ^= Bx[indexBx + 0]);
82             x01 = (B[indexB + 1] ^= Bx[indexBx + 1]);
83             x02 = (B[indexB + 2] ^= Bx[indexBx + 2]);
84             x03 = (B[indexB + 3] ^= Bx[indexBx + 3]);
85             x04 = (B[indexB + 4] ^= Bx[indexBx + 4]);
86             x05 = (B[indexB + 5] ^= Bx[indexBx + 5]);
87             x06 = (B[indexB + 6] ^= Bx[indexBx + 6]);
88             x07 = (B[indexB + 7] ^= Bx[indexBx + 7]);
89             x08 = (B[indexB + 8] ^= Bx[indexBx + 8]);
90             x09 = (B[indexB + 9] ^= Bx[indexBx + 9]);
91             x10 = (B[indexB + 10] ^= Bx[indexBx + 10]);
92             x11 = (B[indexB + 11] ^= Bx[indexBx + 11]);
93             x12 = (B[indexB + 12] ^= Bx[indexBx + 12]);
94             x13 = (B[indexB + 13] ^= Bx[indexBx + 13]);
95             x14 = (B[indexB + 14] ^= Bx[indexBx + 14]);
96             x15 = (B[indexB + 15] ^= Bx[indexBx + 15]);
97
98             Func<uint, int, uint> R = (a, b) => (((a) << (b)) | ((a) >> (32 - (b))));
99
100             for (i = 0; i < 8; i += 2)
101             {
102                 /* Operate on columns. */
103                 x04 ^= R(x00 + x12, 7); x09 ^= R(x05 + x01, 7);
104                 x14 ^= R(x10 + x06, 7); x03 ^= R(x15 + x11, 7);
105
106                 x08 ^= R(x04 + x00, 9); x13 ^= R(x09 + x05, 9);
107                 x02 ^= R(x14 + x10, 9); x07 ^= R(x03 + x15, 9);
108
109                 x12 ^= R(x08 + x04, 13); x01 ^= R(x13 + x09, 13);
110                 x06 ^= R(x02 + x14, 13); x11 ^= R(x07 + x03, 13);
111
112                 x00 ^= R(x12 + x08, 18); x05 ^= R(x01 + x13, 18);
113                 x10 ^= R(x06 + x02, 18); x15 ^= R(x11 + x07, 18);
114
115                 /* Operate on rows. */
116                 x01 ^= R(x00 + x03, 7); x06 ^= R(x05 + x04, 7);
117                 x11 ^= R(x10 + x09, 7); x12 ^= R(x15 + x14, 7);
118
119                 x02 ^= R(x01 + x00, 9); x07 ^= R(x06 + x05, 9);
120                 x08 ^= R(x11 + x10, 9); x13 ^= R(x12 + x15, 9);
121
122                 x03 ^= R(x02 + x01, 13); x04 ^= R(x07 + x06, 13);
123                 x09 ^= R(x08 + x11, 13); x14 ^= R(x13 + x12, 13);
124
125                 x00 ^= R(x03 + x02, 18); x05 ^= R(x04 + x07, 18);
126                 x10 ^= R(x09 + x08, 18); x15 ^= R(x14 + x13, 18);
127             }
128
129             B[indexB + 0] += x00;
130             B[indexB + 1] += x01;
131             B[indexB + 2] += x02;
132             B[indexB + 3] += x03;
133             B[indexB + 4] += x04;
134             B[indexB + 5] += x05;
135             B[indexB + 6] += x06;
136             B[indexB + 7] += x07;
137             B[indexB + 8] += x08;
138             B[indexB + 9] += x09;
139             B[indexB + 10] += x10;
140             B[indexB + 11] += x11;
141             B[indexB + 12] += x12;
142             B[indexB + 13] += x13;
143             B[indexB + 14] += x14;
144             B[indexB + 15] += x15;
145         }
146     }
147 }