fixed c-style arrays
[tweetnacl.d.git] / tweetNaCl.d
blobcf055dd0ce42140bab0c2dfea86940835b4cf111
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;
17 // define tweetnacl_enable_inlining to speed up tweetNaCl on GDC
18 version(GNU) {
19 version(tweetnacl_enable_inlining) version=tweetnacl_enable_inlining_on_;
20 else version=tweetnacl_enable_inlining_off_;
21 } else {
22 version=tweetnacl_enable_inlining_off_;
25 version(tweetnacl_enable_inlining_on_) {
26 static import gcc.attribute;
27 private enum gcc_inline = gcc.attribute.attribute("forceinline");
28 } else {
29 // hackery for non-gcc compilers
30 private enum gcc_inline;
34 enum {
35 crypto_auth_BYTES = 32,
36 crypto_auth_KEYBYTES = 32,
38 crypto_box_PUBLICKEYBYTES = 32,
39 crypto_box_SECRETKEYBYTES = 32,
40 crypto_box_BEFORENMBYTES = 32,
41 crypto_box_NONCEBYTES = 24,
42 crypto_box_ZEROBYTES = 32,
43 crypto_box_BOXZEROBYTES = 16,
45 crypto_core_salsa20_OUTPUTBYTES = 64,
46 crypto_core_salsa20_INPUTBYTES = 16,
47 crypto_core_salsa20_KEYBYTES = 32,
48 crypto_core_salsa20_CONSTBYTES = 16,
50 crypto_core_hsalsa20_OUTPUTBYTES = 32,
51 crypto_core_hsalsa20_INPUTBYTES = 16,
52 crypto_core_hsalsa20_KEYBYTES = 32,
53 crypto_core_hsalsa20_CONSTBYTES = 16,
55 crypto_hash_BYTES = 64,
57 crypto_onetimeauth_BYTES = 16,
58 crypto_onetimeauth_KEYBYTES = 32,
60 crypto_scalarmult_BYTES = 32,
61 crypto_scalarmult_SCALARBYTES = 32,
63 crypto_secretbox_KEYBYTES = 32,
64 crypto_secretbox_NONCEBYTES = 24,
65 crypto_secretbox_ZEROBYTES = 32,
66 crypto_secretbox_BOXZEROBYTES = 16,
68 crypto_sign_BYTES = 64,
69 crypto_sign_PUBLICKEYBYTES = 32,
70 crypto_sign_SECRETKEYBYTES = 64,
72 crypto_stream_xsalsa20_KEYBYTES = 32,
73 crypto_stream_xsalsa20_NONCEBYTES = 24,
75 crypto_stream_salsa20_KEYBYTES = 32,
76 crypto_stream_salsa20_NONCEBYTES = 8,
78 crypto_stream_KEYBYTES = 32,
79 crypto_stream_NONCEBYTES = 24,
81 crypto_verify_16_BYTES = 16,
82 crypto_verify_32_BYTES = 32,
86 /// set this callback to good (cryptograpic strong) random bytes generator
87 /// you can use /dev/urandom as prng
88 void function (ubyte[] dest, size_t len) randombytes = null;
91 private immutable ubyte[16] _0 = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
92 private immutable ubyte[32] _9 = [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];
94 private immutable long[16]
95 gf0 = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
96 gf1 = [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
97 _121665 = [0xDB41,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
98 D = [0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203],
99 D2 =[0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406],
100 X = [0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169],
101 Y = [0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666],
102 I = [0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83];
104 private @gcc_inline uint ld32() (const(ubyte)[] x) @safe nothrow
105 in {
106 assert(x.length >= 4);
108 body {
109 uint u = x[3];
110 u = (u<<8)|x[2];
111 u = (u<<8)|x[1];
112 return (u<<8)|x[0];
115 private @gcc_inline ulong dl64() (const(ubyte)[] x) @safe nothrow
116 in {
117 assert(x.length >= 8);
119 body {
120 ulong u = x[0];
121 u = (u<<8)|x[1];
122 u = (u<<8)|x[2];
123 u = (u<<8)|x[3];
124 u = (u<<8)|x[4];
125 u = (u<<8)|x[5];
126 u = (u<<8)|x[6];
127 return (u<<8)|x[7];
130 private @gcc_inline void st32() (ubyte[] x, uint u) @safe nothrow
131 in {
132 assert(x.length >= 4);
134 body {
135 x[0] = u&0xff;
136 x[1] = (u>>8)&0xff;
137 x[2] = (u>>16)&0xff;
138 x[3] = (u>>24)&0xff;
141 private @gcc_inline void ts64() (ubyte[] x, ulong u) @safe nothrow
142 in {
143 assert(x.length >= 8);
145 body {
146 x[0] = (u>>56)&0xff;
147 x[1] = (u>>48)&0xff;
148 x[2] = (u>>40)&0xff;
149 x[3] = (u>>32)&0xff;
150 x[4] = (u>>24)&0xff;
151 x[5] = (u>>16)&0xff;
152 x[6] = (u>>8)&0xff;
153 x[7] = u&0xff;
156 private @gcc_inline bool vn() (const(ubyte)[] x, const(ubyte)[] y) @safe nothrow
157 in {
158 assert(x.length >= y.length);
160 body {
161 uint d = 0;
162 foreach (immutable i, immutable v; x) d |= v^y[i];
163 return (1&((d-1)>>8)) != 0;
167 * The crypto_verify_16() function checks that strings 'x' and 'y' has same content.
169 * Params:
170 * x = first string, slice length must be at least crypto_verify_16_BYTES, extra ignored
171 * y = second string, slice length must be at least crypto_verify_16_BYTES, extra ignored
173 * Returns:
174 * success flag
176 @gcc_inline bool crypto_verify_16() (const(ubyte)[] x, const(ubyte)[] y) @safe nothrow
177 in {
178 assert(x.length >= 16 && y.length >= 16);
180 body {
181 return vn(x[0..16], y[0..16]);
185 * The crypto_verify_32() function checks that strings 'x' and 'y' has same content.
187 * Params:
188 * x = first string, slice length must be at least crypto_verify_32_BYTES, extra ignored
189 * y = second string, slice length must be at least crypto_verify_32_BYTES, extra ignored
191 * Returns:
192 * success flag
194 @gcc_inline bool crypto_verify_32() (const(ubyte)[] x, const(ubyte)[] y) @safe nothrow
195 in {
196 assert(x.length >= 32 && y.length >= 32);
198 body {
199 return vn(x[0..32], y[0..32]);
203 private void salsa_core(string type) (ubyte[] output, const(ubyte)[] input, const(ubyte)[] key, const(ubyte)[] constant) @safe nothrow
204 if (type == "salsa" || type == "hsalsa") // constraint
205 in {
206 // magic!
207 assert(mixin(`output.length >= crypto_core_`~type~`20_OUTPUTBYTES`));
208 assert(mixin(`input.length >= crypto_core_`~type~`20_INPUTBYTES`));
209 assert(mixin(`key.length >= crypto_core_`~type~`20_KEYBYTES`));
210 assert(mixin(`constant.length >= crypto_core_`~type~`20_CONSTBYTES`));
212 body {
213 static @gcc_inline uint ROTL32() (uint x, int c) @safe nothrow pure { return (x<<c)|((x&0xffffffff)>>(32-c)); }
215 uint[16] w = void, x = void, y = void;
216 uint[4] t = void;
218 foreach (i; 0..4) {
219 x[5*i] = ld32(constant[4*i..$]);
220 x[1+i] = ld32(key[4*i..$]);
221 x[6+i] = ld32(input[4*i..$]);
222 x[11+i] = ld32(key[16+4*i..$]);
225 y[] = x[];
227 foreach (i; 0..20) {
228 foreach (j; 0..4) {
229 foreach (m; 0..4) t[m] = x[(5*j+4*m)%16];
230 t[1] ^= ROTL32(t[0]+t[3], 7);
231 t[2] ^= ROTL32(t[1]+t[0], 9);
232 t[3] ^= ROTL32(t[2]+t[1], 13);
233 t[0] ^= ROTL32(t[3]+t[2], 18);
234 for (auto m = 0; m < 4; ++m) w[4*j+(j+m)%4] = t[m];
236 for (auto m = 0; m < 16; ++m) x[m] = w[m];
239 static if (type == "hsalsa") {
240 for (auto i = 0; i < 16; ++i) x[i] += y[i];
241 for (auto i = 0; i < 4; ++i) {
242 x[5*i] -= ld32(constant[4*i..$]);
243 x[6+i] -= ld32(input[4*i..$]);
245 for (auto i = 0; i < 4; ++i) {
246 st32(output[4*i..$], x[5*i]);
247 st32(output[16+4*i..$], x[6+i]);
249 } else {
250 for (auto i = 0; i < 16; ++i) st32(output[4*i..$], x[i]+y[i]);
254 @gcc_inline void crypto_core_salsa20() (ubyte[] output, const(ubyte)[] input, const(ubyte)[] key, const(ubyte)[] constant)
255 @safe nothrow {
256 salsa_core!"salsa"(output, input, key, constant);
259 @gcc_inline void crypto_core_hsalsa20() (ubyte[] output, const(ubyte)[] input, const(ubyte)[] key, const(ubyte)[] constant)
260 @safe nothrow {
261 salsa_core!"hsalsa"(output, input, key, constant);
264 private immutable(ubyte)[] sigma = cast(immutable(ubyte)[])"expand 32-byte k";
267 * The crypto_stream_salsa20_xor() function encrypts a message 'msg' using a secret key 'key'
268 * and a nonce 'nonce'. The crypto_stream_salsa20_xor() function returns the ciphertext 'output'.
270 * Params:
271 * output = resulting ciphertext
272 * msg = message
273 * nonce = nonce
274 * key = secret key
276 * Returns:
277 * ciphertext in 'output'
279 void crypto_stream_salsa20_xor (ubyte[] output, const(ubyte)[] msg, const(ubyte)[] nonce, const(ubyte)[] key) @trusted nothrow
280 in {
281 assert(nonce.length == crypto_stream_salsa20_NONCEBYTES);
282 assert(key.length == crypto_stream_salsa20_KEYBYTES);
283 import std.stdio;
284 assert(msg.length == 0 || output.length <= msg.length);
286 body {
287 ubyte[16] z; // autoclear
288 ubyte[64] x = void;
289 uint u;
290 uint cpos = 0, mpos = 0;
291 size_t b = output.length;
292 if (!b) return;
293 z[0..8] = nonce[0..8];
294 while (b >= 64) {
295 crypto_core_salsa20(x, z, key, sigma);
296 if (msg !is null) {
297 foreach (v; x) output[cpos++] = msg[mpos++]^v;
298 } else {
299 output[cpos..cpos+64] = x[];
300 cpos += 64;
302 u = 1;
303 foreach (i; 8..16) {
304 u += cast(uint)z[i];
305 z[i] = u&0xff;
306 u >>= 8;
308 b -= 64;
310 if (b) {
311 crypto_core_salsa20(x, z, key, sigma);
312 if (msg !is null) {
313 foreach (i; 0..b) output[cpos++] = msg[mpos++]^x[i];
314 } else {
315 output[cpos..cpos+b] = x[0..b];
321 * The crypto_stream_salsa20() function produces a stream 'c'
322 * as a function of a secret key 'key' and a nonce 'nonce'.
324 * Params:
325 * c = resulting stream
326 * nonce = nonce
327 * key = secret key
329 * Returns:
330 * ciphertext in 'c'
332 void crypto_stream_salsa20() (ubyte[] c, const(ubyte)[] nonce, const(ubyte)[] key) @safe nothrow
333 in {
334 assert(nonce.length == crypto_stream_salsa20_NONCEBYTES);
335 assert(key.length == crypto_stream_salsa20_KEYBYTES);
337 body {
338 crypto_stream_salsa20_xor(c, null, nonce, key);
342 * The crypto_stream() function produces a stream 'c'
343 * as a function of a secret key 'key' and a nonce 'nonce'.
345 * Params:
346 * c = output slice
347 * nonce = nonce
348 * key = secret key
350 * Returns:
351 * stream in 'c'
353 void crypto_stream() (ubyte[] c, const(ubyte)[] nonce, const(ubyte)[] key) @safe nothrow
354 in {
355 assert(c !is null);
356 assert(nonce.length == crypto_stream_NONCEBYTES);
357 assert(key.length == crypto_stream_KEYBYTES);
359 body {
360 ubyte[32] s = void;
361 crypto_core_hsalsa20(s, nonce, key, sigma);
362 crypto_stream_salsa20(c, nonce[16..$], s);
366 * The crypto_stream_xor() function encrypts a message 'msg' using a secret key 'key'
367 * and a nonce 'nonce'. The crypto_stream_xor() function returns the ciphertext 'c'.
369 * Params:
370 * c = output slice
371 * nonce = nonce
372 * key = secret key
374 * Returns:
375 * ciphertext in 'c'
377 void crypto_stream_xor() (ubyte[] c, const(ubyte)[] msg, const(ubyte)[] nonce, const(ubyte)[] key) @safe nothrow
378 in {
379 assert(c !is null);
380 assert(msg.length >= c.length);
381 assert(nonce.length == crypto_stream_NONCEBYTES);
382 assert(key.length == crypto_stream_KEYBYTES);
384 body {
385 ubyte[32] s = void;
386 crypto_core_hsalsa20(s, nonce, key, sigma);
387 crypto_stream_salsa20_xor(c, msg, nonce[16..$], s);
390 private @gcc_inline void add1305() (uint[] h, const(uint)[] c) @safe nothrow {
391 uint u = 0;
392 foreach (j; 0..17) {
393 u += h[j]+c[j];
394 h[j] = u&255;
395 u >>= 8;
399 private immutable uint[17] minusp = [5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,252];
402 * The crypto_onetimeauth() function authenticates a message 'msg'
403 * using a secret key 'key'. The function returns an authenticator 'output'.
405 * Params:
406 * output = authenticator, slice size must be at least crypto_onetimeauth_BYTES, extra ignored
407 * msg == message
408 * key == secret key, slice size must be at least crypto_onetimeauth_KEYBYTES, extra ignored
410 * Returns:
411 * authenticator in 'output'
413 void crypto_onetimeauth() (ubyte[] output, const(ubyte)[] msg, const(ubyte)[] key) @safe nothrow
414 in {
415 assert(key.length >= crypto_onetimeauth_KEYBYTES);
416 assert(output.length >= crypto_onetimeauth_BYTES);
418 body {
419 uint s, u;
420 uint[17] x = void, r = void, h/*autoclear*/, c = void, g = void;
421 uint mpos = 0;
422 size_t n = msg.length;
424 foreach (i; 0..16) r[i] = key[i];
425 r[16..17] = 0;
427 r[3] &= 15;
428 r[4] &= 252;
429 r[7] &= 15;
430 r[8] &= 252;
431 r[11] &= 15;
432 r[12] &= 252;
433 r[15] &= 15;
435 while (n > 0) {
436 c[0..17] = 0;
438 size_t jj;
439 for (jj = 0; jj < 16 && jj < n; ++jj) c[jj] = msg[mpos+jj];
440 c[jj] = 1;
441 mpos += jj;
442 n -= jj;
444 add1305(h, c);
445 foreach (i; 0..17) {
446 x[i] = 0;
447 foreach (j; 0..17) x[i] += h[j]*(j <= i ? r[i-j] : 320*r[i+17-j]);
449 h[] = x[];
450 u = 0;
451 foreach (j; 0..16) {
452 u += h[j];
453 h[j] = u&255;
454 u >>= 8;
456 u += h[16];
457 h[16] = u&3;
458 u = 5*(u>>2);
459 foreach (j; 0..16) {
460 u += h[j];
461 h[j] = u&255;
462 u >>= 8;
464 u += h[16];
465 h[16] = u;
468 g[] = h[];
469 add1305(h, minusp);
470 s = -(h[16]>>7);
471 foreach (j; 0..17) h[j] ^= s&(g[j]^h[j]);
473 foreach (j; 0..16) c[j] = key[j+16];
474 c[16] = 0;
475 add1305(h, c);
476 foreach (j; 0..16) output[j] = cast(ubyte)(h[j]&0xff);
480 * The crypto_onetimeauth_verify() function checks that
481 * 'h' is a correct authenticator of a message 'msg' under the secret key 'key'.
483 * Params:
484 * h = authenticator, slice size must be at least crypto_onetimeauth_BYTES, extra ignored
485 * msg == message
486 * key == secret key, slice size must be at least crypto_onetimeauth_KEYBYTES, extra ignored
488 * Returns:
489 * success flag
491 bool crypto_onetimeauth_verify() (const(ubyte)[] h, const(ubyte)[] msg, const(ubyte)[] key) @safe nothrow
492 in {
493 assert(h.length >= crypto_onetimeauth_BYTES);
494 assert(key.length >= crypto_onetimeauth_KEYBYTES);
496 body {
497 ubyte[16] x = void;
498 crypto_onetimeauth(x, msg, key);
499 return crypto_verify_16(h, x);
503 * The crypto_secretbox() function encrypts and authenticates
504 * a message 'msg' using a secret key 'key' and a nonce 'nonce'.
505 * The crypto_secretbox() function returns the resulting ciphertext 'c'.
507 * Params:
508 * c = resulting cyphertext
509 * key = secret key
510 * nonce = nonce
512 * Returns:
513 * success flag and cyphertext in 'c'
515 bool crypto_secretbox() (ubyte[] c, const(ubyte)[] msg, const(ubyte)[] nonce, const(ubyte)[] key) @safe nothrow
516 in {
517 assert(key.length >= crypto_secretbox_KEYBYTES);
518 assert(nonce.length >= crypto_secretbox_NONCEBYTES);
520 body {
521 //c.length = msg.length+crypto_secretbox_ZEROBYTES;
522 if (c is null || c.length < 32) return false;
523 crypto_stream_xor(c, msg, nonce, key);
524 crypto_onetimeauth(c[16..$], c[32..$], c);
525 c[0..16] = 0;
526 //return c[crypto_secretbox_BOXZEROBYTES..$];
527 return true;
531 * The crypto_secretbox_open() function verifies and decrypts
532 * a ciphertext 'c' using a secret key 'key' and a nonce 'nonce'.
533 * The crypto_secretbox_open() function returns the resulting plaintext 'output'.
535 * Params:
536 * output = resulting message
537 * c = cyphertext
538 * key = secret key
539 * nonce = nonce
541 * Returns:
542 * success flag and message in 'output'
544 bool crypto_secretbox_open() (ubyte[] output, const(ubyte)[] c, const(ubyte)[] nonce, const(ubyte)[] key) @safe nothrow
545 in {
546 assert(key.length >= crypto_secretbox_KEYBYTES);
547 assert(nonce.length >= crypto_secretbox_NONCEBYTES);
549 body {
550 ubyte[32] x = void;
551 if (output is null || output.length < 32) return false;
552 crypto_stream(x, nonce, key);
553 if (!crypto_onetimeauth_verify(c[16..$], c[32../*$*/32+(output.length-32)], x)) return false;
554 crypto_stream_xor(output, c, nonce, key);
555 output[0..32] = 0;
556 return true;
560 private @gcc_inline void car25519() (long[] o) @safe nothrow {
561 foreach (i; 0..16) {
562 o[i] += (1<<16);
563 long c = o[i]>>16;
564 o[(i+1)*(i<15)] += c-1+37*(c-1)*(i==15);
565 o[i] -= c<<16;
569 private @gcc_inline void sel25519() (long[] p,long[] q, int b) @safe nothrow {
570 long c = ~(b-1);
571 foreach (i; 0..16) {
572 long t = c&(p[i]^q[i]);
573 p[i] ^= t;
574 q[i] ^= t;
578 private @gcc_inline void pack25519() (ubyte[] o, const(long)[] n) @safe nothrow {
579 int b;
580 long[16] m = void, t = void;
581 t[0..16] = n[0..16];
582 car25519(t);
583 car25519(t);
584 car25519(t);
585 foreach (j; 0..2) {
586 m[0] = t[0]-0xffed;
587 foreach (i; 1..15) {
588 m[i] = t[i]-0xffff-((m[i-1]>>16)&1);
589 m[i-1] &= 0xffff;
591 m[15] = t[15]-0x7fff-((m[14]>>16)&1);
592 b = (m[15]>>16)&1;
593 m[14] &= 0xffff;
594 sel25519(t, m, 1-b);
596 foreach (i; 0..16) {
597 o[2*i] = t[i]&0xff;
598 o[2*i+1] = (t[i]>>8)&0xff;
602 private @gcc_inline bool neq25519() (const(long)[] a, const(long)[] b) @safe nothrow {
603 ubyte[32] c = void, d = void;
604 pack25519(c, a);
605 pack25519(d, b);
606 return crypto_verify_32(c, d);
609 private @gcc_inline ubyte par25519() (const(long)[] a) @safe nothrow {
610 ubyte[32] d = void;
611 pack25519(d, a);
612 return d[0]&1;
615 private @gcc_inline void unpack25519() (long[] o, const(ubyte)[] n) @safe nothrow {
616 foreach (i; 0..16) o[i] = n[2*i]+(cast(long)n[2*i+1]<<8);
617 o[15] &= 0x7fff;
620 private @gcc_inline void A() (long[] o, const(long)[] a, const(long)[] b) @safe nothrow {
621 foreach (i; 0..16) o[i] = a[i]+b[i];
624 private @gcc_inline void Z() (long[] o, const(long)[] a, const(long)[] b) @safe nothrow {
625 foreach (i; 0..16) o[i] = a[i]-b[i];
628 private @gcc_inline void M() (long[] o, const(long)[] a, const(long)[] b) @safe nothrow {
629 long[31] t; // automatically becomes 0
630 foreach (i; 0..16) foreach (j; 0..16) t[i+j] += a[i]*b[j];
631 foreach (i; 0..15) t[i] += 38*t[i+16];
632 o[0..16] = t[0..16];
633 car25519(o);
634 car25519(o);
637 private @gcc_inline void S() (long[] o, const(long)[] a) @safe nothrow {
638 M(o, a, a);
641 private @gcc_inline void inv25519() (long[] o, const(long)[] i) @safe nothrow {
642 long[16] c = void;
643 c[] = i[0..16];
644 for (auto a = 253; a >= 0; --a) {
645 S(c, c);
646 if (a != 2 && a != 4) M(c, c, i);
648 o[0..16] = c[];
651 private @gcc_inline void pow2523() (long[] o, const(long)[] i) @safe nothrow {
652 long[16] c = void;
653 c[] = i[0..16];
654 for(auto a = 250; a >= 0; --a) {
655 S(c, c);
656 if (a != 1) M(c, c, i);
658 o[0..16] = c[];
661 /* FIXME!
662 * This function multiplies a group element 'p' by an integer 'n'.
664 * Params:
665 * p = group element
666 * n = number
668 * Returns:
669 * resulting group element 'q' of length crypto_scalarmult_BYTES.
671 private void crypto_scalarmult (ubyte[] q, const(ubyte)[] n, const(ubyte)[] p) @safe nothrow
672 in {
673 assert(q.length == crypto_scalarmult_BYTES);
674 assert(n.length == crypto_scalarmult_BYTES);
675 assert(p.length == crypto_scalarmult_BYTES);
677 body {
678 ubyte[32] z = void;
679 long[80] x = void;
680 long r;
681 long[16] a = void, b = void, c = void, d = void, e = void, f = void;
682 z[] = n[0..32];
683 z[31] = (n[31]&127)|64;
684 z[0] &= 248;
685 unpack25519(x, p);
686 foreach (i; 0..16) {
687 b[i] = x[i];
688 d[i] = a[i] = c[i] = 0;
690 a[0] = d[0] = 1;
691 for (int i = 254; i >= 0; --i) {
692 r = (z[i>>3]>>(i&7))&1;
693 sel25519(a, b, cast(int)r);
694 sel25519(c, d, cast(int)r);
695 A(e, a, c);
696 Z(a, a, c);
697 A(c, b, d);
698 Z(b, b, d);
699 S(d, e);
700 S(f, a);
701 M(a, c, a);
702 M(c, b, e);
703 A(e, a, c);
704 Z(a, a, c);
705 S(b, a);
706 Z(c, d, f);
707 M(a, c, _121665);
708 A(a, a, d);
709 M(c, c, a);
710 M(a, d, f);
711 M(d, b, x);
712 S(b, e);
713 sel25519(a, b, cast(int)r);
714 sel25519(c, d, cast(int)r);
716 foreach (i; 0..16) {
717 x[i+16] = a[i];
718 x[i+32] = c[i];
719 x[i+48] = b[i];
720 x[i+64] = d[i];
722 inv25519(x[32..$], x[32..$]);
723 M(x[16..$], x[16..$], x[32..$]);
724 pack25519(q, x[16..$]);
727 /* FIXME!
728 * The crypto_scalarmult_base() function computes
729 * the scalar product of a standard group element and an integer 'n'.
731 * Params:
732 * n = number
734 * Returns:
735 * resulting group element 'q' of length crypto_scalarmult_BYTES.
737 private void crypto_scalarmult_base() (ubyte[] q, const(ubyte)[] n) @safe nothrow
738 in {
739 assert(q.length == crypto_scalarmult_BYTES);
740 assert(n.length == crypto_scalarmult_SCALARBYTES);
742 body {
743 crypto_scalarmult(q, n, _9);
747 * The crypto_box_keypair() function randomly generates a secret key and
748 * a corresponding public key.
750 * Params:
751 * pk = slice to put generated public key into
752 * sk = slice to put generated secret key into
754 * Returns:
755 * pair of new keys
757 void crypto_box_keypair() (ubyte[] pk, ubyte[] sk) @trusted
758 in {
759 assert(pk.length >= crypto_box_PUBLICKEYBYTES);
760 assert(sk.length >= crypto_box_SECRETKEYBYTES);
762 body {
763 randombytes(sk, 32);
764 crypto_scalarmult_base(pk, sk);
768 * Function crypto_box_beforenm() computes a shared secret 's' from
769 * public key 'pk' and secret key 'sk'.
771 * Params:
772 * skey = slice to put secret into
773 * pk = public
774 * sk = secret
776 * Returns:
777 * generated secret
779 void crypto_box_beforenm() (ubyte[] skey, const(ubyte)[] pk, const(ubyte)[] sk) @safe nothrow
780 in {
781 assert(pk.length >= crypto_box_PUBLICKEYBYTES);
782 assert(sk.length >= crypto_box_SECRETKEYBYTES);
783 assert(skey.length >= crypto_box_BEFORENMBYTES);
785 body {
786 ubyte[32] s = void;
787 crypto_scalarmult(s, sk, pk);
788 crypto_core_hsalsa20(skey, _0, s, sigma);
792 * The crypto_box_afternm() function encrypts and authenticates
793 * a message 'msg' using a secret key 'key' and a nonce 'nonce'.
794 * The crypto_box_afternm() function returns the resulting ciphertext 'c'.
796 * Params:
797 * c = resulting cyphertext
798 * msg = message
799 * nonce = nonce
800 * key = secret
802 * Returns:
803 * success flag and cyphertext in 'c'
805 bool crypto_box_afternm() (ubyte[] c, const(ubyte)[] msg, const(ubyte)[] nonce, const(ubyte)[] key) @safe nothrow
806 in {
807 assert(nonce.length >= crypto_box_NONCEBYTES);
808 assert(key.length >= crypto_box_BEFORENMBYTES);
810 body {
811 return crypto_secretbox(c, msg, nonce, key);
815 * The crypto_box_open_afternm() function verifies and decrypts
816 * a ciphertext 'c' using a secret key 'key' and a nonce 'nonce'.
817 * The crypto_box_open_afternm() function returns the resulting message 'msg'.
819 * Params:
820 * msg = resulting message
821 * c = cyphertext
822 * nonce = nonce
823 * key = secret
825 * Returns:
826 * success flag and resulting message in 'msg'
828 bool crypto_box_open_afternm() (ubyte[] msg, const(ubyte)[] c, const(ubyte)[] nonce, const(ubyte)[] key) @safe nothrow
829 in {
830 assert(nonce.length >= crypto_box_NONCEBYTES);
831 assert(key.length >= crypto_box_BEFORENMBYTES);
833 body {
834 return crypto_secretbox_open(msg, c, nonce, key);
838 * The crypto_box() function encrypts and authenticates a message 'msg'
839 * using the sender's secret key 'sk', the receiver's public key 'pk',
840 * and a nonce 'nonce'. The crypto_box() function returns the resulting ciphertext 'c'.
842 * Params:
843 * c = resulting cyphertext
844 * msg = message
845 * nonce = nonce
846 * pk = receiver's public key
847 * sk = sender's secret key
849 * Returns:
850 * success flag and cyphertext in 'c'
852 bool crypto_box() (ubyte[] c, const(ubyte)[] msg, const(ubyte)[] nonce, const(ubyte)[] pk, const(ubyte)[] sk) @safe nothrow
853 in {
854 assert(nonce.length >= crypto_box_NONCEBYTES);
855 assert(pk.length >= crypto_box_PUBLICKEYBYTES);
856 assert(sk.length >= crypto_box_SECRETKEYBYTES);
858 body {
859 ubyte[32] k = void;
860 crypto_box_beforenm(k, pk, sk);
861 return crypto_box_afternm(c, msg, nonce, k);
865 * The crypto_box_open() function verifies and decrypts
866 * a ciphertext 'c' using the receiver's secret key 'sk',
867 * the sender's public key 'pk', and a nonce 'nonce'.
868 * The crypto_box_open() function returns the resulting message 'msg'.
870 * Params:
871 * msg = resulting message
872 * c = cyphertext
873 * nonce = nonce
874 * pk = receiver's public key
875 * sk = sender's secret key
877 * Returns:
878 * success flag and message in 'msg'
880 bool crypto_box_open() (ubyte[] msg, const(ubyte)[] c, const(ubyte)[] nonce, const(ubyte)[] pk, const(ubyte)[] sk) @safe nothrow
881 in {
882 assert(nonce.length >= crypto_box_NONCEBYTES);
883 assert(pk.length >= crypto_box_PUBLICKEYBYTES);
884 assert(sk.length >= crypto_box_SECRETKEYBYTES);
886 body {
887 ubyte[32] k = void;
888 crypto_box_beforenm(k, pk, sk);
889 return crypto_box_open_afternm(msg, c, nonce, k);
892 private @gcc_inline ulong R() (ulong x, int c) @safe nothrow pure { return (x>>c)|(x<<(64-c)); }
893 private @gcc_inline ulong Ch() (ulong x, ulong y, ulong z) @safe nothrow pure { return (x&y)^(~x&z); }
894 private @gcc_inline ulong Maj() (ulong x, ulong y, ulong z) @safe nothrow pure { return (x&y)^(x&z)^(y&z); }
895 private @gcc_inline ulong Sigma0() (ulong x) @safe nothrow pure { return R(x, 28)^R(x, 34)^R(x, 39); }
896 private @gcc_inline ulong Sigma1() (ulong x) @safe nothrow pure { return R(x, 14)^R(x, 18)^R(x, 41); }
897 private @gcc_inline ulong sigma0() (ulong x) @safe nothrow pure { return R(x, 1)^R(x, 8)^(x>>7); }
898 private @gcc_inline ulong sigma1() (ulong x) @safe nothrow pure { return R(x, 19)^R(x, 61)^(x>>6); }
900 private immutable ulong[80] K = [
901 0x428a2f98d728ae22UL, 0x7137449123ef65cdUL, 0xb5c0fbcfec4d3b2fUL, 0xe9b5dba58189dbbcUL,
902 0x3956c25bf348b538UL, 0x59f111f1b605d019UL, 0x923f82a4af194f9bUL, 0xab1c5ed5da6d8118UL,
903 0xd807aa98a3030242UL, 0x12835b0145706fbeUL, 0x243185be4ee4b28cUL, 0x550c7dc3d5ffb4e2UL,
904 0x72be5d74f27b896fUL, 0x80deb1fe3b1696b1UL, 0x9bdc06a725c71235UL, 0xc19bf174cf692694UL,
905 0xe49b69c19ef14ad2UL, 0xefbe4786384f25e3UL, 0x0fc19dc68b8cd5b5UL, 0x240ca1cc77ac9c65UL,
906 0x2de92c6f592b0275UL, 0x4a7484aa6ea6e483UL, 0x5cb0a9dcbd41fbd4UL, 0x76f988da831153b5UL,
907 0x983e5152ee66dfabUL, 0xa831c66d2db43210UL, 0xb00327c898fb213fUL, 0xbf597fc7beef0ee4UL,
908 0xc6e00bf33da88fc2UL, 0xd5a79147930aa725UL, 0x06ca6351e003826fUL, 0x142929670a0e6e70UL,
909 0x27b70a8546d22ffcUL, 0x2e1b21385c26c926UL, 0x4d2c6dfc5ac42aedUL, 0x53380d139d95b3dfUL,
910 0x650a73548baf63deUL, 0x766a0abb3c77b2a8UL, 0x81c2c92e47edaee6UL, 0x92722c851482353bUL,
911 0xa2bfe8a14cf10364UL, 0xa81a664bbc423001UL, 0xc24b8b70d0f89791UL, 0xc76c51a30654be30UL,
912 0xd192e819d6ef5218UL, 0xd69906245565a910UL, 0xf40e35855771202aUL, 0x106aa07032bbd1b8UL,
913 0x19a4c116b8d2d0c8UL, 0x1e376c085141ab53UL, 0x2748774cdf8eeb99UL, 0x34b0bcb5e19b48a8UL,
914 0x391c0cb3c5c95a63UL, 0x4ed8aa4ae3418acbUL, 0x5b9cca4f7763e373UL, 0x682e6ff3d6b2b8a3UL,
915 0x748f82ee5defb2fcUL, 0x78a5636f43172f60UL, 0x84c87814a1f0ab72UL, 0x8cc702081a6439ecUL,
916 0x90befffa23631e28UL, 0xa4506cebde82bde9UL, 0xbef9a3f7b2c67915UL, 0xc67178f2e372532bUL,
917 0xca273eceea26619cUL, 0xd186b8c721c0c207UL, 0xeada7dd6cde0eb1eUL, 0xf57d4f7fee6ed178UL,
918 0x06f067aa72176fbaUL, 0x0a637dc5a2c898a6UL, 0x113f9804bef90daeUL, 0x1b710b35131c471bUL,
919 0x28db77f523047d84UL, 0x32caab7b40c72493UL, 0x3c9ebe0a15c9bebcUL, 0x431d67c49c100d4cUL,
920 0x4cc5d4becb3e42b6UL, 0x597f299cfc657e2aUL, 0x5fcb6fab3ad6faecUL, 0x6c44198c4a475817UL
923 private void crypto_hashblocks (ubyte[] x, const(ubyte)[] m, ulong n) @safe nothrow {
924 ulong[8] z = void, b = void, a = void;
925 ulong[16] w = void;
926 ulong t;
927 uint mpos = 0;
928 foreach (i; 0..8) z[i] = a[i] = dl64(x[8*i..$]);
929 while (n >= 128) {
930 foreach (i; 0..16) w[i] = dl64(m[mpos+8*i..$]);
931 foreach (i; 0..80) {
932 b[0..8] = a[0..8];
933 t = a[7]+Sigma1(a[4])+Ch(a[4], a[5], a[6])+K[i]+w[i%16];
934 b[7] = t+Sigma0(a[0])+Maj(a[0], a[1], a[2]);
935 b[3] += t;
936 //foreach (j; 0..8) a[(j+1)%8] = b[j];
937 a[1..8] = b[0..7];
938 a[0] = b[7];
939 if (i%16 == 15) {
940 foreach (j; 0..16) w[j] += w[(j+9)%16]+sigma0(w[(j+1)%16])+sigma1(w[(j+14)%16]);
943 foreach (i; 0..8) { a[i] += z[i]; z[i] = a[i]; }
944 mpos += 128;
945 n -= 128;
947 foreach (i; 0..8) ts64(x[8*i..$], z[i]);
950 private immutable ubyte[64] iv = [
951 0x6a, 0x09, 0xe6, 0x67, 0xf3, 0xbc, 0xc9, 0x08,
952 0xbb, 0x67, 0xae, 0x85, 0x84, 0xca, 0xa7, 0x3b,
953 0x3c, 0x6e, 0xf3, 0x72, 0xfe, 0x94, 0xf8, 0x2b,
954 0xa5, 0x4f, 0xf5, 0x3a, 0x5f, 0x1d, 0x36, 0xf1,
955 0x51, 0x0e, 0x52, 0x7f, 0xad, 0xe6, 0x82, 0xd1,
956 0x9b, 0x05, 0x68, 0x8c, 0x2b, 0x3e, 0x6c, 0x1f,
957 0x1f, 0x83, 0xd9, 0xab, 0xfb, 0x41, 0xbd, 0x6b,
958 0x5b, 0xe0, 0xcd, 0x19, 0x13, 0x7e, 0x21, 0x79
962 * The crypto_hash() function hashes a message 'msg'.
963 * It returns a hash 'output'. The output length of 'output' should be at least crypto_hash_BYTES.
965 * Params:
966 * output = resulting hash
967 * msg = message
969 * Returns:
970 * sha512 hash
972 void crypto_hash() (ubyte[] output, const(ubyte)[] msg) @safe nothrow
973 in {
974 assert(output.length >= crypto_hash_BYTES);
976 body {
977 ubyte[64] h = void;
978 ubyte[256] x; /*autoinit*/
979 size_t n = msg.length;
980 ulong b = n;
981 uint mpos = 0;
983 h[] = iv[];
985 crypto_hashblocks(h, msg, n);
986 mpos += n;
987 n &= 127;
988 mpos -= n;
990 x[0..n] = msg[mpos..mpos+n];
991 x[n] = 128;
993 n = 256-128*(n<112);
994 x[n-9] = b>>61;
995 ts64(x[n-8..$], b<<3);
996 crypto_hashblocks(h, x, n);
998 output[0..64] = h;
1001 private @gcc_inline void add() (ref long[16][4] p, ref long[16][4] q) @safe nothrow {
1002 long[16] a = void, b = void, c = void, d = void, t = void, e = void, f = void, g = void, h = void;
1004 Z(a, p[1], p[0]);
1005 Z(t, q[1], q[0]);
1006 M(a, a, t);
1007 A(b, p[0], p[1]);
1008 A(t, q[0], q[1]);
1009 M(b, b, t);
1010 M(c, p[3], q[3]);
1011 M(c, c, D2);
1012 M(d, p[2], q[2]);
1013 A(d, d, d);
1014 Z(e, b, a);
1015 Z(f, d, c);
1016 A(g, d, c);
1017 A(h, b, a);
1019 M(p[0], e, f);
1020 M(p[1], h, g);
1021 M(p[2], g, f);
1022 M(p[3], e, h);
1025 private @gcc_inline void cswap() (ref long[16][4] p, ref long[16][4] q, ubyte b) @safe nothrow {
1026 foreach (i; 0..4) sel25519(p[i], q[i], b);
1029 private @gcc_inline void pack() (ubyte[] r, ref long[16][4] p) @safe nothrow {
1030 long[16] tx = void, ty = void, zi = void;
1031 inv25519(zi, p[2]);
1032 M(tx, p[0], zi);
1033 M(ty, p[1], zi);
1034 pack25519(r, ty);
1035 r[31] ^= par25519(tx)<<7;
1038 private @gcc_inline void scalarmult() (ref long[16][4] p, ref long[16][4] q, const(ubyte)[] s) @safe nothrow {
1039 p[0][] = gf0[];
1040 p[1][] = gf1[];
1041 p[2][] = gf1[];
1042 p[3][] = gf0[];
1043 for (int i = 255; i >= 0; --i) {
1044 ubyte b = (s[i/8]>>(i&7))&1;
1045 cswap(p, q, b);
1046 add(q, p);
1047 add(p, p);
1048 cswap(p, q, b);
1052 private @gcc_inline void scalarbase() (ref long[16][4] p, const(ubyte)[] s) @safe nothrow {
1053 long[16][4] q = void;
1054 q[0][] = X[];
1055 q[1][] = Y[];
1056 q[2][] = gf1[];
1057 M(q[3], X, Y);
1058 scalarmult(p, q, s);
1062 * The crypto_sign_keypair() function randomly generates a secret key and
1063 * a corresponding public key.
1065 * Params:
1066 * pk = slice to put generated public key into
1067 * sk = slice to put generated secret key into
1069 * Returns:
1070 * pair of new keys
1072 void crypto_sign_keypair() (ubyte[] pk, ubyte[] sk) @trusted
1073 in {
1074 assert(pk.length >= crypto_sign_PUBLICKEYBYTES);
1075 assert(sk.length >= crypto_sign_SECRETKEYBYTES);
1077 body {
1078 ubyte[64] d = void;
1079 long[16][4] p = void;
1081 randombytes(sk, 32);
1082 crypto_hash(d, sk[0..32]);
1083 d[0] &= 248;
1084 d[31] &= 127;
1085 d[31] |= 64;
1087 scalarbase(p, d);
1088 pack(pk, p);
1090 sk[32..64] = pk[0..32];
1093 private immutable ulong[32] L = [
1094 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
1097 private @gcc_inline void modL() (ubyte[] r, long[] x) @safe nothrow {
1098 long carry;
1099 for (auto i = 63; i >= 32; --i) {
1100 int j;
1101 carry = 0;
1102 for (j = i-32; j < i-12; ++j) {
1103 x[j] += carry-16*x[i]*L[j-(i-32)];
1104 carry = (x[j]+128)>>8;
1105 x[j] -= carry<<8;
1107 x[j] += carry;
1108 x[i] = 0;
1110 carry = 0;
1111 foreach (j; 0..32) {
1112 x[j] += carry-(x[31]>>4)*L[j];
1113 carry = x[j]>>8;
1114 x[j] &= 255;
1116 foreach (j; 0..32) x[j] -= carry*L[j];
1117 foreach (i; 0..32) {
1118 x[i+1] += x[i]>>8;
1119 r[i] = x[i]&255;
1123 private @gcc_inline void reduce() (ubyte[] r) @safe nothrow {
1124 long[64] x = void;
1125 foreach (i; 0..64) x[i] = cast(ulong)r[i];
1126 r[0..64] = 0;
1127 modL(r, x);
1131 * The crypto_sign() function signs a message 'msg' using the sender's secret key 'sk'.
1132 * The crypto_sign() function returns the resulting signed message.
1134 * Params:
1135 * sm = buffer to receive signed message, must be of size at least msg.length+64
1136 * msg == message
1137 * sk == secret key, slice size must be at least crypto_sign_SECRETKEYBYTES, extra ignored
1139 * Returns:
1140 * signed message
1142 void crypto_sign() (ubyte[] sm, const(ubyte)[] msg, const(ubyte)[] sk) @trusted nothrow
1143 in {
1144 assert(sk.length >= crypto_sign_SECRETKEYBYTES);
1145 assert(sm.length >= msg.length+64);
1147 body {
1148 ubyte[64] d = void, h = void, r = void;
1149 ulong[64] x;/*autoinit*/
1150 long[16][4] p = void;
1151 size_t n = msg.length;
1152 size_t smlen = n+64;
1154 crypto_hash(d, sk[0..32]);
1155 d[0] &= 248;
1156 d[31] &= 127;
1157 d[31] |= 64;
1159 sm[64..64+n] = msg[];
1160 sm[32..64] = d[32..64];
1162 crypto_hash(r, sm[32..32+n+32]);
1163 reduce(r);
1164 scalarbase(p, r);
1165 pack(sm, p);
1167 sm[32..64] = sk[32..64];
1168 crypto_hash(h, sm[0..n+64]);
1169 reduce(h);
1171 foreach (i; 0..32) x[i] = cast(ulong)r[i];
1172 foreach (i; 0..32) foreach (j; 0..32) x[i+j] += h[i]*cast(ulong)d[j];
1173 modL(sm[32..$], cast(long[])x);
1177 * The crypto_sign() function signs a message 'msg' using the sender's secret key 'sk'.
1178 * The crypto_sign() function returns the resulting signed message.
1180 * WARNING! This function allocates!
1182 * Params:
1183 * msg == message
1184 * sk == secret key, slice size must be at least crypto_sign_SECRETKEYBYTES, extra ignored
1186 * Returns:
1187 * signed message
1189 ubyte[] crypto_sign() (const(ubyte)[] msg, const(ubyte)[] sk) @safe nothrow
1190 in {
1191 assert(sk.length >= crypto_sign_SECRETKEYBYTES);
1193 body {
1194 ubyte[] sm;
1195 size_t n = msg.length;
1196 size_t smlen = n+64;
1197 sm.length = smlen;
1198 crypto_sign(sm, msg, sk);
1199 return sm;
1202 private @gcc_inline bool unpackneg() (ref long[16][4] r, const(ubyte)[] p) @safe nothrow {
1203 long[16] t = void, chk = void, num = void, den = void, den2 = void, den4 = void, den6 = void;
1204 r[2][] = gf1[];
1205 unpack25519(r[1], p);
1206 S(num, r[1]);
1207 M(den, num, D);
1208 Z(num, num, r[2]);
1209 A(den, r[2], den);
1211 S(den2, den);
1212 S(den4, den2);
1213 M(den6, den4, den2);
1214 M(t, den6, num);
1215 M(t, t, den);
1217 pow2523(t, t);
1218 M(t, t, num);
1219 M(t, t, den);
1220 M(t, t, den);
1221 M(r[0], t, den);
1223 S(chk, r[0]);
1224 M(chk, chk, den);
1225 if (!neq25519(chk, num)) M(r[0], r[0], I);
1227 S(chk, r[0]);
1228 M(chk, chk, den);
1229 if (!neq25519(chk, num)) return false;
1231 if (par25519(r[0]) == (p[31]>>7)) Z(r[0], gf0, r[0]);
1233 M(r[3], r[0], r[1]);
1234 return true;
1238 * The crypto_sign_open() function verifies the signature in
1239 * 'sm' using the receiver's public key 'pk'.
1241 * Params:
1242 * msg = decrypted message, last 64 bytes are useless zeroes, must be of size at least sm.length
1243 * sm == signed message
1244 * pk == public key, slice size must be at least crypto_sign_PUBLICKEYBYTES, extra ignored
1246 * Returns:
1247 * success flag
1249 bool crypto_sign_open() (ubyte[] msg, const(ubyte)[] sm, const(ubyte)[] pk) @safe nothrow
1250 in {
1251 assert(pk.length >= crypto_sign_PUBLICKEYBYTES);
1252 assert(msg.length >= sm.length);
1254 body {
1255 ubyte[32] t = void;
1256 ubyte[64] h = void;
1257 long[16][4] p = void, q = void;
1258 size_t n = sm.length;
1260 if (n < 64) return false;
1262 if (!unpackneg(q, pk)) return false;
1263 msg[0..n] = sm[];
1264 msg[32..64] = pk[0..32];
1265 crypto_hash(h, msg);
1266 reduce(h);
1267 scalarmult(p, q, h);
1269 scalarbase(q, sm[32..$]);
1270 add(p, q);
1271 pack(t, p);
1273 n -= 64;
1274 if (!crypto_verify_32(sm, t)) {
1275 msg[0..n] = 0;
1276 return false;
1279 msg[0..n] = sm[64..64+n];
1280 msg[n..n+64] = 0;
1282 return true;
1287 * The crypto_sign_open() function verifies the signature in
1288 * 'sm' using the receiver's public key 'pk'.
1289 * The crypto_sign_open() function returns the message.
1291 * WARNING! This function allocates!
1293 * Params:
1294 * sm == signed message
1295 * pk == public key, slice size must be at least crypto_sign_PUBLICKEYBYTES, extra ignored
1297 * Returns:
1298 * decrypted message or null on error
1300 ubyte[] crypto_sign_open() (const(ubyte)[] sm, const(ubyte)[] pk) @safe nothrow {
1301 ubyte[] msg;
1302 msg.length = sm.length;
1303 if (!crypto_sign_open(msg, sm, pk)) return null;
1304 return msg[0..sm.length-64]; // remove signature
1308 unittest {
1309 import std.exception;
1310 import std.random;
1311 import std.range;
1312 import std.stdio;
1315 private extern(C) int open(const(char)* filename, int flags, ...);
1316 void randombytes (ubyte[] dest, size_t len) {
1317 import core.sys.posix.unistd;
1318 static int fd = -1;
1319 if (fd == -1) {
1320 for (;;) {
1321 fd = open("/dev/urandom", /*O_RDONLY*/0);
1322 if (fd != -1) break;
1323 sleep(1);
1326 size_t pos = 0;
1327 while (len > 0) {
1328 ssize_t i = read(fd, cast(void*)(&dest[pos]), (len < 1048576 ? len : 1048576));
1329 if (i < 1) {
1330 sleep(1);
1331 continue;
1333 pos += i;
1334 len -= i;
1339 static void rnd (ubyte[] dest, size_t len) {
1340 for (size_t f = 0; f < len; ++f) dest[f] = cast(ubyte)uniform(0, 256);
1342 randombytes = &rnd;
1345 randombytes = (ubyte[] dest, size_t len) {
1346 for (size_t f = 0; f < len; ++f) dest[f] = cast(ubyte)uniform(0, 256);
1349 void dumpArray(T) (T[] arr) @trusted {
1350 writefln("============================= (%s)", arr.length);
1351 for (auto f = 0; f < arr.length; ++f) {
1352 if (f && f%16 == 0) writeln();
1353 static if (T.sizeof == 1) writef(" 0x%02x", arr[f]);
1354 else static if (T.sizeof == 2) writef(" 0x%04x", arr[f]);
1355 else static if (T.sizeof == 4) writef(" 0x%08x", arr[f]);
1356 else writef(" 0x%08x", arr[f]);
1358 writeln();
1359 writeln("-----------------------------");
1362 string hashToString (const(ubyte)[] hash) {
1363 char[] s;
1364 s.length = hash.length*2;
1365 char toHex(int a) { return cast(char)(a < 10 ? a+'0' : a+'a'-10); }
1366 for (int a = 0; a < hash.length; ++a) {
1367 s[a*2] = toHex(hash[a]>>4);
1368 s[a*2+1] = toHex(hash[a]&0x0f);
1370 return assumeUnique(s);
1373 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];
1374 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];
1375 static immutable ubyte[5] m = [0x61,0x68,0x6f,0x6a,0x0a];
1376 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];
1377 ubyte[] smres, t;
1379 writeln("crypto_sign");
1380 smres = crypto_sign(m, sk);
1381 assert(smres.length == sm.length);
1382 assert(smres == sm);
1384 writeln("crypto_sign_open");
1385 t = crypto_sign_open(smres, pk);
1386 assert(t !is null);
1387 assert(t.length == m.length);
1388 assert(t == m);
1391 // based on the code by Adam D. Ruppe
1392 // 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
1393 template SHARange(T) if (isInputRange!(T)) {
1394 struct SHARange {
1395 T r;
1397 bool empty () { return state == 5; }
1399 void popFront () {
1400 if (state == 0) {
1401 r.popFront;
1402 ++length; // FIXME
1403 if (r.empty) {
1404 state = 1;
1405 position = 2;
1406 current = 0x80;
1408 } else {
1409 bool hackforward = false;
1410 if (state == 1) {
1411 current = 0x0;
1412 state = 2;
1413 if (((position+length+8)*8)%512 == 8) {
1414 --position;
1415 hackforward = true;
1417 goto proceed;
1418 //++position;
1419 } else if (state == 2) {
1420 proceed:
1421 if (!(((position+length+8)*8)%512)) {
1422 state = 3;
1423 position = 7;
1424 length *= 8;
1425 if (hackforward) goto proceedmoar;
1426 } else {
1427 ++position;
1429 } else if (state == 3) {
1430 proceedmoar:
1431 current = (length>>(position*8))&0xff;
1432 if (position == 0) state = 4; else --position;
1433 } else if (state == 4) {
1434 current = 0xff;
1435 state = 5;
1440 ubyte front () {
1441 if (state == 0) return cast(ubyte)r.front();
1442 assert(state != 5);
1443 //writefln("%x", current);
1444 return current;
1447 ubyte current;
1448 uint position;
1449 ulong length;
1450 int state = 0; // reading range, reading appended bit, reading padding, reading length, done
1455 immutable(ubyte)[] SHA256(T) (T data) if (isInputRange!(T)) {
1456 uint[8] h = [0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19];
1457 static immutable(uint[64]) k = [
1458 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
1459 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
1460 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
1461 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
1462 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
1463 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
1464 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
1465 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
1469 SHARange!(T) range;
1470 static if (is(data == SHARange)) range = data; else range.r = data;
1473 while(!range.empty) {
1474 uint[64] words;
1476 for(int a = 0; a < 16; ++a) {
1477 for(int b = 3; b >= 0; --b) {
1478 words[a] |= cast(uint)(range.front())<<(b*8);
1479 range.popFront;
1483 uint ror (uint n, int cnt) {
1484 return cast(uint)(n>>cnt)|cast(uint)(n<<(32-(cnt)));
1487 uint xrot00 (uint reax, int r0, int r1, int r2) {
1488 uint rebx = reax, recx = reax;
1489 reax = ror(reax, r0);
1490 rebx = ror(rebx, r1);
1491 recx >>= r2;
1492 reax ^= rebx;
1493 reax ^= recx;
1494 return reax;
1497 for(int a = 16; a < 64; ++a) {
1498 uint t1 = xrot00(words[a-15], 7, 18, 3);
1499 uint t2 = xrot00(words[a-2], 17, 19, 10);
1500 words[a] = words[a-16]+t1+words[a-7]+t2;
1503 uint A = h[0];
1504 uint B = h[1];
1505 uint C = h[2];
1506 uint D = h[3];
1507 uint E = h[4];
1508 uint F = h[5];
1509 uint G = h[6];
1510 uint H = h[7];
1512 uint xrot01 (uint reax, int r0, int r1, int r2) {
1513 uint rebx = reax, recx = reax;
1514 reax = ror(reax, r0);
1515 rebx = ror(rebx, r1);
1516 recx = ror(recx, r2);
1517 reax ^= rebx;
1518 reax ^= recx;
1519 return reax;
1522 for(int i = 0; i < 64; ++i) {
1523 uint s0 = xrot01(A, 2, 13, 22);
1524 uint maj = (A&B)^(A&C)^(B&C);
1525 uint t2 = s0+maj;
1526 uint s1 = xrot01(E, 6, 11, 25);
1527 uint ch = (E&F)^((~E)&G);
1528 uint t1 = H+s1+ch+k[i]+words[i];
1530 H = G;
1531 G = F;
1532 F = E;
1533 E = D+t1;
1534 D = C;
1535 C = B;
1536 B = A;
1537 A = t1+t2;
1540 h[0] += A;
1541 h[1] += B;
1542 h[2] += C;
1543 h[3] += D;
1544 h[4] += E;
1545 h[5] += F;
1546 h[6] += G;
1547 h[7] += H;
1550 ubyte[] hash;
1551 for(int j = 0; j < 8; ++j)
1552 for(int i = 3; i >= 0; --i) {
1553 hash ~= cast(ubyte)(h[j]>>(i*8))&0xff;
1556 return hash.idup;
1560 void box () {
1561 writeln("box");
1563 static immutable ubyte[32] alicesk = [
1564 0x77,0x07,0x6d,0x0a,0x73,0x18,0xa5,0x7d
1565 ,0x3c,0x16,0xc1,0x72,0x51,0xb2,0x66,0x45
1566 ,0xdf,0x4c,0x2f,0x87,0xeb,0xc0,0x99,0x2a
1567 ,0xb1,0x77,0xfb,0xa5,0x1d,0xb9,0x2c,0x2a
1570 static immutable ubyte[32] bobpk = [
1571 0xde,0x9e,0xdb,0x7d,0x7b,0x7d,0xc1,0xb4
1572 ,0xd3,0x5b,0x61,0xc2,0xec,0xe4,0x35,0x37
1573 ,0x3f,0x83,0x43,0xc8,0x5b,0x78,0x67,0x4d
1574 ,0xad,0xfc,0x7e,0x14,0x6f,0x88,0x2b,0x4f
1577 static immutable ubyte[24] nonce = [
1578 0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73
1579 ,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6
1580 ,0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37
1583 // API requires first 32 bytes to be 0
1584 static immutable ubyte[163] m = [
1585 0, 0, 0, 0, 0, 0, 0, 0
1586 , 0, 0, 0, 0, 0, 0, 0, 0
1587 , 0, 0, 0, 0, 0, 0, 0, 0
1588 , 0, 0, 0, 0, 0, 0, 0, 0
1589 ,0xbe,0x07,0x5f,0xc5,0x3c,0x81,0xf2,0xd5
1590 ,0xcf,0x14,0x13,0x16,0xeb,0xeb,0x0c,0x7b
1591 ,0x52,0x28,0xc5,0x2a,0x4c,0x62,0xcb,0xd4
1592 ,0x4b,0x66,0x84,0x9b,0x64,0x24,0x4f,0xfc
1593 ,0xe5,0xec,0xba,0xaf,0x33,0xbd,0x75,0x1a
1594 ,0x1a,0xc7,0x28,0xd4,0x5e,0x6c,0x61,0x29
1595 ,0x6c,0xdc,0x3c,0x01,0x23,0x35,0x61,0xf4
1596 ,0x1d,0xb6,0x6c,0xce,0x31,0x4a,0xdb,0x31
1597 ,0x0e,0x3b,0xe8,0x25,0x0c,0x46,0xf0,0x6d
1598 ,0xce,0xea,0x3a,0x7f,0xa1,0x34,0x80,0x57
1599 ,0xe2,0xf6,0x55,0x6a,0xd6,0xb1,0x31,0x8a
1600 ,0x02,0x4a,0x83,0x8f,0x21,0xaf,0x1f,0xde
1601 ,0x04,0x89,0x77,0xeb,0x48,0xf5,0x9f,0xfd
1602 ,0x49,0x24,0xca,0x1c,0x60,0x90,0x2e,0x52
1603 ,0xf0,0xa0,0x89,0xbc,0x76,0x89,0x70,0x40
1604 ,0xe0,0x82,0xf9,0x37,0x76,0x38,0x48,0x64
1605 ,0x5e,0x07,0x05
1608 ubyte[163] c;
1611 static immutable ubyte[] res = [
1612 0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5
1613 ,0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9
1614 ,0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73
1615 ,0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce
1616 ,0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4
1617 ,0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a
1618 ,0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b
1619 ,0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72
1620 ,0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2
1621 ,0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38
1622 ,0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a
1623 ,0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae
1624 ,0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea
1625 ,0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda
1626 ,0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde
1627 ,0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3
1628 ,0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6
1629 ,0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74
1630 ,0xe3,0x55,0xa5];
1631 /*crypto_box_curve25519xsalsa20poly1305*/crypto_box(c,m,nonce,bobpk,alicesk);
1632 for (auto f = 16; f < 163; ++f) assert(c[f] == res[f-16]);
1634 box();
1636 void box2 () {
1637 writeln("box2");
1638 static immutable ubyte[32] bobsk = [
1639 0x5d,0xab,0x08,0x7e,0x62,0x4a,0x8a,0x4b
1640 ,0x79,0xe1,0x7f,0x8b,0x83,0x80,0x0e,0xe6
1641 ,0x6f,0x3b,0xb1,0x29,0x26,0x18,0xb6,0xfd
1642 ,0x1c,0x2f,0x8b,0x27,0xff,0x88,0xe0,0xeb
1645 static immutable ubyte[32] alicepk = [
1646 0x85,0x20,0xf0,0x09,0x89,0x30,0xa7,0x54
1647 ,0x74,0x8b,0x7d,0xdc,0xb4,0x3e,0xf7,0x5a
1648 ,0x0d,0xbf,0x3a,0x0d,0x26,0x38,0x1a,0xf4
1649 ,0xeb,0xa4,0xa9,0x8e,0xaa,0x9b,0x4e,0x6a
1652 static immutable ubyte[24] nonce = [
1653 0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73
1654 ,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6
1655 ,0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37
1658 // API requires first 16 bytes to be 0
1659 static immutable ubyte[163] c = [
1660 0, 0, 0, 0, 0, 0, 0, 0
1661 , 0, 0, 0, 0, 0, 0, 0, 0
1662 ,0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5
1663 ,0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9
1664 ,0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73
1665 ,0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce
1666 ,0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4
1667 ,0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a
1668 ,0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b
1669 ,0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72
1670 ,0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2
1671 ,0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38
1672 ,0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a
1673 ,0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae
1674 ,0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea
1675 ,0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda
1676 ,0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde
1677 ,0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3
1678 ,0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6
1679 ,0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74
1680 ,0xe3,0x55,0xa5
1683 ubyte[163] m;
1685 static immutable ubyte[] res = [
1686 0xbe,0x07,0x5f,0xc5,0x3c,0x81,0xf2,0xd5
1687 ,0xcf,0x14,0x13,0x16,0xeb,0xeb,0x0c,0x7b
1688 ,0x52,0x28,0xc5,0x2a,0x4c,0x62,0xcb,0xd4
1689 ,0x4b,0x66,0x84,0x9b,0x64,0x24,0x4f,0xfc
1690 ,0xe5,0xec,0xba,0xaf,0x33,0xbd,0x75,0x1a
1691 ,0x1a,0xc7,0x28,0xd4,0x5e,0x6c,0x61,0x29
1692 ,0x6c,0xdc,0x3c,0x01,0x23,0x35,0x61,0xf4
1693 ,0x1d,0xb6,0x6c,0xce,0x31,0x4a,0xdb,0x31
1694 ,0x0e,0x3b,0xe8,0x25,0x0c,0x46,0xf0,0x6d
1695 ,0xce,0xea,0x3a,0x7f,0xa1,0x34,0x80,0x57
1696 ,0xe2,0xf6,0x55,0x6a,0xd6,0xb1,0x31,0x8a
1697 ,0x02,0x4a,0x83,0x8f,0x21,0xaf,0x1f,0xde
1698 ,0x04,0x89,0x77,0xeb,0x48,0xf5,0x9f,0xfd
1699 ,0x49,0x24,0xca,0x1c,0x60,0x90,0x2e,0x52
1700 ,0xf0,0xa0,0x89,0xbc,0x76,0x89,0x70,0x40
1701 ,0xe0,0x82,0xf9,0x37,0x76,0x38,0x48,0x64
1702 ,0x5e,0x07,0x05
1705 assert(/*crypto_box_curve25519xsalsa20poly1305_open*/crypto_box_open(m,c,nonce,alicepk,bobsk));
1706 for (auto f = 32; f < 163; ++f) assert(m[f] == res[f-32]);
1708 box2();
1710 void box7 () {
1711 writeln("box7");
1712 ubyte[crypto_box_SECRETKEYBYTES] alicesk;
1713 ubyte[crypto_box_PUBLICKEYBYTES] alicepk;
1714 ubyte[crypto_box_SECRETKEYBYTES] bobsk;
1715 ubyte[crypto_box_PUBLICKEYBYTES] bobpk;
1716 ubyte[crypto_box_NONCEBYTES] n;
1717 ubyte[10000] m, c, m2;
1718 for (auto mlen = 0; mlen < 1000 && mlen+crypto_box_ZEROBYTES < m.length; ++mlen) {
1719 crypto_box_keypair(alicepk,alicesk);
1720 crypto_box_keypair(bobpk,bobsk);
1721 randombytes(n,crypto_box_NONCEBYTES);
1722 randombytes(m[crypto_box_ZEROBYTES..$],mlen);
1723 crypto_box(c[0..mlen+crypto_box_ZEROBYTES],m,n,bobpk,alicesk);
1724 assert(crypto_box_open(m2[0..mlen+crypto_box_ZEROBYTES],c,n,alicepk,bobsk));
1725 for (auto i = 0; i < mlen+crypto_box_ZEROBYTES; ++i) assert(m2[i] == m[i]);
1728 version(unittest_full) box7(); // it's slow
1730 void box8 () {
1731 writeln("box8");
1732 ubyte[crypto_box_SECRETKEYBYTES] alicesk;
1733 ubyte[crypto_box_PUBLICKEYBYTES] alicepk;
1734 ubyte[crypto_box_SECRETKEYBYTES] bobsk;
1735 ubyte[crypto_box_PUBLICKEYBYTES] bobpk;
1736 ubyte[crypto_box_NONCEBYTES] n;
1737 ubyte[10000] m, c, m2;
1738 for (auto mlen = 0; mlen < 1000 && mlen+crypto_box_ZEROBYTES < m.length; ++mlen) {
1739 crypto_box_keypair(alicepk,alicesk);
1740 crypto_box_keypair(bobpk,bobsk);
1741 randombytes(n,crypto_box_NONCEBYTES);
1742 randombytes(m[crypto_box_ZEROBYTES..$],mlen);
1743 crypto_box(c[0..mlen+crypto_box_ZEROBYTES],m,n,bobpk,alicesk);
1744 int caught = 0;
1745 while (caught < 10) {
1746 c[uniform(0, mlen+crypto_box_ZEROBYTES)] = cast(ubyte)uniform(0, 256);
1747 if (crypto_box_open(m2[0..mlen+crypto_box_ZEROBYTES],c,n,alicepk,bobsk)) {
1748 for (auto i = 0; i < mlen+crypto_box_ZEROBYTES; ++i) assert(m2[i] == m[i]);
1749 } else {
1750 ++caught;
1753 assert(caught == 10);
1756 version(unittest_full) box8(); // it's slow
1758 void core1 () {
1759 writeln("core1");
1760 static immutable ubyte[32] shared_ = [
1761 0x4a,0x5d,0x9d,0x5b,0xa4,0xce,0x2d,0xe1
1762 ,0x72,0x8e,0x3b,0xf4,0x80,0x35,0x0f,0x25
1763 ,0xe0,0x7e,0x21,0xc9,0x47,0xd1,0x9e,0x33
1764 ,0x76,0xf0,0x9b,0x3c,0x1e,0x16,0x17,0x42
1767 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];
1769 static immutable ubyte[16] c = [
1770 0x65,0x78,0x70,0x61,0x6e,0x64,0x20,0x33
1771 ,0x32,0x2d,0x62,0x79,0x74,0x65,0x20,0x6b
1774 ubyte[32] firstkey;
1776 static immutable ubyte[32] res = [
1777 0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4
1778 ,0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7
1779 ,0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2
1780 ,0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89
1783 crypto_core_hsalsa20(firstkey,zero,shared_,c);
1784 assert(firstkey == res);
1786 core1();
1788 void core2 () {
1789 writeln("core2");
1790 static immutable ubyte[32]firstkey = [
1791 0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4
1792 ,0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7
1793 ,0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2
1794 ,0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89
1797 static immutable ubyte[16]nonceprefix = [
1798 0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73
1799 ,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6
1802 static immutable ubyte[16] c = [
1803 0x65,0x78,0x70,0x61,0x6e,0x64,0x20,0x33
1804 ,0x32,0x2d,0x62,0x79,0x74,0x65,0x20,0x6b
1807 ubyte[32] secondkey;
1809 static immutable ubyte[32] res = [
1810 0xdc,0x90,0x8d,0xda,0x0b,0x93,0x44,0xa9
1811 ,0x53,0x62,0x9b,0x73,0x38,0x20,0x77,0x88
1812 ,0x80,0xf3,0xce,0xb4,0x21,0xbb,0x61,0xb9
1813 ,0x1c,0xbd,0x4c,0x3e,0x66,0x25,0x6c,0xe4
1816 crypto_core_hsalsa20(secondkey,nonceprefix,firstkey,c);
1817 assert(secondkey == res);
1819 core2();
1821 void core3 () {
1822 writeln("core3");
1823 static immutable ubyte[32] secondkey = [
1824 0xdc,0x90,0x8d,0xda,0x0b,0x93,0x44,0xa9
1825 ,0x53,0x62,0x9b,0x73,0x38,0x20,0x77,0x88
1826 ,0x80,0xf3,0xce,0xb4,0x21,0xbb,0x61,0xb9
1827 ,0x1c,0xbd,0x4c,0x3e,0x66,0x25,0x6c,0xe4
1830 static immutable ubyte[8] noncesuffix = [
1831 0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37
1834 static immutable ubyte[16] c = [
1835 0x65,0x78,0x70,0x61,0x6e,0x64,0x20,0x33
1836 ,0x32,0x2d,0x62,0x79,0x74,0x65,0x20,0x6b
1839 static ubyte[16] input = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] ;
1841 static ubyte[64*256*256] output;
1843 static ubyte[64] h;
1845 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];
1847 int pos = 0;
1848 for (auto i = 0; i < 8; ++i) input[i] = noncesuffix[i];
1849 do {
1850 do {
1851 crypto_core_salsa20(output[pos..$],input,secondkey,c);
1852 pos += 64;
1853 } while (++input[8]);
1854 } while (++input[9]);
1855 crypto_hash(h,output);
1856 assert(h == res);
1858 version(unittest_full) core3(); // it's slow
1860 void core4 () {
1861 writeln("core4");
1862 static immutable ubyte[32] k = [
1863 1, 2, 3, 4, 5, 6, 7, 8
1864 , 9, 10, 11, 12, 13, 14, 15, 16
1865 ,201,202,203,204,205,206,207,208
1866 ,209,210,211,212,213,214,215,216
1869 static immutable ubyte[16] input = [
1870 101,102,103,104,105,106,107,108
1871 ,109,110,111,112,113,114,115,116
1874 static immutable ubyte[16] c = [
1875 101,120,112, 97,110,100, 32, 51
1876 , 50, 45, 98,121,116,101, 32,107
1879 ubyte[64] output;
1881 static immutable ubyte[64] res = [
1882 69, 37, 68, 39, 41, 15,107,193
1883 ,255,139,122, 6,170,233,217, 98
1884 , 89,144,182,106, 21, 51,200, 65
1885 ,239, 49,222, 34,215,114, 40,126
1886 ,104,197, 7,225,197,153, 31, 2
1887 ,102, 78, 76,176, 84,245,246,184
1888 ,177,160,133,130, 6, 72,149,119
1889 ,192,195,132,236,234,103,246, 74
1892 crypto_core_salsa20(output,input,k,c);
1893 assert(output == res);
1895 core4();
1897 void core5 () {
1898 writeln("core5");
1899 static immutable ubyte[32] k = [
1900 0xee,0x30,0x4f,0xca,0x27,0x00,0x8d,0x8c
1901 ,0x12,0x6f,0x90,0x02,0x79,0x01,0xd8,0x0f
1902 ,0x7f,0x1d,0x8b,0x8d,0xc9,0x36,0xcf,0x3b
1903 ,0x9f,0x81,0x96,0x92,0x82,0x7e,0x57,0x77
1906 static immutable ubyte[16] input = [
1907 0x81,0x91,0x8e,0xf2,0xa5,0xe0,0xda,0x9b
1908 ,0x3e,0x90,0x60,0x52,0x1e,0x4b,0xb3,0x52
1911 static immutable ubyte[16] c = [
1912 101,120,112, 97,110,100, 32, 51
1913 , 50, 45, 98,121,116,101, 32,107
1916 ubyte[32] output;
1918 static immutable ubyte[32] res = [
1919 0xbc,0x1b,0x30,0xfc,0x07,0x2c,0xc1,0x40
1920 ,0x75,0xe4,0xba,0xa7,0x31,0xb5,0xa8,0x45
1921 ,0xea,0x9b,0x11,0xe9,0xa5,0x19,0x1f,0x94
1922 ,0xe1,0x8c,0xba,0x8f,0xd8,0x21,0xa7,0xcd
1925 crypto_core_hsalsa20(output,input,k,c);
1926 assert(output == res);
1928 core5();
1930 void core6 () {
1931 writeln("core6");
1932 static immutable ubyte[32] k = [
1933 0xee,0x30,0x4f,0xca,0x27,0x00,0x8d,0x8c
1934 ,0x12,0x6f,0x90,0x02,0x79,0x01,0xd8,0x0f
1935 ,0x7f,0x1d,0x8b,0x8d,0xc9,0x36,0xcf,0x3b
1936 ,0x9f,0x81,0x96,0x92,0x82,0x7e,0x57,0x77
1939 static immutable ubyte[16] input = [
1940 0x81,0x91,0x8e,0xf2,0xa5,0xe0,0xda,0x9b
1941 ,0x3e,0x90,0x60,0x52,0x1e,0x4b,0xb3,0x52
1944 static immutable ubyte[16] c = [
1945 101,120,112, 97,110,100, 32, 51
1946 , 50, 45, 98,121,116,101, 32,107
1949 ubyte[64] output;
1951 static immutable ubyte[32] res = [
1952 0xbc,0x1b,0x30,0xfc,0x07,0x2c,0xc1,0x40
1953 ,0x75,0xe4,0xba,0xa7,0x31,0xb5,0xa8,0x45
1954 ,0xea,0x9b,0x11,0xe9,0xa5,0x19,0x1f,0x94
1955 ,0xe1,0x8c,0xba,0x8f,0xd8,0x21,0xa7,0xcd
1958 ubyte[32] pp;
1959 uint pppos = 0;
1961 void print(const(ubyte)[] x, const(ubyte)[] y)
1963 uint borrow = 0;
1964 for (auto i = 0; i < 4; ++i) {
1965 uint xi = x[i];
1966 uint yi = y[i];
1967 //printf(",0x%02x",255&(xi-yi-borrow));
1968 pp[pppos++] = cast(ubyte)(255&(xi-yi-borrow));
1969 borrow = (xi < yi+borrow);
1973 crypto_core_salsa20(output,input,k,c);
1974 print(output,c);
1975 print(output[20..$],c[4..$]);
1976 print(output[40..$],c[8..$]);
1977 print(output[60..$],c[12..$]);
1978 print(output[24..$],input);
1979 print(output[28..$],input[4..$]);
1980 print(output[32..$],input[8..$]);
1981 print(output[36..$],input[12..$]);
1982 assert(pp == res);
1984 core6();
1986 void hash () {
1987 writeln("hash");
1988 static immutable ubyte[8] x = ['t','e','s','t','i','n','g','\n'];
1989 static ubyte[crypto_hash_BYTES] h;
1990 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];
1991 crypto_hash(h,x);
1992 //for (auto f = 0; f < crypto_hash_BYTES; ++f) assert(h[f] == res[f]);
1993 assert(h == res);
1995 hash();
1997 void onetimeauth () {
1998 writeln("onetimeauth");
1999 static immutable ubyte[32] rs = [
2000 0xee,0xa6,0xa7,0x25,0x1c,0x1e,0x72,0x91
2001 ,0x6d,0x11,0xc2,0xcb,0x21,0x4d,0x3c,0x25
2002 ,0x25,0x39,0x12,0x1d,0x8e,0x23,0x4e,0x65
2003 ,0x2d,0x65,0x1f,0xa4,0xc8,0xcf,0xf8,0x80
2006 static immutable ubyte[131] c = [
2007 0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73
2008 ,0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce
2009 ,0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4
2010 ,0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a
2011 ,0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b
2012 ,0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72
2013 ,0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2
2014 ,0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38
2015 ,0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a
2016 ,0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae
2017 ,0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea
2018 ,0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda
2019 ,0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde
2020 ,0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3
2021 ,0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6
2022 ,0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74
2023 ,0xe3,0x55,0xa5
2026 ubyte[16] a;
2028 static immutable ubyte[16] res = [0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5,0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9];
2030 /*crypto_onetimeauth_poly1305*/crypto_onetimeauth(a,c,rs);
2031 assert(a == res);
2033 onetimeauth();
2035 void onetimeauth2 () {
2036 writeln("onetimeauth2");
2037 static immutable ubyte[32] rs = [
2038 0xee,0xa6,0xa7,0x25,0x1c,0x1e,0x72,0x91
2039 ,0x6d,0x11,0xc2,0xcb,0x21,0x4d,0x3c,0x25
2040 ,0x25,0x39,0x12,0x1d,0x8e,0x23,0x4e,0x65
2041 ,0x2d,0x65,0x1f,0xa4,0xc8,0xcf,0xf8,0x80
2044 static immutable ubyte[131] c = [
2045 0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73
2046 ,0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce
2047 ,0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4
2048 ,0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a
2049 ,0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b
2050 ,0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72
2051 ,0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2
2052 ,0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38
2053 ,0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a
2054 ,0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae
2055 ,0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea
2056 ,0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda
2057 ,0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde
2058 ,0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3
2059 ,0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6
2060 ,0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74
2061 ,0xe3,0x55,0xa5
2064 static immutable ubyte[16] a = [
2065 0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5
2066 ,0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9
2069 assert(/*crypto_onetimeauth_poly1305_verify*/crypto_onetimeauth_verify(a,c,rs));
2071 onetimeauth2();
2073 void onetimeauth7 () {
2074 writeln("onetimeauth7");
2075 static ubyte[32] key;
2076 static ubyte[10000] c;
2077 static ubyte[16] a;
2079 for (auto clen = 0; clen < 10000; ++clen) {
2080 //if (clen%512 == 0) { writef("\r%s", clen); stdout.flush(); }
2081 randombytes(key, key.length);
2082 randombytes(c, clen);
2083 crypto_onetimeauth(a,c[0..clen],key);
2084 assert(crypto_onetimeauth_verify(a,c[0..clen],key));
2085 if (clen > 0) {
2086 c[uniform(0, clen)] += 1+(uniform(0, 255));
2087 assert(!crypto_onetimeauth_verify(a,c[0..clen],key));
2088 a[uniform(0, a.length)] += 1+(uniform(0, 255));
2089 assert(!crypto_onetimeauth_verify(a,c[0..clen],key));
2093 version(unittest_full) onetimeauth7(); // it's slow
2095 void scalarmult () {
2096 writeln("scalarmult");
2097 static immutable ubyte[32] alicesk = [
2098 0x77,0x07,0x6d,0x0a,0x73,0x18,0xa5,0x7d
2099 ,0x3c,0x16,0xc1,0x72,0x51,0xb2,0x66,0x45
2100 ,0xdf,0x4c,0x2f,0x87,0xeb,0xc0,0x99,0x2a
2101 ,0xb1,0x77,0xfb,0xa5,0x1d,0xb9,0x2c,0x2a
2104 ubyte[32] alicepk;
2106 static immutable ubyte[32] res = [
2107 0x85,0x20,0xf0,0x09,0x89,0x30,0xa7,0x54
2108 ,0x74,0x8b,0x7d,0xdc,0xb4,0x3e,0xf7,0x5a
2109 ,0x0d,0xbf,0x3a,0x0d,0x26,0x38,0x1a,0xf4
2110 ,0xeb,0xa4,0xa9,0x8e,0xaa,0x9b,0x4e,0x6a
2113 /*crypto_scalarmult_curve25519_base*/crypto_scalarmult_base(alicepk,alicesk);
2114 assert(alicepk == res);
2116 scalarmult();
2118 void scalarmult2 () {
2119 writeln("scalarmult2");
2120 static immutable ubyte[32] bobsk = [
2121 0x5d,0xab,0x08,0x7e,0x62,0x4a,0x8a,0x4b
2122 ,0x79,0xe1,0x7f,0x8b,0x83,0x80,0x0e,0xe6
2123 ,0x6f,0x3b,0xb1,0x29,0x26,0x18,0xb6,0xfd
2124 ,0x1c,0x2f,0x8b,0x27,0xff,0x88,0xe0,0xeb
2127 ubyte[32] bobpk;
2129 static immutable ubyte[32] res = [
2130 0xde,0x9e,0xdb,0x7d,0x7b,0x7d,0xc1,0xb4
2131 ,0xd3,0x5b,0x61,0xc2,0xec,0xe4,0x35,0x37
2132 ,0x3f,0x83,0x43,0xc8,0x5b,0x78,0x67,0x4d
2133 ,0xad,0xfc,0x7e,0x14,0x6f,0x88,0x2b,0x4f
2136 /*crypto_scalarmult_curve25519_base*/crypto_scalarmult_base(bobpk,bobsk);
2137 assert(bobpk == res);
2139 scalarmult2();
2141 void scalarmult5 () {
2142 writeln("scalarmult5");
2143 static immutable ubyte[32] alicesk = [
2144 0x77,0x07,0x6d,0x0a,0x73,0x18,0xa5,0x7d
2145 ,0x3c,0x16,0xc1,0x72,0x51,0xb2,0x66,0x45
2146 ,0xdf,0x4c,0x2f,0x87,0xeb,0xc0,0x99,0x2a
2147 ,0xb1,0x77,0xfb,0xa5,0x1d,0xb9,0x2c,0x2a
2150 static immutable ubyte[32] bobpk = [
2151 0xde,0x9e,0xdb,0x7d,0x7b,0x7d,0xc1,0xb4
2152 ,0xd3,0x5b,0x61,0xc2,0xec,0xe4,0x35,0x37
2153 ,0x3f,0x83,0x43,0xc8,0x5b,0x78,0x67,0x4d
2154 ,0xad,0xfc,0x7e,0x14,0x6f,0x88,0x2b,0x4f
2157 ubyte[32] k;
2159 static immutable ubyte[32] res = [
2160 0x4a,0x5d,0x9d,0x5b,0xa4,0xce,0x2d,0xe1
2161 ,0x72,0x8e,0x3b,0xf4,0x80,0x35,0x0f,0x25
2162 ,0xe0,0x7e,0x21,0xc9,0x47,0xd1,0x9e,0x33
2163 ,0x76,0xf0,0x9b,0x3c,0x1e,0x16,0x17,0x42
2166 crypto_scalarmult(k,alicesk,bobpk);
2167 assert(k == res);
2169 scalarmult5();
2171 void scalarmult6 () {
2172 writeln("scalarmult6");
2173 static immutable ubyte[32] bobsk = [
2174 0x5d,0xab,0x08,0x7e,0x62,0x4a,0x8a,0x4b
2175 ,0x79,0xe1,0x7f,0x8b,0x83,0x80,0x0e,0xe6
2176 ,0x6f,0x3b,0xb1,0x29,0x26,0x18,0xb6,0xfd
2177 ,0x1c,0x2f,0x8b,0x27,0xff,0x88,0xe0,0xeb
2180 static immutable ubyte[32] alicepk = [
2181 0x85,0x20,0xf0,0x09,0x89,0x30,0xa7,0x54
2182 ,0x74,0x8b,0x7d,0xdc,0xb4,0x3e,0xf7,0x5a
2183 ,0x0d,0xbf,0x3a,0x0d,0x26,0x38,0x1a,0xf4
2184 ,0xeb,0xa4,0xa9,0x8e,0xaa,0x9b,0x4e,0x6a
2187 ubyte[32] k;
2189 static immutable ubyte[32] res = [
2190 0x4a,0x5d,0x9d,0x5b,0xa4,0xce,0x2d,0xe1
2191 ,0x72,0x8e,0x3b,0xf4,0x80,0x35,0x0f,0x25
2192 ,0xe0,0x7e,0x21,0xc9,0x47,0xd1,0x9e,0x33
2193 ,0x76,0xf0,0x9b,0x3c,0x1e,0x16,0x17,0x42
2196 crypto_scalarmult(k,bobsk,alicepk);
2197 assert(k == res);
2199 scalarmult6();
2201 void secretbox () {
2202 writeln("secretbox");
2203 static immutable ubyte[32] firstkey = [
2204 0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4
2205 ,0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7
2206 ,0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2
2207 ,0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89
2210 static immutable ubyte[24] nonce = [
2211 0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73
2212 ,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6
2213 ,0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37
2216 // API requires first 32 bytes to be 0
2217 static immutable ubyte[163] m = [
2218 0, 0, 0, 0, 0, 0, 0, 0
2219 , 0, 0, 0, 0, 0, 0, 0, 0
2220 , 0, 0, 0, 0, 0, 0, 0, 0
2221 , 0, 0, 0, 0, 0, 0, 0, 0
2222 ,0xbe,0x07,0x5f,0xc5,0x3c,0x81,0xf2,0xd5
2223 ,0xcf,0x14,0x13,0x16,0xeb,0xeb,0x0c,0x7b
2224 ,0x52,0x28,0xc5,0x2a,0x4c,0x62,0xcb,0xd4
2225 ,0x4b,0x66,0x84,0x9b,0x64,0x24,0x4f,0xfc
2226 ,0xe5,0xec,0xba,0xaf,0x33,0xbd,0x75,0x1a
2227 ,0x1a,0xc7,0x28,0xd4,0x5e,0x6c,0x61,0x29
2228 ,0x6c,0xdc,0x3c,0x01,0x23,0x35,0x61,0xf4
2229 ,0x1d,0xb6,0x6c,0xce,0x31,0x4a,0xdb,0x31
2230 ,0x0e,0x3b,0xe8,0x25,0x0c,0x46,0xf0,0x6d
2231 ,0xce,0xea,0x3a,0x7f,0xa1,0x34,0x80,0x57
2232 ,0xe2,0xf6,0x55,0x6a,0xd6,0xb1,0x31,0x8a
2233 ,0x02,0x4a,0x83,0x8f,0x21,0xaf,0x1f,0xde
2234 ,0x04,0x89,0x77,0xeb,0x48,0xf5,0x9f,0xfd
2235 ,0x49,0x24,0xca,0x1c,0x60,0x90,0x2e,0x52
2236 ,0xf0,0xa0,0x89,0xbc,0x76,0x89,0x70,0x40
2237 ,0xe0,0x82,0xf9,0x37,0x76,0x38,0x48,0x64
2238 ,0x5e,0x07,0x05
2241 static immutable ubyte[] res = [
2242 0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5
2243 ,0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9
2244 ,0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73
2245 ,0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce
2246 ,0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4
2247 ,0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a
2248 ,0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b
2249 ,0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72
2250 ,0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2
2251 ,0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38
2252 ,0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a
2253 ,0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae
2254 ,0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea
2255 ,0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda
2256 ,0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde
2257 ,0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3
2258 ,0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6
2259 ,0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74
2260 ,0xe3,0x55,0xa5
2263 ubyte[163] c;
2264 crypto_secretbox(c,m,nonce,firstkey);
2265 for (auto i = 16; i < 163; ++i) assert(c[i] == res[i-16]);
2267 secretbox();
2269 void secretbox2 () {
2270 writeln("secretbox2");
2271 static immutable ubyte[32] firstkey = [
2272 0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4
2273 ,0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7
2274 ,0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2
2275 ,0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89
2278 static immutable ubyte[24] nonce = [
2279 0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73
2280 ,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6
2281 ,0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37
2284 // API requires first 16 bytes to be 0
2285 static immutable ubyte[163] c = [
2286 0, 0, 0, 0, 0, 0, 0, 0
2287 , 0, 0, 0, 0, 0, 0, 0, 0
2288 ,0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5
2289 ,0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9
2290 ,0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73
2291 ,0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce
2292 ,0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4
2293 ,0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a
2294 ,0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b
2295 ,0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72
2296 ,0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2
2297 ,0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38
2298 ,0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a
2299 ,0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae
2300 ,0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea
2301 ,0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda
2302 ,0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde
2303 ,0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3
2304 ,0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6
2305 ,0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74
2306 ,0xe3,0x55,0xa5
2309 static immutable ubyte[] res = [
2310 0xbe,0x07,0x5f,0xc5,0x3c,0x81,0xf2,0xd5
2311 ,0xcf,0x14,0x13,0x16,0xeb,0xeb,0x0c,0x7b
2312 ,0x52,0x28,0xc5,0x2a,0x4c,0x62,0xcb,0xd4
2313 ,0x4b,0x66,0x84,0x9b,0x64,0x24,0x4f,0xfc
2314 ,0xe5,0xec,0xba,0xaf,0x33,0xbd,0x75,0x1a
2315 ,0x1a,0xc7,0x28,0xd4,0x5e,0x6c,0x61,0x29
2316 ,0x6c,0xdc,0x3c,0x01,0x23,0x35,0x61,0xf4
2317 ,0x1d,0xb6,0x6c,0xce,0x31,0x4a,0xdb,0x31
2318 ,0x0e,0x3b,0xe8,0x25,0x0c,0x46,0xf0,0x6d
2319 ,0xce,0xea,0x3a,0x7f,0xa1,0x34,0x80,0x57
2320 ,0xe2,0xf6,0x55,0x6a,0xd6,0xb1,0x31,0x8a
2321 ,0x02,0x4a,0x83,0x8f,0x21,0xaf,0x1f,0xde
2322 ,0x04,0x89,0x77,0xeb,0x48,0xf5,0x9f,0xfd
2323 ,0x49,0x24,0xca,0x1c,0x60,0x90,0x2e,0x52
2324 ,0xf0,0xa0,0x89,0xbc,0x76,0x89,0x70,0x40
2325 ,0xe0,0x82,0xf9,0x37,0x76,0x38,0x48,0x64
2326 ,0x5e,0x07,0x05
2329 ubyte[163] m;
2331 assert(crypto_secretbox_open(m,c,nonce,firstkey));
2332 for (auto i = 32; i < 163; ++i) assert(m[i] == res[i-32]);
2334 secretbox2();
2336 void secretbox7 () {
2337 writeln("secretbox7");
2338 static ubyte[crypto_secretbox_KEYBYTES] k;
2339 static ubyte[crypto_secretbox_NONCEBYTES] n;
2340 static ubyte[10000] m, c, m2;
2341 for (auto mlen = 0; mlen < 1000 && mlen+crypto_secretbox_ZEROBYTES < m.length; ++mlen) {
2342 randombytes(k,crypto_secretbox_KEYBYTES);
2343 randombytes(n,crypto_secretbox_NONCEBYTES);
2344 randombytes(m[crypto_secretbox_ZEROBYTES..$],mlen);
2345 crypto_secretbox(c[0..mlen+crypto_secretbox_ZEROBYTES],m,n,k);
2346 assert(crypto_secretbox_open(m2[0..mlen+crypto_secretbox_ZEROBYTES],c,n,k));
2347 for (auto i = 0; i < mlen+crypto_secretbox_ZEROBYTES; ++i) assert(m2[i] == m[i]);
2350 secretbox7();
2352 void secretbox8 () {
2353 writeln("secretbox8");
2354 static ubyte[crypto_secretbox_KEYBYTES] k;
2355 static ubyte[crypto_secretbox_NONCEBYTES] n;
2356 static ubyte[10000] m, c, m2;
2357 for (auto mlen = 0; mlen < 1000 && mlen+crypto_secretbox_ZEROBYTES < m.length; ++mlen) {
2358 randombytes(k,crypto_secretbox_KEYBYTES);
2359 randombytes(n,crypto_secretbox_NONCEBYTES);
2360 randombytes(m[crypto_secretbox_ZEROBYTES..$],mlen);
2361 crypto_secretbox(c[0..mlen+crypto_secretbox_ZEROBYTES],m,n,k);
2362 auto caught = 0;
2363 while (caught < 10) {
2364 c[uniform(0, mlen+crypto_secretbox_ZEROBYTES)] = cast(ubyte)uniform(0, 256);
2365 if (crypto_secretbox_open(m2[0..mlen+crypto_secretbox_ZEROBYTES],c,n,k)) {
2366 for (auto i = 0; i < mlen+crypto_secretbox_ZEROBYTES; ++i) assert(m2[i] == m[i]);
2368 ++caught;
2370 assert(caught == 10);
2373 version(unittest_full) secretbox8(); // it's slow
2375 void stream () {
2376 writeln("stream");
2377 static immutable ubyte[32] firstkey = [
2378 0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4
2379 ,0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7
2380 ,0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2
2381 ,0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89
2384 static immutable ubyte[24] nonce = [
2385 0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73
2386 ,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6
2387 ,0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37
2390 static ubyte[4194304] output;
2392 //ubyte h[32];
2393 //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];
2395 crypto_stream(output,nonce,firstkey);
2396 //crypto_hash_sha256(h,output,sizeof output);
2397 assert(hashToString(SHA256(output[0..$])) == "662b9d0e3463029156069b12f918691a98f7dfb2ca0393c96bbfc6b1fbd630a2");
2399 stream();
2401 void stream2 () {
2402 writeln("stream2");
2403 static immutable ubyte[32] secondkey = [
2404 0xdc,0x90,0x8d,0xda,0x0b,0x93,0x44,0xa9
2405 ,0x53,0x62,0x9b,0x73,0x38,0x20,0x77,0x88
2406 ,0x80,0xf3,0xce,0xb4,0x21,0xbb,0x61,0xb9
2407 ,0x1c,0xbd,0x4c,0x3e,0x66,0x25,0x6c,0xe4
2410 static immutable ubyte[8] noncesuffix = [
2411 0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37
2414 static ubyte[4194304] output;
2416 crypto_stream_salsa20(output,noncesuffix,secondkey);
2417 assert(hashToString(SHA256(output[0..$])) == "662b9d0e3463029156069b12f918691a98f7dfb2ca0393c96bbfc6b1fbd630a2");
2419 stream2();
2421 void stream3 () {
2422 writeln("stream3");
2423 static immutable ubyte[32] firstkey = [
2424 0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4
2425 ,0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7
2426 ,0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2
2427 ,0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89
2430 static immutable ubyte[24] nonce = [
2431 0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73
2432 ,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6
2433 ,0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37
2436 ubyte[32] rs;
2438 static immutable ubyte[32] res = [
2439 0xee,0xa6,0xa7,0x25,0x1c,0x1e,0x72,0x91
2440 ,0x6d,0x11,0xc2,0xcb,0x21,0x4d,0x3c,0x25
2441 ,0x25,0x39,0x12,0x1d,0x8e,0x23,0x4e,0x65
2442 ,0x2d,0x65,0x1f,0xa4,0xc8,0xcf,0xf8,0x80
2445 crypto_stream/*_xsalsa20*/(rs,nonce,firstkey);
2446 assert(rs == res);
2448 stream3();
2450 void stream4 () {
2451 writeln("stream4");
2452 static immutable ubyte[32] firstkey = [
2453 0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4
2454 ,0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7
2455 ,0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2
2456 ,0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89
2459 static immutable ubyte[24] nonce = [
2460 0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73
2461 ,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6
2462 ,0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37
2465 static immutable ubyte[163] m = [
2466 0, 0, 0, 0, 0, 0, 0, 0
2467 , 0, 0, 0, 0, 0, 0, 0, 0
2468 , 0, 0, 0, 0, 0, 0, 0, 0
2469 , 0, 0, 0, 0, 0, 0, 0, 0
2470 ,0xbe,0x07,0x5f,0xc5,0x3c,0x81,0xf2,0xd5
2471 ,0xcf,0x14,0x13,0x16,0xeb,0xeb,0x0c,0x7b
2472 ,0x52,0x28,0xc5,0x2a,0x4c,0x62,0xcb,0xd4
2473 ,0x4b,0x66,0x84,0x9b,0x64,0x24,0x4f,0xfc
2474 ,0xe5,0xec,0xba,0xaf,0x33,0xbd,0x75,0x1a
2475 ,0x1a,0xc7,0x28,0xd4,0x5e,0x6c,0x61,0x29
2476 ,0x6c,0xdc,0x3c,0x01,0x23,0x35,0x61,0xf4
2477 ,0x1d,0xb6,0x6c,0xce,0x31,0x4a,0xdb,0x31
2478 ,0x0e,0x3b,0xe8,0x25,0x0c,0x46,0xf0,0x6d
2479 ,0xce,0xea,0x3a,0x7f,0xa1,0x34,0x80,0x57
2480 ,0xe2,0xf6,0x55,0x6a,0xd6,0xb1,0x31,0x8a
2481 ,0x02,0x4a,0x83,0x8f,0x21,0xaf,0x1f,0xde
2482 ,0x04,0x89,0x77,0xeb,0x48,0xf5,0x9f,0xfd
2483 ,0x49,0x24,0xca,0x1c,0x60,0x90,0x2e,0x52
2484 ,0xf0,0xa0,0x89,0xbc,0x76,0x89,0x70,0x40
2485 ,0xe0,0x82,0xf9,0x37,0x76,0x38,0x48,0x64
2486 ,0x5e,0x07,0x05
2489 ubyte[163] c;
2491 static immutable ubyte[] res = [
2492 0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73
2493 ,0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce
2494 ,0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4
2495 ,0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a
2496 ,0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b
2497 ,0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72
2498 ,0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2
2499 ,0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38
2500 ,0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a
2501 ,0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae
2502 ,0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea
2503 ,0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda
2504 ,0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde
2505 ,0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3
2506 ,0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6
2507 ,0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74
2508 ,0xe3,0x55,0xa5
2511 /*crypto_stream_xsalsa20_xor*/crypto_stream_xor(c,m,nonce,firstkey);
2512 for (auto i = 32; i < 163; ++i) assert(c[i] == res[i-32]);
2514 stream4();
2516 version(unittest) {
2517 version(unittest_main) {
2518 void main () {}