ut script; ut defines
[tweetnacl.d.git] / tweetNaCl.d
blobf4978410f39a71e38673b3336bbf56d524b2eeb3
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 version(tweetnacl_unittest)
1302 unittest {
1303 import std.exception;
1304 import std.random;
1305 import std.range;
1306 import std.stdio;
1309 private extern(C) int open(const(char)* filename, int flags, ...);
1310 void randombytes (ubyte[] dest, size_t len) {
1311 import core.sys.posix.unistd;
1312 static int fd = -1;
1313 if (fd == -1) {
1314 for (;;) {
1315 fd = open("/dev/urandom", /*O_RDONLY*/0);
1316 if (fd != -1) break;
1317 sleep(1);
1320 size_t pos = 0;
1321 while (len > 0) {
1322 ssize_t i = read(fd, cast(void*)(&dest[pos]), (len < 1048576 ? len : 1048576));
1323 if (i < 1) {
1324 sleep(1);
1325 continue;
1327 pos += i;
1328 len -= i;
1333 static void rnd (ubyte[] dest, size_t len) {
1334 for (size_t f = 0; f < len; ++f) dest[f] = cast(ubyte)uniform(0, 256);
1336 randombytes = &rnd;
1339 randombytes = (ubyte[] dest, size_t len) {
1340 for (size_t f = 0; f < len; ++f) dest[f] = cast(ubyte)uniform(0, 256);
1343 void dumpArray(T) (T[] arr) {
1344 writefln("============================= (%s)", arr.length);
1345 for (auto f = 0; f < arr.length; ++f) {
1346 if (f && f%16 == 0) writeln();
1347 static if (T.sizeof == 1) writef(" 0x%02x", arr[f]);
1348 else static if (T.sizeof == 2) writef(" 0x%04x", arr[f]);
1349 else static if (T.sizeof == 4) writef(" 0x%08x", arr[f]);
1350 else writef(" 0x%08x", arr[f]);
1352 writeln();
1353 writeln("-----------------------------");
1356 string hashToString (const(ubyte)[] hash) {
1357 char[] s;
1358 s.length = hash.length*2;
1359 char toHex(int a) { return cast(char)(a < 10 ? a+'0' : a+'a'-10); }
1360 for (int a = 0; a < hash.length; ++a) {
1361 s[a*2] = toHex(hash[a]>>4);
1362 s[a*2+1] = toHex(hash[a]&0x0f);
1364 return assumeUnique(s);
1367 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];
1368 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];
1369 static immutable ubyte[5] m = [0x61,0x68,0x6f,0x6a,0x0a];
1370 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];
1371 ubyte[] smres, t;
1373 writeln("crypto_sign");
1374 smres = crypto_sign(m, sk);
1375 assert(smres.length == sm.length);
1376 assert(smres == sm);
1378 writeln("crypto_sign_open");
1379 t = crypto_sign_open(smres, pk);
1380 assert(t !is null);
1381 assert(t.length == m.length);
1382 assert(t == m);
1385 // based on the code by Adam D. Ruppe
1386 // 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
1387 template SHARange(T) if (isInputRange!(T)) {
1388 struct SHARange {
1389 T r;
1391 bool empty () { return state == 5; }
1393 void popFront () {
1394 if (state == 0) {
1395 r.popFront;
1396 ++length; // FIXME
1397 if (r.empty) {
1398 state = 1;
1399 position = 2;
1400 current = 0x80;
1402 } else {
1403 bool hackforward = false;
1404 if (state == 1) {
1405 current = 0x0;
1406 state = 2;
1407 if (((position+length+8)*8)%512 == 8) {
1408 --position;
1409 hackforward = true;
1411 goto proceed;
1412 //++position;
1413 } else if (state == 2) {
1414 proceed:
1415 if (!(((position+length+8)*8)%512)) {
1416 state = 3;
1417 position = 7;
1418 length *= 8;
1419 if (hackforward) goto proceedmoar;
1420 } else {
1421 ++position;
1423 } else if (state == 3) {
1424 proceedmoar:
1425 current = (length>>(position*8))&0xff;
1426 if (position == 0) state = 4; else --position;
1427 } else if (state == 4) {
1428 current = 0xff;
1429 state = 5;
1434 ubyte front () {
1435 if (state == 0) return cast(ubyte)r.front;
1436 assert(state != 5);
1437 //writefln("%x", current);
1438 return current;
1441 ubyte current;
1442 uint position;
1443 ulong length;
1444 int state = 0; // reading range, reading appended bit, reading padding, reading length, done
1449 immutable(ubyte)[] SHA256(T) (T data) if (isInputRange!(T)) {
1450 uint[8] h = [0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19];
1451 static immutable(uint[64]) k = [
1452 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
1453 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
1454 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
1455 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
1456 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
1457 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
1458 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
1459 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
1463 SHARange!(T) range;
1464 static if (is(data == SHARange)) range = data; else range.r = data;
1467 while(!range.empty) {
1468 uint[64] words;
1470 for(int a = 0; a < 16; ++a) {
1471 for(int b = 3; b >= 0; --b) {
1472 words[a] |= cast(uint)(range.front())<<(b*8);
1473 range.popFront;
1477 uint ror (uint n, int cnt) {
1478 return cast(uint)(n>>cnt)|cast(uint)(n<<(32-(cnt)));
1481 uint xrot00 (uint reax, int r0, int r1, int r2) {
1482 uint rebx = reax, recx = reax;
1483 reax = ror(reax, r0);
1484 rebx = ror(rebx, r1);
1485 recx >>= r2;
1486 reax ^= rebx;
1487 reax ^= recx;
1488 return reax;
1491 for(int a = 16; a < 64; ++a) {
1492 uint t1 = xrot00(words[a-15], 7, 18, 3);
1493 uint t2 = xrot00(words[a-2], 17, 19, 10);
1494 words[a] = words[a-16]+t1+words[a-7]+t2;
1497 uint A = h[0];
1498 uint B = h[1];
1499 uint C = h[2];
1500 uint D = h[3];
1501 uint E = h[4];
1502 uint F = h[5];
1503 uint G = h[6];
1504 uint H = h[7];
1506 uint xrot01 (uint reax, int r0, int r1, int r2) {
1507 uint rebx = reax, recx = reax;
1508 reax = ror(reax, r0);
1509 rebx = ror(rebx, r1);
1510 recx = ror(recx, r2);
1511 reax ^= rebx;
1512 reax ^= recx;
1513 return reax;
1516 for(int i = 0; i < 64; ++i) {
1517 uint s0 = xrot01(A, 2, 13, 22);
1518 uint maj = (A&B)^(A&C)^(B&C);
1519 uint t2 = s0+maj;
1520 uint s1 = xrot01(E, 6, 11, 25);
1521 uint ch = (E&F)^((~E)&G);
1522 uint t1 = H+s1+ch+k[i]+words[i];
1524 H = G;
1525 G = F;
1526 F = E;
1527 E = D+t1;
1528 D = C;
1529 C = B;
1530 B = A;
1531 A = t1+t2;
1534 h[0] += A;
1535 h[1] += B;
1536 h[2] += C;
1537 h[3] += D;
1538 h[4] += E;
1539 h[5] += F;
1540 h[6] += G;
1541 h[7] += H;
1544 ubyte[] hash;
1545 for(int j = 0; j < 8; ++j)
1546 for(int i = 3; i >= 0; --i) {
1547 hash ~= cast(ubyte)(h[j]>>(i*8))&0xff;
1550 return hash.idup;
1554 void box () {
1555 writeln("box");
1557 static immutable ubyte[32] alicesk = [
1558 0x77,0x07,0x6d,0x0a,0x73,0x18,0xa5,0x7d
1559 ,0x3c,0x16,0xc1,0x72,0x51,0xb2,0x66,0x45
1560 ,0xdf,0x4c,0x2f,0x87,0xeb,0xc0,0x99,0x2a
1561 ,0xb1,0x77,0xfb,0xa5,0x1d,0xb9,0x2c,0x2a
1564 static immutable ubyte[32] bobpk = [
1565 0xde,0x9e,0xdb,0x7d,0x7b,0x7d,0xc1,0xb4
1566 ,0xd3,0x5b,0x61,0xc2,0xec,0xe4,0x35,0x37
1567 ,0x3f,0x83,0x43,0xc8,0x5b,0x78,0x67,0x4d
1568 ,0xad,0xfc,0x7e,0x14,0x6f,0x88,0x2b,0x4f
1571 static immutable ubyte[24] nonce = [
1572 0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73
1573 ,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6
1574 ,0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37
1577 // API requires first 32 bytes to be 0
1578 static immutable ubyte[163] m = [
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 , 0, 0, 0, 0, 0, 0, 0, 0
1583 ,0xbe,0x07,0x5f,0xc5,0x3c,0x81,0xf2,0xd5
1584 ,0xcf,0x14,0x13,0x16,0xeb,0xeb,0x0c,0x7b
1585 ,0x52,0x28,0xc5,0x2a,0x4c,0x62,0xcb,0xd4
1586 ,0x4b,0x66,0x84,0x9b,0x64,0x24,0x4f,0xfc
1587 ,0xe5,0xec,0xba,0xaf,0x33,0xbd,0x75,0x1a
1588 ,0x1a,0xc7,0x28,0xd4,0x5e,0x6c,0x61,0x29
1589 ,0x6c,0xdc,0x3c,0x01,0x23,0x35,0x61,0xf4
1590 ,0x1d,0xb6,0x6c,0xce,0x31,0x4a,0xdb,0x31
1591 ,0x0e,0x3b,0xe8,0x25,0x0c,0x46,0xf0,0x6d
1592 ,0xce,0xea,0x3a,0x7f,0xa1,0x34,0x80,0x57
1593 ,0xe2,0xf6,0x55,0x6a,0xd6,0xb1,0x31,0x8a
1594 ,0x02,0x4a,0x83,0x8f,0x21,0xaf,0x1f,0xde
1595 ,0x04,0x89,0x77,0xeb,0x48,0xf5,0x9f,0xfd
1596 ,0x49,0x24,0xca,0x1c,0x60,0x90,0x2e,0x52
1597 ,0xf0,0xa0,0x89,0xbc,0x76,0x89,0x70,0x40
1598 ,0xe0,0x82,0xf9,0x37,0x76,0x38,0x48,0x64
1599 ,0x5e,0x07,0x05
1602 ubyte[163] c;
1605 static immutable ubyte[] res = [
1606 0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5
1607 ,0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9
1608 ,0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73
1609 ,0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce
1610 ,0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4
1611 ,0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a
1612 ,0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b
1613 ,0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72
1614 ,0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2
1615 ,0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38
1616 ,0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a
1617 ,0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae
1618 ,0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea
1619 ,0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda
1620 ,0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde
1621 ,0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3
1622 ,0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6
1623 ,0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74
1624 ,0xe3,0x55,0xa5];
1625 /*crypto_box_curve25519xsalsa20poly1305*/crypto_box(c,m,nonce,bobpk,alicesk);
1626 for (auto f = 16; f < 163; ++f) assert(c[f] == res[f-16]);
1628 box();
1630 void box2 () {
1631 writeln("box2");
1632 static immutable ubyte[32] bobsk = [
1633 0x5d,0xab,0x08,0x7e,0x62,0x4a,0x8a,0x4b
1634 ,0x79,0xe1,0x7f,0x8b,0x83,0x80,0x0e,0xe6
1635 ,0x6f,0x3b,0xb1,0x29,0x26,0x18,0xb6,0xfd
1636 ,0x1c,0x2f,0x8b,0x27,0xff,0x88,0xe0,0xeb
1639 static immutable ubyte[32] alicepk = [
1640 0x85,0x20,0xf0,0x09,0x89,0x30,0xa7,0x54
1641 ,0x74,0x8b,0x7d,0xdc,0xb4,0x3e,0xf7,0x5a
1642 ,0x0d,0xbf,0x3a,0x0d,0x26,0x38,0x1a,0xf4
1643 ,0xeb,0xa4,0xa9,0x8e,0xaa,0x9b,0x4e,0x6a
1646 static immutable ubyte[24] nonce = [
1647 0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73
1648 ,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6
1649 ,0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37
1652 // API requires first 16 bytes to be 0
1653 static immutable ubyte[163] c = [
1654 0, 0, 0, 0, 0, 0, 0, 0
1655 , 0, 0, 0, 0, 0, 0, 0, 0
1656 ,0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5
1657 ,0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9
1658 ,0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73
1659 ,0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce
1660 ,0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4
1661 ,0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a
1662 ,0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b
1663 ,0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72
1664 ,0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2
1665 ,0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38
1666 ,0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a
1667 ,0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae
1668 ,0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea
1669 ,0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda
1670 ,0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde
1671 ,0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3
1672 ,0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6
1673 ,0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74
1674 ,0xe3,0x55,0xa5
1677 ubyte[163] m;
1679 static immutable ubyte[] res = [
1680 0xbe,0x07,0x5f,0xc5,0x3c,0x81,0xf2,0xd5
1681 ,0xcf,0x14,0x13,0x16,0xeb,0xeb,0x0c,0x7b
1682 ,0x52,0x28,0xc5,0x2a,0x4c,0x62,0xcb,0xd4
1683 ,0x4b,0x66,0x84,0x9b,0x64,0x24,0x4f,0xfc
1684 ,0xe5,0xec,0xba,0xaf,0x33,0xbd,0x75,0x1a
1685 ,0x1a,0xc7,0x28,0xd4,0x5e,0x6c,0x61,0x29
1686 ,0x6c,0xdc,0x3c,0x01,0x23,0x35,0x61,0xf4
1687 ,0x1d,0xb6,0x6c,0xce,0x31,0x4a,0xdb,0x31
1688 ,0x0e,0x3b,0xe8,0x25,0x0c,0x46,0xf0,0x6d
1689 ,0xce,0xea,0x3a,0x7f,0xa1,0x34,0x80,0x57
1690 ,0xe2,0xf6,0x55,0x6a,0xd6,0xb1,0x31,0x8a
1691 ,0x02,0x4a,0x83,0x8f,0x21,0xaf,0x1f,0xde
1692 ,0x04,0x89,0x77,0xeb,0x48,0xf5,0x9f,0xfd
1693 ,0x49,0x24,0xca,0x1c,0x60,0x90,0x2e,0x52
1694 ,0xf0,0xa0,0x89,0xbc,0x76,0x89,0x70,0x40
1695 ,0xe0,0x82,0xf9,0x37,0x76,0x38,0x48,0x64
1696 ,0x5e,0x07,0x05
1699 assert(/*crypto_box_curve25519xsalsa20poly1305_open*/crypto_box_open(m,c,nonce,alicepk,bobsk));
1700 for (auto f = 32; f < 163; ++f) assert(m[f] == res[f-32]);
1702 box2();
1704 void box7 () {
1705 writeln("box7");
1706 ubyte[crypto_box_SECRETKEYBYTES] alicesk;
1707 ubyte[crypto_box_PUBLICKEYBYTES] alicepk;
1708 ubyte[crypto_box_SECRETKEYBYTES] bobsk;
1709 ubyte[crypto_box_PUBLICKEYBYTES] bobpk;
1710 ubyte[crypto_box_NONCEBYTES] n;
1711 ubyte[10000] m, c, m2;
1712 for (auto mlen = 0; mlen < 1000 && mlen+crypto_box_ZEROBYTES < m.length; ++mlen) {
1713 crypto_box_keypair(alicepk,alicesk);
1714 crypto_box_keypair(bobpk,bobsk);
1715 randombytes(n,crypto_box_NONCEBYTES);
1716 randombytes(m[crypto_box_ZEROBYTES..$],mlen);
1717 crypto_box(c[0..mlen+crypto_box_ZEROBYTES],m,n,bobpk,alicesk);
1718 assert(crypto_box_open(m2[0..mlen+crypto_box_ZEROBYTES],c,n,alicepk,bobsk));
1719 for (auto i = 0; i < mlen+crypto_box_ZEROBYTES; ++i) assert(m2[i] == m[i]);
1722 version(unittest_full) box7(); // it's slow
1724 void box8 () {
1725 writeln("box8");
1726 ubyte[crypto_box_SECRETKEYBYTES] alicesk;
1727 ubyte[crypto_box_PUBLICKEYBYTES] alicepk;
1728 ubyte[crypto_box_SECRETKEYBYTES] bobsk;
1729 ubyte[crypto_box_PUBLICKEYBYTES] bobpk;
1730 ubyte[crypto_box_NONCEBYTES] n;
1731 ubyte[10000] m, c, m2;
1732 for (auto mlen = 0; mlen < 1000 && mlen+crypto_box_ZEROBYTES < m.length; ++mlen) {
1733 crypto_box_keypair(alicepk,alicesk);
1734 crypto_box_keypair(bobpk,bobsk);
1735 randombytes(n,crypto_box_NONCEBYTES);
1736 randombytes(m[crypto_box_ZEROBYTES..$],mlen);
1737 crypto_box(c[0..mlen+crypto_box_ZEROBYTES],m,n,bobpk,alicesk);
1738 int caught = 0;
1739 while (caught < 10) {
1740 c[uniform(0, mlen+crypto_box_ZEROBYTES)] = cast(ubyte)uniform(0, 256);
1741 if (crypto_box_open(m2[0..mlen+crypto_box_ZEROBYTES],c,n,alicepk,bobsk)) {
1742 for (auto i = 0; i < mlen+crypto_box_ZEROBYTES; ++i) assert(m2[i] == m[i]);
1743 } else {
1744 ++caught;
1747 assert(caught == 10);
1750 version(unittest_full) box8(); // it's slow
1752 void core1 () {
1753 writeln("core1");
1754 static immutable ubyte[32] shared_ = [
1755 0x4a,0x5d,0x9d,0x5b,0xa4,0xce,0x2d,0xe1
1756 ,0x72,0x8e,0x3b,0xf4,0x80,0x35,0x0f,0x25
1757 ,0xe0,0x7e,0x21,0xc9,0x47,0xd1,0x9e,0x33
1758 ,0x76,0xf0,0x9b,0x3c,0x1e,0x16,0x17,0x42
1761 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];
1763 static immutable ubyte[16] c = [
1764 0x65,0x78,0x70,0x61,0x6e,0x64,0x20,0x33
1765 ,0x32,0x2d,0x62,0x79,0x74,0x65,0x20,0x6b
1768 ubyte[32] firstkey;
1770 static immutable ubyte[32] res = [
1771 0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4
1772 ,0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7
1773 ,0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2
1774 ,0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89
1777 crypto_core_hsalsa20(firstkey,zero,shared_,c);
1778 assert(firstkey == res);
1780 core1();
1782 void core2 () {
1783 writeln("core2");
1784 static immutable ubyte[32]firstkey = [
1785 0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4
1786 ,0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7
1787 ,0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2
1788 ,0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89
1791 static immutable ubyte[16]nonceprefix = [
1792 0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73
1793 ,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6
1796 static immutable ubyte[16] c = [
1797 0x65,0x78,0x70,0x61,0x6e,0x64,0x20,0x33
1798 ,0x32,0x2d,0x62,0x79,0x74,0x65,0x20,0x6b
1801 ubyte[32] secondkey;
1803 static immutable ubyte[32] res = [
1804 0xdc,0x90,0x8d,0xda,0x0b,0x93,0x44,0xa9
1805 ,0x53,0x62,0x9b,0x73,0x38,0x20,0x77,0x88
1806 ,0x80,0xf3,0xce,0xb4,0x21,0xbb,0x61,0xb9
1807 ,0x1c,0xbd,0x4c,0x3e,0x66,0x25,0x6c,0xe4
1810 crypto_core_hsalsa20(secondkey,nonceprefix,firstkey,c);
1811 assert(secondkey == res);
1813 core2();
1815 void core3 () {
1816 writeln("core3");
1817 static immutable ubyte[32] secondkey = [
1818 0xdc,0x90,0x8d,0xda,0x0b,0x93,0x44,0xa9
1819 ,0x53,0x62,0x9b,0x73,0x38,0x20,0x77,0x88
1820 ,0x80,0xf3,0xce,0xb4,0x21,0xbb,0x61,0xb9
1821 ,0x1c,0xbd,0x4c,0x3e,0x66,0x25,0x6c,0xe4
1824 static immutable ubyte[8] noncesuffix = [
1825 0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37
1828 static immutable ubyte[16] c = [
1829 0x65,0x78,0x70,0x61,0x6e,0x64,0x20,0x33
1830 ,0x32,0x2d,0x62,0x79,0x74,0x65,0x20,0x6b
1833 static ubyte[16] input = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] ;
1835 static ubyte[64*256*256] output;
1837 static ubyte[64] h;
1839 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];
1841 int pos = 0;
1842 for (auto i = 0; i < 8; ++i) input[i] = noncesuffix[i];
1843 do {
1844 do {
1845 crypto_core_salsa20(output[pos..$],input,secondkey,c);
1846 pos += 64;
1847 } while (++input[8]);
1848 } while (++input[9]);
1849 crypto_hash(h,output);
1850 assert(h == res);
1852 version(unittest_full) core3(); // it's slow
1854 void core4 () {
1855 writeln("core4");
1856 static immutable ubyte[32] k = [
1857 1, 2, 3, 4, 5, 6, 7, 8
1858 , 9, 10, 11, 12, 13, 14, 15, 16
1859 ,201,202,203,204,205,206,207,208
1860 ,209,210,211,212,213,214,215,216
1863 static immutable ubyte[16] input = [
1864 101,102,103,104,105,106,107,108
1865 ,109,110,111,112,113,114,115,116
1868 static immutable ubyte[16] c = [
1869 101,120,112, 97,110,100, 32, 51
1870 , 50, 45, 98,121,116,101, 32,107
1873 ubyte[64] output;
1875 static immutable ubyte[64] res = [
1876 69, 37, 68, 39, 41, 15,107,193
1877 ,255,139,122, 6,170,233,217, 98
1878 , 89,144,182,106, 21, 51,200, 65
1879 ,239, 49,222, 34,215,114, 40,126
1880 ,104,197, 7,225,197,153, 31, 2
1881 ,102, 78, 76,176, 84,245,246,184
1882 ,177,160,133,130, 6, 72,149,119
1883 ,192,195,132,236,234,103,246, 74
1886 crypto_core_salsa20(output,input,k,c);
1887 assert(output == res);
1889 core4();
1891 void core5 () {
1892 writeln("core5");
1893 static immutable ubyte[32] k = [
1894 0xee,0x30,0x4f,0xca,0x27,0x00,0x8d,0x8c
1895 ,0x12,0x6f,0x90,0x02,0x79,0x01,0xd8,0x0f
1896 ,0x7f,0x1d,0x8b,0x8d,0xc9,0x36,0xcf,0x3b
1897 ,0x9f,0x81,0x96,0x92,0x82,0x7e,0x57,0x77
1900 static immutable ubyte[16] input = [
1901 0x81,0x91,0x8e,0xf2,0xa5,0xe0,0xda,0x9b
1902 ,0x3e,0x90,0x60,0x52,0x1e,0x4b,0xb3,0x52
1905 static immutable ubyte[16] c = [
1906 101,120,112, 97,110,100, 32, 51
1907 , 50, 45, 98,121,116,101, 32,107
1910 ubyte[32] output;
1912 static immutable ubyte[32] res = [
1913 0xbc,0x1b,0x30,0xfc,0x07,0x2c,0xc1,0x40
1914 ,0x75,0xe4,0xba,0xa7,0x31,0xb5,0xa8,0x45
1915 ,0xea,0x9b,0x11,0xe9,0xa5,0x19,0x1f,0x94
1916 ,0xe1,0x8c,0xba,0x8f,0xd8,0x21,0xa7,0xcd
1919 crypto_core_hsalsa20(output,input,k,c);
1920 assert(output == res);
1922 core5();
1924 void core6 () {
1925 writeln("core6");
1926 static immutable ubyte[32] k = [
1927 0xee,0x30,0x4f,0xca,0x27,0x00,0x8d,0x8c
1928 ,0x12,0x6f,0x90,0x02,0x79,0x01,0xd8,0x0f
1929 ,0x7f,0x1d,0x8b,0x8d,0xc9,0x36,0xcf,0x3b
1930 ,0x9f,0x81,0x96,0x92,0x82,0x7e,0x57,0x77
1933 static immutable ubyte[16] input = [
1934 0x81,0x91,0x8e,0xf2,0xa5,0xe0,0xda,0x9b
1935 ,0x3e,0x90,0x60,0x52,0x1e,0x4b,0xb3,0x52
1938 static immutable ubyte[16] c = [
1939 101,120,112, 97,110,100, 32, 51
1940 , 50, 45, 98,121,116,101, 32,107
1943 ubyte[64] output;
1945 static immutable ubyte[32] res = [
1946 0xbc,0x1b,0x30,0xfc,0x07,0x2c,0xc1,0x40
1947 ,0x75,0xe4,0xba,0xa7,0x31,0xb5,0xa8,0x45
1948 ,0xea,0x9b,0x11,0xe9,0xa5,0x19,0x1f,0x94
1949 ,0xe1,0x8c,0xba,0x8f,0xd8,0x21,0xa7,0xcd
1952 ubyte[32] pp;
1953 uint pppos = 0;
1955 void print(const(ubyte)[] x, const(ubyte)[] y)
1957 uint borrow = 0;
1958 for (auto i = 0; i < 4; ++i) {
1959 uint xi = x[i];
1960 uint yi = y[i];
1961 //printf(",0x%02x",255&(xi-yi-borrow));
1962 pp[pppos++] = cast(ubyte)(255&(xi-yi-borrow));
1963 borrow = (xi < yi+borrow);
1967 crypto_core_salsa20(output,input,k,c);
1968 print(output,c);
1969 print(output[20..$],c[4..$]);
1970 print(output[40..$],c[8..$]);
1971 print(output[60..$],c[12..$]);
1972 print(output[24..$],input);
1973 print(output[28..$],input[4..$]);
1974 print(output[32..$],input[8..$]);
1975 print(output[36..$],input[12..$]);
1976 assert(pp == res);
1978 core6();
1980 void hash () {
1981 writeln("hash");
1982 static immutable ubyte[8] x = ['t','e','s','t','i','n','g','\n'];
1983 static ubyte[crypto_hash_BYTES] h;
1984 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];
1985 crypto_hash(h,x);
1986 //for (auto f = 0; f < crypto_hash_BYTES; ++f) assert(h[f] == res[f]);
1987 assert(h == res);
1989 hash();
1991 void onetimeauth () {
1992 writeln("onetimeauth");
1993 static immutable ubyte[32] rs = [
1994 0xee,0xa6,0xa7,0x25,0x1c,0x1e,0x72,0x91
1995 ,0x6d,0x11,0xc2,0xcb,0x21,0x4d,0x3c,0x25
1996 ,0x25,0x39,0x12,0x1d,0x8e,0x23,0x4e,0x65
1997 ,0x2d,0x65,0x1f,0xa4,0xc8,0xcf,0xf8,0x80
2000 static immutable ubyte[131] c = [
2001 0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73
2002 ,0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce
2003 ,0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4
2004 ,0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a
2005 ,0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b
2006 ,0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72
2007 ,0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2
2008 ,0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38
2009 ,0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a
2010 ,0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae
2011 ,0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea
2012 ,0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda
2013 ,0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde
2014 ,0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3
2015 ,0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6
2016 ,0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74
2017 ,0xe3,0x55,0xa5
2020 ubyte[16] a;
2022 static immutable ubyte[16] res = [0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5,0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9];
2024 /*crypto_onetimeauth_poly1305*/crypto_onetimeauth(a,c,rs);
2025 assert(a == res);
2027 onetimeauth();
2029 void onetimeauth2 () {
2030 writeln("onetimeauth2");
2031 static immutable ubyte[32] rs = [
2032 0xee,0xa6,0xa7,0x25,0x1c,0x1e,0x72,0x91
2033 ,0x6d,0x11,0xc2,0xcb,0x21,0x4d,0x3c,0x25
2034 ,0x25,0x39,0x12,0x1d,0x8e,0x23,0x4e,0x65
2035 ,0x2d,0x65,0x1f,0xa4,0xc8,0xcf,0xf8,0x80
2038 static immutable ubyte[131] c = [
2039 0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73
2040 ,0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce
2041 ,0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4
2042 ,0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a
2043 ,0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b
2044 ,0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72
2045 ,0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2
2046 ,0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38
2047 ,0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a
2048 ,0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae
2049 ,0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea
2050 ,0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda
2051 ,0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde
2052 ,0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3
2053 ,0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6
2054 ,0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74
2055 ,0xe3,0x55,0xa5
2058 static immutable ubyte[16] a = [
2059 0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5
2060 ,0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9
2063 assert(/*crypto_onetimeauth_poly1305_verify*/crypto_onetimeauth_verify(a,c,rs));
2065 onetimeauth2();
2067 void onetimeauth7 () {
2068 writeln("onetimeauth7");
2069 static ubyte[32] key;
2070 static ubyte[10000] c;
2071 static ubyte[16] a;
2073 for (auto clen = 0; clen < 10000; ++clen) {
2074 //if (clen%512 == 0) { writef("\r%s", clen); stdout.flush(); }
2075 randombytes(key, key.length);
2076 randombytes(c, clen);
2077 crypto_onetimeauth(a,c[0..clen],key);
2078 assert(crypto_onetimeauth_verify(a,c[0..clen],key));
2079 if (clen > 0) {
2080 c[uniform(0, clen)] += 1+(uniform(0, 255));
2081 assert(!crypto_onetimeauth_verify(a,c[0..clen],key));
2082 a[uniform(0, a.length)] += 1+(uniform(0, 255));
2083 assert(!crypto_onetimeauth_verify(a,c[0..clen],key));
2087 version(unittest_full) onetimeauth7(); // it's slow
2089 void scalarmult () {
2090 writeln("scalarmult");
2091 static immutable ubyte[32] alicesk = [
2092 0x77,0x07,0x6d,0x0a,0x73,0x18,0xa5,0x7d
2093 ,0x3c,0x16,0xc1,0x72,0x51,0xb2,0x66,0x45
2094 ,0xdf,0x4c,0x2f,0x87,0xeb,0xc0,0x99,0x2a
2095 ,0xb1,0x77,0xfb,0xa5,0x1d,0xb9,0x2c,0x2a
2098 ubyte[32] alicepk;
2100 static immutable ubyte[32] res = [
2101 0x85,0x20,0xf0,0x09,0x89,0x30,0xa7,0x54
2102 ,0x74,0x8b,0x7d,0xdc,0xb4,0x3e,0xf7,0x5a
2103 ,0x0d,0xbf,0x3a,0x0d,0x26,0x38,0x1a,0xf4
2104 ,0xeb,0xa4,0xa9,0x8e,0xaa,0x9b,0x4e,0x6a
2107 /*crypto_scalarmult_curve25519_base*/crypto_scalarmult_base(alicepk,alicesk);
2108 assert(alicepk == res);
2110 scalarmult();
2112 void scalarmult2 () {
2113 writeln("scalarmult2");
2114 static immutable ubyte[32] bobsk = [
2115 0x5d,0xab,0x08,0x7e,0x62,0x4a,0x8a,0x4b
2116 ,0x79,0xe1,0x7f,0x8b,0x83,0x80,0x0e,0xe6
2117 ,0x6f,0x3b,0xb1,0x29,0x26,0x18,0xb6,0xfd
2118 ,0x1c,0x2f,0x8b,0x27,0xff,0x88,0xe0,0xeb
2121 ubyte[32] bobpk;
2123 static immutable ubyte[32] res = [
2124 0xde,0x9e,0xdb,0x7d,0x7b,0x7d,0xc1,0xb4
2125 ,0xd3,0x5b,0x61,0xc2,0xec,0xe4,0x35,0x37
2126 ,0x3f,0x83,0x43,0xc8,0x5b,0x78,0x67,0x4d
2127 ,0xad,0xfc,0x7e,0x14,0x6f,0x88,0x2b,0x4f
2130 /*crypto_scalarmult_curve25519_base*/crypto_scalarmult_base(bobpk,bobsk);
2131 assert(bobpk == res);
2133 scalarmult2();
2135 void scalarmult5 () {
2136 writeln("scalarmult5");
2137 static immutable ubyte[32] alicesk = [
2138 0x77,0x07,0x6d,0x0a,0x73,0x18,0xa5,0x7d
2139 ,0x3c,0x16,0xc1,0x72,0x51,0xb2,0x66,0x45
2140 ,0xdf,0x4c,0x2f,0x87,0xeb,0xc0,0x99,0x2a
2141 ,0xb1,0x77,0xfb,0xa5,0x1d,0xb9,0x2c,0x2a
2144 static immutable ubyte[32] bobpk = [
2145 0xde,0x9e,0xdb,0x7d,0x7b,0x7d,0xc1,0xb4
2146 ,0xd3,0x5b,0x61,0xc2,0xec,0xe4,0x35,0x37
2147 ,0x3f,0x83,0x43,0xc8,0x5b,0x78,0x67,0x4d
2148 ,0xad,0xfc,0x7e,0x14,0x6f,0x88,0x2b,0x4f
2151 ubyte[32] k;
2153 static immutable ubyte[32] res = [
2154 0x4a,0x5d,0x9d,0x5b,0xa4,0xce,0x2d,0xe1
2155 ,0x72,0x8e,0x3b,0xf4,0x80,0x35,0x0f,0x25
2156 ,0xe0,0x7e,0x21,0xc9,0x47,0xd1,0x9e,0x33
2157 ,0x76,0xf0,0x9b,0x3c,0x1e,0x16,0x17,0x42
2160 crypto_scalarmult(k,alicesk,bobpk);
2161 assert(k == res);
2163 scalarmult5();
2165 void scalarmult6 () {
2166 writeln("scalarmult6");
2167 static immutable ubyte[32] bobsk = [
2168 0x5d,0xab,0x08,0x7e,0x62,0x4a,0x8a,0x4b
2169 ,0x79,0xe1,0x7f,0x8b,0x83,0x80,0x0e,0xe6
2170 ,0x6f,0x3b,0xb1,0x29,0x26,0x18,0xb6,0xfd
2171 ,0x1c,0x2f,0x8b,0x27,0xff,0x88,0xe0,0xeb
2174 static immutable ubyte[32] alicepk = [
2175 0x85,0x20,0xf0,0x09,0x89,0x30,0xa7,0x54
2176 ,0x74,0x8b,0x7d,0xdc,0xb4,0x3e,0xf7,0x5a
2177 ,0x0d,0xbf,0x3a,0x0d,0x26,0x38,0x1a,0xf4
2178 ,0xeb,0xa4,0xa9,0x8e,0xaa,0x9b,0x4e,0x6a
2181 ubyte[32] k;
2183 static immutable ubyte[32] res = [
2184 0x4a,0x5d,0x9d,0x5b,0xa4,0xce,0x2d,0xe1
2185 ,0x72,0x8e,0x3b,0xf4,0x80,0x35,0x0f,0x25
2186 ,0xe0,0x7e,0x21,0xc9,0x47,0xd1,0x9e,0x33
2187 ,0x76,0xf0,0x9b,0x3c,0x1e,0x16,0x17,0x42
2190 crypto_scalarmult(k,bobsk,alicepk);
2191 assert(k == res);
2193 scalarmult6();
2195 void secretbox () {
2196 writeln("secretbox");
2197 static immutable ubyte[32] firstkey = [
2198 0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4
2199 ,0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7
2200 ,0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2
2201 ,0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89
2204 static immutable ubyte[24] nonce = [
2205 0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73
2206 ,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6
2207 ,0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37
2210 // API requires first 32 bytes to be 0
2211 static immutable ubyte[163] m = [
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 , 0, 0, 0, 0, 0, 0, 0, 0
2216 ,0xbe,0x07,0x5f,0xc5,0x3c,0x81,0xf2,0xd5
2217 ,0xcf,0x14,0x13,0x16,0xeb,0xeb,0x0c,0x7b
2218 ,0x52,0x28,0xc5,0x2a,0x4c,0x62,0xcb,0xd4
2219 ,0x4b,0x66,0x84,0x9b,0x64,0x24,0x4f,0xfc
2220 ,0xe5,0xec,0xba,0xaf,0x33,0xbd,0x75,0x1a
2221 ,0x1a,0xc7,0x28,0xd4,0x5e,0x6c,0x61,0x29
2222 ,0x6c,0xdc,0x3c,0x01,0x23,0x35,0x61,0xf4
2223 ,0x1d,0xb6,0x6c,0xce,0x31,0x4a,0xdb,0x31
2224 ,0x0e,0x3b,0xe8,0x25,0x0c,0x46,0xf0,0x6d
2225 ,0xce,0xea,0x3a,0x7f,0xa1,0x34,0x80,0x57
2226 ,0xe2,0xf6,0x55,0x6a,0xd6,0xb1,0x31,0x8a
2227 ,0x02,0x4a,0x83,0x8f,0x21,0xaf,0x1f,0xde
2228 ,0x04,0x89,0x77,0xeb,0x48,0xf5,0x9f,0xfd
2229 ,0x49,0x24,0xca,0x1c,0x60,0x90,0x2e,0x52
2230 ,0xf0,0xa0,0x89,0xbc,0x76,0x89,0x70,0x40
2231 ,0xe0,0x82,0xf9,0x37,0x76,0x38,0x48,0x64
2232 ,0x5e,0x07,0x05
2235 static immutable ubyte[] res = [
2236 0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5
2237 ,0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9
2238 ,0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73
2239 ,0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce
2240 ,0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4
2241 ,0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a
2242 ,0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b
2243 ,0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72
2244 ,0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2
2245 ,0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38
2246 ,0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a
2247 ,0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae
2248 ,0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea
2249 ,0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda
2250 ,0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde
2251 ,0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3
2252 ,0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6
2253 ,0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74
2254 ,0xe3,0x55,0xa5
2257 ubyte[163] c;
2258 crypto_secretbox(c,m,nonce,firstkey);
2259 for (auto i = 16; i < 163; ++i) assert(c[i] == res[i-16]);
2261 secretbox();
2263 void secretbox2 () {
2264 writeln("secretbox2");
2265 static immutable ubyte[32] firstkey = [
2266 0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4
2267 ,0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7
2268 ,0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2
2269 ,0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89
2272 static immutable ubyte[24] nonce = [
2273 0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73
2274 ,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6
2275 ,0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37
2278 // API requires first 16 bytes to be 0
2279 static immutable ubyte[163] c = [
2280 0, 0, 0, 0, 0, 0, 0, 0
2281 , 0, 0, 0, 0, 0, 0, 0, 0
2282 ,0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5
2283 ,0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9
2284 ,0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73
2285 ,0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce
2286 ,0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4
2287 ,0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a
2288 ,0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b
2289 ,0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72
2290 ,0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2
2291 ,0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38
2292 ,0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a
2293 ,0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae
2294 ,0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea
2295 ,0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda
2296 ,0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde
2297 ,0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3
2298 ,0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6
2299 ,0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74
2300 ,0xe3,0x55,0xa5
2303 static immutable ubyte[] res = [
2304 0xbe,0x07,0x5f,0xc5,0x3c,0x81,0xf2,0xd5
2305 ,0xcf,0x14,0x13,0x16,0xeb,0xeb,0x0c,0x7b
2306 ,0x52,0x28,0xc5,0x2a,0x4c,0x62,0xcb,0xd4
2307 ,0x4b,0x66,0x84,0x9b,0x64,0x24,0x4f,0xfc
2308 ,0xe5,0xec,0xba,0xaf,0x33,0xbd,0x75,0x1a
2309 ,0x1a,0xc7,0x28,0xd4,0x5e,0x6c,0x61,0x29
2310 ,0x6c,0xdc,0x3c,0x01,0x23,0x35,0x61,0xf4
2311 ,0x1d,0xb6,0x6c,0xce,0x31,0x4a,0xdb,0x31
2312 ,0x0e,0x3b,0xe8,0x25,0x0c,0x46,0xf0,0x6d
2313 ,0xce,0xea,0x3a,0x7f,0xa1,0x34,0x80,0x57
2314 ,0xe2,0xf6,0x55,0x6a,0xd6,0xb1,0x31,0x8a
2315 ,0x02,0x4a,0x83,0x8f,0x21,0xaf,0x1f,0xde
2316 ,0x04,0x89,0x77,0xeb,0x48,0xf5,0x9f,0xfd
2317 ,0x49,0x24,0xca,0x1c,0x60,0x90,0x2e,0x52
2318 ,0xf0,0xa0,0x89,0xbc,0x76,0x89,0x70,0x40
2319 ,0xe0,0x82,0xf9,0x37,0x76,0x38,0x48,0x64
2320 ,0x5e,0x07,0x05
2323 ubyte[163] m;
2325 assert(crypto_secretbox_open(m,c,nonce,firstkey));
2326 for (auto i = 32; i < 163; ++i) assert(m[i] == res[i-32]);
2328 secretbox2();
2330 void secretbox7 () {
2331 writeln("secretbox7");
2332 static ubyte[crypto_secretbox_KEYBYTES] k;
2333 static ubyte[crypto_secretbox_NONCEBYTES] n;
2334 static ubyte[10000] m, c, m2;
2335 for (auto mlen = 0; mlen < 1000 && mlen+crypto_secretbox_ZEROBYTES < m.length; ++mlen) {
2336 randombytes(k,crypto_secretbox_KEYBYTES);
2337 randombytes(n,crypto_secretbox_NONCEBYTES);
2338 randombytes(m[crypto_secretbox_ZEROBYTES..$],mlen);
2339 crypto_secretbox(c[0..mlen+crypto_secretbox_ZEROBYTES],m,n,k);
2340 assert(crypto_secretbox_open(m2[0..mlen+crypto_secretbox_ZEROBYTES],c,n,k));
2341 for (auto i = 0; i < mlen+crypto_secretbox_ZEROBYTES; ++i) assert(m2[i] == m[i]);
2344 secretbox7();
2346 void secretbox8 () {
2347 writeln("secretbox8");
2348 static ubyte[crypto_secretbox_KEYBYTES] k;
2349 static ubyte[crypto_secretbox_NONCEBYTES] n;
2350 static ubyte[10000] m, c, m2;
2351 for (auto mlen = 0; mlen < 1000 && mlen+crypto_secretbox_ZEROBYTES < m.length; ++mlen) {
2352 randombytes(k,crypto_secretbox_KEYBYTES);
2353 randombytes(n,crypto_secretbox_NONCEBYTES);
2354 randombytes(m[crypto_secretbox_ZEROBYTES..$],mlen);
2355 crypto_secretbox(c[0..mlen+crypto_secretbox_ZEROBYTES],m,n,k);
2356 auto caught = 0;
2357 while (caught < 10) {
2358 c[uniform(0, mlen+crypto_secretbox_ZEROBYTES)] = cast(ubyte)uniform(0, 256);
2359 if (crypto_secretbox_open(m2[0..mlen+crypto_secretbox_ZEROBYTES],c,n,k)) {
2360 for (auto i = 0; i < mlen+crypto_secretbox_ZEROBYTES; ++i) assert(m2[i] == m[i]);
2362 ++caught;
2364 assert(caught == 10);
2367 version(unittest_full) secretbox8(); // it's slow
2369 void stream () {
2370 writeln("stream");
2371 static immutable ubyte[32] firstkey = [
2372 0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4
2373 ,0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7
2374 ,0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2
2375 ,0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89
2378 static immutable ubyte[24] nonce = [
2379 0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73
2380 ,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6
2381 ,0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37
2384 static ubyte[4194304] output;
2386 //ubyte h[32];
2387 //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];
2389 crypto_stream(output,nonce,firstkey);
2390 //crypto_hash_sha256(h,output,sizeof output);
2391 assert(hashToString(SHA256(output[0..$])) == "662b9d0e3463029156069b12f918691a98f7dfb2ca0393c96bbfc6b1fbd630a2");
2393 stream();
2395 void stream2 () {
2396 writeln("stream2");
2397 static immutable ubyte[32] secondkey = [
2398 0xdc,0x90,0x8d,0xda,0x0b,0x93,0x44,0xa9
2399 ,0x53,0x62,0x9b,0x73,0x38,0x20,0x77,0x88
2400 ,0x80,0xf3,0xce,0xb4,0x21,0xbb,0x61,0xb9
2401 ,0x1c,0xbd,0x4c,0x3e,0x66,0x25,0x6c,0xe4
2404 static immutable ubyte[8] noncesuffix = [
2405 0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37
2408 static ubyte[4194304] output;
2410 crypto_stream_salsa20(output,noncesuffix,secondkey);
2411 assert(hashToString(SHA256(output[0..$])) == "662b9d0e3463029156069b12f918691a98f7dfb2ca0393c96bbfc6b1fbd630a2");
2413 stream2();
2415 void stream3 () {
2416 writeln("stream3");
2417 static immutable ubyte[32] firstkey = [
2418 0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4
2419 ,0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7
2420 ,0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2
2421 ,0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89
2424 static immutable ubyte[24] nonce = [
2425 0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73
2426 ,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6
2427 ,0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37
2430 ubyte[32] rs;
2432 static immutable ubyte[32] res = [
2433 0xee,0xa6,0xa7,0x25,0x1c,0x1e,0x72,0x91
2434 ,0x6d,0x11,0xc2,0xcb,0x21,0x4d,0x3c,0x25
2435 ,0x25,0x39,0x12,0x1d,0x8e,0x23,0x4e,0x65
2436 ,0x2d,0x65,0x1f,0xa4,0xc8,0xcf,0xf8,0x80
2439 crypto_stream/*_xsalsa20*/(rs,nonce,firstkey);
2440 assert(rs == res);
2442 stream3();
2444 void stream4 () {
2445 writeln("stream4");
2446 static immutable ubyte[32] firstkey = [
2447 0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4
2448 ,0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7
2449 ,0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2
2450 ,0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89
2453 static immutable ubyte[24] nonce = [
2454 0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73
2455 ,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6
2456 ,0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37
2459 static immutable ubyte[163] m = [
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 , 0, 0, 0, 0, 0, 0, 0, 0
2464 ,0xbe,0x07,0x5f,0xc5,0x3c,0x81,0xf2,0xd5
2465 ,0xcf,0x14,0x13,0x16,0xeb,0xeb,0x0c,0x7b
2466 ,0x52,0x28,0xc5,0x2a,0x4c,0x62,0xcb,0xd4
2467 ,0x4b,0x66,0x84,0x9b,0x64,0x24,0x4f,0xfc
2468 ,0xe5,0xec,0xba,0xaf,0x33,0xbd,0x75,0x1a
2469 ,0x1a,0xc7,0x28,0xd4,0x5e,0x6c,0x61,0x29
2470 ,0x6c,0xdc,0x3c,0x01,0x23,0x35,0x61,0xf4
2471 ,0x1d,0xb6,0x6c,0xce,0x31,0x4a,0xdb,0x31
2472 ,0x0e,0x3b,0xe8,0x25,0x0c,0x46,0xf0,0x6d
2473 ,0xce,0xea,0x3a,0x7f,0xa1,0x34,0x80,0x57
2474 ,0xe2,0xf6,0x55,0x6a,0xd6,0xb1,0x31,0x8a
2475 ,0x02,0x4a,0x83,0x8f,0x21,0xaf,0x1f,0xde
2476 ,0x04,0x89,0x77,0xeb,0x48,0xf5,0x9f,0xfd
2477 ,0x49,0x24,0xca,0x1c,0x60,0x90,0x2e,0x52
2478 ,0xf0,0xa0,0x89,0xbc,0x76,0x89,0x70,0x40
2479 ,0xe0,0x82,0xf9,0x37,0x76,0x38,0x48,0x64
2480 ,0x5e,0x07,0x05
2483 ubyte[163] c;
2485 static immutable ubyte[] res = [
2486 0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73
2487 ,0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce
2488 ,0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4
2489 ,0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a
2490 ,0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b
2491 ,0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72
2492 ,0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2
2493 ,0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38
2494 ,0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a
2495 ,0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae
2496 ,0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea
2497 ,0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda
2498 ,0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde
2499 ,0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3
2500 ,0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6
2501 ,0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74
2502 ,0xe3,0x55,0xa5
2505 /*crypto_stream_xsalsa20_xor*/crypto_stream_xor(c,m,nonce,firstkey);
2506 for (auto i = 32; i < 163; ++i) assert(c[i] == res[i-32]);
2508 stream4();
2511 version(unittest)
2512 version(tweetnacl_unittest)
2513 version(unittest_main)
2514 void main () {}