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.2 by root, Sun Sep 7 00:58:23 2003 UTC vs.
Revision 1.8 by root, Wed Jul 22 10:33:08 2015 UTC

3#include "XSUB.h" 3#include "XSUB.h"
4 4
5#include <time.h> 5#include <time.h>
6#include <stdlib.h> 6#include <stdlib.h>
7#include <stdint.h> 7#include <stdint.h>
8
9#include "perlmulticore.h"
8 10
9/* NIST Secure Hash Algorithm */ 11/* NIST Secure Hash Algorithm */
10/* heavily modified by Uwe Hollerbach <uh@alumni.caltech edu> */ 12/* heavily modified by Uwe Hollerbach <uh@alumni.caltech edu> */
11/* from Peter C. Gutmann's implementation as found in */ 13/* from Peter C. Gutmann's implementation as found in */
12/* Applied Cryptography by Bruce Schneier */ 14/* Applied Cryptography by Bruce Schneier */
17/* pcg: I was tempted to just rip this code off, after all, if you don't 19/* pcg: I was tempted to just rip this code off, after all, if you don't
18 * demand anything I am inclined not to give anything. *Sigh* something 20 * demand anything I am inclined not to give anything. *Sigh* something
19 * kept me from doing it, so here's the truth: I took this code from the 21 * kept me from doing it, so here's the truth: I took this code from the
20 * SHA1 perl module, since it looked reasonably well-crafted. I modified 22 * SHA1 perl module, since it looked reasonably well-crafted. I modified
21 * it here and there, though. 23 * it here and there, though.
24 */
25
26/*
27 * we have lots of micro-optimizations here, this is just for toying
28 * around...
22 */ 29 */
23 30
24/* don't expect _too_ much from compilers for now. */ 31/* don't expect _too_ much from compilers for now. */
25#if __GNUC__ > 2 32#if __GNUC__ > 2
26# define restrict __restrict__ 33# define restrict __restrict__
31#elif __STDC_VERSION__ < 199900 38#elif __STDC_VERSION__ < 199900
32# define restrict 39# define restrict
33# define inline 40# define inline
34#endif 41#endif
35 42
43#if __GNUC__ < 2
44# define __attribute__(x)
45#endif
46
47#ifdef __i386
48# define a_regparm(n) __attribute__((__regparm__(n)))
49#else
50# define a_regparm(n)
51#endif
52
53#define a_const __attribute__((__const__))
54
36/* Useful defines & typedefs */ 55/* Useful defines & typedefs */
37 56
38#if defined(U64TYPE) && (defined(USE_64_BIT_INT) || ((BYTEORDER != 0x1234) && (BYTEORDER != 0x4321))) 57#if defined(U64TYPE) && (defined(USE_64_BIT_INT) || ((BYTEORDER != 0x1234) && (BYTEORDER != 0x4321)))
39typedef U64TYPE ULONG; 58typedef U64TYPE XULONG;
40# if BYTEORDER == 0x1234 59# if BYTEORDER == 0x1234
41# undef BYTEORDER 60# undef BYTEORDER
42# define BYTEORDER 0x12345678 61# define BYTEORDER 0x12345678
43# elif BYTEORDER == 0x4321 62# elif BYTEORDER == 0x4321
44# undef BYTEORDER 63# undef BYTEORDER
45# define BYTEORDER 0x87654321 64# define BYTEORDER 0x87654321
46# endif 65# endif
47#else 66#else
48typedef uint_fast32_t ULONG; /* 32-or-more-bit quantity */ 67typedef uint_fast32_t XULONG; /* 32-or-more-bit quantity */
49#endif 68#endif
50 69
51#if GCCX86ASM 70#if GCCX86ASM
52# define zprefix(n) ({ int _r; __asm__ ("bsrl %1, %0" : "=r" (_r) : "r" (n)); 31 - _r ; }) 71# define zprefix(n) ({ int _r; __asm__ ("bsrl %1, %0" : "=r" (_r) : "r" (n)); 31 - _r ; })
72#elif __GNUC__ > 2 && __GNUC_MINOR__ > 3
73# define zprefix(n) (__extension__ ({ uint32_t n__ = (n); n ? __builtin_clz (n) : 32; }))
53#else 74#else
54static int zprefix (ULONG n) 75static int a_const zprefix (U32 n)
55{ 76{
56 static char zp[256] = 77 static char zp[256] =
57 { 78 {
58 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 79 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, 80 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
83 104
84#define SHA_BLOCKSIZE 64 105#define SHA_BLOCKSIZE 64
85#define SHA_DIGESTSIZE 20 106#define SHA_DIGESTSIZE 20
86 107
87typedef struct { 108typedef struct {
88 ULONG digest[5]; /* message digest */ 109 U32 digest[5]; /* message digest */
89 ULONG count; /* 32-bit bit count */ 110 U32 count; /* 32-bit bit count */
90 int local; /* unprocessed amount in data */ 111 int local; /* unprocessed amount in data */
91 U8 data[SHA_BLOCKSIZE]; /* SHA data buffer */ 112 U8 data[SHA_BLOCKSIZE]; /* SHA data buffer */
92} SHA_INFO; 113} SHA_INFO;
93 114
94 115
127 B = T32(R32(C,5) + f##n(D,E,T) + A + *WP++ + CONST##n); D = R32(D,30) 148 B = T32(R32(C,5) + f##n(D,E,T) + A + *WP++ + CONST##n); D = R32(D,30)
128 149
129#define FT(n) \ 150#define FT(n) \
130 A = T32(R32(B,5) + f##n(C,D,E) + T + *WP++ + CONST##n); C = R32(C,30) 151 A = T32(R32(B,5) + f##n(C,D,E) + T + *WP++ + CONST##n); C = R32(C,30)
131 152
132static void sha_transform(SHA_INFO *restrict sha_info) 153static void a_regparm(1) sha_transform(SHA_INFO *restrict sha_info)
133{ 154{
134 int i; 155 int i;
135 U8 *dp; 156 U8 *restrict dp;
136 ULONG T, A, B, C, D, E, W[80], *restrict WP; 157 U32 A, B, C, D, E, W[80], *restrict WP;
158 XULONG T;
137 159
138 dp = sha_info->data; 160 dp = sha_info->data;
139 161
140#if BYTEORDER == 0x1234 162#if BYTEORDER == 0x1234
141 assert(sizeof(ULONG) == 4); 163 assert(sizeof(XULONG) == 4);
142# ifdef HAS_NTOHL 164# ifdef HAS_NTOHL
143 for (i = 0; i < 16; ++i) { 165 for (i = 0; i < 16; ++i) {
144 T = *((ULONG *) dp); 166 T = *((XULONG *) dp);
145 dp += 4; 167 dp += 4;
146 W[i] = ntohl (T); 168 W[i] = ntohl (T);
147 } 169 }
148# else 170# else
149 for (i = 0; i < 16; ++i) { 171 for (i = 0; i < 16; ++i) {
150 T = *((ULONG *) dp); 172 T = *((XULONG *) dp);
151 dp += 4; 173 dp += 4;
152 W[i] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) | 174 W[i] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
153 ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff); 175 ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
154 } 176 }
155# endif 177# endif
156#elif BYTEORDER == 0x4321 178#elif BYTEORDER == 0x4321
157 assert(sizeof(ULONG) == 4); 179 assert(sizeof(XULONG) == 4);
158 for (i = 0; i < 16; ++i) { 180 for (i = 0; i < 16; ++i) {
159 T = *((ULONG *) dp); 181 T = *((XULONG *) dp);
160 dp += 4; 182 dp += 4;
161 W[i] = T32(T); 183 W[i] = T32(T);
162 } 184 }
163#elif BYTEORDER == 0x12345678 185#elif BYTEORDER == 0x12345678
164 assert(sizeof(ULONG) == 8); 186 assert(sizeof(XULONG) == 8);
165 for (i = 0; i < 16; i += 2) { 187 for (i = 0; i < 16; i += 2) {
166 T = *((ULONG *) dp); 188 T = *((XULONG *) dp);
167 dp += 8; 189 dp += 8;
168 W[i] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) | 190 W[i] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
169 ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff); 191 ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
170 T >>= 32; 192 T >>= 32;
171 W[i+1] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) | 193 W[i+1] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
172 ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff); 194 ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
173 } 195 }
174#elif BYTEORDER == 0x87654321 196#elif BYTEORDER == 0x87654321
175 assert(sizeof(ULONG) == 8); 197 assert(sizeof(XULONG) == 8);
176 for (i = 0; i < 16; i += 2) { 198 for (i = 0; i < 16; i += 2) {
177 T = *((ULONG *) dp); 199 T = *((XULONG *) dp);
178 dp += 8; 200 dp += 8;
179 W[i] = T32(T >> 32); 201 W[i] = T32(T >> 32);
180 W[i+1] = T32(T); 202 W[i+1] = T32(T);
181 } 203 }
182#else 204#else
283 : zprefix (sha_info->digest[1]) + 32; 305 : zprefix (sha_info->digest[1]) + 32;
284} 306}
285 307
286#define TRIALCHAR "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%&()*+,-./;<=>?@[]{}^_|" 308#define TRIALCHAR "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%&()*+,-./;<=>?@[]{}^_|"
287 309
288static char nextenc[256]; 310static char
311nextenc[256];
289 312
290static char rand_char () 313static char
314rand_char ()
291{ 315{
292 return TRIALCHAR[rand () % sizeof (TRIALCHAR)]; 316 return TRIALCHAR[(int)(Drand01 () * sizeof (TRIALCHAR))];
293} 317}
294 318
295typedef double (*NVTime)(void); 319typedef double (*NVTime)(void);
296 320
297static double simple_nvtime (void) 321static double
322simple_nvtime (void)
298{ 323{
299 return time (0); 324 return time (0);
300} 325}
301 326
302static NVTime get_nvtime (void) 327static NVTime
328get_nvtime (void)
303{ 329{
304 SV **svp = hv_fetch (PL_modglobal, "Time::NVtime", 12, 0); 330 SV **svp = hv_fetch (PL_modglobal, "Time::NVtime", 12, 0);
305 331
306 if (svp && SvIOK(*svp)) 332 if (svp && SvIOK(*svp))
307 return INT2PTR(NVTime, SvIV(*svp)); 333 return INT2PTR(NVTime, SvIV(*svp));
324 350
325# could be improved quite a bit in accuracy 351# could be improved quite a bit in accuracy
326NV 352NV
327_estimate_rounds () 353_estimate_rounds ()
328 CODE: 354 CODE:
355{
329 char data[40]; 356 char data[40];
330 NVTime nvtime = get_nvtime (); 357 NVTime nvtime = get_nvtime ();
331 NV t1, t2, t; 358 NV t1, t2, t;
332 int count = 0; 359 int count = 0;
333 SHA_INFO ctx; 360 SHA_INFO ctx;
348 t2 = nvtime (); 375 t2 = nvtime ();
349 376
350 } while (t == t2); 377 } while (t == t2);
351 378
352 RETVAL = (NV)count / (t2 - t1); 379 RETVAL = (NV)count / (t2 - t1);
380}
353 OUTPUT: 381 OUTPUT:
354 RETVAL 382 RETVAL
355 383
356SV * 384SV *
357_gentoken (int size, IV timestamp, char *resource, char *trial = "", int extrarand = 0) 385_gentoken (int size, IV timestamp, char *resource, char *trial = "", int extrarand = 0)
358 CODE: 386 CODE:
387{
359 SHA_INFO ctx1, ctx; 388 SHA_INFO ctx1, ctx;
360 char *token, *seq, *s; 389 char *token, *seq, *s;
361 int toklen, i; 390 int toklen, i;
362 time_t tstamp = timestamp ? timestamp : time (0); 391 time_t tstamp = timestamp ? timestamp : time (0);
363 struct tm *tm = gmtime (&tstamp); 392 struct tm *tm = gmtime (&tstamp);
364 393
365 New (0, token, 394 New (0, token,
366 1 + 1 // version 395 1 + 1 // version
367 + 12 + 1 // time field sans century 396 + 12 + 1 // time field sans century
368 + strlen (resource) + 1 // ressource 397 + strlen (resource) + 1 // ressource
369 + strlen (trial) + extrarand + 8 + 1 // trial 398 + strlen (trial) + extrarand + 8 + 1 // trial
370 + 1, 399 + 1,
371 char); 400 char);
372 401
373 if (!token) 402 if (!token)
374 croak ("out of memory"); 403 croak ("out of memory");
375 404
376 if (size > 64) 405 if (size > 64)
381 tm->tm_hour, tm->tm_min, tm->tm_sec, 410 tm->tm_hour, tm->tm_min, tm->tm_sec,
382 resource, trial); 411 resource, trial);
383 412
384 if (toklen > 8000) 413 if (toklen > 8000)
385 croak ("token length must be <= 8000 in this implementation\n"); 414 croak ("token length must be <= 8000 in this implementation\n");
415
416 perlinterp_release ();
386 417
387 i = toklen + extrarand; 418 i = toklen + extrarand;
388 while (toklen < i) 419 while (toklen < i)
389 token[toklen++] = rand_char (); 420 token[toklen++] = rand_char ();
390 421
409 do { 440 do {
410 *s = nextenc [*s]; 441 *s = nextenc [*s];
411 } while (*s++ == 'a'); 442 } while (*s++ == 'a');
412 } 443 }
413 444
445 perlinterp_acquire ();
446
414 RETVAL = newSVpvn (token, toklen); 447 RETVAL = newSVpvn (token, toklen);
448}
415 OUTPUT: 449 OUTPUT:
416 RETVAL 450 RETVAL
417 451
418int 452int
419_prefixlen (SV *tok) 453_prefixlen (SV *tok)
420 CODE: 454 CODE:
455{
421 STRLEN toklen; 456 STRLEN toklen;
422 char *token = SvPV (tok, toklen); 457 char *token = SvPV (tok, toklen);
423 SHA_INFO ctx; 458 SHA_INFO ctx;
424 459
425 sha_init (&ctx); 460 sha_init (&ctx);
426 sha_update (&ctx, token, toklen); 461 sha_update (&ctx, token, toklen);
427 RETVAL = sha_final (&ctx); 462 RETVAL = sha_final (&ctx);
463}
428 OUTPUT: 464 OUTPUT:
429 RETVAL 465 RETVAL
430 466
431 467

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines