ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Digest-Hashcash/Hashcash.xs
(Generate patch)

Comparing Digest-Hashcash/Hashcash.xs (file contents):
Revision 1.1 by root, Sat Sep 6 22:12:00 2003 UTC vs.
Revision 1.2 by root, Sun Sep 7 00:58:23 2003 UTC

20 * SHA1 perl module, since it looked reasonably well-crafted. I modified 20 * SHA1 perl module, since it looked reasonably well-crafted. I modified
21 * it here and there, though. 21 * it here and there, though.
22 */ 22 */
23 23
24/* don't expect _too_ much from compilers for now. */ 24/* don't expect _too_ much from compilers for now. */
25#if __GNUC_MAJOR > 2 25#if __GNUC__ > 2
26# define restrict __restrict__ 26# define restrict __restrict__
27# define inline __inline__
28# ifdef __i386
29# define GCCX86ASM 1
30# endif
27#elif __STDC_VERSION__ < 199900 31#elif __STDC_VERSION__ < 199900
28# define restrict 32# define restrict
33# define inline
29#endif 34#endif
30 35
31/* Useful defines & typedefs */ 36/* Useful defines & typedefs */
32 37
33#if defined(U64TYPE) && (defined(USE_64_BIT_INT) || ((BYTEORDER != 0x1234) && (BYTEORDER != 0x4321))) 38#if defined(U64TYPE) && (defined(USE_64_BIT_INT) || ((BYTEORDER != 0x1234) && (BYTEORDER != 0x4321)))
41# endif 46# endif
42#else 47#else
43typedef uint_fast32_t ULONG; /* 32-or-more-bit quantity */ 48typedef uint_fast32_t ULONG; /* 32-or-more-bit quantity */
44#endif 49#endif
45 50
51#if GCCX86ASM
52# define zprefix(n) ({ int _r; __asm__ ("bsrl %1, %0" : "=r" (_r) : "r" (n)); 31 - _r ; })
53#else
54static int zprefix (ULONG n)
55{
56 static char zp[256] =
57 {
58 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
59 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
60 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
61 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
62 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
63 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
64 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
65 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
66 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
67 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
68 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
69 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
70 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
71 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
72 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
73 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
74 };
75
76 return
77 n > 0xffffff ? zp[n >> 24]
78 : n > 0xffff ? 8 + zp[n >> 16]
79 : n > 0xff ? 16 + zp[n >> 8]
80 : 24 + zp[n];
81}
82#endif
83
46#define SHA_BLOCKSIZE 64 84#define SHA_BLOCKSIZE 64
47#define SHA_DIGESTSIZE 20 85#define SHA_DIGESTSIZE 20
48 86
49typedef struct { 87typedef struct {
50 ULONG digest[5]; /* message digest */ 88 ULONG digest[5]; /* message digest */
51 ULONG count; /* 32-bit bit count */ 89 ULONG count; /* 32-bit bit count */
90 int local; /* unprocessed amount in data */
52 U8 data[SHA_BLOCKSIZE]; /* SHA data buffer */ 91 U8 data[SHA_BLOCKSIZE]; /* SHA data buffer */
53 int local; /* unprocessed amount in data */
54} SHA_INFO; 92} SHA_INFO;
55 93
56
57/* UNRAVEL should be fastest & biggest */
58/* UNROLL_LOOPS should be just as big, but slightly slower */
59/* both undefined should be smallest and slowest */
60
61#define SHA_VERSION 1
62#define UNRAVEL
63/* #define UNROLL_LOOPS */
64 94
65/* SHA f()-functions */ 95/* SHA f()-functions */
66#define f1(x,y,z) ((x & y) | (~x & z)) 96#define f1(x,y,z) ((x & y) | (~x & z))
67#define f2(x,y,z) (x ^ y ^ z) 97#define f2(x,y,z) (x ^ y ^ z)
68#define f3(x,y,z) ((x & y) | (x & z) | (y & z)) 98#define f3(x,y,z) ((x & y) | (x & z) | (y & z))
78#define T32(x) ((x) & 0xffffffffL) 108#define T32(x) ((x) & 0xffffffffL)
79 109
80/* 32-bit rotate */ 110/* 32-bit rotate */
81#define R32(x,n) T32(((x << n) | (x >> (32 - n)))) 111#define R32(x,n) T32(((x << n) | (x >> (32 - n))))
82 112
83/* the generic case, for when the overall rotation is not unraveled */
84#define FG(n) \
85 T = T32(R32(A,5) + f##n(B,C,D) + E + *WP++ + CONST##n); \
86 E = D; D = C; C = R32(B,30); B = A; A = T
87
88/* specific cases, for when the overall rotation is unraveled */ 113/* specific cases, for when the overall rotation is unraveled */
89#define FA(n) \ 114#define FA(n) \
90 T = T32(R32(A,5) + f##n(B,C,D) + E + *WP++ + CONST##n); B = R32(B,30) 115 T = T32(R32(A,5) + f##n(B,C,D) + E + *WP++ + CONST##n); B = R32(B,30)
91 116
92#define FB(n) \ 117#define FB(n) \
102 B = T32(R32(C,5) + f##n(D,E,T) + A + *WP++ + CONST##n); D = R32(D,30) 127 B = T32(R32(C,5) + f##n(D,E,T) + A + *WP++ + CONST##n); D = R32(D,30)
103 128
104#define FT(n) \ 129#define FT(n) \
105 A = T32(R32(B,5) + f##n(C,D,E) + T + *WP++ + CONST##n); C = R32(C,30) 130 A = T32(R32(B,5) + f##n(C,D,E) + T + *WP++ + CONST##n); C = R32(C,30)
106 131
107
108static void sha_transform(restrict SHA_INFO *sha_info) 132static void sha_transform(SHA_INFO *restrict sha_info)
109{ 133{
110 int i; 134 int i;
111 U8 *dp; 135 U8 *dp;
112 ULONG T, A, B, C, D, E, W[80], *WP; 136 ULONG T, A, B, C, D, E, W[80], *restrict WP;
113 137
114 dp = sha_info->data; 138 dp = sha_info->data;
115 139
116/*
117the following makes sure that at least one code block below is
118traversed or an error is reported, without the necessity for nested
119preprocessor if/else/endif blocks, which are a great pain in the
120nether regions of the anatomy...
121*/
122#undef SWAP_DONE
123
124#if BYTEORDER == 0x1234 140#if BYTEORDER == 0x1234
125#define SWAP_DONE
126 assert(sizeof(ULONG) == 4); 141 assert(sizeof(ULONG) == 4);
142# ifdef HAS_NTOHL
143 for (i = 0; i < 16; ++i) {
144 T = *((ULONG *) dp);
145 dp += 4;
146 W[i] = ntohl (T);
147 }
148# else
127 for (i = 0; i < 16; ++i) { 149 for (i = 0; i < 16; ++i) {
128 T = *((ULONG *) dp); 150 T = *((ULONG *) dp);
129 dp += 4; 151 dp += 4;
130 W[i] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) | 152 W[i] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
131 ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff); 153 ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
132 } 154 }
133#endif 155# endif
134
135#if BYTEORDER == 0x4321 156#elif BYTEORDER == 0x4321
136#define SWAP_DONE
137 assert(sizeof(ULONG) == 4); 157 assert(sizeof(ULONG) == 4);
138 for (i = 0; i < 16; ++i) { 158 for (i = 0; i < 16; ++i) {
139 T = *((ULONG *) dp); 159 T = *((ULONG *) dp);
140 dp += 4; 160 dp += 4;
141 W[i] = T32(T); 161 W[i] = T32(T);
142 } 162 }
143#endif
144
145#if BYTEORDER == 0x12345678 163#elif BYTEORDER == 0x12345678
146#define SWAP_DONE
147 assert(sizeof(ULONG) == 8); 164 assert(sizeof(ULONG) == 8);
148 for (i = 0; i < 16; i += 2) { 165 for (i = 0; i < 16; i += 2) {
149 T = *((ULONG *) dp); 166 T = *((ULONG *) dp);
150 dp += 8; 167 dp += 8;
151 W[i] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) | 168 W[i] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
152 ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff); 169 ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
153 T >>= 32; 170 T >>= 32;
154 W[i+1] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) | 171 W[i+1] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
155 ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff); 172 ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
156 } 173 }
157#endif
158
159#if BYTEORDER == 0x87654321 174#elif BYTEORDER == 0x87654321
160#define SWAP_DONE
161 assert(sizeof(ULONG) == 8); 175 assert(sizeof(ULONG) == 8);
162 for (i = 0; i < 16; i += 2) { 176 for (i = 0; i < 16; i += 2) {
163 T = *((ULONG *) dp); 177 T = *((ULONG *) dp);
164 dp += 8; 178 dp += 8;
165 W[i] = T32(T >> 32); 179 W[i] = T32(T >> 32);
166 W[i+1] = T32(T); 180 W[i+1] = T32(T);
167 } 181 }
182#else
183#error Unknown byte order -- you need to add code here
168#endif 184#endif
169 185
170#ifndef SWAP_DONE
171#error Unknown byte order -- you need to add code here
172#endif /* SWAP_DONE */
173
174 for (i = 16; i < 80; ++i) { 186 for (i = 16; i < 80; ++i)
187 {
175 W[i] = W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16]; 188 T = W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16];
176#if (SHA_VERSION == 1) 189 W[i] = R32(T,1);
177 W[i] = R32(W[i], 1);
178#endif /* SHA_VERSION */
179 } 190 }
191
180 A = sha_info->digest[0]; 192 A = sha_info->digest[0];
181 B = sha_info->digest[1]; 193 B = sha_info->digest[1];
182 C = sha_info->digest[2]; 194 C = sha_info->digest[2];
183 D = sha_info->digest[3]; 195 D = sha_info->digest[3];
184 E = sha_info->digest[4]; 196 E = sha_info->digest[4];
197
185 WP = W; 198 WP = W;
186#ifdef UNRAVEL
187 FA(1); FB(1); FC(1); FD(1); FE(1); FT(1); FA(1); FB(1); FC(1); FD(1); 199 FA(1); FB(1); FC(1); FD(1); FE(1); FT(1); FA(1); FB(1); FC(1); FD(1);
188 FE(1); FT(1); FA(1); FB(1); FC(1); FD(1); FE(1); FT(1); FA(1); FB(1); 200 FE(1); FT(1); FA(1); FB(1); FC(1); FD(1); FE(1); FT(1); FA(1); FB(1);
189 FC(2); FD(2); FE(2); FT(2); FA(2); FB(2); FC(2); FD(2); FE(2); FT(2); 201 FC(2); FD(2); FE(2); FT(2); FA(2); FB(2); FC(2); FD(2); FE(2); FT(2);
190 FA(2); FB(2); FC(2); FD(2); FE(2); FT(2); FA(2); FB(2); FC(2); FD(2); 202 FA(2); FB(2); FC(2); FD(2); FE(2); FT(2); FA(2); FB(2); FC(2); FD(2);
191 FE(3); FT(3); FA(3); FB(3); FC(3); FD(3); FE(3); FT(3); FA(3); FB(3); 203 FE(3); FT(3); FA(3); FB(3); FC(3); FD(3); FE(3); FT(3); FA(3); FB(3);
192 FC(3); FD(3); FE(3); FT(3); FA(3); FB(3); FC(3); FD(3); FE(3); FT(3); 204 FC(3); FD(3); FE(3); FT(3); FA(3); FB(3); FC(3); FD(3); FE(3); FT(3);
193 FA(4); FB(4); FC(4); FD(4); FE(4); FT(4); FA(4); FB(4); FC(4); FD(4); 205 FA(4); FB(4); FC(4); FD(4); FE(4); FT(4); FA(4); FB(4); FC(4); FD(4);
194 FE(4); FT(4); FA(4); FB(4); FC(4); FD(4); FE(4); FT(4); FA(4); FB(4); 206 FE(4); FT(4); FA(4); FB(4); FC(4); FD(4); FE(4); FT(4); FA(4); FB(4);
207
195 sha_info->digest[0] = T32(sha_info->digest[0] + E); 208 sha_info->digest[0] = T32(sha_info->digest[0] + E);
196 sha_info->digest[1] = T32(sha_info->digest[1] + T); 209 sha_info->digest[1] = T32(sha_info->digest[1] + T);
197 sha_info->digest[2] = T32(sha_info->digest[2] + A); 210 sha_info->digest[2] = T32(sha_info->digest[2] + A);
198 sha_info->digest[3] = T32(sha_info->digest[3] + B); 211 sha_info->digest[3] = T32(sha_info->digest[3] + B);
199 sha_info->digest[4] = T32(sha_info->digest[4] + C); 212 sha_info->digest[4] = T32(sha_info->digest[4] + C);
200#else /* !UNRAVEL */
201#ifdef UNROLL_LOOPS
202 FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1);
203 FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1);
204 FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2);
205 FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2);
206 FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3);
207 FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3);
208 FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4);
209 FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4);
210#else /* !UNROLL_LOOPS */
211 for (i = 0; i < 20; ++i) { FG(1); }
212 for (i = 20; i < 40; ++i) { FG(2); }
213 for (i = 40; i < 60; ++i) { FG(3); }
214 for (i = 60; i < 80; ++i) { FG(4); }
215#endif /* !UNROLL_LOOPS */
216 sha_info->digest[0] = T32(sha_info->digest[0] + A);
217 sha_info->digest[1] = T32(sha_info->digest[1] + B);
218 sha_info->digest[2] = T32(sha_info->digest[2] + C);
219 sha_info->digest[3] = T32(sha_info->digest[3] + D);
220 sha_info->digest[4] = T32(sha_info->digest[4] + E);
221#endif /* !UNRAVEL */
222} 213}
223 214
224/* initialize the SHA digest */ 215/* initialize the SHA digest */
225 216
226static void sha_init(restrict SHA_INFO *sha_info) 217static void sha_init(SHA_INFO *restrict sha_info)
227{ 218{
228 sha_info->digest[0] = 0x67452301L; 219 sha_info->digest[0] = 0x67452301L;
229 sha_info->digest[1] = 0xefcdab89L; 220 sha_info->digest[1] = 0xefcdab89L;
230 sha_info->digest[2] = 0x98badcfeL; 221 sha_info->digest[2] = 0x98badcfeL;
231 sha_info->digest[3] = 0x10325476L; 222 sha_info->digest[3] = 0x10325476L;
234 sha_info->local = 0; 225 sha_info->local = 0;
235} 226}
236 227
237/* update the SHA digest */ 228/* update the SHA digest */
238 229
239static void sha_update(restrict SHA_INFO *sha_info, restrict U8 *buffer, int count) 230static void sha_update(SHA_INFO *restrict sha_info, U8 *restrict buffer, int count)
240{ 231{
241 int i; 232 int i;
242 233
243 sha_info->count += count << 3; 234 sha_info->count += count;
244 if (sha_info->local) { 235 if (sha_info->local) {
245 i = SHA_BLOCKSIZE - sha_info->local; 236 i = SHA_BLOCKSIZE - sha_info->local;
246 if (i > count) { 237 if (i > count) {
247 i = count; 238 i = count;
248 } 239 }
264 } 255 }
265 memcpy(sha_info->data, buffer, count); 256 memcpy(sha_info->data, buffer, count);
266 sha_info->local = count; 257 sha_info->local = count;
267} 258}
268 259
269
270#if 0
271static void sha_transform_and_copy (unsigned char digest[20], restrict SHA_INFO *sha_info)
272{
273 sha_transform (sha_info);
274
275 digest[ 0] = (unsigned char) ((sha_info->digest[0] >> 24) & 0xff);
276 digest[ 1] = (unsigned char) ((sha_info->digest[0] >> 16) & 0xff);
277 digest[ 2] = (unsigned char) ((sha_info->digest[0] >> 8) & 0xff);
278 digest[ 3] = (unsigned char) ((sha_info->digest[0] ) & 0xff);
279 digest[ 4] = (unsigned char) ((sha_info->digest[1] >> 24) & 0xff);
280 digest[ 5] = (unsigned char) ((sha_info->digest[1] >> 16) & 0xff);
281 digest[ 6] = (unsigned char) ((sha_info->digest[1] >> 8) & 0xff);
282 digest[ 7] = (unsigned char) ((sha_info->digest[1] ) & 0xff);
283 digest[ 8] = (unsigned char) ((sha_info->digest[2] >> 24) & 0xff);
284 digest[ 9] = (unsigned char) ((sha_info->digest[2] >> 16) & 0xff);
285 digest[10] = (unsigned char) ((sha_info->digest[2] >> 8) & 0xff);
286 digest[11] = (unsigned char) ((sha_info->digest[2] ) & 0xff);
287 digest[12] = (unsigned char) ((sha_info->digest[3] >> 24) & 0xff);
288 digest[13] = (unsigned char) ((sha_info->digest[3] >> 16) & 0xff);
289 digest[14] = (unsigned char) ((sha_info->digest[3] >> 8) & 0xff);
290 digest[15] = (unsigned char) ((sha_info->digest[3] ) & 0xff);
291 digest[16] = (unsigned char) ((sha_info->digest[4] >> 24) & 0xff);
292 digest[17] = (unsigned char) ((sha_info->digest[4] >> 16) & 0xff);
293 digest[18] = (unsigned char) ((sha_info->digest[4] >> 8) & 0xff);
294 digest[19] = (unsigned char) ((sha_info->digest[4] ) & 0xff);
295}
296#endif
297
298/* finish computing the SHA digest */ 260/* finish computing the SHA digest */
299static void sha_final(SHA_INFO *sha_info) 261static int sha_final(SHA_INFO *sha_info)
300{ 262{
301 int count;
302 U32 bit_count;
303
304 bit_count = sha_info->count; 263 int count = sha_info->count;
305 count = (int) ((bit_count >> 3) & 0x3f); 264 int local = sha_info->local;
306 ((U8 *) sha_info->data)[count++] = 0x80;
307 265
308 if (count > SHA_BLOCKSIZE - 8) {
309 memset(((U8 *) sha_info->data) + count, 0, SHA_BLOCKSIZE - count);
310 sha_transform(sha_info);
311 memset((U8 *) sha_info->data, 0, SHA_BLOCKSIZE - 8);
312 } else {
313 memset(((U8 *) sha_info->data) + count, 0, SHA_BLOCKSIZE - 8 - count);
314 }
315
316 sha_info->data[56] = 0; 266 sha_info->data[local] = 0x80;
317 sha_info->data[57] = 0;
318 sha_info->data[58] = 0;
319 sha_info->data[59] = 0;
320 sha_info->data[60] = (bit_count >> 24) & 0xff;
321 sha_info->data[61] = (bit_count >> 16) & 0xff;
322 sha_info->data[62] = (bit_count >> 8) & 0xff;
323 sha_info->data[63] = (bit_count >> 0) & 0xff;
324 267
268 if (sha_info->local >= SHA_BLOCKSIZE - 8) {
269 memset(sha_info->data + local + 1, 0, SHA_BLOCKSIZE - 1 - local);
325 sha_transform (sha_info); 270 sha_transform(sha_info);
271 memset(sha_info->data, 0, SHA_BLOCKSIZE - 2);
272 } else {
273 memset(sha_info->data + local + 1, 0, SHA_BLOCKSIZE - 3 - local);
274 }
275
276 sha_info->data[62] = count >> 5;
277 sha_info->data[63] = count << 3;
278
279 sha_transform (sha_info);
280
281 return sha_info->digest[0]
282 ? zprefix (sha_info->digest[0])
283 : zprefix (sha_info->digest[1]) + 32;
326} 284}
327 285
328#define TRIALCHAR "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%&()*+,-./;<=>?@[]{}^_|" 286#define TRIALCHAR "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%&()*+,-./;<=>?@[]{}^_|"
329 287
330static char nextenc[256]; 288static char nextenc[256];
332static char rand_char () 290static char rand_char ()
333{ 291{
334 return TRIALCHAR[rand () % sizeof (TRIALCHAR)]; 292 return TRIALCHAR[rand () % sizeof (TRIALCHAR)];
335} 293}
336 294
337static int zprefix (ULONG n) 295typedef double (*NVTime)(void);
338{
339 static char zp[256] =
340 {
341 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
342 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
343 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
344 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
345 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
346 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
347 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
348 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
349 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
350 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
351 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
352 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
353 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
354 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
355 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
356 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
357 };
358 296
359 return 297static double simple_nvtime (void)
360 n > 0xffffff ? zp[n >> 24] 298{
361 : n > 0xffff ? 8 + zp[n >> 16] 299 return time (0);
362 : n > 0xff ? 16 + zp[n >> 8] 300}
363 : 24 + zp[n]; 301
302static NVTime get_nvtime (void)
303{
304 SV **svp = hv_fetch (PL_modglobal, "Time::NVtime", 12, 0);
305
306 if (svp && SvIOK(*svp))
307 return INT2PTR(NVTime, SvIV(*svp));
308 else
309 return simple_nvtime;
310
364} 311}
365 312
366MODULE = Digest::Hashcash PACKAGE = Digest::Hashcash 313MODULE = Digest::Hashcash PACKAGE = Digest::Hashcash
367 314
368BOOT: 315BOOT:
373 nextenc[TRIALCHAR[i]] = TRIALCHAR[(i + 1) % sizeof (TRIALCHAR)]; 320 nextenc[TRIALCHAR[i]] = TRIALCHAR[(i + 1) % sizeof (TRIALCHAR)];
374} 321}
375 322
376PROTOTYPES: ENABLE 323PROTOTYPES: ENABLE
377 324
378int 325# could be improved quite a bit in accuracy
379_estimate_time (float seconds = 2, float minfactor = 1) 326NV
327_estimate_rounds ()
380 CODE: 328 CODE:
381 RETVAL = minfactor; 329 char data[40];
330 NVTime nvtime = get_nvtime ();
331 NV t1, t2, t;
332 int count = 0;
333 SHA_INFO ctx;
334
335 t = nvtime ();
336 do {
337 t1 = nvtime ();
338 } while (t == t1);
339
340 t = t2 = nvtime ();
341 do {
342 volatile int i;
343 sha_init (&ctx);
344 sha_update (&ctx, data, sizeof (data));
345 i = sha_final (&ctx);
346
347 if (!(++count & 1023))
348 t2 = nvtime ();
349
350 } while (t == t2);
351
352 RETVAL = (NV)count / (t2 - t1);
382 OUTPUT: 353 OUTPUT:
383 RETVAL 354 RETVAL
384 355
385SV * 356SV *
386_gentoken (int collisions, IV timestamp, char *resource, char *trial = "", int extrarand = 0) 357_gentoken (int size, IV timestamp, char *resource, char *trial = "", int extrarand = 0)
387 CODE: 358 CODE:
388 SHA_INFO ctx1, ctx; 359 SHA_INFO ctx1, ctx;
389 char *token, *seq, *s; 360 char *token, *seq, *s;
390 int toklen, i; 361 int toklen, i;
391 time_t tstamp = timestamp ? timestamp : time (0); 362 time_t tstamp = timestamp ? timestamp : time (0);
400 char); 371 char);
401 372
402 if (!token) 373 if (!token)
403 croak ("out of memory"); 374 croak ("out of memory");
404 375
405 if (collisions > 32) 376 if (size > 64)
406 croak ("collisions must be <= 32 in this implementation\n"); 377 croak ("size must be <= 64 in this implementation\n");
407 378
408 toklen = sprintf (token, "%d:%02d%02d%02d%02d%02d%02d:%s:%s", 379 toklen = sprintf (token, "%d:%02d%02d%02d%02d%02d%02d:%s:%s",
409 0, tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, 380 0, tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday,
410 tm->tm_hour, tm->tm_min, tm->tm_sec, 381 tm->tm_hour, tm->tm_min, tm->tm_sec,
411 resource, trial); 382 resource, trial);
412 383
384 if (toklen > 8000)
385 croak ("token length must be <= 8000 in this implementation\n");
386
413 i = toklen + extrarand; 387 i = toklen + extrarand;
414 while (toklen < i) 388 while (toklen < i)
415 token[toklen++] = rand_char (); 389 token[toklen++] = rand_char ();
416 390
417 sha_init (&ctx1); 391 sha_init (&ctx1);
424 398
425 for (;;) 399 for (;;)
426 { 400 {
427 ctx = ctx1; // this "optimization" can help a lot for longer resource strings 401 ctx = ctx1; // this "optimization" can help a lot for longer resource strings
428 sha_update (&ctx, seq, 8); 402 sha_update (&ctx, seq, 8);
429 sha_final (&ctx); 403 i = sha_final (&ctx);
430 404
431 i = zprefix (ctx.digest[0]);
432
433 if (i >= collisions) 405 if (i >= size)
434 break; 406 break;
435 407
436 s = seq; 408 s = seq;
437 do { 409 do {
438 *s = nextenc [*s]; 410 *s = nextenc [*s];
450 char *token = SvPV (tok, toklen); 422 char *token = SvPV (tok, toklen);
451 SHA_INFO ctx; 423 SHA_INFO ctx;
452 424
453 sha_init (&ctx); 425 sha_init (&ctx);
454 sha_update (&ctx, token, toklen); 426 sha_update (&ctx, token, toklen);
455 sha_final (&ctx); 427 RETVAL = sha_final (&ctx);
456
457 RETVAL = zprefix (ctx.digest[0]);
458 OUTPUT: 428 OUTPUT:
459 RETVAL 429 RETVAL
460 430
461 431

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines