2 * Novacoin classes library
3 * Copyright (C) 2015 Alex D. (balthazar.ad@gmail.com)
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Affero General Public License as
7 * published by the Free Software Foundation, either version 3 of the
8 * License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Affero General Public License for more details.
15 * You should have received a copy of the GNU Affero General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 /// Representation of scrypt hash
26 public class ScryptHash256 : Hash
29 public override int hashSize
34 public ScryptHash256() : base() { }
35 public ScryptHash256(byte[] bytes, int offset = 0) : base(bytes, offset) { }
36 public ScryptHash256(ScryptHash256 h) : base(h) { }
39 /// Calculate scrypt hash and return new instance of ScryptHash256 class
41 /// <param name="inputBytes">Byte sequence to hash</param>
42 /// <returns>Hashing result instance</returns>
43 public static ScryptHash256 Compute256(byte[] inputBytes)
45 var V = new uint[(131072 + 63) / sizeof(uint)];
47 var keyBytes1 = CryptoUtils.PBKDF2_Sha256(128, (byte[])inputBytes, (byte[])inputBytes, 1);
48 var X = ToUInt32Array(keyBytes1);
50 for (var i = 0; i < 1024; i++)
52 Array.Copy(X, 0, V, i * 32, 32);
54 xor_salsa8(ref X, 0, ref X, 16);
55 xor_salsa8(ref X, 16, ref X, 0);
57 for (var i = 0; i < 1024; i++)
59 var j = 32 * (X[16] & 1023);
60 for (var k = 0; k < 32; k++)
64 xor_salsa8(ref X, 0, ref X, 16);
65 xor_salsa8(ref X, 16, ref X, 0);
68 var xBytes = LEBytes(X);
69 var keyBytes2 = CryptoUtils.PBKDF2_Sha256(32, (byte[])inputBytes, xBytes, 1);
71 return new ScryptHash256(keyBytes2);
74 private static void xor_salsa8(ref uint[] B, int indexB, ref uint[] Bx, int indexBx)
76 uint x00, x01, x02, x03, x04, x05, x06, x07, x08, x09, x10, x11, x12, x13, x14, x15;
79 x00 = (B[indexB + 0] ^= Bx[indexBx + 0]);
80 x01 = (B[indexB + 1] ^= Bx[indexBx + 1]);
81 x02 = (B[indexB + 2] ^= Bx[indexBx + 2]);
82 x03 = (B[indexB + 3] ^= Bx[indexBx + 3]);
83 x04 = (B[indexB + 4] ^= Bx[indexBx + 4]);
84 x05 = (B[indexB + 5] ^= Bx[indexBx + 5]);
85 x06 = (B[indexB + 6] ^= Bx[indexBx + 6]);
86 x07 = (B[indexB + 7] ^= Bx[indexBx + 7]);
87 x08 = (B[indexB + 8] ^= Bx[indexBx + 8]);
88 x09 = (B[indexB + 9] ^= Bx[indexBx + 9]);
89 x10 = (B[indexB + 10] ^= Bx[indexBx + 10]);
90 x11 = (B[indexB + 11] ^= Bx[indexBx + 11]);
91 x12 = (B[indexB + 12] ^= Bx[indexBx + 12]);
92 x13 = (B[indexB + 13] ^= Bx[indexBx + 13]);
93 x14 = (B[indexB + 14] ^= Bx[indexBx + 14]);
94 x15 = (B[indexB + 15] ^= Bx[indexBx + 15]);
96 Func<uint, int, uint> R = (a, b) => (((a) << (b)) | ((a) >> (32 - (b))));
98 for (i = 0; i < 8; i += 2)
100 /* Operate on columns. */
101 x04 ^= R(x00 + x12, 7); x09 ^= R(x05 + x01, 7);
102 x14 ^= R(x10 + x06, 7); x03 ^= R(x15 + x11, 7);
104 x08 ^= R(x04 + x00, 9); x13 ^= R(x09 + x05, 9);
105 x02 ^= R(x14 + x10, 9); x07 ^= R(x03 + x15, 9);
107 x12 ^= R(x08 + x04, 13); x01 ^= R(x13 + x09, 13);
108 x06 ^= R(x02 + x14, 13); x11 ^= R(x07 + x03, 13);
110 x00 ^= R(x12 + x08, 18); x05 ^= R(x01 + x13, 18);
111 x10 ^= R(x06 + x02, 18); x15 ^= R(x11 + x07, 18);
113 /* Operate on rows. */
114 x01 ^= R(x00 + x03, 7); x06 ^= R(x05 + x04, 7);
115 x11 ^= R(x10 + x09, 7); x12 ^= R(x15 + x14, 7);
117 x02 ^= R(x01 + x00, 9); x07 ^= R(x06 + x05, 9);
118 x08 ^= R(x11 + x10, 9); x13 ^= R(x12 + x15, 9);
120 x03 ^= R(x02 + x01, 13); x04 ^= R(x07 + x06, 13);
121 x09 ^= R(x08 + x11, 13); x14 ^= R(x13 + x12, 13);
123 x00 ^= R(x03 + x02, 18); x05 ^= R(x04 + x07, 18);
124 x10 ^= R(x09 + x08, 18); x15 ^= R(x14 + x13, 18);
127 B[indexB + 0] += x00;
128 B[indexB + 1] += x01;
129 B[indexB + 2] += x02;
130 B[indexB + 3] += x03;
131 B[indexB + 4] += x04;
132 B[indexB + 5] += x05;
133 B[indexB + 6] += x06;
134 B[indexB + 7] += x07;
135 B[indexB + 8] += x08;
136 B[indexB + 9] += x09;
137 B[indexB + 10] += x10;
138 B[indexB + 11] += x11;
139 B[indexB + 12] += x12;
140 B[indexB + 13] += x13;
141 B[indexB + 14] += x14;
142 B[indexB + 15] += x15;
146 /// Convert array of unsigned integers to array of bytes.
148 /// <param name="values">Array of unsigned integer values.</param>
149 /// <returns>Byte array</returns>
150 private static byte[] LEBytes(uint[] values)
152 var result = new byte[values.Length * sizeof(uint)];
153 Buffer.BlockCopy(values, 0, result, 0, result.Length);
159 /// Convert byte array to array of unsigned integers.
161 /// <param name="bytes">Byte array.</param>
162 /// <returns>Array of integers</returns>
163 private static uint[] ToUInt32Array(byte[] bytes)
165 var result = new uint[bytes.Length / sizeof(uint)];
166 Buffer.BlockCopy(bytes, 0, result, 0, bytes.Length);