cosmetix
[tweetnacl.d.git] / tweetNaCl.d
blobc1ee58771b75f2e61236bec8711b685d1633c7ef
1 /*
2 * Contributors (alphabetical order)
3 * Daniel J. Bernstein, University of Illinois at Chicago and Technische Universiteit Eindhoven
4 * Wesley Janssen, Radboud Universiteit Nijmegen
5 * Tanja Lange, Technische Universiteit Eindhoven
6 * Peter Schwabe, Radboud Universiteit Nijmegen
8 * Ported by Ketmar // Invisible Vector ( ketmar@ketmar.no-ip.org )
10 * Public Domain (or WTFPL).
12 //k8: yes, i know that this code sux. i know that i should rewrite it to be more 'D-ish'.
13 // i'll not do that. make your own port or do it yourself if you dissatisfied with my
14 // attitude. thank you.
15 module tweetNaCl;
18 public:
19 enum {
20 crypto_auth_BYTES = 32,
21 crypto_auth_KEYBYTES = 32,
23 crypto_box_PUBLICKEYBYTES = 32,
24 crypto_box_SECRETKEYBYTES = 32,
25 crypto_box_BEFORENMBYTES = 32,
26 crypto_box_NONCEBYTES = 24,
27 crypto_box_ZEROBYTES = 32,
28 crypto_box_BOXZEROBYTES = 16,
30 crypto_core_salsa20_OUTPUTBYTES = 64,
31 crypto_core_salsa20_INPUTBYTES = 16,
32 crypto_core_salsa20_KEYBYTES = 32,
33 crypto_core_salsa20_CONSTBYTES = 16,
35 crypto_core_hsalsa20_OUTPUTBYTES = 32,
36 crypto_core_hsalsa20_INPUTBYTES = 16,
37 crypto_core_hsalsa20_KEYBYTES = 32,
38 crypto_core_hsalsa20_CONSTBYTES = 16,
40 crypto_hash_BYTES = 64,
42 crypto_onetimeauth_BYTES = 16,
43 crypto_onetimeauth_KEYBYTES = 32,
45 crypto_scalarmult_BYTES = 32,
46 crypto_scalarmult_SCALARBYTES = 32,
48 crypto_secretbox_KEYBYTES = 32,
49 crypto_secretbox_NONCEBYTES = 24,
50 crypto_secretbox_ZEROBYTES = 32,
51 crypto_secretbox_BOXZEROBYTES = 16,
53 crypto_sign_BYTES = 64,
54 crypto_sign_PUBLICKEYBYTES = 32,
55 crypto_sign_SECRETKEYBYTES = 64,
57 crypto_stream_xsalsa20_KEYBYTES = 32,
58 crypto_stream_xsalsa20_NONCEBYTES = 24,
60 crypto_stream_salsa20_KEYBYTES = 32,
61 crypto_stream_salsa20_NONCEBYTES = 8,
63 crypto_stream_KEYBYTES = 32,
64 crypto_stream_NONCEBYTES = 24,
66 crypto_verify_16_BYTES = 16,
67 crypto_verify_32_BYTES = 32,
71 /// set this callback to good (cryptograpic strong) random bytes generator
72 /// you can use /dev/urandom as prng
73 void delegate (ubyte[] dest, size_t len) randombytes = null;
76 private:
77 immutable ubyte[16] zero_ = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
78 immutable ubyte[32] nine_ = [9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
80 immutable long[16]
81 gf0 = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
82 gf1 = [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
83 xx121665 = [0xDB41,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
84 D = [0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203],
85 D2 =[0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406],
86 X = [0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169],
87 Y = [0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666],
88 I = [0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83];
90 uint ld32() (const(ubyte)[] x)
91 in {
92 assert(x.length >= 4);
94 body {
95 uint u = x[3];
96 u = (u<<8)|x[2];
97 u = (u<<8)|x[1];
98 return (u<<8)|x[0];
101 ulong dl64() (const(ubyte)[] x)
102 in {
103 assert(x.length >= 8);
105 body {
106 ulong u = x[0];
107 u = (u<<8)|x[1];
108 u = (u<<8)|x[2];
109 u = (u<<8)|x[3];
110 u = (u<<8)|x[4];
111 u = (u<<8)|x[5];
112 u = (u<<8)|x[6];
113 return (u<<8)|x[7];
116 void st32() (ubyte[] x, uint u)
117 in {
118 assert(x.length >= 4);
120 body {
121 x[0] = u&0xff;
122 x[1] = (u>>8)&0xff;
123 x[2] = (u>>16)&0xff;
124 x[3] = (u>>24)&0xff;
127 void ts64() (ubyte[] x, ulong u)
128 in {
129 assert(x.length >= 8);
131 body {
132 x[0] = (u>>56)&0xff;
133 x[1] = (u>>48)&0xff;
134 x[2] = (u>>40)&0xff;
135 x[3] = (u>>32)&0xff;
136 x[4] = (u>>24)&0xff;
137 x[5] = (u>>16)&0xff;
138 x[6] = (u>>8)&0xff;
139 x[7] = u&0xff;
142 bool vn() (const(ubyte)[] x, const(ubyte)[] y)
143 in {
144 assert(x.length >= y.length);
146 body {
147 uint d = 0;
148 foreach (immutable i, immutable v; x) d |= v^y[i];
149 return (1&((d-1)>>8)) != 0;
152 public:
154 * The crypto_verify_16() function checks that strings 'x' and 'y' has same content.
156 * Params:
157 * x = first string, slice length must be at least crypto_verify_16_BYTES, extra ignored
158 * y = second string, slice length must be at least crypto_verify_16_BYTES, extra ignored
160 * Returns:
161 * success flag
163 bool crypto_verify_16() (const(ubyte)[] x, const(ubyte)[] y)
164 in {
165 assert(x.length >= 16 && y.length >= 16);
167 body {
168 return vn(x[0..16], y[0..16]);
172 * The crypto_verify_32() function checks that strings 'x' and 'y' has same content.
174 * Params:
175 * x = first string, slice length must be at least crypto_verify_32_BYTES, extra ignored
176 * y = second string, slice length must be at least crypto_verify_32_BYTES, extra ignored
178 * Returns:
179 * success flag
181 bool crypto_verify_32() (const(ubyte)[] x, const(ubyte)[] y)
182 in {
183 assert(x.length >= 32 && y.length >= 32);
185 body {
186 return vn(x[0..32], y[0..32]);
190 private void salsa_core(string type) (ubyte[] output, const(ubyte)[] input, const(ubyte)[] key, const(ubyte)[] constant)
191 if (type == "salsa" || type == "hsalsa") // constraint
192 in {
193 // magic!
194 assert(mixin(`output.length >= crypto_core_`~type~`20_OUTPUTBYTES`));
195 assert(mixin(`input.length >= crypto_core_`~type~`20_INPUTBYTES`));
196 assert(mixin(`key.length >= crypto_core_`~type~`20_KEYBYTES`));
197 assert(mixin(`constant.length >= crypto_core_`~type~`20_CONSTBYTES`));
199 body {
200 static uint ROTL32() (uint x, int c) { return (x<<c)|((x&0xffffffff)>>(32-c)); }
202 uint[16] w = void, x = void, y = void;
203 uint[4] t = void;
205 foreach (i; 0..4) {
206 x[5*i] = ld32(constant[4*i..$]);
207 x[1+i] = ld32(key[4*i..$]);
208 x[6+i] = ld32(input[4*i..$]);
209 x[11+i] = ld32(key[16+4*i..$]);
212 y[] = x[];
214 foreach (i; 0..20) {
215 foreach (j; 0..4) {
216 foreach (m; 0..4) t[m] = x[(5*j+4*m)%16];
217 t[1] ^= ROTL32(t[0]+t[3], 7);
218 t[2] ^= ROTL32(t[1]+t[0], 9);
219 t[3] ^= ROTL32(t[2]+t[1], 13);
220 t[0] ^= ROTL32(t[3]+t[2], 18);
221 for (auto m = 0; m < 4; ++m) w[4*j+(j+m)%4] = t[m];
223 for (auto m = 0; m < 16; ++m) x[m] = w[m];
226 static if (type == "hsalsa") {
227 for (auto i = 0; i < 16; ++i) x[i] += y[i];
228 for (auto i = 0; i < 4; ++i) {
229 x[5*i] -= ld32(constant[4*i..$]);
230 x[6+i] -= ld32(input[4*i..$]);
232 for (auto i = 0; i < 4; ++i) {
233 st32(output[4*i..$], x[5*i]);
234 st32(output[16+4*i..$], x[6+i]);
236 } else {
237 for (auto i = 0; i < 16; ++i) st32(output[4*i..$], x[i]+y[i]);
241 void crypto_core_salsa20() (ubyte[] output, const(ubyte)[] input, const(ubyte)[] key, const(ubyte)[] constant)
243 salsa_core!"salsa"(output, input, key, constant);
246 void crypto_core_hsalsa20() (ubyte[] output, const(ubyte)[] input, const(ubyte)[] key, const(ubyte)[] constant)
248 salsa_core!"hsalsa"(output, input, key, constant);
251 private immutable(ubyte)[] sigma = cast(immutable(ubyte)[])"expand 32-byte k";
254 * The crypto_stream_salsa20_xor() function encrypts a message 'msg' using a secret key 'key'
255 * and a nonce 'nonce'. The crypto_stream_salsa20_xor() function returns the ciphertext 'output'.
257 * Params:
258 * output = resulting ciphertext
259 * msg = message
260 * nonce = nonce
261 * key = secret key
263 * Returns:
264 * ciphertext in 'output'
266 void crypto_stream_salsa20_xor (ubyte[] output, const(ubyte)[] msg, const(ubyte)[] nonce, const(ubyte)[] key)
267 @trusted nothrow @nogc
268 in {
269 assert(nonce.length == crypto_stream_salsa20_NONCEBYTES);
270 assert(key.length == crypto_stream_salsa20_KEYBYTES);
271 import std.stdio;
272 assert(msg.length == 0 || output.length <= msg.length);
274 body {
275 ubyte[16] z; // autoclear
276 ubyte[64] x = void;
277 uint u;
278 uint cpos = 0, mpos = 0;
279 size_t b = output.length;
280 if (!b) return;
281 z[0..8] = nonce[0..8];
282 while (b >= 64) {
283 crypto_core_salsa20(x[], z[], key, sigma[]);
284 if (msg !is null) {
285 foreach (v; x) output[cpos++] = msg[mpos++]^v;
286 } else {
287 output[cpos..cpos+64] = x[];
288 cpos += 64;
290 u = 1;
291 foreach (i; 8..16) {
292 u += cast(uint)z[i];
293 z[i] = u&0xff;
294 u >>= 8;
296 b -= 64;
298 if (b) {
299 crypto_core_salsa20(x[], z[], key, sigma[]);
300 if (msg !is null) {
301 foreach (i; 0..b) output[cpos++] = msg[mpos++]^x[i];
302 } else {
303 output[cpos..cpos+b] = x[0..b];
309 * The crypto_stream_salsa20() function produces a stream 'c'
310 * as a function of a secret key 'key' and a nonce 'nonce'.
312 * Params:
313 * c = resulting stream
314 * nonce = nonce
315 * key = secret key
317 * Returns:
318 * ciphertext in 'c'
320 void crypto_stream_salsa20() (ubyte[] c, const(ubyte)[] nonce, const(ubyte)[] key)
321 in {
322 assert(nonce.length == crypto_stream_salsa20_NONCEBYTES);
323 assert(key.length == crypto_stream_salsa20_KEYBYTES);
325 body {
326 crypto_stream_salsa20_xor(c, null, nonce, key);
330 * The crypto_stream() function produces a stream 'c'
331 * as a function of a secret key 'key' and a nonce 'nonce'.
333 * Params:
334 * c = output slice
335 * nonce = nonce
336 * key = secret key
338 * Returns:
339 * stream in 'c'
341 void crypto_stream() (ubyte[] c, const(ubyte)[] nonce, const(ubyte)[] key)
342 in {
343 assert(c !is null);
344 assert(nonce.length == crypto_stream_NONCEBYTES);
345 assert(key.length == crypto_stream_KEYBYTES);
347 body {
348 ubyte[32] s = void;
349 crypto_core_hsalsa20(s[], nonce, key, sigma[]);
350 crypto_stream_salsa20(c, nonce[16..$], s[]);
354 * The crypto_stream_xor() function encrypts a message 'msg' using a secret key 'key'
355 * and a nonce 'nonce'. The crypto_stream_xor() function returns the ciphertext 'c'.
357 * Params:
358 * c = output slice
359 * nonce = nonce
360 * key = secret key
362 * Returns:
363 * ciphertext in 'c'
365 void crypto_stream_xor() (ubyte[] c, const(ubyte)[] msg, const(ubyte)[] nonce, const(ubyte)[] key)
366 in {
367 assert(c !is null);
368 assert(msg.length >= c.length);
369 assert(nonce.length == crypto_stream_NONCEBYTES);
370 assert(key.length == crypto_stream_KEYBYTES);
372 body {
373 ubyte[32] s = void;
374 crypto_core_hsalsa20(s[], nonce, key, sigma[]);
375 crypto_stream_salsa20_xor(c, msg, nonce[16..$], s);
378 private void add1305() (uint[] h, const(uint)[] c) {
379 uint u = 0;
380 foreach (j; 0..17) {
381 u += h[j]+c[j];
382 h[j] = u&255;
383 u >>= 8;
387 private immutable uint[17] minusp = [5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,252];
390 * The crypto_onetimeauth() function authenticates a message 'msg'
391 * using a secret key 'key'. The function returns an authenticator 'output'.
393 * Params:
394 * output = authenticator, slice size must be at least crypto_onetimeauth_BYTES, extra ignored
395 * msg == message
396 * key == secret key, slice size must be at least crypto_onetimeauth_KEYBYTES, extra ignored
398 * Returns:
399 * authenticator in 'output'
401 void crypto_onetimeauth() (ubyte[] output, const(ubyte)[] msg, const(ubyte)[] key)
402 in {
403 assert(key.length >= crypto_onetimeauth_KEYBYTES);
404 assert(output.length >= crypto_onetimeauth_BYTES);
406 body {
407 uint s, u;
408 uint[17] x = void, r = void, h/*autoclear*/, c = void, g = void;
409 uint mpos = 0;
410 size_t n = msg.length;
412 foreach (i; 0..16) r[i] = key[i];
413 r[16..17] = 0;
415 r[3] &= 15;
416 r[4] &= 252;
417 r[7] &= 15;
418 r[8] &= 252;
419 r[11] &= 15;
420 r[12] &= 252;
421 r[15] &= 15;
423 while (n > 0) {
424 c[0..17] = 0;
426 size_t jj;
427 for (jj = 0; jj < 16 && jj < n; ++jj) c[jj] = msg[mpos+jj];
428 c[jj] = 1;
429 mpos += jj;
430 n -= jj;
432 add1305(h, c);
433 foreach (i; 0..17) {
434 x[i] = 0;
435 foreach (j; 0..17) x[i] += h[j]*(j <= i ? r[i-j] : 320*r[i+17-j]);
437 h[] = x[];
438 u = 0;
439 foreach (j; 0..16) {
440 u += h[j];
441 h[j] = u&255;
442 u >>= 8;
444 u += h[16];
445 h[16] = u&3;
446 u = 5*(u>>2);
447 foreach (j; 0..16) {
448 u += h[j];
449 h[j] = u&255;
450 u >>= 8;
452 u += h[16];
453 h[16] = u;
456 g[] = h[];
457 add1305(h, minusp);
458 s = -(h[16]>>7);
459 foreach (j; 0..17) h[j] ^= s&(g[j]^h[j]);
461 foreach (j; 0..16) c[j] = key[j+16];
462 c[16] = 0;
463 add1305(h, c);
464 foreach (j; 0..16) output[j] = cast(ubyte)(h[j]&0xff);
468 * The crypto_onetimeauth_verify() function checks that
469 * 'h' is a correct authenticator of a message 'msg' under the secret key 'key'.
471 * Params:
472 * h = authenticator, slice size must be at least crypto_onetimeauth_BYTES, extra ignored
473 * msg == message
474 * key == secret key, slice size must be at least crypto_onetimeauth_KEYBYTES, extra ignored
476 * Returns:
477 * success flag
479 bool crypto_onetimeauth_verify() (const(ubyte)[] h, const(ubyte)[] msg, const(ubyte)[] key)
480 in {
481 assert(h.length >= crypto_onetimeauth_BYTES);
482 assert(key.length >= crypto_onetimeauth_KEYBYTES);
484 body {
485 ubyte[16] x = void;
486 crypto_onetimeauth(x, msg, key);
487 return crypto_verify_16(h, x);
491 * The crypto_secretbox() function encrypts and authenticates
492 * a message 'msg' using a secret key 'key' and a nonce 'nonce'.
493 * The crypto_secretbox() function returns the resulting ciphertext 'c'.
495 * Params:
496 * c = resulting cyphertext
497 * key = secret key
498 * nonce = nonce
500 * Returns:
501 * success flag and cyphertext in 'c'
503 bool crypto_secretbox() (ubyte[] c, const(ubyte)[] msg, const(ubyte)[] nonce, const(ubyte)[] key)
504 in {
505 assert(key.length >= crypto_secretbox_KEYBYTES);
506 assert(nonce.length >= crypto_secretbox_NONCEBYTES);
508 body {
509 //c.length = msg.length+crypto_secretbox_ZEROBYTES;
510 if (c is null || c.length < 32) return false;
511 crypto_stream_xor(c, msg, nonce, key);
512 crypto_onetimeauth(c[16..$], c[32..$], c);
513 c[0..16] = 0;
514 //return c[crypto_secretbox_BOXZEROBYTES..$];
515 return true;
519 * The crypto_secretbox_open() function verifies and decrypts
520 * a ciphertext 'c' using a secret key 'key' and a nonce 'nonce'.
521 * The crypto_secretbox_open() function returns the resulting plaintext 'output'.
523 * Params:
524 * output = resulting message
525 * c = cyphertext
526 * key = secret key
527 * nonce = nonce
529 * Returns:
530 * success flag and message in 'output'
532 bool crypto_secretbox_open() (ubyte[] output, const(ubyte)[] c, const(ubyte)[] nonce, const(ubyte)[] key)
533 in {
534 assert(key.length >= crypto_secretbox_KEYBYTES);
535 assert(nonce.length >= crypto_secretbox_NONCEBYTES);
537 body {
538 ubyte[32] x = void;
539 if (output is null || output.length < 32) return false;
540 crypto_stream(x, nonce, key);
541 if (!crypto_onetimeauth_verify(c[16..$], c[32../*$*/32+(output.length-32)], x)) return false;
542 crypto_stream_xor(output, c, nonce, key);
543 output[0..32] = 0;
544 return true;
548 private:
549 void car25519() (long[] o) {
550 foreach (i; 0..16) {
551 o[i] += (1<<16);
552 long c = o[i]>>16;
553 o[(i+1)*(i<15)] += c-1+37*(c-1)*(i==15);
554 o[i] -= c<<16;
558 void sel25519() (long[] p,long[] q, int b) {
559 long c = ~(b-1);
560 foreach (i; 0..16) {
561 long t = c&(p[i]^q[i]);
562 p[i] ^= t;
563 q[i] ^= t;
567 void pack25519() (ubyte[] o, const(long)[] n) {
568 int b;
569 long[16] m = void, t = void;
570 t[0..16] = n[0..16];
571 car25519(t);
572 car25519(t);
573 car25519(t);
574 foreach (j; 0..2) {
575 m[0] = t[0]-0xffed;
576 foreach (i; 1..15) {
577 m[i] = t[i]-0xffff-((m[i-1]>>16)&1);
578 m[i-1] &= 0xffff;
580 m[15] = t[15]-0x7fff-((m[14]>>16)&1);
581 b = (m[15]>>16)&1;
582 m[14] &= 0xffff;
583 sel25519(t, m, 1-b);
585 foreach (i; 0..16) {
586 o[2*i] = t[i]&0xff;
587 o[2*i+1] = (t[i]>>8)&0xff;
591 bool neq25519() (const(long)[] a, const(long)[] b) {
592 ubyte[32] c = void, d = void;
593 pack25519(c, a);
594 pack25519(d, b);
595 return crypto_verify_32(c, d);
598 ubyte par25519() (const(long)[] a) {
599 ubyte[32] d = void;
600 pack25519(d, a);
601 return d[0]&1;
604 void unpack25519() (long[] o, const(ubyte)[] n) {
605 foreach (i; 0..16) o[i] = n[2*i]+(cast(long)n[2*i+1]<<8);
606 o[15] &= 0x7fff;
609 void A() (long[] o, const(long)[] a, const(long)[] b) {
610 foreach (i; 0..16) o[i] = a[i]+b[i];
613 void Z() (long[] o, const(long)[] a, const(long)[] b) {
614 foreach (i; 0..16) o[i] = a[i]-b[i];
617 void M() (long[] o, const(long)[] a, const(long)[] b) {
618 long[31] t; // automatically becomes 0
619 foreach (i; 0..16) foreach (j; 0..16) t[i+j] += a[i]*b[j];
620 foreach (i; 0..15) t[i] += 38*t[i+16];
621 o[0..16] = t[0..16];
622 car25519(o);
623 car25519(o);
626 void S() (long[] o, const(long)[] a) {
627 M(o, a, a);
630 void inv25519() (long[] o, const(long)[] i) {
631 long[16] c = void;
632 c[] = i[0..16];
633 for (auto a = 253; a >= 0; --a) {
634 S(c, c);
635 if (a != 2 && a != 4) M(c, c, i);
637 o[0..16] = c[];
640 void pow2523() (long[] o, const(long)[] i) {
641 long[16] c = void;
642 c[] = i[0..16];
643 for(auto a = 250; a >= 0; --a) {
644 S(c, c);
645 if (a != 1) M(c, c, i);
647 o[0..16] = c[];
650 /* FIXME!
651 * This function multiplies a group element 'p' by an integer 'n'.
653 * Params:
654 * p = group element
655 * n = number
657 * Returns:
658 * resulting group element 'q' of length crypto_scalarmult_BYTES.
660 void crypto_scalarmult (ubyte[] q, const(ubyte)[] n, const(ubyte)[] p) @safe nothrow @nogc
661 in {
662 assert(q.length == crypto_scalarmult_BYTES);
663 assert(n.length == crypto_scalarmult_BYTES);
664 assert(p.length == crypto_scalarmult_BYTES);
666 body {
667 ubyte[32] z = void;
668 long[80] x = void;
669 long r;
670 long[16] a = void, b = void, c = void, d = void, e = void, f = void;
671 z[] = n[0..32];
672 z[31] = (n[31]&127)|64;
673 z[0] &= 248;
674 unpack25519(x, p);
675 foreach (i; 0..16) {
676 b[i] = x[i];
677 d[i] = a[i] = c[i] = 0;
679 a[0] = d[0] = 1;
680 for (int i = 254; i >= 0; --i) {
681 r = (z[i>>3]>>(i&7))&1;
682 sel25519(a, b, cast(int)r);
683 sel25519(c, d, cast(int)r);
684 A(e, a, c);
685 Z(a, a, c);
686 A(c, b, d);
687 Z(b, b, d);
688 S(d, e);
689 S(f, a);
690 M(a, c, a);
691 M(c, b, e);
692 A(e, a, c);
693 Z(a, a, c);
694 S(b, a);
695 Z(c, d, f);
696 M(a, c, xx121665);
697 A(a, a, d);
698 M(c, c, a);
699 M(a, d, f);
700 M(d, b, x);
701 S(b, e);
702 sel25519(a, b, cast(int)r);
703 sel25519(c, d, cast(int)r);
705 foreach (i; 0..16) {
706 x[i+16] = a[i];
707 x[i+32] = c[i];
708 x[i+48] = b[i];
709 x[i+64] = d[i];
711 inv25519(x[32..$], x[32..$]);
712 M(x[16..$], x[16..$], x[32..$]);
713 pack25519(q, x[16..$]);
716 /* FIXME!
717 * The crypto_scalarmult_base() function computes
718 * the scalar product of a standard group element and an integer 'n'.
720 * Params:
721 * n = number
723 * Returns:
724 * resulting group element 'q' of length crypto_scalarmult_BYTES.
726 void crypto_scalarmult_base() (ubyte[] q, const(ubyte)[] n)
727 in {
728 assert(q.length == crypto_scalarmult_BYTES);
729 assert(n.length == crypto_scalarmult_SCALARBYTES);
731 body {
732 crypto_scalarmult(q, n, nine_);
735 public:
737 * The crypto_box_keypair() function randomly generates a secret key and
738 * a corresponding public key.
740 * Params:
741 * pk = slice to put generated public key into
742 * sk = slice to put generated secret key into
744 * Returns:
745 * pair of new keys
747 void crypto_box_keypair() (ubyte[] pk, ubyte[] sk)
748 in {
749 assert(pk.length >= crypto_box_PUBLICKEYBYTES);
750 assert(sk.length >= crypto_box_SECRETKEYBYTES);
752 body {
753 randombytes(sk, 32);
754 crypto_scalarmult_base(pk, sk);
758 * Function crypto_box_beforenm() computes a shared secret 's' from
759 * public key 'pk' and secret key 'sk'.
761 * Params:
762 * skey = slice to put secret into
763 * pk = public
764 * sk = secret
766 * Returns:
767 * generated secret
769 void crypto_box_beforenm() (ubyte[] skey, const(ubyte)[] pk, const(ubyte)[] sk)
770 in {
771 assert(pk.length >= crypto_box_PUBLICKEYBYTES);
772 assert(sk.length >= crypto_box_SECRETKEYBYTES);
773 assert(skey.length >= crypto_box_BEFORENMBYTES);
775 body {
776 ubyte[32] s = void;
777 crypto_scalarmult(s, sk, pk);
778 crypto_core_hsalsa20(skey, zero_[], s[], sigma[]);
782 * The crypto_box_afternm() function encrypts and authenticates
783 * a message 'msg' using a secret key 'key' and a nonce 'nonce'.
784 * The crypto_box_afternm() function returns the resulting ciphertext 'c'.
786 * Params:
787 * c = resulting cyphertext
788 * msg = message
789 * nonce = nonce
790 * key = secret
792 * Returns:
793 * success flag and cyphertext in 'c'
795 bool crypto_box_afternm() (ubyte[] c, const(ubyte)[] msg, const(ubyte)[] nonce, const(ubyte)[] key)
796 in {
797 assert(nonce.length >= crypto_box_NONCEBYTES);
798 assert(key.length >= crypto_box_BEFORENMBYTES);
800 body {
801 return crypto_secretbox(c, msg, nonce, key);
805 * The crypto_box_open_afternm() function verifies and decrypts
806 * a ciphertext 'c' using a secret key 'key' and a nonce 'nonce'.
807 * The crypto_box_open_afternm() function returns the resulting message 'msg'.
809 * Params:
810 * msg = resulting message
811 * c = cyphertext
812 * nonce = nonce
813 * key = secret
815 * Returns:
816 * success flag and resulting message in 'msg'
818 bool crypto_box_open_afternm() (ubyte[] msg, const(ubyte)[] c, const(ubyte)[] nonce, const(ubyte)[] key)
819 in {
820 assert(nonce.length >= crypto_box_NONCEBYTES);
821 assert(key.length >= crypto_box_BEFORENMBYTES);
823 body {
824 return crypto_secretbox_open(msg, c, nonce, key);
828 * The crypto_box() function encrypts and authenticates a message 'msg'
829 * using the sender's secret key 'sk', the receiver's public key 'pk',
830 * and a nonce 'nonce'. The crypto_box() function returns the resulting ciphertext 'c'.
832 * Params:
833 * c = resulting cyphertext
834 * msg = message
835 * nonce = nonce
836 * pk = receiver's public key
837 * sk = sender's secret key
839 * Returns:
840 * success flag and cyphertext in 'c'
842 bool crypto_box() (ubyte[] c, const(ubyte)[] msg, const(ubyte)[] nonce, const(ubyte)[] pk, const(ubyte)[] sk)
843 in {
844 assert(nonce.length >= crypto_box_NONCEBYTES);
845 assert(pk.length >= crypto_box_PUBLICKEYBYTES);
846 assert(sk.length >= crypto_box_SECRETKEYBYTES);
848 body {
849 ubyte[32] k = void;
850 crypto_box_beforenm(k, pk, sk);
851 return crypto_box_afternm(c, msg, nonce, k);
855 * The crypto_box_open() function verifies and decrypts
856 * a ciphertext 'c' using the receiver's secret key 'sk',
857 * the sender's public key 'pk', and a nonce 'nonce'.
858 * The crypto_box_open() function returns the resulting message 'msg'.
860 * Params:
861 * msg = resulting message
862 * c = cyphertext
863 * nonce = nonce
864 * pk = receiver's public key
865 * sk = sender's secret key
867 * Returns:
868 * success flag and message in 'msg'
870 bool crypto_box_open() (ubyte[] msg, const(ubyte)[] c, const(ubyte)[] nonce, const(ubyte)[] pk, const(ubyte)[] sk)
871 in {
872 assert(nonce.length >= crypto_box_NONCEBYTES);
873 assert(pk.length >= crypto_box_PUBLICKEYBYTES);
874 assert(sk.length >= crypto_box_SECRETKEYBYTES);
876 body {
877 ubyte[32] k = void;
878 crypto_box_beforenm(k, pk, sk);
879 return crypto_box_open_afternm(msg, c, nonce, k);
882 private:
883 ulong R() (ulong x, int c) { return (x>>c)|(x<<(64-c)); }
884 ulong Ch() (ulong x, ulong y, ulong z) { return (x&y)^(~x&z); }
885 ulong Maj() (ulong x, ulong y, ulong z) { return (x&y)^(x&z)^(y&z); }
886 ulong Sigma0() (ulong x) { return R(x, 28)^R(x, 34)^R(x, 39); }
887 ulong Sigma1() (ulong x) { return R(x, 14)^R(x, 18)^R(x, 41); }
888 ulong sigma0() (ulong x) { return R(x, 1)^R(x, 8)^(x>>7); }
889 ulong sigma1() (ulong x) { return R(x, 19)^R(x, 61)^(x>>6); }
891 immutable ulong[80] K = [
892 0x428a2f98d728ae22UL, 0x7137449123ef65cdUL, 0xb5c0fbcfec4d3b2fUL, 0xe9b5dba58189dbbcUL,
893 0x3956c25bf348b538UL, 0x59f111f1b605d019UL, 0x923f82a4af194f9bUL, 0xab1c5ed5da6d8118UL,
894 0xd807aa98a3030242UL, 0x12835b0145706fbeUL, 0x243185be4ee4b28cUL, 0x550c7dc3d5ffb4e2UL,
895 0x72be5d74f27b896fUL, 0x80deb1fe3b1696b1UL, 0x9bdc06a725c71235UL, 0xc19bf174cf692694UL,
896 0xe49b69c19ef14ad2UL, 0xefbe4786384f25e3UL, 0x0fc19dc68b8cd5b5UL, 0x240ca1cc77ac9c65UL,
897 0x2de92c6f592b0275UL, 0x4a7484aa6ea6e483UL, 0x5cb0a9dcbd41fbd4UL, 0x76f988da831153b5UL,
898 0x983e5152ee66dfabUL, 0xa831c66d2db43210UL, 0xb00327c898fb213fUL, 0xbf597fc7beef0ee4UL,
899 0xc6e00bf33da88fc2UL, 0xd5a79147930aa725UL, 0x06ca6351e003826fUL, 0x142929670a0e6e70UL,
900 0x27b70a8546d22ffcUL, 0x2e1b21385c26c926UL, 0x4d2c6dfc5ac42aedUL, 0x53380d139d95b3dfUL,
901 0x650a73548baf63deUL, 0x766a0abb3c77b2a8UL, 0x81c2c92e47edaee6UL, 0x92722c851482353bUL,
902 0xa2bfe8a14cf10364UL, 0xa81a664bbc423001UL, 0xc24b8b70d0f89791UL, 0xc76c51a30654be30UL,
903 0xd192e819d6ef5218UL, 0xd69906245565a910UL, 0xf40e35855771202aUL, 0x106aa07032bbd1b8UL,
904 0x19a4c116b8d2d0c8UL, 0x1e376c085141ab53UL, 0x2748774cdf8eeb99UL, 0x34b0bcb5e19b48a8UL,
905 0x391c0cb3c5c95a63UL, 0x4ed8aa4ae3418acbUL, 0x5b9cca4f7763e373UL, 0x682e6ff3d6b2b8a3UL,
906 0x748f82ee5defb2fcUL, 0x78a5636f43172f60UL, 0x84c87814a1f0ab72UL, 0x8cc702081a6439ecUL,
907 0x90befffa23631e28UL, 0xa4506cebde82bde9UL, 0xbef9a3f7b2c67915UL, 0xc67178f2e372532bUL,
908 0xca273eceea26619cUL, 0xd186b8c721c0c207UL, 0xeada7dd6cde0eb1eUL, 0xf57d4f7fee6ed178UL,
909 0x06f067aa72176fbaUL, 0x0a637dc5a2c898a6UL, 0x113f9804bef90daeUL, 0x1b710b35131c471bUL,
910 0x28db77f523047d84UL, 0x32caab7b40c72493UL, 0x3c9ebe0a15c9bebcUL, 0x431d67c49c100d4cUL,
911 0x4cc5d4becb3e42b6UL, 0x597f299cfc657e2aUL, 0x5fcb6fab3ad6faecUL, 0x6c44198c4a475817UL
914 void crypto_hashblocks (ubyte[] x, const(ubyte)[] m, ulong n) @safe nothrow @nogc {
915 ulong[8] z = void, b = void, a = void;
916 ulong[16] w = void;
917 ulong t;
918 uint mpos = 0;
919 foreach (i; 0..8) z[i] = a[i] = dl64(x[8*i..$]);
920 while (n >= 128) {
921 foreach (i; 0..16) w[i] = dl64(m[mpos+8*i..$]);
922 foreach (i; 0..80) {
923 b[0..8] = a[0..8];
924 t = a[7]+Sigma1(a[4])+Ch(a[4], a[5], a[6])+K[i]+w[i%16];
925 b[7] = t+Sigma0(a[0])+Maj(a[0], a[1], a[2]);
926 b[3] += t;
927 //foreach (j; 0..8) a[(j+1)%8] = b[j];
928 a[1..8] = b[0..7];
929 a[0] = b[7];
930 if (i%16 == 15) {
931 foreach (j; 0..16) w[j] += w[(j+9)%16]+sigma0(w[(j+1)%16])+sigma1(w[(j+14)%16]);
934 foreach (i; 0..8) { a[i] += z[i]; z[i] = a[i]; }
935 mpos += 128;
936 n -= 128;
938 foreach (i; 0..8) ts64(x[8*i..$], z[i]);
941 immutable ubyte[64] iv = [
942 0x6a, 0x09, 0xe6, 0x67, 0xf3, 0xbc, 0xc9, 0x08,
943 0xbb, 0x67, 0xae, 0x85, 0x84, 0xca, 0xa7, 0x3b,
944 0x3c, 0x6e, 0xf3, 0x72, 0xfe, 0x94, 0xf8, 0x2b,
945 0xa5, 0x4f, 0xf5, 0x3a, 0x5f, 0x1d, 0x36, 0xf1,
946 0x51, 0x0e, 0x52, 0x7f, 0xad, 0xe6, 0x82, 0xd1,
947 0x9b, 0x05, 0x68, 0x8c, 0x2b, 0x3e, 0x6c, 0x1f,
948 0x1f, 0x83, 0xd9, 0xab, 0xfb, 0x41, 0xbd, 0x6b,
949 0x5b, 0xe0, 0xcd, 0x19, 0x13, 0x7e, 0x21, 0x79
953 * The crypto_hash() function hashes a message 'msg'.
954 * It returns a hash 'output'. The output length of 'output' should be at least crypto_hash_BYTES.
956 * Params:
957 * output = resulting hash
958 * msg = message
960 * Returns:
961 * sha512 hash
963 public void crypto_hash() (ubyte[] output, const(ubyte)[] msg)
964 in {
965 assert(output.length >= crypto_hash_BYTES);
967 body {
968 ubyte[64] h = void;
969 ubyte[256] x; /*autoinit*/
970 size_t n = msg.length;
971 ulong b = n;
972 uint mpos = 0;
974 h[] = iv[];
976 crypto_hashblocks(h, msg, n);
977 mpos += n;
978 n &= 127;
979 mpos -= n;
981 x[0..n] = msg[mpos..mpos+n];
982 x[n] = 128;
984 n = 256-128*(n<112);
985 x[n-9] = b>>61;
986 ts64(x[n-8..$], b<<3);
987 crypto_hashblocks(h, x, n);
989 output[0..64] = h;
992 private void add() (ref long[16][4] p, ref long[16][4] q) {
993 long[16] a = void, b = void, c = void, d = void, t = void, e = void, f = void, g = void, h = void;
995 Z(a, p[1], p[0]);
996 Z(t, q[1], q[0]);
997 M(a, a, t);
998 A(b, p[0], p[1]);
999 A(t, q[0], q[1]);
1000 M(b, b, t);
1001 M(c, p[3], q[3]);
1002 M(c, c, D2);
1003 M(d, p[2], q[2]);
1004 A(d, d, d);
1005 Z(e, b, a);
1006 Z(f, d, c);
1007 A(g, d, c);
1008 A(h, b, a);
1010 M(p[0], e, f);
1011 M(p[1], h, g);
1012 M(p[2], g, f);
1013 M(p[3], e, h);
1016 void cswap() (ref long[16][4] p, ref long[16][4] q, ubyte b) {
1017 foreach (i; 0..4) sel25519(p[i], q[i], b);
1020 void pack() (ubyte[] r, ref long[16][4] p) {
1021 long[16] tx = void, ty = void, zi = void;
1022 inv25519(zi, p[2]);
1023 M(tx, p[0], zi);
1024 M(ty, p[1], zi);
1025 pack25519(r, ty);
1026 r[31] ^= par25519(tx)<<7;
1029 void scalarmult() (ref long[16][4] p, ref long[16][4] q, const(ubyte)[] s) {
1030 p[0][] = gf0[];
1031 p[1][] = gf1[];
1032 p[2][] = gf1[];
1033 p[3][] = gf0[];
1034 for (int i = 255; i >= 0; --i) {
1035 ubyte b = (s[i/8]>>(i&7))&1;
1036 cswap(p, q, b);
1037 add(q, p);
1038 add(p, p);
1039 cswap(p, q, b);
1043 void scalarbase() (ref long[16][4] p, const(ubyte)[] s) {
1044 long[16][4] q = void;
1045 q[0][] = X[];
1046 q[1][] = Y[];
1047 q[2][] = gf1[];
1048 M(q[3], X, Y);
1049 scalarmult(p, q, s);
1053 * The crypto_sign_keypair() function randomly generates a secret key and
1054 * a corresponding public key.
1056 * Params:
1057 * pk = slice to put generated public key into
1058 * sk = slice to put generated secret key into
1060 * Returns:
1061 * pair of new keys
1063 public void crypto_sign_keypair() (ubyte[] pk, ubyte[] sk)
1064 in {
1065 assert(pk.length >= crypto_sign_PUBLICKEYBYTES);
1066 assert(sk.length >= crypto_sign_SECRETKEYBYTES);
1068 body {
1069 ubyte[64] d = void;
1070 long[16][4] p = void;
1072 randombytes(sk, 32);
1073 crypto_hash(d, sk[0..32]);
1074 d[0] &= 248;
1075 d[31] &= 127;
1076 d[31] |= 64;
1078 scalarbase(p, d);
1079 pack(pk, p);
1081 sk[32..64] = pk[0..32];
1084 immutable ulong[32] L = [
1085 0xed,0xd3,0xf5,0x5c,0x1a,0x63,0x12,0x58,0xd6,0x9c,0xf7,0xa2,0xde,0xf9,0xde,0x14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x10
1088 void modL() (ubyte[] r, long[] x) {
1089 long carry;
1090 for (auto i = 63; i >= 32; --i) {
1091 int j;
1092 carry = 0;
1093 for (j = i-32; j < i-12; ++j) {
1094 x[j] += carry-16*x[i]*L[j-(i-32)];
1095 carry = (x[j]+128)>>8;
1096 x[j] -= carry<<8;
1098 x[j] += carry;
1099 x[i] = 0;
1101 carry = 0;
1102 foreach (j; 0..32) {
1103 x[j] += carry-(x[31]>>4)*L[j];
1104 carry = x[j]>>8;
1105 x[j] &= 255;
1107 foreach (j; 0..32) x[j] -= carry*L[j];
1108 foreach (i; 0..32) {
1109 x[i+1] += x[i]>>8;
1110 r[i] = x[i]&255;
1114 void reduce() (ubyte[] r) {
1115 long[64] x = void;
1116 foreach (i; 0..64) x[i] = cast(ulong)r[i];
1117 r[0..64] = 0;
1118 modL(r, x);
1122 public:
1124 * The crypto_sign() function signs a message 'msg' using the sender's secret key 'sk'.
1125 * The crypto_sign() function returns the resulting signed message.
1127 * Params:
1128 * sm = buffer to receive signed message, must be of size at least msg.length+64
1129 * msg == message
1130 * sk == secret key, slice size must be at least crypto_sign_SECRETKEYBYTES, extra ignored
1132 * Returns:
1133 * signed message
1135 void crypto_sign() (ubyte[] sm, const(ubyte)[] msg, const(ubyte)[] sk)
1136 in {
1137 assert(sk.length >= crypto_sign_SECRETKEYBYTES);
1138 assert(sm.length >= msg.length+64);
1140 body {
1141 ubyte[64] d = void, h = void, r = void;
1142 ulong[64] x;/*autoinit*/
1143 long[16][4] p = void;
1144 size_t n = msg.length;
1145 size_t smlen = n+64;
1147 crypto_hash(d, sk[0..32]);
1148 d[0] &= 248;
1149 d[31] &= 127;
1150 d[31] |= 64;
1152 sm[64..64+n] = msg[];
1153 sm[32..64] = d[32..64];
1155 crypto_hash(r, sm[32..32+n+32]);
1156 reduce(r);
1157 scalarbase(p, r);
1158 pack(sm, p);
1160 sm[32..64] = sk[32..64];
1161 crypto_hash(h, sm[0..n+64]);
1162 reduce(h);
1164 foreach (i; 0..32) x[i] = cast(ulong)r[i];
1165 foreach (i; 0..32) foreach (j; 0..32) x[i+j] += h[i]*cast(ulong)d[j];
1166 modL(sm[32..$], cast(long[])x);
1170 * The crypto_sign() function signs a message 'msg' using the sender's secret key 'sk'.
1171 * The crypto_sign() function returns the resulting signed message.
1173 * WARNING! This function allocates!
1175 * Params:
1176 * msg == message
1177 * sk == secret key, slice size must be at least crypto_sign_SECRETKEYBYTES, extra ignored
1179 * Returns:
1180 * signed message
1182 ubyte[] crypto_sign() (const(ubyte)[] msg, const(ubyte)[] sk)
1183 in {
1184 assert(sk.length >= crypto_sign_SECRETKEYBYTES);
1186 body {
1187 ubyte[] sm;
1188 size_t n = msg.length;
1189 size_t smlen = n+64;
1190 sm.length = smlen;
1191 crypto_sign(sm, msg, sk);
1192 return sm;
1195 private bool unpackneg() (ref long[16][4] r, const(ubyte)[] p) {
1196 long[16] t = void, chk = void, num = void, den = void, den2 = void, den4 = void, den6 = void;
1197 r[2][] = gf1[];
1198 unpack25519(r[1], p);
1199 S(num, r[1]);
1200 M(den, num, D);
1201 Z(num, num, r[2]);
1202 A(den, r[2], den);
1204 S(den2, den);
1205 S(den4, den2);
1206 M(den6, den4, den2);
1207 M(t, den6, num);
1208 M(t, t, den);
1210 pow2523(t, t);
1211 M(t, t, num);
1212 M(t, t, den);
1213 M(t, t, den);
1214 M(r[0], t, den);
1216 S(chk, r[0]);
1217 M(chk, chk, den);
1218 if (!neq25519(chk, num)) M(r[0], r[0], I);
1220 S(chk, r[0]);
1221 M(chk, chk, den);
1222 if (!neq25519(chk, num)) return false;
1224 if (par25519(r[0]) == (p[31]>>7)) Z(r[0], gf0, r[0]);
1226 M(r[3], r[0], r[1]);
1227 return true;
1231 * The crypto_sign_open() function verifies the signature in
1232 * 'sm' using the receiver's public key 'pk'.
1234 * Params:
1235 * msg = decrypted message, last 64 bytes are useless zeroes, must be of size at least sm.length
1236 * sm == signed message
1237 * pk == public key, slice size must be at least crypto_sign_PUBLICKEYBYTES, extra ignored
1239 * Returns:
1240 * success flag
1242 bool crypto_sign_open() (ubyte[] msg, const(ubyte)[] sm, const(ubyte)[] pk)
1243 in {
1244 assert(pk.length >= crypto_sign_PUBLICKEYBYTES);
1245 assert(msg.length >= sm.length);
1247 body {
1248 ubyte[32] t = void;
1249 ubyte[64] h = void;
1250 long[16][4] p = void, q = void;
1251 size_t n = sm.length;
1253 if (n < 64) return false;
1255 if (!unpackneg(q, pk)) return false;
1256 msg[0..n] = sm[];
1257 msg[32..64] = pk[0..32];
1258 crypto_hash(h, msg);
1259 reduce(h);
1260 scalarmult(p, q, h);
1262 scalarbase(q, sm[32..$]);
1263 add(p, q);
1264 pack(t, p);
1266 n -= 64;
1267 if (!crypto_verify_32(sm, t)) {
1268 msg[0..n] = 0;
1269 return false;
1272 msg[0..n] = sm[64..64+n];
1273 msg[n..n+64] = 0;
1275 return true;
1280 * The crypto_sign_open() function verifies the signature in
1281 * 'sm' using the receiver's public key 'pk'.
1282 * The crypto_sign_open() function returns the message.
1284 * WARNING! This function allocates!
1286 * Params:
1287 * sm == signed message
1288 * pk == public key, slice size must be at least crypto_sign_PUBLICKEYBYTES, extra ignored
1290 * Returns:
1291 * decrypted message or null on error
1293 ubyte[] crypto_sign_open() (const(ubyte)[] sm, const(ubyte)[] pk) {
1294 ubyte[] msg;
1295 msg.length = sm.length;
1296 if (!crypto_sign_open(msg, sm, pk)) return null;
1297 return msg[0..sm.length-64]; // remove signature
1301 unittest {
1302 import std.exception;
1303 import std.random;
1304 import std.range;
1305 import std.stdio;
1308 private extern(C) int open(const(char)* filename, int flags, ...);
1309 void randombytes (ubyte[] dest, size_t len) {
1310 import core.sys.posix.unistd;
1311 static int fd = -1;
1312 if (fd == -1) {
1313 for (;;) {
1314 fd = open("/dev/urandom", /*O_RDONLY*/0);
1315 if (fd != -1) break;
1316 sleep(1);
1319 size_t pos = 0;
1320 while (len > 0) {
1321 ssize_t i = read(fd, cast(void*)(&dest[pos]), (len < 1048576 ? len : 1048576));
1322 if (i < 1) {
1323 sleep(1);
1324 continue;
1326 pos += i;
1327 len -= i;
1332 static void rnd (ubyte[] dest, size_t len) {
1333 for (size_t f = 0; f < len; ++f) dest[f] = cast(ubyte)uniform(0, 256);
1335 randombytes = &rnd;
1338 randombytes = (ubyte[] dest, size_t len) {
1339 for (size_t f = 0; f < len; ++f) dest[f] = cast(ubyte)uniform(0, 256);
1342 void dumpArray(T) (T[] arr) {
1343 writefln("============================= (%s)", arr.length);
1344 for (auto f = 0; f < arr.length; ++f) {
1345 if (f && f%16 == 0) writeln();
1346 static if (T.sizeof == 1) writef(" 0x%02x", arr[f]);
1347 else static if (T.sizeof == 2) writef(" 0x%04x", arr[f]);
1348 else static if (T.sizeof == 4) writef(" 0x%08x", arr[f]);
1349 else writef(" 0x%08x", arr[f]);
1351 writeln();
1352 writeln("-----------------------------");
1355 string hashToString (const(ubyte)[] hash) {
1356 char[] s;
1357 s.length = hash.length*2;
1358 char toHex(int a) { return cast(char)(a < 10 ? a+'0' : a+'a'-10); }
1359 for (int a = 0; a < hash.length; ++a) {
1360 s[a*2] = toHex(hash[a]>>4);
1361 s[a*2+1] = toHex(hash[a]&0x0f);
1363 return assumeUnique(s);
1366 static immutable ubyte[crypto_sign_PUBLICKEYBYTES] pk = [0x8f,0x58,0xd8,0xbf,0xb1,0x92,0xd1,0xd7,0xe0,0xc3,0x99,0x8a,0x8d,0x5c,0xb5,0xef,0xfc,0x92,0x2a,0x0d,0x70,0x80,0xe8,0x3b,0xe0,0x27,0xeb,0xf6,0x14,0x95,0xfd,0x16];
1367 static immutable ubyte[crypto_sign_SECRETKEYBYTES] sk = [0x78,0x34,0x09,0x59,0x54,0xaa,0xa9,0x2c,0x52,0x3a,0x41,0x3f,0xb6,0xfa,0x6b,0xe1,0xd7,0x0f,0x39,0x30,0x5a,0xe1,0x70,0x12,0x59,0x7d,0x32,0x59,0x9b,0x8b,0x6b,0x2f, 0x8f,0x58,0xd8,0xbf,0xb1,0x92,0xd1,0xd7,0xe0,0xc3,0x99,0x8a,0x8d,0x5c,0xb5,0xef,0xfc,0x92,0x2a,0x0d,0x70,0x80,0xe8,0x3b,0xe0,0x27,0xeb,0xf6,0x14,0x95,0xfd,0x16];
1368 static immutable ubyte[5] m = [0x61,0x68,0x6f,0x6a,0x0a];
1369 static immutable ubyte[69] sm = [0xce,0x1e,0x15,0xad,0xc3,0x17,0x47,0x15,0x7d,0x44,0x60,0xc1,0x7f,0xb8,0xba,0x45,0xf3,0x6d,0x0b,0xbf,0x51,0xf9,0xbb,0x6b,0xb9,0xa1,0xd2,0x4e,0x44,0x8d,0x9e,0x8c,0x36,0x6f,0x7a,0x8b,0x5e,0x2c,0x69,0xba,0x90,0x2e,0x95,0x46,0x19,0xd8,0xc1,0x8a,0x47,0xc5,0x6e,0x4a,0x28,0x9e,0x81,0x17,0xae,0x90,0x69,0x71,0x7d,0x84,0x6a,0x01,0x61,0x68,0x6f,0x6a,0x0a];
1370 ubyte[] smres, t;
1372 writeln("crypto_sign");
1373 smres = crypto_sign(m, sk);
1374 assert(smres.length == sm.length);
1375 assert(smres == sm);
1377 writeln("crypto_sign_open");
1378 t = crypto_sign_open(smres, pk);
1379 assert(t !is null);
1380 assert(t.length == m.length);
1381 assert(t == m);
1384 // based on the code by Adam D. Ruppe
1385 // This does the preprocessing of input data, fetching one byte at a time of the data until it is empty, then the padding and length at the end
1386 template SHARange(T) if (isInputRange!(T)) {
1387 struct SHARange {
1388 T r;
1390 bool empty () { return state == 5; }
1392 void popFront () {
1393 if (state == 0) {
1394 r.popFront;
1395 ++length; // FIXME
1396 if (r.empty) {
1397 state = 1;
1398 position = 2;
1399 current = 0x80;
1401 } else {
1402 bool hackforward = false;
1403 if (state == 1) {
1404 current = 0x0;
1405 state = 2;
1406 if (((position+length+8)*8)%512 == 8) {
1407 --position;
1408 hackforward = true;
1410 goto proceed;
1411 //++position;
1412 } else if (state == 2) {
1413 proceed:
1414 if (!(((position+length+8)*8)%512)) {
1415 state = 3;
1416 position = 7;
1417 length *= 8;
1418 if (hackforward) goto proceedmoar;
1419 } else {
1420 ++position;
1422 } else if (state == 3) {
1423 proceedmoar:
1424 current = (length>>(position*8))&0xff;
1425 if (position == 0) state = 4; else --position;
1426 } else if (state == 4) {
1427 current = 0xff;
1428 state = 5;
1433 ubyte front () {
1434 if (state == 0) return cast(ubyte)r.front;
1435 assert(state != 5);
1436 //writefln("%x", current);
1437 return current;
1440 ubyte current;
1441 uint position;
1442 ulong length;
1443 int state = 0; // reading range, reading appended bit, reading padding, reading length, done
1448 immutable(ubyte)[] SHA256(T) (T data) if (isInputRange!(T)) {
1449 uint[8] h = [0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19];
1450 static immutable(uint[64]) k = [
1451 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
1452 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
1453 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
1454 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
1455 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
1456 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
1457 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
1458 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
1462 SHARange!(T) range;
1463 static if (is(data == SHARange)) range = data; else range.r = data;
1466 while(!range.empty) {
1467 uint[64] words;
1469 for(int a = 0; a < 16; ++a) {
1470 for(int b = 3; b >= 0; --b) {
1471 words[a] |= cast(uint)(range.front())<<(b*8);
1472 range.popFront;
1476 uint ror (uint n, int cnt) {
1477 return cast(uint)(n>>cnt)|cast(uint)(n<<(32-(cnt)));
1480 uint xrot00 (uint reax, int r0, int r1, int r2) {
1481 uint rebx = reax, recx = reax;
1482 reax = ror(reax, r0);
1483 rebx = ror(rebx, r1);
1484 recx >>= r2;
1485 reax ^= rebx;
1486 reax ^= recx;
1487 return reax;
1490 for(int a = 16; a < 64; ++a) {
1491 uint t1 = xrot00(words[a-15], 7, 18, 3);
1492 uint t2 = xrot00(words[a-2], 17, 19, 10);
1493 words[a] = words[a-16]+t1+words[a-7]+t2;
1496 uint A = h[0];
1497 uint B = h[1];
1498 uint C = h[2];
1499 uint D = h[3];
1500 uint E = h[4];
1501 uint F = h[5];
1502 uint G = h[6];
1503 uint H = h[7];
1505 uint xrot01 (uint reax, int r0, int r1, int r2) {
1506 uint rebx = reax, recx = reax;
1507 reax = ror(reax, r0);
1508 rebx = ror(rebx, r1);
1509 recx = ror(recx, r2);
1510 reax ^= rebx;
1511 reax ^= recx;
1512 return reax;
1515 for(int i = 0; i < 64; ++i) {
1516 uint s0 = xrot01(A, 2, 13, 22);
1517 uint maj = (A&B)^(A&C)^(B&C);
1518 uint t2 = s0+maj;
1519 uint s1 = xrot01(E, 6, 11, 25);
1520 uint ch = (E&F)^((~E)&G);
1521 uint t1 = H+s1+ch+k[i]+words[i];
1523 H = G;
1524 G = F;
1525 F = E;
1526 E = D+t1;
1527 D = C;
1528 C = B;
1529 B = A;
1530 A = t1+t2;
1533 h[0] += A;
1534 h[1] += B;
1535 h[2] += C;
1536 h[3] += D;
1537 h[4] += E;
1538 h[5] += F;
1539 h[6] += G;
1540 h[7] += H;
1543 ubyte[] hash;
1544 for(int j = 0; j < 8; ++j)
1545 for(int i = 3; i >= 0; --i) {
1546 hash ~= cast(ubyte)(h[j]>>(i*8))&0xff;
1549 return hash.idup;
1553 void box () {
1554 writeln("box");
1556 static immutable ubyte[32] alicesk = [
1557 0x77,0x07,0x6d,0x0a,0x73,0x18,0xa5,0x7d
1558 ,0x3c,0x16,0xc1,0x72,0x51,0xb2,0x66,0x45
1559 ,0xdf,0x4c,0x2f,0x87,0xeb,0xc0,0x99,0x2a
1560 ,0xb1,0x77,0xfb,0xa5,0x1d,0xb9,0x2c,0x2a
1563 static immutable ubyte[32] bobpk = [
1564 0xde,0x9e,0xdb,0x7d,0x7b,0x7d,0xc1,0xb4
1565 ,0xd3,0x5b,0x61,0xc2,0xec,0xe4,0x35,0x37
1566 ,0x3f,0x83,0x43,0xc8,0x5b,0x78,0x67,0x4d
1567 ,0xad,0xfc,0x7e,0x14,0x6f,0x88,0x2b,0x4f
1570 static immutable ubyte[24] nonce = [
1571 0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73
1572 ,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6
1573 ,0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37
1576 // API requires first 32 bytes to be 0
1577 static immutable ubyte[163] m = [
1578 0, 0, 0, 0, 0, 0, 0, 0
1579 , 0, 0, 0, 0, 0, 0, 0, 0
1580 , 0, 0, 0, 0, 0, 0, 0, 0
1581 , 0, 0, 0, 0, 0, 0, 0, 0
1582 ,0xbe,0x07,0x5f,0xc5,0x3c,0x81,0xf2,0xd5
1583 ,0xcf,0x14,0x13,0x16,0xeb,0xeb,0x0c,0x7b
1584 ,0x52,0x28,0xc5,0x2a,0x4c,0x62,0xcb,0xd4
1585 ,0x4b,0x66,0x84,0x9b,0x64,0x24,0x4f,0xfc
1586 ,0xe5,0xec,0xba,0xaf,0x33,0xbd,0x75,0x1a
1587 ,0x1a,0xc7,0x28,0xd4,0x5e,0x6c,0x61,0x29
1588 ,0x6c,0xdc,0x3c,0x01,0x23,0x35,0x61,0xf4
1589 ,0x1d,0xb6,0x6c,0xce,0x31,0x4a,0xdb,0x31
1590 ,0x0e,0x3b,0xe8,0x25,0x0c,0x46,0xf0,0x6d
1591 ,0xce,0xea,0x3a,0x7f,0xa1,0x34,0x80,0x57
1592 ,0xe2,0xf6,0x55,0x6a,0xd6,0xb1,0x31,0x8a
1593 ,0x02,0x4a,0x83,0x8f,0x21,0xaf,0x1f,0xde
1594 ,0x04,0x89,0x77,0xeb,0x48,0xf5,0x9f,0xfd
1595 ,0x49,0x24,0xca,0x1c,0x60,0x90,0x2e,0x52
1596 ,0xf0,0xa0,0x89,0xbc,0x76,0x89,0x70,0x40
1597 ,0xe0,0x82,0xf9,0x37,0x76,0x38,0x48,0x64
1598 ,0x5e,0x07,0x05
1601 ubyte[163] c;
1604 static immutable ubyte[] res = [
1605 0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5
1606 ,0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9
1607 ,0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73
1608 ,0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce
1609 ,0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4
1610 ,0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a
1611 ,0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b
1612 ,0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72
1613 ,0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2
1614 ,0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38
1615 ,0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a
1616 ,0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae
1617 ,0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea
1618 ,0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda
1619 ,0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde
1620 ,0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3
1621 ,0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6
1622 ,0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74
1623 ,0xe3,0x55,0xa5];
1624 /*crypto_box_curve25519xsalsa20poly1305*/crypto_box(c,m,nonce,bobpk,alicesk);
1625 for (auto f = 16; f < 163; ++f) assert(c[f] == res[f-16]);
1627 box();
1629 void box2 () {
1630 writeln("box2");
1631 static immutable ubyte[32] bobsk = [
1632 0x5d,0xab,0x08,0x7e,0x62,0x4a,0x8a,0x4b
1633 ,0x79,0xe1,0x7f,0x8b,0x83,0x80,0x0e,0xe6
1634 ,0x6f,0x3b,0xb1,0x29,0x26,0x18,0xb6,0xfd
1635 ,0x1c,0x2f,0x8b,0x27,0xff,0x88,0xe0,0xeb
1638 static immutable ubyte[32] alicepk = [
1639 0x85,0x20,0xf0,0x09,0x89,0x30,0xa7,0x54
1640 ,0x74,0x8b,0x7d,0xdc,0xb4,0x3e,0xf7,0x5a
1641 ,0x0d,0xbf,0x3a,0x0d,0x26,0x38,0x1a,0xf4
1642 ,0xeb,0xa4,0xa9,0x8e,0xaa,0x9b,0x4e,0x6a
1645 static immutable ubyte[24] nonce = [
1646 0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73
1647 ,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6
1648 ,0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37
1651 // API requires first 16 bytes to be 0
1652 static immutable ubyte[163] c = [
1653 0, 0, 0, 0, 0, 0, 0, 0
1654 , 0, 0, 0, 0, 0, 0, 0, 0
1655 ,0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5
1656 ,0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9
1657 ,0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73
1658 ,0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce
1659 ,0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4
1660 ,0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a
1661 ,0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b
1662 ,0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72
1663 ,0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2
1664 ,0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38
1665 ,0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a
1666 ,0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae
1667 ,0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea
1668 ,0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda
1669 ,0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde
1670 ,0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3
1671 ,0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6
1672 ,0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74
1673 ,0xe3,0x55,0xa5
1676 ubyte[163] m;
1678 static immutable ubyte[] res = [
1679 0xbe,0x07,0x5f,0xc5,0x3c,0x81,0xf2,0xd5
1680 ,0xcf,0x14,0x13,0x16,0xeb,0xeb,0x0c,0x7b
1681 ,0x52,0x28,0xc5,0x2a,0x4c,0x62,0xcb,0xd4
1682 ,0x4b,0x66,0x84,0x9b,0x64,0x24,0x4f,0xfc
1683 ,0xe5,0xec,0xba,0xaf,0x33,0xbd,0x75,0x1a
1684 ,0x1a,0xc7,0x28,0xd4,0x5e,0x6c,0x61,0x29
1685 ,0x6c,0xdc,0x3c,0x01,0x23,0x35,0x61,0xf4
1686 ,0x1d,0xb6,0x6c,0xce,0x31,0x4a,0xdb,0x31
1687 ,0x0e,0x3b,0xe8,0x25,0x0c,0x46,0xf0,0x6d
1688 ,0xce,0xea,0x3a,0x7f,0xa1,0x34,0x80,0x57
1689 ,0xe2,0xf6,0x55,0x6a,0xd6,0xb1,0x31,0x8a
1690 ,0x02,0x4a,0x83,0x8f,0x21,0xaf,0x1f,0xde
1691 ,0x04,0x89,0x77,0xeb,0x48,0xf5,0x9f,0xfd
1692 ,0x49,0x24,0xca,0x1c,0x60,0x90,0x2e,0x52
1693 ,0xf0,0xa0,0x89,0xbc,0x76,0x89,0x70,0x40
1694 ,0xe0,0x82,0xf9,0x37,0x76,0x38,0x48,0x64
1695 ,0x5e,0x07,0x05
1698 assert(/*crypto_box_curve25519xsalsa20poly1305_open*/crypto_box_open(m,c,nonce,alicepk,bobsk));
1699 for (auto f = 32; f < 163; ++f) assert(m[f] == res[f-32]);
1701 box2();
1703 void box7 () {
1704 writeln("box7");
1705 ubyte[crypto_box_SECRETKEYBYTES] alicesk;
1706 ubyte[crypto_box_PUBLICKEYBYTES] alicepk;
1707 ubyte[crypto_box_SECRETKEYBYTES] bobsk;
1708 ubyte[crypto_box_PUBLICKEYBYTES] bobpk;
1709 ubyte[crypto_box_NONCEBYTES] n;
1710 ubyte[10000] m, c, m2;
1711 for (auto mlen = 0; mlen < 1000 && mlen+crypto_box_ZEROBYTES < m.length; ++mlen) {
1712 crypto_box_keypair(alicepk,alicesk);
1713 crypto_box_keypair(bobpk,bobsk);
1714 randombytes(n,crypto_box_NONCEBYTES);
1715 randombytes(m[crypto_box_ZEROBYTES..$],mlen);
1716 crypto_box(c[0..mlen+crypto_box_ZEROBYTES],m,n,bobpk,alicesk);
1717 assert(crypto_box_open(m2[0..mlen+crypto_box_ZEROBYTES],c,n,alicepk,bobsk));
1718 for (auto i = 0; i < mlen+crypto_box_ZEROBYTES; ++i) assert(m2[i] == m[i]);
1721 version(unittest_full) box7(); // it's slow
1723 void box8 () {
1724 writeln("box8");
1725 ubyte[crypto_box_SECRETKEYBYTES] alicesk;
1726 ubyte[crypto_box_PUBLICKEYBYTES] alicepk;
1727 ubyte[crypto_box_SECRETKEYBYTES] bobsk;
1728 ubyte[crypto_box_PUBLICKEYBYTES] bobpk;
1729 ubyte[crypto_box_NONCEBYTES] n;
1730 ubyte[10000] m, c, m2;
1731 for (auto mlen = 0; mlen < 1000 && mlen+crypto_box_ZEROBYTES < m.length; ++mlen) {
1732 crypto_box_keypair(alicepk,alicesk);
1733 crypto_box_keypair(bobpk,bobsk);
1734 randombytes(n,crypto_box_NONCEBYTES);
1735 randombytes(m[crypto_box_ZEROBYTES..$],mlen);
1736 crypto_box(c[0..mlen+crypto_box_ZEROBYTES],m,n,bobpk,alicesk);
1737 int caught = 0;
1738 while (caught < 10) {
1739 c[uniform(0, mlen+crypto_box_ZEROBYTES)] = cast(ubyte)uniform(0, 256);
1740 if (crypto_box_open(m2[0..mlen+crypto_box_ZEROBYTES],c,n,alicepk,bobsk)) {
1741 for (auto i = 0; i < mlen+crypto_box_ZEROBYTES; ++i) assert(m2[i] == m[i]);
1742 } else {
1743 ++caught;
1746 assert(caught == 10);
1749 version(unittest_full) box8(); // it's slow
1751 void core1 () {
1752 writeln("core1");
1753 static immutable ubyte[32] shared_ = [
1754 0x4a,0x5d,0x9d,0x5b,0xa4,0xce,0x2d,0xe1
1755 ,0x72,0x8e,0x3b,0xf4,0x80,0x35,0x0f,0x25
1756 ,0xe0,0x7e,0x21,0xc9,0x47,0xd1,0x9e,0x33
1757 ,0x76,0xf0,0x9b,0x3c,0x1e,0x16,0x17,0x42
1760 static immutable ubyte[32] zero = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
1762 static immutable ubyte[16] c = [
1763 0x65,0x78,0x70,0x61,0x6e,0x64,0x20,0x33
1764 ,0x32,0x2d,0x62,0x79,0x74,0x65,0x20,0x6b
1767 ubyte[32] firstkey;
1769 static immutable ubyte[32] res = [
1770 0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4
1771 ,0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7
1772 ,0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2
1773 ,0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89
1776 crypto_core_hsalsa20(firstkey,zero,shared_,c);
1777 assert(firstkey == res);
1779 core1();
1781 void core2 () {
1782 writeln("core2");
1783 static immutable ubyte[32]firstkey = [
1784 0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4
1785 ,0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7
1786 ,0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2
1787 ,0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89
1790 static immutable ubyte[16]nonceprefix = [
1791 0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73
1792 ,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6
1795 static immutable ubyte[16] c = [
1796 0x65,0x78,0x70,0x61,0x6e,0x64,0x20,0x33
1797 ,0x32,0x2d,0x62,0x79,0x74,0x65,0x20,0x6b
1800 ubyte[32] secondkey;
1802 static immutable ubyte[32] res = [
1803 0xdc,0x90,0x8d,0xda,0x0b,0x93,0x44,0xa9
1804 ,0x53,0x62,0x9b,0x73,0x38,0x20,0x77,0x88
1805 ,0x80,0xf3,0xce,0xb4,0x21,0xbb,0x61,0xb9
1806 ,0x1c,0xbd,0x4c,0x3e,0x66,0x25,0x6c,0xe4
1809 crypto_core_hsalsa20(secondkey,nonceprefix,firstkey,c);
1810 assert(secondkey == res);
1812 core2();
1814 void core3 () {
1815 writeln("core3");
1816 static immutable ubyte[32] secondkey = [
1817 0xdc,0x90,0x8d,0xda,0x0b,0x93,0x44,0xa9
1818 ,0x53,0x62,0x9b,0x73,0x38,0x20,0x77,0x88
1819 ,0x80,0xf3,0xce,0xb4,0x21,0xbb,0x61,0xb9
1820 ,0x1c,0xbd,0x4c,0x3e,0x66,0x25,0x6c,0xe4
1823 static immutable ubyte[8] noncesuffix = [
1824 0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37
1827 static immutable ubyte[16] c = [
1828 0x65,0x78,0x70,0x61,0x6e,0x64,0x20,0x33
1829 ,0x32,0x2d,0x62,0x79,0x74,0x65,0x20,0x6b
1832 static ubyte[16] input = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] ;
1834 static ubyte[64*256*256] output;
1836 static ubyte[64] h;
1838 static immutable ubyte[64] res = [0x2b,0xd8,0xe7,0xdb,0x68,0x77,0x53,0x9e,0x4f,0x2b,0x29,0x5e,0xe4,0x15,0xcd,0x37,0x8a,0xe2,0x14,0xaa,0x3b,0xeb,0x3e,0x08,0xe9,0x11,0xa5,0xbd,0x4a,0x25,0xe6,0xac,0x16,0xca,0x28,0x3c,0x79,0xc3,0x4c,0x08,0xc9,0x9f,0x7b,0xdb,0x56,0x01,0x11,0xe8,0xca,0xc1,0xae,0x65,0xee,0xa0,0x8a,0xc3,0x84,0xd7,0xa5,0x91,0x46,0x1a,0xb6,0xe3];
1840 int pos = 0;
1841 for (auto i = 0; i < 8; ++i) input[i] = noncesuffix[i];
1842 do {
1843 do {
1844 crypto_core_salsa20(output[pos..$],input,secondkey,c);
1845 pos += 64;
1846 } while (++input[8]);
1847 } while (++input[9]);
1848 crypto_hash(h,output);
1849 assert(h == res);
1851 version(unittest_full) core3(); // it's slow
1853 void core4 () {
1854 writeln("core4");
1855 static immutable ubyte[32] k = [
1856 1, 2, 3, 4, 5, 6, 7, 8
1857 , 9, 10, 11, 12, 13, 14, 15, 16
1858 ,201,202,203,204,205,206,207,208
1859 ,209,210,211,212,213,214,215,216
1862 static immutable ubyte[16] input = [
1863 101,102,103,104,105,106,107,108
1864 ,109,110,111,112,113,114,115,116
1867 static immutable ubyte[16] c = [
1868 101,120,112, 97,110,100, 32, 51
1869 , 50, 45, 98,121,116,101, 32,107
1872 ubyte[64] output;
1874 static immutable ubyte[64] res = [
1875 69, 37, 68, 39, 41, 15,107,193
1876 ,255,139,122, 6,170,233,217, 98
1877 , 89,144,182,106, 21, 51,200, 65
1878 ,239, 49,222, 34,215,114, 40,126
1879 ,104,197, 7,225,197,153, 31, 2
1880 ,102, 78, 76,176, 84,245,246,184
1881 ,177,160,133,130, 6, 72,149,119
1882 ,192,195,132,236,234,103,246, 74
1885 crypto_core_salsa20(output,input,k,c);
1886 assert(output == res);
1888 core4();
1890 void core5 () {
1891 writeln("core5");
1892 static immutable ubyte[32] k = [
1893 0xee,0x30,0x4f,0xca,0x27,0x00,0x8d,0x8c
1894 ,0x12,0x6f,0x90,0x02,0x79,0x01,0xd8,0x0f
1895 ,0x7f,0x1d,0x8b,0x8d,0xc9,0x36,0xcf,0x3b
1896 ,0x9f,0x81,0x96,0x92,0x82,0x7e,0x57,0x77
1899 static immutable ubyte[16] input = [
1900 0x81,0x91,0x8e,0xf2,0xa5,0xe0,0xda,0x9b
1901 ,0x3e,0x90,0x60,0x52,0x1e,0x4b,0xb3,0x52
1904 static immutable ubyte[16] c = [
1905 101,120,112, 97,110,100, 32, 51
1906 , 50, 45, 98,121,116,101, 32,107
1909 ubyte[32] output;
1911 static immutable ubyte[32] res = [
1912 0xbc,0x1b,0x30,0xfc,0x07,0x2c,0xc1,0x40
1913 ,0x75,0xe4,0xba,0xa7,0x31,0xb5,0xa8,0x45
1914 ,0xea,0x9b,0x11,0xe9,0xa5,0x19,0x1f,0x94
1915 ,0xe1,0x8c,0xba,0x8f,0xd8,0x21,0xa7,0xcd
1918 crypto_core_hsalsa20(output,input,k,c);
1919 assert(output == res);
1921 core5();
1923 void core6 () {
1924 writeln("core6");
1925 static immutable ubyte[32] k = [
1926 0xee,0x30,0x4f,0xca,0x27,0x00,0x8d,0x8c
1927 ,0x12,0x6f,0x90,0x02,0x79,0x01,0xd8,0x0f
1928 ,0x7f,0x1d,0x8b,0x8d,0xc9,0x36,0xcf,0x3b
1929 ,0x9f,0x81,0x96,0x92,0x82,0x7e,0x57,0x77
1932 static immutable ubyte[16] input = [
1933 0x81,0x91,0x8e,0xf2,0xa5,0xe0,0xda,0x9b
1934 ,0x3e,0x90,0x60,0x52,0x1e,0x4b,0xb3,0x52
1937 static immutable ubyte[16] c = [
1938 101,120,112, 97,110,100, 32, 51
1939 , 50, 45, 98,121,116,101, 32,107
1942 ubyte[64] output;
1944 static immutable ubyte[32] res = [
1945 0xbc,0x1b,0x30,0xfc,0x07,0x2c,0xc1,0x40
1946 ,0x75,0xe4,0xba,0xa7,0x31,0xb5,0xa8,0x45
1947 ,0xea,0x9b,0x11,0xe9,0xa5,0x19,0x1f,0x94
1948 ,0xe1,0x8c,0xba,0x8f,0xd8,0x21,0xa7,0xcd
1951 ubyte[32] pp;
1952 uint pppos = 0;
1954 void print(const(ubyte)[] x, const(ubyte)[] y)
1956 uint borrow = 0;
1957 for (auto i = 0; i < 4; ++i) {
1958 uint xi = x[i];
1959 uint yi = y[i];
1960 //printf(",0x%02x",255&(xi-yi-borrow));
1961 pp[pppos++] = cast(ubyte)(255&(xi-yi-borrow));
1962 borrow = (xi < yi+borrow);
1966 crypto_core_salsa20(output,input,k,c);
1967 print(output,c);
1968 print(output[20..$],c[4..$]);
1969 print(output[40..$],c[8..$]);
1970 print(output[60..$],c[12..$]);
1971 print(output[24..$],input);
1972 print(output[28..$],input[4..$]);
1973 print(output[32..$],input[8..$]);
1974 print(output[36..$],input[12..$]);
1975 assert(pp == res);
1977 core6();
1979 void hash () {
1980 writeln("hash");
1981 static immutable ubyte[8] x = ['t','e','s','t','i','n','g','\n'];
1982 static ubyte[crypto_hash_BYTES] h;
1983 static immutable ubyte[crypto_hash_BYTES] res = [0x24,0xf9,0x50,0xaa,0xc7,0xb9,0xea,0x9b,0x3c,0xb7,0x28,0x22,0x8a,0x0c,0x82,0xb6,0x7c,0x39,0xe9,0x6b,0x4b,0x34,0x47,0x98,0x87,0x0d,0x5d,0xae,0xe9,0x3e,0x3a,0xe5,0x93,0x1b,0xaa,0xe8,0xc7,0xca,0xcf,0xea,0x4b,0x62,0x94,0x52,0xc3,0x80,0x26,0xa8,0x1d,0x13,0x8b,0xc7,0xaa,0xd1,0xaf,0x3e,0xf7,0xbf,0xd5,0xec,0x64,0x6d,0x6c,0x28];
1984 crypto_hash(h,x);
1985 //for (auto f = 0; f < crypto_hash_BYTES; ++f) assert(h[f] == res[f]);
1986 assert(h == res);
1988 hash();
1990 void onetimeauth () {
1991 writeln("onetimeauth");
1992 static immutable ubyte[32] rs = [
1993 0xee,0xa6,0xa7,0x25,0x1c,0x1e,0x72,0x91
1994 ,0x6d,0x11,0xc2,0xcb,0x21,0x4d,0x3c,0x25
1995 ,0x25,0x39,0x12,0x1d,0x8e,0x23,0x4e,0x65
1996 ,0x2d,0x65,0x1f,0xa4,0xc8,0xcf,0xf8,0x80
1999 static immutable ubyte[131] c = [
2000 0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73
2001 ,0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce
2002 ,0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4
2003 ,0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a
2004 ,0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b
2005 ,0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72
2006 ,0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2
2007 ,0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38
2008 ,0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a
2009 ,0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae
2010 ,0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea
2011 ,0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda
2012 ,0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde
2013 ,0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3
2014 ,0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6
2015 ,0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74
2016 ,0xe3,0x55,0xa5
2019 ubyte[16] a;
2021 static immutable ubyte[16] res = [0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5,0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9];
2023 /*crypto_onetimeauth_poly1305*/crypto_onetimeauth(a,c,rs);
2024 assert(a == res);
2026 onetimeauth();
2028 void onetimeauth2 () {
2029 writeln("onetimeauth2");
2030 static immutable ubyte[32] rs = [
2031 0xee,0xa6,0xa7,0x25,0x1c,0x1e,0x72,0x91
2032 ,0x6d,0x11,0xc2,0xcb,0x21,0x4d,0x3c,0x25
2033 ,0x25,0x39,0x12,0x1d,0x8e,0x23,0x4e,0x65
2034 ,0x2d,0x65,0x1f,0xa4,0xc8,0xcf,0xf8,0x80
2037 static immutable ubyte[131] c = [
2038 0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73
2039 ,0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce
2040 ,0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4
2041 ,0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a
2042 ,0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b
2043 ,0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72
2044 ,0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2
2045 ,0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38
2046 ,0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a
2047 ,0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae
2048 ,0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea
2049 ,0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda
2050 ,0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde
2051 ,0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3
2052 ,0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6
2053 ,0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74
2054 ,0xe3,0x55,0xa5
2057 static immutable ubyte[16] a = [
2058 0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5
2059 ,0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9
2062 assert(/*crypto_onetimeauth_poly1305_verify*/crypto_onetimeauth_verify(a,c,rs));
2064 onetimeauth2();
2066 void onetimeauth7 () {
2067 writeln("onetimeauth7");
2068 static ubyte[32] key;
2069 static ubyte[10000] c;
2070 static ubyte[16] a;
2072 for (auto clen = 0; clen < 10000; ++clen) {
2073 //if (clen%512 == 0) { writef("\r%s", clen); stdout.flush(); }
2074 randombytes(key, key.length);
2075 randombytes(c, clen);
2076 crypto_onetimeauth(a,c[0..clen],key);
2077 assert(crypto_onetimeauth_verify(a,c[0..clen],key));
2078 if (clen > 0) {
2079 c[uniform(0, clen)] += 1+(uniform(0, 255));
2080 assert(!crypto_onetimeauth_verify(a,c[0..clen],key));
2081 a[uniform(0, a.length)] += 1+(uniform(0, 255));
2082 assert(!crypto_onetimeauth_verify(a,c[0..clen],key));
2086 version(unittest_full) onetimeauth7(); // it's slow
2088 void scalarmult () {
2089 writeln("scalarmult");
2090 static immutable ubyte[32] alicesk = [
2091 0x77,0x07,0x6d,0x0a,0x73,0x18,0xa5,0x7d
2092 ,0x3c,0x16,0xc1,0x72,0x51,0xb2,0x66,0x45
2093 ,0xdf,0x4c,0x2f,0x87,0xeb,0xc0,0x99,0x2a
2094 ,0xb1,0x77,0xfb,0xa5,0x1d,0xb9,0x2c,0x2a
2097 ubyte[32] alicepk;
2099 static immutable ubyte[32] res = [
2100 0x85,0x20,0xf0,0x09,0x89,0x30,0xa7,0x54
2101 ,0x74,0x8b,0x7d,0xdc,0xb4,0x3e,0xf7,0x5a
2102 ,0x0d,0xbf,0x3a,0x0d,0x26,0x38,0x1a,0xf4
2103 ,0xeb,0xa4,0xa9,0x8e,0xaa,0x9b,0x4e,0x6a
2106 /*crypto_scalarmult_curve25519_base*/crypto_scalarmult_base(alicepk,alicesk);
2107 assert(alicepk == res);
2109 scalarmult();
2111 void scalarmult2 () {
2112 writeln("scalarmult2");
2113 static immutable ubyte[32] bobsk = [
2114 0x5d,0xab,0x08,0x7e,0x62,0x4a,0x8a,0x4b
2115 ,0x79,0xe1,0x7f,0x8b,0x83,0x80,0x0e,0xe6
2116 ,0x6f,0x3b,0xb1,0x29,0x26,0x18,0xb6,0xfd
2117 ,0x1c,0x2f,0x8b,0x27,0xff,0x88,0xe0,0xeb
2120 ubyte[32] bobpk;
2122 static immutable ubyte[32] res = [
2123 0xde,0x9e,0xdb,0x7d,0x7b,0x7d,0xc1,0xb4
2124 ,0xd3,0x5b,0x61,0xc2,0xec,0xe4,0x35,0x37
2125 ,0x3f,0x83,0x43,0xc8,0x5b,0x78,0x67,0x4d
2126 ,0xad,0xfc,0x7e,0x14,0x6f,0x88,0x2b,0x4f
2129 /*crypto_scalarmult_curve25519_base*/crypto_scalarmult_base(bobpk,bobsk);
2130 assert(bobpk == res);
2132 scalarmult2();
2134 void scalarmult5 () {
2135 writeln("scalarmult5");
2136 static immutable ubyte[32] alicesk = [
2137 0x77,0x07,0x6d,0x0a,0x73,0x18,0xa5,0x7d
2138 ,0x3c,0x16,0xc1,0x72,0x51,0xb2,0x66,0x45
2139 ,0xdf,0x4c,0x2f,0x87,0xeb,0xc0,0x99,0x2a
2140 ,0xb1,0x77,0xfb,0xa5,0x1d,0xb9,0x2c,0x2a
2143 static immutable ubyte[32] bobpk = [
2144 0xde,0x9e,0xdb,0x7d,0x7b,0x7d,0xc1,0xb4
2145 ,0xd3,0x5b,0x61,0xc2,0xec,0xe4,0x35,0x37
2146 ,0x3f,0x83,0x43,0xc8,0x5b,0x78,0x67,0x4d
2147 ,0xad,0xfc,0x7e,0x14,0x6f,0x88,0x2b,0x4f
2150 ubyte[32] k;
2152 static immutable ubyte[32] res = [
2153 0x4a,0x5d,0x9d,0x5b,0xa4,0xce,0x2d,0xe1
2154 ,0x72,0x8e,0x3b,0xf4,0x80,0x35,0x0f,0x25
2155 ,0xe0,0x7e,0x21,0xc9,0x47,0xd1,0x9e,0x33
2156 ,0x76,0xf0,0x9b,0x3c,0x1e,0x16,0x17,0x42
2159 crypto_scalarmult(k,alicesk,bobpk);
2160 assert(k == res);
2162 scalarmult5();
2164 void scalarmult6 () {
2165 writeln("scalarmult6");
2166 static immutable ubyte[32] bobsk = [
2167 0x5d,0xab,0x08,0x7e,0x62,0x4a,0x8a,0x4b
2168 ,0x79,0xe1,0x7f,0x8b,0x83,0x80,0x0e,0xe6
2169 ,0x6f,0x3b,0xb1,0x29,0x26,0x18,0xb6,0xfd
2170 ,0x1c,0x2f,0x8b,0x27,0xff,0x88,0xe0,0xeb
2173 static immutable ubyte[32] alicepk = [
2174 0x85,0x20,0xf0,0x09,0x89,0x30,0xa7,0x54
2175 ,0x74,0x8b,0x7d,0xdc,0xb4,0x3e,0xf7,0x5a
2176 ,0x0d,0xbf,0x3a,0x0d,0x26,0x38,0x1a,0xf4
2177 ,0xeb,0xa4,0xa9,0x8e,0xaa,0x9b,0x4e,0x6a
2180 ubyte[32] k;
2182 static immutable ubyte[32] res = [
2183 0x4a,0x5d,0x9d,0x5b,0xa4,0xce,0x2d,0xe1
2184 ,0x72,0x8e,0x3b,0xf4,0x80,0x35,0x0f,0x25
2185 ,0xe0,0x7e,0x21,0xc9,0x47,0xd1,0x9e,0x33
2186 ,0x76,0xf0,0x9b,0x3c,0x1e,0x16,0x17,0x42
2189 crypto_scalarmult(k,bobsk,alicepk);
2190 assert(k == res);
2192 scalarmult6();
2194 void secretbox () {
2195 writeln("secretbox");
2196 static immutable ubyte[32] firstkey = [
2197 0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4
2198 ,0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7
2199 ,0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2
2200 ,0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89
2203 static immutable ubyte[24] nonce = [
2204 0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73
2205 ,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6
2206 ,0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37
2209 // API requires first 32 bytes to be 0
2210 static immutable ubyte[163] m = [
2211 0, 0, 0, 0, 0, 0, 0, 0
2212 , 0, 0, 0, 0, 0, 0, 0, 0
2213 , 0, 0, 0, 0, 0, 0, 0, 0
2214 , 0, 0, 0, 0, 0, 0, 0, 0
2215 ,0xbe,0x07,0x5f,0xc5,0x3c,0x81,0xf2,0xd5
2216 ,0xcf,0x14,0x13,0x16,0xeb,0xeb,0x0c,0x7b
2217 ,0x52,0x28,0xc5,0x2a,0x4c,0x62,0xcb,0xd4
2218 ,0x4b,0x66,0x84,0x9b,0x64,0x24,0x4f,0xfc
2219 ,0xe5,0xec,0xba,0xaf,0x33,0xbd,0x75,0x1a
2220 ,0x1a,0xc7,0x28,0xd4,0x5e,0x6c,0x61,0x29
2221 ,0x6c,0xdc,0x3c,0x01,0x23,0x35,0x61,0xf4
2222 ,0x1d,0xb6,0x6c,0xce,0x31,0x4a,0xdb,0x31
2223 ,0x0e,0x3b,0xe8,0x25,0x0c,0x46,0xf0,0x6d
2224 ,0xce,0xea,0x3a,0x7f,0xa1,0x34,0x80,0x57
2225 ,0xe2,0xf6,0x55,0x6a,0xd6,0xb1,0x31,0x8a
2226 ,0x02,0x4a,0x83,0x8f,0x21,0xaf,0x1f,0xde
2227 ,0x04,0x89,0x77,0xeb,0x48,0xf5,0x9f,0xfd
2228 ,0x49,0x24,0xca,0x1c,0x60,0x90,0x2e,0x52
2229 ,0xf0,0xa0,0x89,0xbc,0x76,0x89,0x70,0x40
2230 ,0xe0,0x82,0xf9,0x37,0x76,0x38,0x48,0x64
2231 ,0x5e,0x07,0x05
2234 static immutable ubyte[] res = [
2235 0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5
2236 ,0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9
2237 ,0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73
2238 ,0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce
2239 ,0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4
2240 ,0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a
2241 ,0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b
2242 ,0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72
2243 ,0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2
2244 ,0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38
2245 ,0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a
2246 ,0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae
2247 ,0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea
2248 ,0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda
2249 ,0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde
2250 ,0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3
2251 ,0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6
2252 ,0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74
2253 ,0xe3,0x55,0xa5
2256 ubyte[163] c;
2257 crypto_secretbox(c,m,nonce,firstkey);
2258 for (auto i = 16; i < 163; ++i) assert(c[i] == res[i-16]);
2260 secretbox();
2262 void secretbox2 () {
2263 writeln("secretbox2");
2264 static immutable ubyte[32] firstkey = [
2265 0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4
2266 ,0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7
2267 ,0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2
2268 ,0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89
2271 static immutable ubyte[24] nonce = [
2272 0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73
2273 ,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6
2274 ,0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37
2277 // API requires first 16 bytes to be 0
2278 static immutable ubyte[163] c = [
2279 0, 0, 0, 0, 0, 0, 0, 0
2280 , 0, 0, 0, 0, 0, 0, 0, 0
2281 ,0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5
2282 ,0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9
2283 ,0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73
2284 ,0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce
2285 ,0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4
2286 ,0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a
2287 ,0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b
2288 ,0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72
2289 ,0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2
2290 ,0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38
2291 ,0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a
2292 ,0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae
2293 ,0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea
2294 ,0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda
2295 ,0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde
2296 ,0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3
2297 ,0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6
2298 ,0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74
2299 ,0xe3,0x55,0xa5
2302 static immutable ubyte[] res = [
2303 0xbe,0x07,0x5f,0xc5,0x3c,0x81,0xf2,0xd5
2304 ,0xcf,0x14,0x13,0x16,0xeb,0xeb,0x0c,0x7b
2305 ,0x52,0x28,0xc5,0x2a,0x4c,0x62,0xcb,0xd4
2306 ,0x4b,0x66,0x84,0x9b,0x64,0x24,0x4f,0xfc
2307 ,0xe5,0xec,0xba,0xaf,0x33,0xbd,0x75,0x1a
2308 ,0x1a,0xc7,0x28,0xd4,0x5e,0x6c,0x61,0x29
2309 ,0x6c,0xdc,0x3c,0x01,0x23,0x35,0x61,0xf4
2310 ,0x1d,0xb6,0x6c,0xce,0x31,0x4a,0xdb,0x31
2311 ,0x0e,0x3b,0xe8,0x25,0x0c,0x46,0xf0,0x6d
2312 ,0xce,0xea,0x3a,0x7f,0xa1,0x34,0x80,0x57
2313 ,0xe2,0xf6,0x55,0x6a,0xd6,0xb1,0x31,0x8a
2314 ,0x02,0x4a,0x83,0x8f,0x21,0xaf,0x1f,0xde
2315 ,0x04,0x89,0x77,0xeb,0x48,0xf5,0x9f,0xfd
2316 ,0x49,0x24,0xca,0x1c,0x60,0x90,0x2e,0x52
2317 ,0xf0,0xa0,0x89,0xbc,0x76,0x89,0x70,0x40
2318 ,0xe0,0x82,0xf9,0x37,0x76,0x38,0x48,0x64
2319 ,0x5e,0x07,0x05
2322 ubyte[163] m;
2324 assert(crypto_secretbox_open(m,c,nonce,firstkey));
2325 for (auto i = 32; i < 163; ++i) assert(m[i] == res[i-32]);
2327 secretbox2();
2329 void secretbox7 () {
2330 writeln("secretbox7");
2331 static ubyte[crypto_secretbox_KEYBYTES] k;
2332 static ubyte[crypto_secretbox_NONCEBYTES] n;
2333 static ubyte[10000] m, c, m2;
2334 for (auto mlen = 0; mlen < 1000 && mlen+crypto_secretbox_ZEROBYTES < m.length; ++mlen) {
2335 randombytes(k,crypto_secretbox_KEYBYTES);
2336 randombytes(n,crypto_secretbox_NONCEBYTES);
2337 randombytes(m[crypto_secretbox_ZEROBYTES..$],mlen);
2338 crypto_secretbox(c[0..mlen+crypto_secretbox_ZEROBYTES],m,n,k);
2339 assert(crypto_secretbox_open(m2[0..mlen+crypto_secretbox_ZEROBYTES],c,n,k));
2340 for (auto i = 0; i < mlen+crypto_secretbox_ZEROBYTES; ++i) assert(m2[i] == m[i]);
2343 secretbox7();
2345 void secretbox8 () {
2346 writeln("secretbox8");
2347 static ubyte[crypto_secretbox_KEYBYTES] k;
2348 static ubyte[crypto_secretbox_NONCEBYTES] n;
2349 static ubyte[10000] m, c, m2;
2350 for (auto mlen = 0; mlen < 1000 && mlen+crypto_secretbox_ZEROBYTES < m.length; ++mlen) {
2351 randombytes(k,crypto_secretbox_KEYBYTES);
2352 randombytes(n,crypto_secretbox_NONCEBYTES);
2353 randombytes(m[crypto_secretbox_ZEROBYTES..$],mlen);
2354 crypto_secretbox(c[0..mlen+crypto_secretbox_ZEROBYTES],m,n,k);
2355 auto caught = 0;
2356 while (caught < 10) {
2357 c[uniform(0, mlen+crypto_secretbox_ZEROBYTES)] = cast(ubyte)uniform(0, 256);
2358 if (crypto_secretbox_open(m2[0..mlen+crypto_secretbox_ZEROBYTES],c,n,k)) {
2359 for (auto i = 0; i < mlen+crypto_secretbox_ZEROBYTES; ++i) assert(m2[i] == m[i]);
2361 ++caught;
2363 assert(caught == 10);
2366 version(unittest_full) secretbox8(); // it's slow
2368 void stream () {
2369 writeln("stream");
2370 static immutable ubyte[32] firstkey = [
2371 0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4
2372 ,0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7
2373 ,0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2
2374 ,0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89
2377 static immutable ubyte[24] nonce = [
2378 0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73
2379 ,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6
2380 ,0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37
2383 static ubyte[4194304] output;
2385 //ubyte h[32];
2386 //static immutable ubyte[32] res = [0x66,0x2b,0x9d,0x0e,0x34,0x63,0x02,0x91,0x56,0x06,0x9b,0x12,0xf9,0x18,0x69,0x1a,0x98,0xf7,0xdf,0xb2,0xca,0x03,0x93,0xc9,0x6b,0xbf,0xc6,0xb1,0xfb,0xd6,0x30,0xa2];
2388 crypto_stream(output,nonce,firstkey);
2389 //crypto_hash_sha256(h,output,sizeof output);
2390 assert(hashToString(SHA256(output[0..$])) == "662b9d0e3463029156069b12f918691a98f7dfb2ca0393c96bbfc6b1fbd630a2");
2392 stream();
2394 void stream2 () {
2395 writeln("stream2");
2396 static immutable ubyte[32] secondkey = [
2397 0xdc,0x90,0x8d,0xda,0x0b,0x93,0x44,0xa9
2398 ,0x53,0x62,0x9b,0x73,0x38,0x20,0x77,0x88
2399 ,0x80,0xf3,0xce,0xb4,0x21,0xbb,0x61,0xb9
2400 ,0x1c,0xbd,0x4c,0x3e,0x66,0x25,0x6c,0xe4
2403 static immutable ubyte[8] noncesuffix = [
2404 0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37
2407 static ubyte[4194304] output;
2409 crypto_stream_salsa20(output,noncesuffix,secondkey);
2410 assert(hashToString(SHA256(output[0..$])) == "662b9d0e3463029156069b12f918691a98f7dfb2ca0393c96bbfc6b1fbd630a2");
2412 stream2();
2414 void stream3 () {
2415 writeln("stream3");
2416 static immutable ubyte[32] firstkey = [
2417 0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4
2418 ,0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7
2419 ,0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2
2420 ,0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89
2423 static immutable ubyte[24] nonce = [
2424 0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73
2425 ,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6
2426 ,0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37
2429 ubyte[32] rs;
2431 static immutable ubyte[32] res = [
2432 0xee,0xa6,0xa7,0x25,0x1c,0x1e,0x72,0x91
2433 ,0x6d,0x11,0xc2,0xcb,0x21,0x4d,0x3c,0x25
2434 ,0x25,0x39,0x12,0x1d,0x8e,0x23,0x4e,0x65
2435 ,0x2d,0x65,0x1f,0xa4,0xc8,0xcf,0xf8,0x80
2438 crypto_stream/*_xsalsa20*/(rs,nonce,firstkey);
2439 assert(rs == res);
2441 stream3();
2443 void stream4 () {
2444 writeln("stream4");
2445 static immutable ubyte[32] firstkey = [
2446 0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4
2447 ,0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7
2448 ,0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2
2449 ,0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89
2452 static immutable ubyte[24] nonce = [
2453 0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73
2454 ,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6
2455 ,0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37
2458 static immutable ubyte[163] m = [
2459 0, 0, 0, 0, 0, 0, 0, 0
2460 , 0, 0, 0, 0, 0, 0, 0, 0
2461 , 0, 0, 0, 0, 0, 0, 0, 0
2462 , 0, 0, 0, 0, 0, 0, 0, 0
2463 ,0xbe,0x07,0x5f,0xc5,0x3c,0x81,0xf2,0xd5
2464 ,0xcf,0x14,0x13,0x16,0xeb,0xeb,0x0c,0x7b
2465 ,0x52,0x28,0xc5,0x2a,0x4c,0x62,0xcb,0xd4
2466 ,0x4b,0x66,0x84,0x9b,0x64,0x24,0x4f,0xfc
2467 ,0xe5,0xec,0xba,0xaf,0x33,0xbd,0x75,0x1a
2468 ,0x1a,0xc7,0x28,0xd4,0x5e,0x6c,0x61,0x29
2469 ,0x6c,0xdc,0x3c,0x01,0x23,0x35,0x61,0xf4
2470 ,0x1d,0xb6,0x6c,0xce,0x31,0x4a,0xdb,0x31
2471 ,0x0e,0x3b,0xe8,0x25,0x0c,0x46,0xf0,0x6d
2472 ,0xce,0xea,0x3a,0x7f,0xa1,0x34,0x80,0x57
2473 ,0xe2,0xf6,0x55,0x6a,0xd6,0xb1,0x31,0x8a
2474 ,0x02,0x4a,0x83,0x8f,0x21,0xaf,0x1f,0xde
2475 ,0x04,0x89,0x77,0xeb,0x48,0xf5,0x9f,0xfd
2476 ,0x49,0x24,0xca,0x1c,0x60,0x90,0x2e,0x52
2477 ,0xf0,0xa0,0x89,0xbc,0x76,0x89,0x70,0x40
2478 ,0xe0,0x82,0xf9,0x37,0x76,0x38,0x48,0x64
2479 ,0x5e,0x07,0x05
2482 ubyte[163] c;
2484 static immutable ubyte[] res = [
2485 0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73
2486 ,0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce
2487 ,0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4
2488 ,0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a
2489 ,0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b
2490 ,0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72
2491 ,0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2
2492 ,0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38
2493 ,0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a
2494 ,0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae
2495 ,0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea
2496 ,0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda
2497 ,0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde
2498 ,0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3
2499 ,0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6
2500 ,0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74
2501 ,0xe3,0x55,0xa5
2504 /*crypto_stream_xsalsa20_xor*/crypto_stream_xor(c,m,nonce,firstkey);
2505 for (auto i = 32; i < 163; ++i) assert(c[i] == res[i-32]);
2507 stream4();
2509 version(unittest) {
2510 version(unittest_main) {
2511 void main () {}