Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
tpruvot
GitHub Repository: tpruvot/cpuminer-multi
Path: blob/linux/scryptjane/scrypt-jane-hash_skein512.h
1201 views
1
#define SCRYPT_HASH "Skein-512"
2
#define SCRYPT_HASH_BLOCK_SIZE 64
3
#define SCRYPT_HASH_DIGEST_SIZE 64
4
5
typedef uint8_t scrypt_hash_digest[SCRYPT_HASH_DIGEST_SIZE];
6
7
typedef struct scrypt_hash_state_t {
8
uint64_t X[8], T[2];
9
uint32_t leftover;
10
uint8_t buffer[SCRYPT_HASH_BLOCK_SIZE];
11
} scrypt_hash_state;
12
13
#include <stdio.h>
14
15
static void
16
skein512_blocks(scrypt_hash_state *S, const uint8_t *in, size_t blocks, size_t add) {
17
uint64_t X[8], key[8], Xt[9+18], T[3+1];
18
size_t r;
19
20
while (blocks--) {
21
T[0] = S->T[0] + add;
22
T[1] = S->T[1];
23
T[2] = T[0] ^ T[1];
24
key[0] = U8TO64_LE(in + 0); Xt[0] = S->X[0]; X[0] = key[0] + Xt[0];
25
key[1] = U8TO64_LE(in + 8); Xt[1] = S->X[1]; X[1] = key[1] + Xt[1];
26
key[2] = U8TO64_LE(in + 16); Xt[2] = S->X[2]; X[2] = key[2] + Xt[2];
27
key[3] = U8TO64_LE(in + 24); Xt[3] = S->X[3]; X[3] = key[3] + Xt[3];
28
key[4] = U8TO64_LE(in + 32); Xt[4] = S->X[4]; X[4] = key[4] + Xt[4];
29
key[5] = U8TO64_LE(in + 40); Xt[5] = S->X[5]; X[5] = key[5] + Xt[5] + T[0];
30
key[6] = U8TO64_LE(in + 48); Xt[6] = S->X[6]; X[6] = key[6] + Xt[6] + T[1];
31
key[7] = U8TO64_LE(in + 56); Xt[7] = S->X[7]; X[7] = key[7] + Xt[7];
32
Xt[8] = 0x1BD11BDAA9FC1A22ull ^ Xt[0] ^ Xt[1] ^ Xt[2] ^ Xt[3] ^ Xt[4] ^ Xt[5] ^ Xt[6] ^ Xt[7];
33
in += SCRYPT_HASH_BLOCK_SIZE;
34
35
for (r = 0; r < 18; r++)
36
Xt[r + 9] = Xt[r + 0];
37
38
for (r = 0; r < 18; r += 2) {
39
X[0] += X[1]; X[1] = ROTL64(X[1], 46) ^ X[0];
40
X[2] += X[3]; X[3] = ROTL64(X[3], 36) ^ X[2];
41
X[4] += X[5]; X[5] = ROTL64(X[5], 19) ^ X[4];
42
X[6] += X[7]; X[7] = ROTL64(X[7], 37) ^ X[6];
43
X[2] += X[1]; X[1] = ROTL64(X[1], 33) ^ X[2];
44
X[0] += X[3]; X[3] = ROTL64(X[3], 42) ^ X[0];
45
X[6] += X[5]; X[5] = ROTL64(X[5], 14) ^ X[6];
46
X[4] += X[7]; X[7] = ROTL64(X[7], 27) ^ X[4];
47
X[4] += X[1]; X[1] = ROTL64(X[1], 17) ^ X[4];
48
X[6] += X[3]; X[3] = ROTL64(X[3], 49) ^ X[6];
49
X[0] += X[5]; X[5] = ROTL64(X[5], 36) ^ X[0];
50
X[2] += X[7]; X[7] = ROTL64(X[7], 39) ^ X[2];
51
X[6] += X[1]; X[1] = ROTL64(X[1], 44) ^ X[6];
52
X[4] += X[3]; X[3] = ROTL64(X[3], 56) ^ X[4];
53
X[2] += X[5]; X[5] = ROTL64(X[5], 54) ^ X[2];
54
X[0] += X[7]; X[7] = ROTL64(X[7], 9) ^ X[0];
55
56
X[0] += Xt[r + 1];
57
X[1] += Xt[r + 2];
58
X[2] += Xt[r + 3];
59
X[3] += Xt[r + 4];
60
X[4] += Xt[r + 5];
61
X[5] += Xt[r + 6] + T[1];
62
X[6] += Xt[r + 7] + T[2];
63
X[7] += Xt[r + 8] + r + 1;
64
65
T[3] = T[0];
66
T[0] = T[1];
67
T[1] = T[2];
68
T[2] = T[3];
69
70
X[0] += X[1]; X[1] = ROTL64(X[1], 39) ^ X[0];
71
X[2] += X[3]; X[3] = ROTL64(X[3], 30) ^ X[2];
72
X[4] += X[5]; X[5] = ROTL64(X[5], 34) ^ X[4];
73
X[6] += X[7]; X[7] = ROTL64(X[7], 24) ^ X[6];
74
X[2] += X[1]; X[1] = ROTL64(X[1], 13) ^ X[2];
75
X[0] += X[3]; X[3] = ROTL64(X[3], 17) ^ X[0];
76
X[6] += X[5]; X[5] = ROTL64(X[5], 10) ^ X[6];
77
X[4] += X[7]; X[7] = ROTL64(X[7], 50) ^ X[4];
78
X[4] += X[1]; X[1] = ROTL64(X[1], 25) ^ X[4];
79
X[6] += X[3]; X[3] = ROTL64(X[3], 29) ^ X[6];
80
X[0] += X[5]; X[5] = ROTL64(X[5], 39) ^ X[0];
81
X[2] += X[7]; X[7] = ROTL64(X[7], 43) ^ X[2];
82
X[6] += X[1]; X[1] = ROTL64(X[1], 8) ^ X[6];
83
X[4] += X[3]; X[3] = ROTL64(X[3], 22) ^ X[4];
84
X[2] += X[5]; X[5] = ROTL64(X[5], 56) ^ X[2];
85
X[0] += X[7]; X[7] = ROTL64(X[7], 35) ^ X[0];
86
87
X[0] += Xt[r + 2];
88
X[1] += Xt[r + 3];
89
X[2] += Xt[r + 4];
90
X[3] += Xt[r + 5];
91
X[4] += Xt[r + 6];
92
X[5] += Xt[r + 7] + T[1];
93
X[6] += Xt[r + 8] + T[2];
94
X[7] += Xt[r + 9] + r + 2;
95
96
T[3] = T[0];
97
T[0] = T[1];
98
T[1] = T[2];
99
T[2] = T[3];
100
}
101
102
S->X[0] = key[0] ^ X[0];
103
S->X[1] = key[1] ^ X[1];
104
S->X[2] = key[2] ^ X[2];
105
S->X[3] = key[3] ^ X[3];
106
S->X[4] = key[4] ^ X[4];
107
S->X[5] = key[5] ^ X[5];
108
S->X[6] = key[6] ^ X[6];
109
S->X[7] = key[7] ^ X[7];
110
111
S->T[0] = T[0];
112
S->T[1] = T[1] & ~0x4000000000000000ull;
113
}
114
}
115
116
static void
117
scrypt_hash_init(scrypt_hash_state *S) {
118
S->X[0] = 0x4903ADFF749C51CEull;
119
S->X[1] = 0x0D95DE399746DF03ull;
120
S->X[2] = 0x8FD1934127C79BCEull;
121
S->X[3] = 0x9A255629FF352CB1ull;
122
S->X[4] = 0x5DB62599DF6CA7B0ull;
123
S->X[5] = 0xEABE394CA9D5C3F4ull;
124
S->X[6] = 0x991112C71A75B523ull;
125
S->X[7] = 0xAE18A40B660FCC33ull;
126
S->T[0] = 0x0000000000000000ull;
127
S->T[1] = 0x7000000000000000ull;
128
S->leftover = 0;
129
}
130
131
static void
132
scrypt_hash_update(scrypt_hash_state *S, const uint8_t *in, size_t inlen) {
133
size_t blocks, want;
134
135
/* skein processes the final <=64 bytes raw, so we can only update if there are at least 64+1 bytes available */
136
if ((S->leftover + inlen) > SCRYPT_HASH_BLOCK_SIZE) {
137
/* handle the previous data, we know there is enough for at least one block */
138
if (S->leftover) {
139
want = (SCRYPT_HASH_BLOCK_SIZE - S->leftover);
140
memcpy(S->buffer + S->leftover, in, want);
141
in += want;
142
inlen -= want;
143
S->leftover = 0;
144
skein512_blocks(S, S->buffer, 1, SCRYPT_HASH_BLOCK_SIZE);
145
}
146
147
/* handle the current data if there's more than one block */
148
if (inlen > SCRYPT_HASH_BLOCK_SIZE) {
149
blocks = ((inlen - 1) & ~(SCRYPT_HASH_BLOCK_SIZE - 1));
150
skein512_blocks(S, in, blocks / SCRYPT_HASH_BLOCK_SIZE, SCRYPT_HASH_BLOCK_SIZE);
151
inlen -= blocks;
152
in += blocks;
153
}
154
}
155
156
/* handle leftover data */
157
memcpy(S->buffer + S->leftover, in, inlen);
158
S->leftover += inlen;
159
}
160
161
static void
162
scrypt_hash_finish(scrypt_hash_state *S, uint8_t *hash) {
163
memset(S->buffer + S->leftover, 0, SCRYPT_HASH_BLOCK_SIZE - S->leftover);
164
S->T[1] |= 0x8000000000000000ull;
165
skein512_blocks(S, S->buffer, 1, S->leftover);
166
167
memset(S->buffer, 0, SCRYPT_HASH_BLOCK_SIZE);
168
S->T[0] = 0;
169
S->T[1] = 0xff00000000000000ull;
170
skein512_blocks(S, S->buffer, 1, 8);
171
172
U64TO8_LE(&hash[ 0], S->X[0]);
173
U64TO8_LE(&hash[ 8], S->X[1]);
174
U64TO8_LE(&hash[16], S->X[2]);
175
U64TO8_LE(&hash[24], S->X[3]);
176
U64TO8_LE(&hash[32], S->X[4]);
177
U64TO8_LE(&hash[40], S->X[5]);
178
U64TO8_LE(&hash[48], S->X[6]);
179
U64TO8_LE(&hash[56], S->X[7]);
180
}
181
182
183
static const uint8_t scrypt_test_hash_expected[SCRYPT_HASH_DIGEST_SIZE] = {
184
0x4d,0x52,0x29,0xff,0x10,0xbc,0xd2,0x62,0xd1,0x61,0x83,0xc8,0xe6,0xf0,0x83,0xc4,
185
0x9f,0xf5,0x6a,0x42,0x75,0x2a,0x26,0x4e,0xf0,0x28,0x72,0x28,0x47,0xe8,0x23,0xdf,
186
0x1e,0x64,0xf1,0x51,0x38,0x35,0x9d,0xc2,0x83,0xfc,0x35,0x4e,0xc0,0x52,0x5f,0x41,
187
0x6a,0x0b,0x7d,0xf5,0xce,0x98,0xde,0x6f,0x36,0xd8,0x51,0x15,0x78,0x78,0x93,0x67,
188
};
189
190