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
7  *
8  * Ported by Ketmar // Invisible Vector ( ketmar@ketmar.no-ip.org )
9  *
10  * Public Domain (or WTFPL).
11  */
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;
16 
17 
18 public:
19 enum {
20   crypto_auth_BYTES = 32,
21   crypto_auth_KEYBYTES = 32,
22 
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,
29 
30   crypto_core_salsa20_OUTPUTBYTES = 64,
31   crypto_core_salsa20_INPUTBYTES = 16,
32   crypto_core_salsa20_KEYBYTES = 32,
33   crypto_core_salsa20_CONSTBYTES = 16,
34 
35   crypto_core_hsalsa20_OUTPUTBYTES = 32,
36   crypto_core_hsalsa20_INPUTBYTES = 16,
37   crypto_core_hsalsa20_KEYBYTES = 32,
38   crypto_core_hsalsa20_CONSTBYTES = 16,
39 
40   crypto_hash_BYTES = 64,
41 
42   crypto_onetimeauth_BYTES = 16,
43   crypto_onetimeauth_KEYBYTES = 32,
44 
45   crypto_scalarmult_BYTES = 32,
46   crypto_scalarmult_SCALARBYTES = 32,
47 
48   crypto_secretbox_KEYBYTES = 32,
49   crypto_secretbox_NONCEBYTES = 24,
50   crypto_secretbox_ZEROBYTES = 32,
51   crypto_secretbox_BOXZEROBYTES = 16,
52 
53   crypto_sign_BYTES = 64,
54   crypto_sign_PUBLICKEYBYTES = 32,
55   crypto_sign_SECRETKEYBYTES = 64,
56 
57   crypto_stream_xsalsa20_KEYBYTES = 32,
58   crypto_stream_xsalsa20_NONCEBYTES = 24,
59 
60   crypto_stream_salsa20_KEYBYTES = 32,
61   crypto_stream_salsa20_NONCEBYTES = 8,
62 
63   crypto_stream_KEYBYTES = 32,
64   crypto_stream_NONCEBYTES = 24,
65 
66   crypto_verify_16_BYTES = 16,
67   crypto_verify_32_BYTES = 32,
68 }
69 
70 
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;
74 
75 
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];
79 
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];
89 
90 uint ld32() (const(ubyte)[] x)
91 in {
92   assert(x.length >= 4);
93 }
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];
99 }
100 
101 ulong dl64() (const(ubyte)[] x)
102 in {
103   assert(x.length >= 8);
104 }
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];
114 }
115 
116 void st32() (ubyte[] x, uint u)
117 in {
118   assert(x.length >= 4);
119 }
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;
125 }
126 
127 void ts64() (ubyte[] x, ulong u)
128 in {
129   assert(x.length >= 8);
130 }
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;
140 }
141 
142 bool vn() (const(ubyte)[] x, const(ubyte)[] y)
143 in {
144   assert(x.length >= y.length);
145 }
146 body {
147   uint d = 0;
148   foreach (immutable i, immutable v; x) d |= v^y[i];
149   return (1&((d-1)>>8)) != 0;
150 }
151 
152 public:
153 /**
154  * The crypto_verify_16() function checks that strings 'x' and 'y' has same content.
155  *
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
159  *
160  * Returns:
161  *  success flag
162  */
163 bool crypto_verify_16() (const(ubyte)[] x, const(ubyte)[] y)
164 in {
165   assert(x.length >= 16 && y.length >= 16);
166 }
167 body {
168   return vn(x[0..16], y[0..16]);
169 }
170 
171 /**
172  * The crypto_verify_32() function checks that strings 'x' and 'y' has same content.
173  *
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
177  *
178  * Returns:
179  *  success flag
180  */
181 bool crypto_verify_32() (const(ubyte)[] x, const(ubyte)[] y)
182 in {
183   assert(x.length >= 32 && y.length >= 32);
184 }
185 body {
186   return vn(x[0..32], y[0..32]);
187 }
188 
189 
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`));
198 }
199 body {
200   static uint ROTL32() (uint x, int c) { return (x<<c)|((x&0xffffffff)>>(32-c)); }
201 
202   uint[16] w = void, x = void, y = void;
203   uint[4] t = void;
204 
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..$]);
210   }
211 
212   y[] = x[];
213 
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];
222     }
223     for (auto m = 0; m < 16; ++m) x[m] = w[m];
224   }
225 
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..$]);
231     }
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]);
235     }
236   } else {
237     for (auto i = 0; i < 16; ++i) st32(output[4*i..$], x[i]+y[i]);
238   }
239 }
240 
241 void crypto_core_salsa20() (ubyte[] output, const(ubyte)[] input, const(ubyte)[] key, const(ubyte)[] constant)
242 {
243   salsa_core!"salsa"(output, input, key, constant);
244 }
245 
246 void crypto_core_hsalsa20() (ubyte[] output, const(ubyte)[] input, const(ubyte)[] key, const(ubyte)[] constant)
247 {
248   salsa_core!"hsalsa"(output, input, key, constant);
249 }
250 
251 private immutable(ubyte)[] sigma = cast(immutable(ubyte)[])"expand 32-byte k";
252 
253 /**
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'.
256  *
257  * Params:
258  *  output = resulting ciphertext
259  *  msg = message
260  *  nonce = nonce
261  *  key = secret key
262  *
263  * Returns:
264  *  ciphertext in 'output'
265  */
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);
273 }
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;
289     }
290     u = 1;
291     foreach (i; 8..16) {
292       u += cast(uint)z[i];
293       z[i] = u&0xff;
294       u >>= 8;
295     }
296     b -= 64;
297   }
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];
304     }
305   }
306 }
307 
308 /**
309  * The crypto_stream_salsa20() function produces a stream 'c'
310  * as a function of a secret key 'key' and a nonce 'nonce'.
311  *
312  * Params:
313  *  c = resulting stream
314  *  nonce = nonce
315  *  key = secret key
316  *
317  * Returns:
318  *  ciphertext in 'c'
319  */
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);
324 }
325 body {
326   crypto_stream_salsa20_xor(c, null, nonce, key);
327 }
328 
329 /**
330  * The crypto_stream() function produces a stream 'c'
331  * as a function of a secret key 'key' and a nonce 'nonce'.
332  *
333  * Params:
334  *  c = output slice
335  *  nonce = nonce
336  *  key = secret key
337  *
338  * Returns:
339  *  stream in 'c'
340  */
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);
346 }
347 body {
348   ubyte[32] s = void;
349   crypto_core_hsalsa20(s[], nonce, key, sigma[]);
350   crypto_stream_salsa20(c, nonce[16..$], s[]);
351 }
352 
353 /**
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'.
356  *
357  * Params:
358  *  c = output slice
359  *  nonce = nonce
360  *  key = secret key
361  *
362  * Returns:
363  *  ciphertext in 'c'
364  */
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);
371 }
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);
376 }
377 
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;
384   }
385 }
386 
387 private immutable uint[17] minusp = [5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,252];
388 
389 /**
390  * The crypto_onetimeauth() function authenticates a message 'msg'
391  * using a secret key 'key'. The function returns an authenticator 'output'.
392  *
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
397  *
398  * Returns:
399  *  authenticator in 'output'
400  */
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);
405 }
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;
411 
412   foreach (i; 0..16) r[i] = key[i];
413   r[16..17] = 0;
414 
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;
422 
423   while (n > 0) {
424     c[0..17] = 0;
425     {
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;
431     }
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]);
436     }
437     h[] = x[];
438     u = 0;
439     foreach (j; 0..16) {
440       u += h[j];
441       h[j] = u&255;
442       u >>= 8;
443     }
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;
451     }
452     u += h[16];
453     h[16] = u;
454   }
455 
456   g[] = h[];
457   add1305(h, minusp);
458   s = -(h[16]>>7);
459   foreach (j; 0..17) h[j] ^= s&(g[j]^h[j]);
460 
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);
465 }
466 
467 /**
468  * The crypto_onetimeauth_verify() function checks that
469  * 'h' is a correct authenticator of a message 'msg' under the secret key 'key'.
470  *
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
475  *
476  * Returns:
477  *  success flag
478  */
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);
483 }
484 body {
485   ubyte[16] x = void;
486   crypto_onetimeauth(x, msg, key);
487   return crypto_verify_16(h, x);
488 }
489 
490 /**
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'.
494  *
495  * Params:
496  *  c = resulting cyphertext
497  *  key = secret key
498  *  nonce = nonce
499  *
500  * Returns:
501  *  success flag and cyphertext in 'c'
502  */
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);
507 }
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;
516 }
517 
518 /**
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'.
522  *
523  * Params:
524  *  output = resulting message
525  *  c = cyphertext
526  *  key = secret key
527  *  nonce = nonce
528  *
529  * Returns:
530  *  success flag and message in 'output'
531  */
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);
536 }
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;
545 }
546 
547 
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;
555   }
556 }
557 
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;
564   }
565 }
566 
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;
579     }
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);
584   }
585   foreach (i; 0..16) {
586     o[2*i] = t[i]&0xff;
587     o[2*i+1] = (t[i]>>8)&0xff;
588   }
589 }
590 
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);
596 }
597 
598 ubyte par25519() (const(long)[] a) {
599   ubyte[32] d = void;
600   pack25519(d, a);
601   return d[0]&1;
602 }
603 
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;
607 }
608 
609 void A() (long[] o, const(long)[] a, const(long)[] b) {
610   foreach (i; 0..16) o[i] = a[i]+b[i];
611 }
612 
613 void Z() (long[] o, const(long)[] a, const(long)[] b) {
614   foreach (i; 0..16) o[i] = a[i]-b[i];
615 }
616 
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);
624 }
625 
626 void S() (long[] o, const(long)[] a) {
627   M(o, a, a);
628 }
629 
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);
636   }
637   o[0..16] = c[];
638 }
639 
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);
646   }
647   o[0..16] = c[];
648 }
649 
650 /* FIXME!
651  * This function multiplies a group element 'p' by an integer 'n'.
652  *
653  * Params:
654  *  p = group element
655  *  n = number
656  *
657  * Returns:
658  *  resulting group element 'q' of length crypto_scalarmult_BYTES.
659  */
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);
665 }
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;
678   }
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);
704   }
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];
710   }
711   inv25519(x[32..$], x[32..$]);
712   M(x[16..$], x[16..$], x[32..$]);
713   pack25519(q, x[16..$]);
714 }
715 
716 /* FIXME!
717  * The crypto_scalarmult_base() function computes
718  * the scalar product of a standard group element and an integer 'n'.
719  *
720  * Params:
721  *  n = number
722  *
723  * Returns:
724  *  resulting group element 'q' of length crypto_scalarmult_BYTES.
725  */
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);
730 }
731 body {
732   crypto_scalarmult(q, n, nine_);
733 }
734 
735 public:
736 /**
737  * The crypto_box_keypair() function randomly generates a secret key and
738  * a corresponding public key.
739  *
740  * Params:
741  *  pk = slice to put generated public key into
742  *  sk = slice to put generated secret key into
743  *
744  * Returns:
745  *  pair of new keys
746  */
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);
751 }
752 body {
753   randombytes(sk, 32);
754   crypto_scalarmult_base(pk, sk);
755 }
756 
757 /**
758  * Function crypto_box_beforenm() computes a shared secret 's' from
759  * public key 'pk' and secret key 'sk'.
760  *
761  * Params:
762  *  skey = slice to put secret into
763  *  pk = public
764  *  sk = secret
765  *
766  * Returns:
767  *  generated secret
768  */
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);
774 }
775 body {
776   ubyte[32] s = void;
777   crypto_scalarmult(s, sk, pk);
778   crypto_core_hsalsa20(skey, zero_[], s[], sigma[]);
779 }
780 
781 /**
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'.
785  *
786  * Params:
787  *  c = resulting cyphertext
788  *  msg = message
789  *  nonce = nonce
790  *  key = secret
791  *
792  * Returns:
793  *  success flag and cyphertext in 'c'
794  */
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);
799 }
800 body {
801   return crypto_secretbox(c, msg, nonce, key);
802 }
803 
804 /**
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'.
808  *
809  * Params:
810  *  msg = resulting message
811  *  c = cyphertext
812  *  nonce = nonce
813  *  key = secret
814  *
815  * Returns:
816  *  success flag and resulting message in 'msg'
817  */
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);
822 }
823 body {
824   return crypto_secretbox_open(msg, c, nonce, key);
825 }
826 
827 /**
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'.
831  *
832  * Params:
833  *  c = resulting cyphertext
834  *  msg = message
835  *  nonce = nonce
836  *  pk = receiver's public key
837  *  sk = sender's secret key
838  *
839  * Returns:
840  *  success flag and cyphertext in 'c'
841  */
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);
847 }
848 body {
849   ubyte[32] k = void;
850   crypto_box_beforenm(k, pk, sk);
851   return crypto_box_afternm(c, msg, nonce, k);
852 }
853 
854 /**
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'.
859  *
860  * Params:
861  *  msg = resulting message
862  *  c = cyphertext
863  *  nonce = nonce
864  *  pk = receiver's public key
865  *  sk = sender's secret key
866  *
867  * Returns:
868  *  success flag and message in 'msg'
869  */
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);
875 }
876 body {
877   ubyte[32] k = void;
878   crypto_box_beforenm(k, pk, sk);
879   return crypto_box_open_afternm(msg, c, nonce, k);
880 }
881 
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); }
890 
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
912 ];
913 
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]);
932       }
933     }
934     foreach (i; 0..8) { a[i] += z[i]; z[i] = a[i]; }
935     mpos += 128;
936     n -= 128;
937   }
938   foreach (i; 0..8) ts64(x[8*i..$], z[i]);
939 }
940 
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
950 ];
951 
952 /**
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.
955  *
956  * Params:
957  *  output = resulting hash
958  *  msg = message
959  *
960  * Returns:
961  *  sha512 hash
962  */
963 public void crypto_hash() (ubyte[] output, const(ubyte)[] msg)
964 in {
965   assert(output.length >= crypto_hash_BYTES);
966 }
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;
973 
974   h[] = iv[];
975 
976   crypto_hashblocks(h, msg, n);
977   mpos += n;
978   n &= 127;
979   mpos -= n;
980 
981   x[0..n] = msg[mpos..mpos+n];
982   x[n] = 128;
983 
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);
988 
989   output[0..64] = h;
990 }
991 
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;
994 
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);
1009 
1010   M(p[0], e, f);
1011   M(p[1], h, g);
1012   M(p[2], g, f);
1013   M(p[3], e, h);
1014 }
1015 
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);
1018 }
1019 
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;
1027 }
1028 
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);
1040   }
1041 }
1042 
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);
1050 }
1051 
1052 /**
1053  * The crypto_sign_keypair() function randomly generates a secret key and
1054  * a corresponding public key.
1055  *
1056  * Params:
1057  *  pk = slice to put generated public key into
1058  *  sk = slice to put generated secret key into
1059  *
1060  * Returns:
1061  *  pair of new keys
1062  */
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);
1067 }
1068 body {
1069   ubyte[64] d = void;
1070   long[16][4] p = void;
1071 
1072   randombytes(sk, 32);
1073   crypto_hash(d, sk[0..32]);
1074   d[0] &= 248;
1075   d[31] &= 127;
1076   d[31] |= 64;
1077 
1078   scalarbase(p, d);
1079   pack(pk, p);
1080 
1081   sk[32..64] = pk[0..32];
1082 }
1083 
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
1086 ];
1087 
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;
1097     }
1098     x[j] += carry;
1099     x[i] = 0;
1100   }
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;
1106   }
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;
1111   }
1112 }
1113 
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);
1119 }
1120 
1121 
1122 public:
1123 /**
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.
1126  *
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
1131  *
1132  * Returns:
1133  *  signed message
1134  */
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);
1139 }
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;
1146 
1147   crypto_hash(d, sk[0..32]);
1148   d[0] &= 248;
1149   d[31] &= 127;
1150   d[31] |= 64;
1151 
1152   sm[64..64+n] = msg[];
1153   sm[32..64] = d[32..64];
1154 
1155   crypto_hash(r, sm[32..32+n+32]);
1156   reduce(r);
1157   scalarbase(p, r);
1158   pack(sm, p);
1159 
1160   sm[32..64] = sk[32..64];
1161   crypto_hash(h, sm[0..n+64]);
1162   reduce(h);
1163 
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);
1167 }
1168 
1169 /**
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.
1172  *
1173  * WARNING! This function allocates!
1174  *
1175  * Params:
1176  *  msg == message
1177  *  sk == secret key, slice size must be at least crypto_sign_SECRETKEYBYTES, extra ignored
1178  *
1179  * Returns:
1180  *  signed message
1181  */
1182 ubyte[] crypto_sign() (const(ubyte)[] msg, const(ubyte)[] sk)
1183 in {
1184   assert(sk.length >= crypto_sign_SECRETKEYBYTES);
1185 }
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;
1193 }
1194 
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);
1203 
1204   S(den2, den);
1205   S(den4, den2);
1206   M(den6, den4, den2);
1207   M(t, den6, num);
1208   M(t, t, den);
1209 
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);
1215 
1216   S(chk, r[0]);
1217   M(chk, chk, den);
1218   if (!neq25519(chk, num)) M(r[0], r[0], I);
1219 
1220   S(chk, r[0]);
1221   M(chk, chk, den);
1222   if (!neq25519(chk, num)) return false;
1223 
1224   if (par25519(r[0]) == (p[31]>>7)) Z(r[0], gf0, r[0]);
1225 
1226   M(r[3], r[0], r[1]);
1227   return true;
1228 }
1229 
1230 /**
1231  * The crypto_sign_open() function verifies the signature in
1232  * 'sm' using the receiver's public key 'pk'.
1233  *
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
1238  *
1239  * Returns:
1240  *  success flag
1241  */
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);
1246 }
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;
1252 
1253   if (n < 64) return false;
1254 
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);
1261 
1262   scalarbase(q, sm[32..$]);
1263   add(p, q);
1264   pack(t, p);
1265 
1266   n -= 64;
1267   if (!crypto_verify_32(sm, t)) {
1268     msg[0..n] = 0;
1269     return false;
1270   }
1271 
1272   msg[0..n] = sm[64..64+n];
1273   msg[n..n+64] = 0;
1274 
1275   return true;
1276 }
1277 
1278 
1279 /**
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.
1283  *
1284  * WARNING! This function allocates!
1285  *
1286  * Params:
1287  *  sm == signed message
1288  *  pk == public key, slice size must be at least crypto_sign_PUBLICKEYBYTES, extra ignored
1289  *
1290  * Returns:
1291  *  decrypted message or null on error
1292  */
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
1298 }
1299 
1300 
1301 
1302 unittest {
1303   import std.exception;
1304   import std.random;
1305   import std.range;
1306   import std.stdio;
1307 
1308   /+
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);
1318       }
1319     }
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;
1326       }
1327       pos += i;
1328       len -= i;
1329     }
1330   }
1331   +/
1332   /+
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);
1335   }
1336   randombytes = &rnd;
1337   +/
1338 
1339   randombytes = (ubyte[] dest, size_t len) {
1340     for (size_t f = 0; f < len; ++f) dest[f] = cast(ubyte)uniform(0, 256);
1341   };
1342 
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]);
1351     }
1352     writeln();
1353     writeln("-----------------------------");
1354   }
1355 
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);
1363     }
1364     return assumeUnique(s);
1365   }
1366 
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;
1372 
1373   writeln("crypto_sign");
1374   smres = crypto_sign(m, sk);
1375   assert(smres.length == sm.length);
1376   assert(smres == sm);
1377 
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);
1383 
1384 
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;
1390 
1391       bool empty () { return state == 5; }
1392 
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;
1401           }
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;
1410             }
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;
1422             }
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;
1430           }
1431         }
1432       }
1433 
1434       ubyte front () {
1435         if (state == 0) return cast(ubyte)r.front;
1436         assert(state != 5);
1437         //writefln("%x", current);
1438         return current;
1439       }
1440 
1441       ubyte current;
1442       uint position;
1443       ulong length;
1444       int state = 0; // reading range, reading appended bit, reading padding, reading length, done
1445     }
1446   }
1447 
1448 
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
1460     ];
1461 
1462 
1463     SHARange!(T) range;
1464     static if (is(data == SHARange)) range = data; else range.r = data;
1465 
1466 
1467     while(!range.empty) {
1468       uint[64] words;
1469 
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;
1474         }
1475       }
1476 
1477       uint ror (uint n, int cnt) {
1478         return cast(uint)(n>>cnt)|cast(uint)(n<<(32-(cnt)));
1479       }
1480 
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;
1489       }
1490 
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;
1495       }
1496 
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];
1505 
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;
1514       }
1515 
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];
1523 
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;
1532       }
1533 
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;
1542     }
1543 
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;
1548     }
1549 
1550     return hash.idup;
1551   }
1552 
1553 
1554   void box () {
1555     writeln("box");
1556 
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
1562     ] ;
1563 
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
1569     ] ;
1570 
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
1575     ] ;
1576 
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
1600     ] ;
1601 
1602     ubyte[163] c;
1603 
1604 
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]);
1627   }
1628   box();
1629 
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
1637     ] ;
1638 
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
1644     ] ;
1645 
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
1650     ] ;
1651 
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
1675     ] ;
1676 
1677     ubyte[163] m;
1678 
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
1697     ];
1698 
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]);
1701   }
1702   box2();
1703 
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]);
1720     }
1721   }
1722   version(unittest_full) box7(); // it's slow
1723 
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;
1745         }
1746       }
1747       assert(caught == 10);
1748     }
1749   }
1750   version(unittest_full) box8(); // it's slow
1751 
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
1759     ] ;
1760 
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];
1762 
1763     static immutable ubyte[16] c = [
1764      0x65,0x78,0x70,0x61,0x6e,0x64,0x20,0x33
1765     ,0x32,0x2d,0x62,0x79,0x74,0x65,0x20,0x6b
1766     ] ;
1767 
1768     ubyte[32] firstkey;
1769 
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
1775     ];
1776 
1777     crypto_core_hsalsa20(firstkey,zero,shared_,c);
1778     assert(firstkey == res);
1779   }
1780   core1();
1781 
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
1789     ] ;
1790 
1791     static immutable ubyte[16]nonceprefix = [
1792      0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73
1793     ,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6
1794     ] ;
1795 
1796     static immutable ubyte[16] c = [
1797      0x65,0x78,0x70,0x61,0x6e,0x64,0x20,0x33
1798     ,0x32,0x2d,0x62,0x79,0x74,0x65,0x20,0x6b
1799     ] ;
1800 
1801     ubyte[32] secondkey;
1802 
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
1808     ];
1809 
1810     crypto_core_hsalsa20(secondkey,nonceprefix,firstkey,c);
1811     assert(secondkey == res);
1812   }
1813   core2();
1814 
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
1822     ] ;
1823 
1824     static immutable ubyte[8] noncesuffix = [
1825      0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37
1826     ] ;
1827 
1828     static immutable ubyte[16] c = [
1829      0x65,0x78,0x70,0x61,0x6e,0x64,0x20,0x33
1830     ,0x32,0x2d,0x62,0x79,0x74,0x65,0x20,0x6b
1831     ] ;
1832 
1833     static ubyte[16] input = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] ;
1834 
1835     static ubyte[64*256*256] output;
1836 
1837     static ubyte[64] h;
1838 
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];
1840 
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);
1851   }
1852   version(unittest_full) core3(); // it's slow
1853 
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
1861     ] ;
1862 
1863     static immutable ubyte[16] input = [
1864      101,102,103,104,105,106,107,108
1865     ,109,110,111,112,113,114,115,116
1866     ] ;
1867 
1868     static immutable ubyte[16] c = [
1869      101,120,112, 97,110,100, 32, 51
1870     , 50, 45, 98,121,116,101, 32,107
1871     ] ;
1872 
1873     ubyte[64] output;
1874 
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
1884     ];
1885 
1886     crypto_core_salsa20(output,input,k,c);
1887     assert(output == res);
1888   }
1889   core4();
1890 
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
1898     ] ;
1899 
1900     static immutable ubyte[16] input = [
1901      0x81,0x91,0x8e,0xf2,0xa5,0xe0,0xda,0x9b
1902     ,0x3e,0x90,0x60,0x52,0x1e,0x4b,0xb3,0x52
1903     ] ;
1904 
1905     static immutable ubyte[16] c = [
1906      101,120,112, 97,110,100, 32, 51
1907     , 50, 45, 98,121,116,101, 32,107
1908     ] ;
1909 
1910     ubyte[32] output;
1911 
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
1917     ];
1918 
1919     crypto_core_hsalsa20(output,input,k,c);
1920     assert(output == res);
1921   }
1922   core5();
1923 
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
1931     ] ;
1932 
1933     static immutable ubyte[16] input = [
1934      0x81,0x91,0x8e,0xf2,0xa5,0xe0,0xda,0x9b
1935     ,0x3e,0x90,0x60,0x52,0x1e,0x4b,0xb3,0x52
1936     ] ;
1937 
1938     static immutable ubyte[16] c = [
1939      101,120,112, 97,110,100, 32, 51
1940     , 50, 45, 98,121,116,101, 32,107
1941     ] ;
1942 
1943     ubyte[64] output;
1944 
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
1950     ];
1951 
1952     ubyte[32] pp;
1953     uint pppos = 0;
1954 
1955     void print(const(ubyte)[] x, const(ubyte)[] y)
1956     {
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);
1964       }
1965     }
1966 
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);
1977   }
1978   core6();
1979 
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);
1988   }
1989   hash();
1990 
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
1998     ] ;
1999 
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
2018     ] ;
2019 
2020     ubyte[16] a;
2021 
2022     static immutable ubyte[16] res = [0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5,0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9];
2023 
2024     /*crypto_onetimeauth_poly1305*/crypto_onetimeauth(a,c,rs);
2025     assert(a == res);
2026   }
2027   onetimeauth();
2028 
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
2036     ] ;
2037 
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
2056     ] ;
2057 
2058     static immutable ubyte[16] a = [
2059      0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5
2060     ,0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9
2061     ] ;
2062 
2063     assert(/*crypto_onetimeauth_poly1305_verify*/crypto_onetimeauth_verify(a,c,rs));
2064   }
2065   onetimeauth2();
2066 
2067   void onetimeauth7 () {
2068     writeln("onetimeauth7");
2069     static ubyte[32] key;
2070     static ubyte[10000] c;
2071     static ubyte[16] a;
2072 
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));
2084       }
2085     }
2086   }
2087   version(unittest_full) onetimeauth7(); // it's slow
2088 
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
2096     ] ;
2097 
2098     ubyte[32] alicepk;
2099 
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
2105     ];
2106 
2107     /*crypto_scalarmult_curve25519_base*/crypto_scalarmult_base(alicepk,alicesk);
2108     assert(alicepk == res);
2109   }
2110   scalarmult();
2111 
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
2119     ] ;
2120 
2121     ubyte[32] bobpk;
2122 
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
2128     ];
2129 
2130     /*crypto_scalarmult_curve25519_base*/crypto_scalarmult_base(bobpk,bobsk);
2131     assert(bobpk == res);
2132   }
2133   scalarmult2();
2134 
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
2142     ] ;
2143 
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
2149     ] ;
2150 
2151     ubyte[32] k;
2152 
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
2158     ];
2159 
2160     crypto_scalarmult(k,alicesk,bobpk);
2161     assert(k == res);
2162   }
2163   scalarmult5();
2164 
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
2172    ] ;
2173 
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
2179     ] ;
2180 
2181     ubyte[32] k;
2182 
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
2188     ];
2189 
2190     crypto_scalarmult(k,bobsk,alicepk);
2191     assert(k == res);
2192   }
2193   scalarmult6();
2194 
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
2202     ] ;
2203 
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
2208     ] ;
2209 
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
2233     ] ;
2234 
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
2255     ];
2256 
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]);
2260   }
2261   secretbox();
2262 
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
2270     ] ;
2271 
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
2276     ] ;
2277 
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
2301     ] ;
2302 
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
2321     ];
2322 
2323     ubyte[163] m;
2324 
2325     assert(crypto_secretbox_open(m,c,nonce,firstkey));
2326     for (auto i = 32; i < 163; ++i) assert(m[i] == res[i-32]);
2327   }
2328   secretbox2();
2329 
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]);
2342     }
2343   }
2344   secretbox7();
2345 
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]);
2361         }
2362         ++caught;
2363       }
2364       assert(caught == 10);
2365     }
2366   }
2367   version(unittest_full) secretbox8(); // it's slow
2368 
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
2376     ] ;
2377 
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
2382     ] ;
2383 
2384     static ubyte[4194304] output;
2385 
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];
2388 
2389     crypto_stream(output,nonce,firstkey);
2390     //crypto_hash_sha256(h,output,sizeof output);
2391     assert(hashToString(SHA256(output[0..$])) == "662b9d0e3463029156069b12f918691a98f7dfb2ca0393c96bbfc6b1fbd630a2");
2392   }
2393   stream();
2394 
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
2402     ] ;
2403 
2404     static immutable ubyte[8] noncesuffix = [
2405      0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37
2406     ] ;
2407 
2408     static ubyte[4194304] output;
2409 
2410     crypto_stream_salsa20(output,noncesuffix,secondkey);
2411     assert(hashToString(SHA256(output[0..$])) == "662b9d0e3463029156069b12f918691a98f7dfb2ca0393c96bbfc6b1fbd630a2");
2412   }
2413   stream2();
2414 
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
2422     ] ;
2423 
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
2428     ] ;
2429 
2430     ubyte[32] rs;
2431 
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
2437     ];
2438 
2439     crypto_stream/*_xsalsa20*/(rs,nonce,firstkey);
2440     assert(rs == res);
2441   }
2442   stream3();
2443 
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
2451     ] ;
2452 
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
2457     ] ;
2458 
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
2481     ] ;
2482 
2483     ubyte[163] c;
2484 
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
2503     ];
2504 
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]);
2507   }
2508   stream4();
2509 }
2510 
2511