-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathduco_hash.cpp
150 lines (124 loc) · 3.71 KB
/
duco_hash.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#include "duco_hash.h"
#pragma GCC optimize ("-Ofast")
#define sha1_rotl(bits,word) (((word) << (bits)) | ((word) >> (32 - (bits))))
void duco_hash_block(duco_hash_state_t * hasher) {
// NOTE: keeping this static improves performance quite a lot
static uint32_t w[16];
for (uint8_t i = 0, i4 = 0; i < 16; i++, i4 += 4) {
w[i] = (uint32_t(hasher->buffer[i4]) << 24) |
(uint32_t(hasher->buffer[i4 + 1]) << 16) |
(uint32_t(hasher->buffer[i4 + 2]) << 8) |
(uint32_t(hasher->buffer[i4 + 3]));
}
uint32_t a = hasher->tempState[0];
uint32_t b = hasher->tempState[1];
uint32_t c = hasher->tempState[2];
uint32_t d = hasher->tempState[3];
uint32_t e = hasher->tempState[4];
for (uint8_t i = 10; i < 80; i++) {
if (i >= 16) {
w[i & 15] = sha1_rotl(1, w[(i-3) & 15] ^ w[(i-8) & 15] ^ w[(i-14) & 15] ^ w[(i-16) & 15]);
}
uint32_t temp = sha1_rotl(5, a) + e + w[i & 15];
if (i < 20) {
temp += (b & c) | ((~b) & d);
temp += 0x5a827999;
} else if(i < 40) {
temp += b ^ c ^ d;
temp += 0x6ed9eba1;
} else if(i < 60) {
temp += (b & c) | (b & d) | (c & d);
temp += 0x8f1bbcdc;
} else {
temp += b ^ c ^ d;
temp += 0xca62c1d6;
}
e = d;
d = c;
c = sha1_rotl(30, b);
b = a;
a = temp;
}
a += 0x67452301;
b += 0xefcdab89;
c += 0x98badcfe;
d += 0x10325476;
e += 0xc3d2e1f0;
hasher->result[0 * 4 + 0] = a >> 24;
hasher->result[0 * 4 + 1] = a >> 16;
hasher->result[0 * 4 + 2] = a >> 8;
hasher->result[0 * 4 + 3] = a;
hasher->result[1 * 4 + 0] = b >> 24;
hasher->result[1 * 4 + 1] = b >> 16;
hasher->result[1 * 4 + 2] = b >> 8;
hasher->result[1 * 4 + 3] = b;
hasher->result[2 * 4 + 0] = c >> 24;
hasher->result[2 * 4 + 1] = c >> 16;
hasher->result[2 * 4 + 2] = c >> 8;
hasher->result[2 * 4 + 3] = c;
hasher->result[3 * 4 + 0] = d >> 24;
hasher->result[3 * 4 + 1] = d >> 16;
hasher->result[3 * 4 + 2] = d >> 8;
hasher->result[3 * 4 + 3] = d;
hasher->result[4 * 4 + 0] = e >> 24;
hasher->result[4 * 4 + 1] = e >> 16;
hasher->result[4 * 4 + 2] = e >> 8;
hasher->result[4 * 4 + 3] = e;
}
void duco_hash_init(duco_hash_state_t * hasher, char const * prevHash) {
memcpy(hasher->buffer, prevHash, 40);
if (prevHash == (void*)(0xffffffff)) {
// NOTE: THIS IS NEVER CALLED
// This is here to keep a live reference to hash_block
// Otherwise GCC tries to inline it entirely into the main loop
// Which causes massive perf degradation
duco_hash_block(nullptr);
}
// Do first 10 rounds as these are going to be the same all time
uint32_t a = 0x67452301;
uint32_t b = 0xefcdab89;
uint32_t c = 0x98badcfe;
uint32_t d = 0x10325476;
uint32_t e = 0xc3d2e1f0;
static uint32_t w[10];
for (uint8_t i = 0, i4 = 0; i < 10; i++, i4 += 4) {
w[i] = (uint32_t(hasher->buffer[i4]) << 24) |
(uint32_t(hasher->buffer[i4 + 1]) << 16) |
(uint32_t(hasher->buffer[i4 + 2]) << 8) |
(uint32_t(hasher->buffer[i4 + 3]));
}
for (uint8_t i = 0; i < 10; i++) {
uint32_t temp = sha1_rotl(5, a) + e + w[i & 15];
temp += (b & c) | ((~b) & d);
temp += 0x5a827999;
e = d;
d = c;
c = sha1_rotl(30, b);
b = a;
a = temp;
}
hasher->tempState[0] = a;
hasher->tempState[1] = b;
hasher->tempState[2] = c;
hasher->tempState[3] = d;
hasher->tempState[4] = e;
}
void duco_hash_set_nonce(duco_hash_state_t * hasher, char const * nonce) {
uint8_t * b = hasher->buffer;
uint8_t off = SHA1_HASH_LEN * 2;
for (uint8_t i = 0; i < 10 && nonce[i] != 0; i++) {
b[off++] = nonce[i];
}
uint8_t total_bytes = off;
b[off++] = 0x80;
while (off < 62) {
b[off++] = 0;
}
b[62] = total_bytes >> 5;
b[63] = total_bytes << 3;
}
uint8_t const * duco_hash_try_nonce(duco_hash_state_t * hasher, char const * nonce) {
duco_hash_set_nonce(hasher, nonce);
duco_hash_block(hasher);
return hasher->result;
}