d-fication
[tweetnacl.d.git] / tweetNaCl.d
blobceda13393fb302d0b446054600ecf8b4afd02439
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 module tweetNaCl;
14 // define tweetnacl_enable_inlining to speed up tweetNaCl on GDC
15 version(GNU) {
16 version(tweetnacl_enable_inlining) version=tweetnacl_enable_inlining_on_;
17 else version=tweetnacl_enable_inlining_off_;
18 } else {
19 version=tweetnacl_enable_inlining_off_;
22 version(tweetnacl_enable_inlining_off_) {
23 private struct tweetNaCl_gdc_Attribute(A...) {
24 A args;
26 auto tweetNaCl_gdc_attribute(A...)(A args) if(A.length > 0 && is(A[0] == string)) {
27 return tweetNaCl_gdc_Attribute!A(args);
29 } else {
30 import gcc.attribute;
31 alias tweetNaCl_gdc_attribute = attribute;
35 enum {
36 crypto_auth_BYTES = 32,
37 crypto_auth_KEYBYTES = 32,
39 crypto_box_PUBLICKEYBYTES = 32,
40 crypto_box_SECRETKEYBYTES = 32,
41 crypto_box_BEFORENMBYTES = 32,
42 crypto_box_NONCEBYTES = 24,
43 crypto_box_ZEROBYTES = 32,
44 crypto_box_BOXZEROBYTES = 16,
46 crypto_core_salsa20_OUTPUTBYTES = 64,
47 crypto_core_salsa20_INPUTBYTES = 16,
48 crypto_core_salsa20_KEYBYTES = 32,
49 crypto_core_salsa20_CONSTBYTES = 16,
51 crypto_core_hsalsa20_OUTPUTBYTES = 32,
52 crypto_core_hsalsa20_INPUTBYTES = 16,
53 crypto_core_hsalsa20_KEYBYTES = 32,
54 crypto_core_hsalsa20_CONSTBYTES = 16,
56 crypto_hash_BYTES = 64,
58 crypto_onetimeauth_BYTES = 16,
59 crypto_onetimeauth_KEYBYTES = 32,
61 crypto_scalarmult_BYTES = 32,
62 crypto_scalarmult_SCALARBYTES = 32,
64 crypto_secretbox_KEYBYTES = 32,
65 crypto_secretbox_NONCEBYTES = 24,
66 crypto_secretbox_ZEROBYTES = 32,
67 crypto_secretbox_BOXZEROBYTES = 16,
69 crypto_sign_BYTES = 64,
70 crypto_sign_PUBLICKEYBYTES = 32,
71 crypto_sign_SECRETKEYBYTES = 64,
73 crypto_stream_xsalsa20_KEYBYTES = 32,
74 crypto_stream_xsalsa20_NONCEBYTES = 24,
76 crypto_stream_salsa20_KEYBYTES = 32,
77 crypto_stream_salsa20_NONCEBYTES = 8,
79 crypto_stream_KEYBYTES = 32,
80 crypto_stream_NONCEBYTES = 24,
82 crypto_verify_16_BYTES = 16,
83 crypto_verify_32_BYTES = 32,
87 /// set this callback to good (cryptograpic strong) random bytes generator
88 /// you can use /dev/urandom as prng
89 void function (ubyte[] dest, size_t len) randombytes = null;
92 private static __gshared immutable ubyte[16] _0 = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
93 private static __gshared 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];
95 private static __gshared immutable long[16]
96 gf0 = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
97 gf1 = [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
98 _121665 = [0xDB41,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
99 D = [0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203],
100 D2 =[0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406],
101 X = [0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169],
102 Y = [0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666],
103 I = [0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83];
105 private @tweetNaCl_gdc_attribute("forceinline") uint ld32() (const(ubyte)[] x) @safe nothrow
106 in {
107 assert(x.length >= 4);
109 body {
110 uint u = x[3];
111 u = (u<<8)|x[2];
112 u = (u<<8)|x[1];
113 return (u<<8)|x[0];
116 private @tweetNaCl_gdc_attribute("forceinline") ulong dl64() (const(ubyte)[] x) @safe nothrow
117 in {
118 assert(x.length >= 8);
120 body {
121 ulong u = x[0];
122 u = (u<<8)|x[1];
123 u = (u<<8)|x[2];
124 u = (u<<8)|x[3];
125 u = (u<<8)|x[4];
126 u = (u<<8)|x[5];
127 u = (u<<8)|x[6];
128 return (u<<8)|x[7];
131 private @tweetNaCl_gdc_attribute("forceinline") void st32() (ubyte[] x, uint u) @safe nothrow
132 in {
133 assert(x.length >= 4);
135 body {
136 x[0] = u&0xff;
137 x[1] = (u>>8)&0xff;
138 x[2] = (u>>16)&0xff;
139 x[3] = (u>>24)&0xff;
142 private @tweetNaCl_gdc_attribute("forceinline") void ts64() (ubyte[] x, ulong u) @safe nothrow
143 in {
144 assert(x.length >= 8);
146 body {
147 x[0] = (u>>56)&0xff;
148 x[1] = (u>>48)&0xff;
149 x[2] = (u>>40)&0xff;
150 x[3] = (u>>32)&0xff;
151 x[4] = (u>>24)&0xff;
152 x[5] = (u>>16)&0xff;
153 x[6] = (u>>8)&0xff;
154 x[7] = u&0xff;
157 private @tweetNaCl_gdc_attribute("forceinline") bool vn() (const(ubyte)[] x, const(ubyte)[] y) @safe nothrow
158 in {
159 assert(x.length >= y.length);
161 body {
162 uint d = 0;
163 foreach (immutable i, immutable v; x) d |= v^y[i];
164 return (1&((d-1)>>8)) != 0;
168 * The crypto_verify_16() function checks that strings 'x' and 'y' has same content.
170 * Params:
171 * x = first string, slice length must be at least crypto_verify_16_BYTES, extra ignored
172 * y = second string, slice length must be at least crypto_verify_16_BYTES, extra ignored
174 * Returns:
175 * success flag
177 @tweetNaCl_gdc_attribute("forceinline") bool crypto_verify_16() (const(ubyte)[] x, const(ubyte)[] y) @safe nothrow
178 in {
179 assert(x.length >= 16 && y.length >= 16);
181 body {
182 return vn(x[0..16], y[0..16]);
186 * The crypto_verify_32() function checks that strings 'x' and 'y' has same content.
188 * Params:
189 * x = first string, slice length must be at least crypto_verify_32_BYTES, extra ignored
190 * y = second string, slice length must be at least crypto_verify_32_BYTES, extra ignored
192 * Returns:
193 * success flag
195 @tweetNaCl_gdc_attribute("forceinline") bool crypto_verify_32() (const(ubyte)[] x, const(ubyte)[] y) @safe nothrow
196 in {
197 assert(x.length >= 32 && y.length >= 32);
199 body {
200 return vn(x[0..32], y[0..32]);
204 private void salsa_core(alias type) (ubyte[] output, const(ubyte)[] input, const(ubyte)[] key, const(ubyte)[] constant) @safe nothrow
205 if (type == "salsa" || type == "hsalsa") // constraint
206 in {
207 // magic!
208 assert(mixin(`output.length >= crypto_core_`~type~`20_OUTPUTBYTES`));
209 assert(mixin(`input.length >= crypto_core_`~type~`20_INPUTBYTES`));
210 assert(mixin(`key.length >= crypto_core_`~type~`20_KEYBYTES`));
211 assert(mixin(`constant.length >= crypto_core_`~type~`20_CONSTBYTES`));
213 body {
214 static @tweetNaCl_gdc_attribute("forceinline") uint ROTL32() (uint x, int c) @safe nothrow pure { return (x<<c)|((x&0xffffffff)>>(32-c)); }
216 uint[16] w = void, x = void, y = void;
217 uint[4] t = void;
219 foreach (i; 0..4) {
220 x[5*i] = ld32(constant[4*i..$]);
221 x[1+i] = ld32(key[4*i..$]);
222 x[6+i] = ld32(input[4*i..$]);
223 x[11+i] = ld32(key[16+4*i..$]);
226 y[] = x[];
228 foreach (i; 0..20) {
229 foreach (j; 0..4) {
230 foreach (m; 0..4) t[m] = x[(5*j+4*m)%16];
231 t[1] ^= ROTL32(t[0]+t[3], 7);
232 t[2] ^= ROTL32(t[1]+t[0], 9);
233 t[3] ^= ROTL32(t[2]+t[1], 13);
234 t[0] ^= ROTL32(t[3]+t[2], 18);
235 for (auto m = 0; m < 4; ++m) w[4*j+(j+m)%4] = t[m];
237 for (auto m = 0; m < 16; ++m) x[m] = w[m];
240 static if (type == "hsalsa") {
241 for (auto i = 0; i < 16; ++i) x[i] += y[i];
242 for (auto i = 0; i < 4; ++i) {
243 x[5*i] -= ld32(constant[4*i..$]);
244 x[6+i] -= ld32(input[4*i..$]);
246 for (auto i = 0; i < 4; ++i) {
247 st32(output[4*i..$], x[5*i]);
248 st32(output[16+4*i..$], x[6+i]);
250 } else {
251 for (auto i = 0; i < 16; ++i) st32(output[4*i..$], x[i]+y[i]);
255 @tweetNaCl_gdc_attribute("forceinline") void crypto_core_salsa20() (ubyte[] output, const(ubyte)[] input, const(ubyte)[] key, const(ubyte)[] constant)
256 @safe nothrow {
257 salsa_core!"salsa"(output, input, key, constant);
260 @tweetNaCl_gdc_attribute("forceinline") void crypto_core_hsalsa20() (ubyte[] output, const(ubyte)[] input, const(ubyte)[] key, const(ubyte)[] constant)
261 @safe nothrow {
262 salsa_core!"hsalsa"(output, input, key, constant);
265 private static __gshared immutable immutable(ubyte)[] sigma = cast(immutable(ubyte)[])"expand 32-byte k";
268 * The crypto_stream_salsa20_xor() function encrypts a message 'msg' using a secret key 'key'
269 * and a nonce 'nonce'. The crypto_stream_salsa20_xor() function returns the ciphertext 'output'.
271 * Params:
272 * output = resulting ciphertext
273 * msg = message
274 * nonce = nonce
275 * key = secret key
277 * Returns:
278 * ciphertext in 'output'
280 void crypto_stream_salsa20_xor (ubyte[] output, const(ubyte)[] msg, const(ubyte)[] nonce, const(ubyte)[] key) @trusted nothrow
281 in {
282 assert(nonce.length == crypto_stream_salsa20_NONCEBYTES);
283 assert(key.length == crypto_stream_salsa20_KEYBYTES);
284 import std.stdio;
285 assert(msg.length == 0 || output.length <= msg.length);
287 body {
288 ubyte[16] z = void;
289 ubyte[64] x = void;
290 uint u;
291 uint cpos = 0, mpos = 0;
292 size_t b = output.length;
293 if (!b) return;
294 z[] = 0;
295 z[0..8] = nonce[0..8];
296 while (b >= 64) {
297 crypto_core_salsa20(x, z, key, sigma);
298 if (msg !is null) {
299 foreach (v; x) output[cpos++] = msg[mpos++]^v;
300 } else {
301 output[cpos..cpos+64] = x[];
302 cpos += 64;
304 u = 1;
305 foreach (i; 8..16) {
306 u += cast(uint)z[i];
307 z[i] = u&0xff;
308 u >>= 8;
310 b -= 64;
312 if (b) {
313 crypto_core_salsa20(x, z, key, sigma);
314 if (msg !is null) {
315 foreach (i; 0..b) output[cpos++] = msg[mpos++]^x[i];
316 } else {
317 output[cpos..cpos+b] = x[0..b];
323 * The crypto_stream_salsa20() function produces a stream 'c'
324 * as a function of a secret key 'key' and a nonce 'nonce'.
326 * Params:
327 * c = resulting stream
328 * nonce = nonce
329 * key = secret key
331 * Returns:
332 * ciphertext in 'c'
334 void crypto_stream_salsa20() (ubyte[] c, const(ubyte)[] nonce, const(ubyte)[] key) @safe nothrow
335 in {
336 assert(nonce.length == crypto_stream_salsa20_NONCEBYTES);
337 assert(key.length == crypto_stream_salsa20_KEYBYTES);
339 body {
340 crypto_stream_salsa20_xor(c, null, nonce, key);
344 * The crypto_stream() function produces a stream 'c'
345 * as a function of a secret key 'key' and a nonce 'nonce'.
347 * Params:
348 * c = output slice
349 * nonce = nonce
350 * key = secret key
352 * Returns:
353 * stream in 'c'
355 void crypto_stream() (ubyte[] c, const(ubyte)[] nonce, const(ubyte)[] key) @safe nothrow
356 in {
357 assert(c !is null);
358 assert(nonce.length == crypto_stream_NONCEBYTES);
359 assert(key.length == crypto_stream_KEYBYTES);
361 body {
362 ubyte[32] s = void;
363 crypto_core_hsalsa20(s, nonce, key, sigma);
364 crypto_stream_salsa20(c, nonce[16..$], s);
368 * The crypto_stream_xor() function encrypts a message 'msg' using a secret key 'key'
369 * and a nonce 'nonce'. The crypto_stream_xor() function returns the ciphertext 'c'.
371 * Params:
372 * c = output slice
373 * nonce = nonce
374 * key = secret key
376 * Returns:
377 * ciphertext in 'c'
379 void crypto_stream_xor() (ubyte[] c, const(ubyte)[] msg, const(ubyte)[] nonce, const(ubyte)[] key) @safe nothrow
380 in {
381 assert(c !is null);
382 assert(msg.length >= c.length);
383 assert(nonce.length == crypto_stream_NONCEBYTES);
384 assert(key.length == crypto_stream_KEYBYTES);
386 body {
387 ubyte s[32] = void;
388 crypto_core_hsalsa20(s, nonce, key, sigma);
389 crypto_stream_salsa20_xor(c, msg, nonce[16..$], s);
392 private @tweetNaCl_gdc_attribute("forceinline") void add1305() (uint[] h, const(uint)[] c) @safe nothrow {
393 uint u = 0;
394 foreach (j; 0..17) {
395 u += h[j]+c[j];
396 h[j] = u&255;
397 u >>= 8;
401 private static __gshared immutable uint[17] minusp = [5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,252];
404 * The crypto_onetimeauth() function authenticates a message 'msg'
405 * using a secret key 'key'. The function returns an authenticator 'output'.
407 * Params:
408 * output = authenticator, slice size must be at least crypto_onetimeauth_BYTES, extra ignored
409 * msg == message
410 * key == secret key, slice size must be at least crypto_onetimeauth_KEYBYTES, extra ignored
412 * Returns:
413 * authenticator in 'output'
415 void crypto_onetimeauth() (ubyte[] output, const(ubyte)[] msg, const(ubyte)[] key) @safe nothrow
416 in {
417 assert(key.length >= crypto_onetimeauth_KEYBYTES);
418 assert(output.length >= crypto_onetimeauth_BYTES);
420 body {
421 uint s, i, j, u;
422 uint[17] x = void, r = void, h = void, c = void, g = void;
423 uint mpos = 0;
424 size_t n = msg.length;
426 for (j = 0; j < 17; ++j) r[j] = h[j] = 0;
427 for (j = 0; j < 16; ++j) r[j] = key[j];
428 r[3]&=15;
429 r[4]&=252;
430 r[7]&=15;
431 r[8]&=252;
432 r[11]&=15;
433 r[12]&=252;
434 r[15]&=15;
436 while (n > 0) {
437 for (j = 0; j < 17; ++j) c[j] = 0;
438 for (j = 0; j < 16 && j < n; ++j) c[j] = msg[mpos+j];
439 c[j] = 1;
440 mpos += j;
441 n -= j;
442 add1305(h, c);
443 for (i = 0; i < 17; ++i) {
444 x[i] = 0;
445 for (j = 0; j < 17; ++j) x[i] += h[j]*(j <= i ? r[i-j] : 320*r[i+17-j]);
447 for (i = 0; i < 17; ++i) h[i] = x[i];
448 u = 0;
449 for (j = 0; j < 16; ++j) {
450 u += h[j];
451 h[j] = u&255;
452 u >>= 8;
454 u += h[16];
455 h[16] = u&3;
456 u = 5*(u>>2);
457 for (j = 0; j < 16; ++j) {
458 u += h[j];
459 h[j] = u&255;
460 u >>= 8;
462 u += h[16]; h[16] = u;
465 for (j = 0; j < 17; ++j) g[j] = h[j];
466 add1305(h, minusp);
467 s = -(h[16]>>7);
468 for (j = 0; j < 17; ++j) h[j] ^= s&(g[j]^h[j]);
470 for (j = 0; j < 16; ++j) c[j] = key[j+16];
471 c[16] = 0;
472 add1305(h, c);
473 for (j = 0; j < 16; ++j) output[j] = cast(ubyte)(h[j]&0xff);
477 * The crypto_onetimeauth_verify() function checks that
478 * 'h' is a correct authenticator of a message 'msg' under the secret key 'key'.
480 * Params:
481 * h = authenticator, slice size must be at least crypto_onetimeauth_BYTES, extra ignored
482 * msg == message
483 * key == secret key, slice size must be at least crypto_onetimeauth_KEYBYTES, extra ignored
485 * Returns:
486 * success flag
488 bool crypto_onetimeauth_verify() (const(ubyte)[] h, const(ubyte)[] msg, const(ubyte)[] key) @safe nothrow
489 in {
490 assert(h.length >= crypto_onetimeauth_BYTES);
491 assert(key.length >= crypto_onetimeauth_KEYBYTES);
493 body {
494 ubyte x[16] = void;
495 crypto_onetimeauth(x, msg, key);
496 return crypto_verify_16(h, x);
500 * The crypto_secretbox() function encrypts and authenticates
501 * a message 'msg' using a secret key 'key' and a nonce 'nonce'.
502 * The crypto_secretbox() function returns the resulting ciphertext 'c'.
504 * Params:
505 * c = resulting cyphertext
506 * key = secret key
507 * nonce = nonce
509 * Returns:
510 * success flag and cyphertext in 'c'
512 bool crypto_secretbox() (ubyte[] c, const(ubyte)[] msg, const(ubyte)[] nonce, const(ubyte)[] key) @safe nothrow
513 in {
514 assert(key.length >= crypto_secretbox_KEYBYTES);
515 assert(nonce.length >= crypto_secretbox_NONCEBYTES);
517 body {
518 //c.length = msg.length+crypto_secretbox_ZEROBYTES;
519 if (c is null || c.length < 32) return false;
520 //assert(msg.length >= c.length);
521 crypto_stream_xor(c, msg, nonce, key);
522 crypto_onetimeauth(c[16..$], c[32..$], c);
523 for (auto i = 0; i < 16; ++i) c[i] = 0;
524 //return c[crypto_secretbox_BOXZEROBYTES..$];
525 return true;
529 * The crypto_secretbox_open() function verifies and decrypts
530 * a ciphertext 'c' using a secret key 'key' and a nonce 'nonce'.
531 * The crypto_secretbox_open() function returns the resulting plaintext 'output'.
533 * Params:
534 * output = resulting message
535 * c = cyphertext
536 * key = secret key
537 * nonce = nonce
539 * Returns:
540 * success flag and message in 'output'
542 bool crypto_secretbox_open() (ubyte[] output, const(ubyte)[] c, const(ubyte)[] nonce, const(ubyte)[] key) @safe nothrow
543 in {
544 assert(key.length >= crypto_secretbox_KEYBYTES);
545 assert(nonce.length >= crypto_secretbox_NONCEBYTES);
547 body {
548 ubyte x[32] = void;
549 if (output is null || output.length < 32) return false;
550 crypto_stream(x, nonce, key);
551 if (!crypto_onetimeauth_verify(c[16..$], c[32../*$*/32+(output.length-32)], x)) return false;
552 crypto_stream_xor(output, c, nonce, key);
553 for (auto i = 0; i < 32; ++i) output[i] = 0;
554 return true;
557 private @tweetNaCl_gdc_attribute("forceinline") void set25519() (long[/*16*/] r, const(long)[/*16*/] a) @safe nothrow {
558 for (auto i = 0; i < 16; ++i) r[i] = a[i];
561 private @tweetNaCl_gdc_attribute("forceinline") void car25519() (long[] o) @safe nothrow {
562 long c;
563 for (auto i = 0; i < 16; ++i) {
564 o[i]+=(1<<16);
565 c = o[i]>>16;
566 o[(i+1)*(i<15)]+=c-1+37*(c-1)*(i==15);
567 o[i]-=c<<16;
571 private @tweetNaCl_gdc_attribute("forceinline") void sel25519() (long[] p,long[] q, int b) @safe nothrow {
572 long t, c = ~(b-1);
573 for (auto i = 0; i < 16; ++i) {
574 t= c&(p[i]^q[i]);
575 p[i]^=t;
576 q[i]^=t;
580 private @tweetNaCl_gdc_attribute("forceinline") void pack25519() (ubyte[] o, const(long)[] n) @safe nothrow {
581 int b;
582 long[16] m, t;
583 for (auto i = 0; i < 16; ++i) t[i] = n[i];
584 car25519(t);
585 car25519(t);
586 car25519(t);
587 for (auto j = 0; j < 2; ++j) {
588 m[0] = t[0]-0xffed;
589 for(auto i = 1; i < 15; ++i) {
590 m[i] = t[i]-0xffff-((m[i-1]>>16)&1);
591 m[i-1]&=0xffff;
593 m[15] = t[15]-0x7fff-((m[14]>>16)&1);
594 b = (m[15]>>16)&1;
595 m[14]&=0xffff;
596 sel25519(t, m, 1-b);
598 for (auto i = 0; i < 16; ++i) {
599 o[2*i] = t[i]&0xff;
600 o[2*i+1] = (t[i]>>8)&0xff;
604 private @tweetNaCl_gdc_attribute("forceinline") bool neq25519() (const(long)[] a, const(long)[] b) @safe nothrow {
605 ubyte[32] c = void, d = void;
606 pack25519(c, a);
607 pack25519(d, b);
608 return crypto_verify_32(c, d);
611 private @tweetNaCl_gdc_attribute("forceinline") ubyte par25519() (const(long)[] a) @safe nothrow {
612 ubyte d[32];
613 pack25519(d, a);
614 return d[0]&1;
617 private @tweetNaCl_gdc_attribute("forceinline") void unpack25519() (long[] o, const(ubyte)[] n) @safe nothrow {
618 for (auto i = 0; i < 16; ++i) o[i] = n[2*i]+(cast(long)n[2*i+1]<<8);
619 o[15]&=0x7fff;
622 private @tweetNaCl_gdc_attribute("forceinline") void A() (long[] o, const(long)[] a, const(long)[] b) @safe nothrow {
623 for (auto i = 0; i < 16; ++i) o[i] = a[i]+b[i];
626 private @tweetNaCl_gdc_attribute("forceinline") void Z() (long[] o, const(long)[] a, const(long)[] b) @safe nothrow {
627 for (auto i = 0; i < 16; ++i) o[i] = a[i]-b[i];
630 private @tweetNaCl_gdc_attribute("forceinline") void M() (long[] o, const(long)[] a, const(long)[] b) @safe nothrow {
631 long[31] t;
632 for (auto i = 0; i < 31; ++i) t[i] = 0;
633 for (auto i = 0; i < 16; ++i) for (auto j = 0; j < 16; ++j) t[i+j]+=a[i]*b[j];
634 for (auto i = 0; i < 15; ++i) t[i]+=38*t[i+16];
635 for (auto i = 0; i < 16; ++i) o[i] = t[i];
636 car25519(o);
637 car25519(o);
640 private @tweetNaCl_gdc_attribute("forceinline") void S() (long[] o, const(long)[] a) @safe nothrow {
641 M(o, a, a);
644 private @tweetNaCl_gdc_attribute("forceinline") void inv25519() (long[] o, const(long)[] i) @safe nothrow {
645 long[16] c;
646 for (auto a = 0; a < 16; ++a) c[a] = i[a];
647 for(auto a = 253; a >= 0; --a) {
648 S(c, c);
649 if (a !=2 && a != 4) M(c, c, i);
651 for (auto a = 0; a < 16; ++a) o[a] = c[a];
654 private @tweetNaCl_gdc_attribute("forceinline") void pow2523() (long[] o, const(long)[] i) @safe nothrow {
655 long[16] c;
656 for (auto a = 0; a < 16; ++a) c[a] = i[a];
657 for(auto a = 250; a >= 0; --a) {
658 S(c, c);
659 if (a != 1) M(c, c, i);
661 for (auto a = 0; a < 16; ++a) o[a] = c[a];
664 /* FIXME!
665 * This function multiplies a group element 'p' by an integer 'n'.
667 * Params:
668 * p = group element
669 * n = number
671 * Returns:
672 * resulting group element 'q' of length crypto_scalarmult_BYTES.
674 private void crypto_scalarmult (ubyte[] q, const(ubyte)[] n, const(ubyte)[] p) @safe nothrow {
675 assert(q.length == crypto_scalarmult_BYTES);
676 assert(n.length == crypto_scalarmult_BYTES);
677 assert(p.length == crypto_scalarmult_BYTES);
678 int i;
679 ubyte z[32];
680 long[80] x;
681 long r;
682 long[16] a, b, c, d, e, f;
683 for (i = 0; i < 31; ++i) z[i] = n[i];
684 z[31] = (n[31]&127)|64;
685 z[0]&=248;
686 unpack25519(x, p);
687 for (i = 0; i < 16; ++i) {
688 b[i] = x[i];
689 d[i] = a[i] = c[i] = 0;
691 a[0] = d[0] = 1;
692 for (i = 254; i >= 0; --i) {
693 r = (z[i>>3]>>(i&7))&1;
694 sel25519(a, b, cast(int)r);
695 sel25519(c, d, cast(int)r);
696 A(e, a, c);
697 Z(a, a, c);
698 A(c, b, d);
699 Z(b, b, d);
700 S(d, e);
701 S(f, a);
702 M(a, c, a);
703 M(c, b, e);
704 A(e, a, c);
705 Z(a, a, c);
706 S(b, a);
707 Z(c, d, f);
708 M(a, c, _121665);
709 A(a, a, d);
710 M(c, c, a);
711 M(a, d, f);
712 M(d, b, x);
713 S(b, e);
714 sel25519(a, b, cast(int)r);
715 sel25519(c, d, cast(int)r);
717 for (i = 0; i < 16; ++i) {
718 x[i+16] = a[i];
719 x[i+32] = c[i];
720 x[i+48] = b[i];
721 x[i+64] = d[i];
723 inv25519(x[32..$], x[32..$]);
724 M(x[16..$], x[16..$], x[32..$]);
725 pack25519(q, x[16..$]);
728 /* FIXME!
729 * The crypto_scalarmult_base() function computes
730 * the scalar product of a standard group element and an integer 'n'.
732 * Params:
733 * n = number
735 * Returns:
736 * resulting group element 'q' of length crypto_scalarmult_BYTES.
738 private void crypto_scalarmult_base() (ubyte[] q, const(ubyte)[] n) @safe nothrow {
739 assert(q.length == crypto_scalarmult_BYTES);
740 assert(n.length == crypto_scalarmult_SCALARBYTES);
741 crypto_scalarmult(q, n, _9);
745 * The crypto_box_keypair() function randomly generates a secret key and
746 * a corresponding public key.
748 * Params:
749 * pk = slice to put generated public key into
750 * sk = slice to put generated secret key into
752 * Returns:
753 * pair of new keys
755 void crypto_box_keypair() (ubyte[] pk, ubyte[] sk)
756 in {
757 assert(pk.length >= crypto_box_PUBLICKEYBYTES);
758 assert(sk.length >= crypto_box_SECRETKEYBYTES);
760 body {
761 randombytes(sk, 32);
762 crypto_scalarmult_base(pk, sk);
766 * Function crypto_box_beforenm() computes a shared secret 's' from
767 * public key 'pk' and secret key 'sk'.
769 * Params:
770 * skey = slice to put secret into
771 * pk = public
772 * sk = secret
774 * Returns:
775 * generated secret
777 void crypto_box_beforenm() (ubyte[] skey, const(ubyte)[] pk, const(ubyte)[] sk) @safe nothrow
778 in {
779 assert(pk.length >= crypto_box_PUBLICKEYBYTES);
780 assert(sk.length >= crypto_box_SECRETKEYBYTES);
781 assert(skey.length >= crypto_box_BEFORENMBYTES);
783 body {
784 ubyte s[32] = void;
785 crypto_scalarmult(s, sk, pk);
786 crypto_core_hsalsa20(skey, _0, s, sigma);
790 * The crypto_box_afternm() function encrypts and authenticates
791 * a message 'msg' using a secret key 'key' and a nonce 'nonce'.
792 * The crypto_box_afternm() function returns the resulting ciphertext 'c'.
794 * Params:
795 * c = resulting cyphertext
796 * msg = message
797 * nonce = nonce
798 * key = secret
800 * Returns:
801 * success flag and cyphertext in 'c'
803 bool crypto_box_afternm() (ubyte[] c, const(ubyte)[] msg, const(ubyte)[] nonce, const(ubyte)[] key) @safe nothrow
804 in {
805 assert(nonce.length >= crypto_box_NONCEBYTES);
806 assert(key.length >= crypto_box_BEFORENMBYTES);
808 body {
809 return crypto_secretbox(c, msg, nonce, key);
813 * The crypto_box_open_afternm() function verifies and decrypts
814 * a ciphertext 'c' using a secret key 'key' and a nonce 'nonce'.
815 * The crypto_box_open_afternm() function returns the resulting message 'msg'.
817 * Params:
818 * msg = resulting message
819 * c = cyphertext
820 * nonce = nonce
821 * key = secret
823 * Returns:
824 * success flag and resulting message in 'msg'
826 bool crypto_box_open_afternm() (ubyte[] msg, const(ubyte)[] c, const(ubyte)[] nonce, const(ubyte)[] key) @safe nothrow
827 in {
828 assert(nonce.length >= crypto_box_NONCEBYTES);
829 assert(key.length >= crypto_box_BEFORENMBYTES);
831 body {
832 return crypto_secretbox_open(msg, c, nonce, key);
836 * The crypto_box() function encrypts and authenticates a message 'msg'
837 * using the sender's secret key 'sk', the receiver's public key 'pk',
838 * and a nonce 'nonce'. The crypto_box() function returns the resulting ciphertext 'c'.
840 * Params:
841 * c = resulting cyphertext
842 * msg = message
843 * nonce = nonce
844 * pk = receiver's public key
845 * sk = sender's secret key
847 * Returns:
848 * success flag and cyphertext in 'c'
850 bool crypto_box() (ubyte[] c, const(ubyte)[] msg, const(ubyte)[] nonce, const(ubyte)[] pk, const(ubyte)[] sk) @safe nothrow
851 in {
852 assert(nonce.length >= crypto_box_NONCEBYTES);
853 assert(pk.length >= crypto_box_PUBLICKEYBYTES);
854 assert(sk.length >= crypto_box_SECRETKEYBYTES);
856 body {
857 ubyte k[32] = void;
858 crypto_box_beforenm(k, pk, sk);
859 return crypto_box_afternm(c, msg, nonce, k);
863 * The crypto_box_open() function verifies and decrypts
864 * a ciphertext 'c' using the receiver's secret key 'sk',
865 * the sender's public key 'pk', and a nonce 'nonce'.
866 * The crypto_box_open() function returns the resulting message 'msg'.
868 * Params:
869 * msg = resulting message
870 * c = cyphertext
871 * nonce = nonce
872 * pk = receiver's public key
873 * sk = sender's secret key
875 * Returns:
876 * success flag and message in 'msg'
878 bool crypto_box_open() (ubyte[] msg, const(ubyte)[] c, const(ubyte)[] nonce, const(ubyte)[] pk, const(ubyte)[] sk) @safe nothrow
879 in {
880 assert(nonce.length >= crypto_box_NONCEBYTES);
881 assert(pk.length >= crypto_box_PUBLICKEYBYTES);
882 assert(sk.length >= crypto_box_SECRETKEYBYTES);
884 body {
885 ubyte k[32] = void;
886 crypto_box_beforenm(k, pk, sk);
887 return crypto_box_open_afternm(msg, c, nonce, k);
890 private @tweetNaCl_gdc_attribute("forceinline") ulong R() (ulong x, int c) @safe nothrow pure { return (x>>c)|(x<<(64-c)); }
891 private @tweetNaCl_gdc_attribute("forceinline") ulong Ch() (ulong x, ulong y, ulong z) @safe nothrow pure { return (x&y)^(~x&z); }
892 private @tweetNaCl_gdc_attribute("forceinline") ulong Maj() (ulong x, ulong y, ulong z) @safe nothrow pure { return (x&y)^(x&z)^(y&z); }
893 private @tweetNaCl_gdc_attribute("forceinline") ulong Sigma0() (ulong x) @safe nothrow pure { return R(x, 28)^R(x, 34)^R(x, 39); }
894 private @tweetNaCl_gdc_attribute("forceinline") ulong Sigma1() (ulong x) @safe nothrow pure { return R(x, 14)^R(x, 18)^R(x, 41); }
895 private @tweetNaCl_gdc_attribute("forceinline") ulong sigma0() (ulong x) @safe nothrow pure { return R(x, 1)^R(x, 8)^(x>>7); }
896 private @tweetNaCl_gdc_attribute("forceinline") ulong sigma1() (ulong x) @safe nothrow pure { return R(x, 19)^R(x, 61)^(x>>6); }
898 private static __gshared immutable ulong[80] K = [
899 0x428a2f98d728ae22UL, 0x7137449123ef65cdUL, 0xb5c0fbcfec4d3b2fUL, 0xe9b5dba58189dbbcUL,
900 0x3956c25bf348b538UL, 0x59f111f1b605d019UL, 0x923f82a4af194f9bUL, 0xab1c5ed5da6d8118UL,
901 0xd807aa98a3030242UL, 0x12835b0145706fbeUL, 0x243185be4ee4b28cUL, 0x550c7dc3d5ffb4e2UL,
902 0x72be5d74f27b896fUL, 0x80deb1fe3b1696b1UL, 0x9bdc06a725c71235UL, 0xc19bf174cf692694UL,
903 0xe49b69c19ef14ad2UL, 0xefbe4786384f25e3UL, 0x0fc19dc68b8cd5b5UL, 0x240ca1cc77ac9c65UL,
904 0x2de92c6f592b0275UL, 0x4a7484aa6ea6e483UL, 0x5cb0a9dcbd41fbd4UL, 0x76f988da831153b5UL,
905 0x983e5152ee66dfabUL, 0xa831c66d2db43210UL, 0xb00327c898fb213fUL, 0xbf597fc7beef0ee4UL,
906 0xc6e00bf33da88fc2UL, 0xd5a79147930aa725UL, 0x06ca6351e003826fUL, 0x142929670a0e6e70UL,
907 0x27b70a8546d22ffcUL, 0x2e1b21385c26c926UL, 0x4d2c6dfc5ac42aedUL, 0x53380d139d95b3dfUL,
908 0x650a73548baf63deUL, 0x766a0abb3c77b2a8UL, 0x81c2c92e47edaee6UL, 0x92722c851482353bUL,
909 0xa2bfe8a14cf10364UL, 0xa81a664bbc423001UL, 0xc24b8b70d0f89791UL, 0xc76c51a30654be30UL,
910 0xd192e819d6ef5218UL, 0xd69906245565a910UL, 0xf40e35855771202aUL, 0x106aa07032bbd1b8UL,
911 0x19a4c116b8d2d0c8UL, 0x1e376c085141ab53UL, 0x2748774cdf8eeb99UL, 0x34b0bcb5e19b48a8UL,
912 0x391c0cb3c5c95a63UL, 0x4ed8aa4ae3418acbUL, 0x5b9cca4f7763e373UL, 0x682e6ff3d6b2b8a3UL,
913 0x748f82ee5defb2fcUL, 0x78a5636f43172f60UL, 0x84c87814a1f0ab72UL, 0x8cc702081a6439ecUL,
914 0x90befffa23631e28UL, 0xa4506cebde82bde9UL, 0xbef9a3f7b2c67915UL, 0xc67178f2e372532bUL,
915 0xca273eceea26619cUL, 0xd186b8c721c0c207UL, 0xeada7dd6cde0eb1eUL, 0xf57d4f7fee6ed178UL,
916 0x06f067aa72176fbaUL, 0x0a637dc5a2c898a6UL, 0x113f9804bef90daeUL, 0x1b710b35131c471bUL,
917 0x28db77f523047d84UL, 0x32caab7b40c72493UL, 0x3c9ebe0a15c9bebcUL, 0x431d67c49c100d4cUL,
918 0x4cc5d4becb3e42b6UL, 0x597f299cfc657e2aUL, 0x5fcb6fab3ad6faecUL, 0x6c44198c4a475817UL
921 private void crypto_hashblocks (ubyte[] x, const(ubyte)[] m, ulong n) @safe nothrow {
922 ulong[8] z = void, b = void, a = void;
923 ulong[16] w = void;
924 ulong t;
925 uint mpos = 0;
927 for (auto i = 0; i < 8; ++i) z[i] = a[i] = dl64(x[8*i..$]);
929 while (n >= 128) {
930 for (auto i = 0; i < 16; ++i) w[i] = dl64(m[mpos+8*i..$]);
932 for (auto i = 0; i < 80; ++i) {
933 for (auto j = 0; j < 8; ++j) b[j] = a[j];
934 t = a[7]+Sigma1(a[4])+Ch(a[4], a[5], a[6])+K[i]+w[i%16];
935 b[7] = t+Sigma0(a[0])+Maj(a[0], a[1], a[2]);
936 b[3] += t;
937 for (auto j = 0; j < 8; ++j) a[(j+1)%8] = b[j];
938 if (i%16 == 15) {
939 for (auto j = 0; j < 16; ++j) w[j] += w[(j+9)%16]+sigma0(w[(j+1)%16])+sigma1(w[(j+14)%16]);
943 for (auto i = 0; i < 8; ++i) { a[i] += z[i]; z[i] = a[i]; }
945 mpos += 128;
946 n -= 128;
949 for (auto i = 0; i < 8; ++i) ts64(x[8*i..$], z[i]);
952 private static __gshared immutable ubyte[64] iv = [
953 0x6a, 0x09, 0xe6, 0x67, 0xf3, 0xbc, 0xc9, 0x08,
954 0xbb, 0x67, 0xae, 0x85, 0x84, 0xca, 0xa7, 0x3b,
955 0x3c, 0x6e, 0xf3, 0x72, 0xfe, 0x94, 0xf8, 0x2b,
956 0xa5, 0x4f, 0xf5, 0x3a, 0x5f, 0x1d, 0x36, 0xf1,
957 0x51, 0x0e, 0x52, 0x7f, 0xad, 0xe6, 0x82, 0xd1,
958 0x9b, 0x05, 0x68, 0x8c, 0x2b, 0x3e, 0x6c, 0x1f,
959 0x1f, 0x83, 0xd9, 0xab, 0xfb, 0x41, 0xbd, 0x6b,
960 0x5b, 0xe0, 0xcd, 0x19, 0x13, 0x7e, 0x21, 0x79
964 * The crypto_hash() function hashes a message 'msg'.
965 * It returns a hash 'output'. The output length of 'output' should be at least crypto_hash_BYTES.
967 * Params:
968 * output = resulting hash
969 * msg = message
971 * Returns:
972 * sha512 hash
974 void crypto_hash() (ubyte[] output, const(ubyte)[] msg) @safe nothrow
975 in {
976 assert(output.length >= crypto_hash_BYTES);
978 body {
979 ubyte[64] h = void;
980 ubyte[256] x = void;
981 size_t n = msg.length;
982 ulong b = n;
983 uint mpos = 0;
985 for (auto i = 0; i < 64; ++i) h[i] = iv[i];
987 crypto_hashblocks(h, msg, n);
988 mpos += n;
989 n &= 127;
990 mpos -= n;
992 for (auto i = 0; i < 256; ++i) x[i] = 0;
993 for (auto i = 0; i < n; ++i) x[i] = msg[mpos+i];
994 x[cast(uint)n] = 128;
996 n = 256-128*(n<112);
997 x[cast(uint)(n-9)] = b>>61;
998 ts64(x[cast(uint)(n-8)..$], b<<3);
999 crypto_hashblocks(h, x, n);
1001 for (auto i = 0; i < 64; ++i) output[i] = h[i];
1004 private @tweetNaCl_gdc_attribute("forceinline") void add() (ref long[16][4] p, ref long[16][4] q) @safe nothrow {
1005 long[16] a = void, b = void, c = void, d = void, t = void, e = void, f = void, g = void, h = void;
1007 Z(a, p[1], p[0]);
1008 Z(t, q[1], q[0]);
1009 M(a, a, t);
1010 A(b, p[0], p[1]);
1011 A(t, q[0], q[1]);
1012 M(b, b, t);
1013 M(c, p[3], q[3]);
1014 M(c, c, D2);
1015 M(d, p[2], q[2]);
1016 A(d, d, d);
1017 Z(e, b, a);
1018 Z(f, d, c);
1019 A(g, d, c);
1020 A(h, b, a);
1022 M(p[0], e, f);
1023 M(p[1], h, g);
1024 M(p[2], g, f);
1025 M(p[3], e, h);
1028 private @tweetNaCl_gdc_attribute("forceinline") void cswap() (ref long[16][4] p, ref long[16][4] q, ubyte b) @safe nothrow {
1029 for (auto i = 0; i < 4; ++i) sel25519(p[i], q[i], b);
1032 private @tweetNaCl_gdc_attribute("forceinline") void pack() (ubyte[] r, ref long[16][4] p) @safe nothrow {
1033 long[16] tx = void, ty = void, zi = void;
1034 inv25519(zi, p[2]);
1035 M(tx, p[0], zi);
1036 M(ty, p[1], zi);
1037 pack25519(r, ty);
1038 r[31] ^= par25519(tx)<<7;
1041 private @tweetNaCl_gdc_attribute("forceinline") void scalarmult() (ref long[16][4] p, ref long[16][4] q, const(ubyte)[] s) @safe nothrow {
1042 set25519(p[0], gf0);
1043 set25519(p[1], gf1);
1044 set25519(p[2], gf1);
1045 set25519(p[3], gf0);
1046 for (auto i = 255; i >= 0; --i) {
1047 ubyte b = (s[i/8]>>(i&7))&1;
1048 cswap(p, q, b);
1049 add(q, p);
1050 add(p, p);
1051 cswap(p, q, b);
1055 private @tweetNaCl_gdc_attribute("forceinline") void scalarbase() (ref long[16][4] p, const(ubyte)[] s) @safe nothrow {
1056 long[16][4] q = void;
1057 set25519(q[0], X);
1058 set25519(q[1], Y);
1059 set25519(q[2], gf1);
1060 M(q[3], X, Y);
1061 scalarmult(p, q, s);
1065 * The crypto_sign_keypair() function randomly generates a secret key and
1066 * a corresponding public key.
1068 * Params:
1069 * pk = slice to put generated public key into
1070 * sk = slice to put generated secret key into
1072 * Returns:
1073 * pair of new keys
1075 void crypto_sign_keypair() (ubyte[] pk, ubyte[] sk)
1076 in {
1077 assert(pk.length >= crypto_sign_PUBLICKEYBYTES);
1078 assert(sk.length >= crypto_sign_SECRETKEYBYTES);
1080 body {
1081 ubyte d[64] = void;
1082 long[16][4] p = void;
1084 randombytes(sk, 32);
1085 crypto_hash(d, sk[0..32]);
1086 d[0] &= 248;
1087 d[31] &= 127;
1088 d[31] |= 64;
1090 scalarbase(p, d);
1091 pack(pk, p);
1093 for (auto i = 0; i < 32; ++i) sk[32+i] = pk[i];
1096 private static __gshared immutable ulong[32] L = [
1097 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
1100 private @tweetNaCl_gdc_attribute("forceinline") void modL() (ubyte[] r, long[] x) @safe nothrow {
1101 long carry;
1102 for (auto i = 63; i >= 32; --i) {
1103 int j;
1104 carry = 0;
1105 for (j = i-32; j < i-12; ++j) {
1106 x[j] += carry-16*x[i]*L[j-(i-32)];
1107 carry = (x[j]+128)>>8;
1108 x[j] -= carry<<8;
1110 x[j] += carry;
1111 x[i] = 0;
1113 carry = 0;
1114 for (auto j = 0; j < 32; ++j) {
1115 x[j] += carry-(x[31]>>4)*L[j];
1116 carry = x[j]>>8;
1117 x[j] &= 255;
1119 for (auto j = 0; j < 32; ++j) x[j] -= carry*L[j];
1120 for (auto i = 0; i < 32; ++i) {
1121 x[i+1] += x[i]>>8;
1122 r[i] = x[i]&255;
1126 private @tweetNaCl_gdc_attribute("forceinline") void reduce() (ubyte[] r) @safe nothrow {
1127 long[64] x = void;
1128 for (auto i = 0; i < 64; ++i) x[i] = cast(ulong)r[i];
1129 for (auto i = 0; i < 64; ++i) r[i] = 0;
1130 modL(r, x);
1134 * The crypto_sign() function signs a message 'msg' using the sender's secret key 'sk'.
1135 * The crypto_sign() function returns the resulting signed message.
1137 * Params:
1138 * sm = buffer to receive signed message, must be of size at least msg.length+64
1139 * msg == message
1140 * sk == secret key, slice size must be at least crypto_sign_SECRETKEYBYTES, extra ignored
1142 * Returns:
1143 * signed message
1145 void crypto_sign() (ubyte[] sm, const(ubyte)[] msg, const(ubyte)[] sk) @trusted nothrow
1146 in {
1147 assert(sk.length >= crypto_sign_SECRETKEYBYTES);
1148 assert(sm.length >= msg.length+64);
1150 body {
1151 ubyte[64] d = void, h = void, r = void;
1152 ulong[64] x = void;
1153 long[16][4] p = void;
1154 size_t n = msg.length;
1155 size_t smlen = n+64;
1157 crypto_hash(d, sk[0..32]);
1158 d[0] &= 248;
1159 d[31] &= 127;
1160 d[31] |= 64;
1162 for (auto i = 0; i < n; ++i) sm[64+i] = msg[i];
1163 for (auto i = 0; i < 32; ++i) sm[32+i] = d[32+i];
1165 crypto_hash(r, sm[32../*$*/32+n+32]/*, n+32*/);
1166 reduce(r);
1167 scalarbase(p, r);
1168 pack(sm, p);
1170 for (auto i = 0; i < 32; ++i) sm[i+32] = sk[i+32];
1171 crypto_hash(h, sm[0..n+64]);
1172 reduce(h);
1174 for (auto i = 0; i < 64; ++i) x[i] = 0;
1175 for (auto i = 0; i < 32; ++i) x[i] = cast(ulong)r[i];
1176 for (auto i = 0; i < 32; ++i) for (auto j = 0; j < 32; ++j) x[i+j] += h[i]*cast(ulong)d[j];
1177 modL(sm[32..$], cast(long[])x);
1181 * The crypto_sign() function signs a message 'msg' using the sender's secret key 'sk'.
1182 * The crypto_sign() function returns the resulting signed message.
1184 * WARNING! This function allocates!
1186 * Params:
1187 * msg == message
1188 * sk == secret key, slice size must be at least crypto_sign_SECRETKEYBYTES, extra ignored
1190 * Returns:
1191 * signed message
1193 ubyte[] crypto_sign() (const(ubyte)[] msg, const(ubyte)[] sk) @safe nothrow
1194 in {
1195 assert(sk.length >= crypto_sign_SECRETKEYBYTES);
1197 body {
1198 ubyte[] sm;
1199 size_t n = msg.length;
1200 size_t smlen = n+64;
1201 sm.length = smlen;
1202 crypto_sign(sm, msg, sk);
1203 return sm;
1206 private @tweetNaCl_gdc_attribute("forceinline") bool unpackneg() (ref long[16][4] r, const(ubyte)[] p) @safe nothrow {
1207 long[16] t = void, chk = void, num = void, den = void, den2 = void, den4 = void, den6 = void;
1208 set25519(r[2], gf1);
1209 unpack25519(r[1], p);
1210 S(num, r[1]);
1211 M(den, num, D);
1212 Z(num, num, r[2]);
1213 A(den, r[2], den);
1215 S(den2, den);
1216 S(den4, den2);
1217 M(den6, den4, den2);
1218 M(t, den6, num);
1219 M(t, t, den);
1221 pow2523(t, t);
1222 M(t, t, num);
1223 M(t, t, den);
1224 M(t, t, den);
1225 M(r[0], t, den);
1227 S(chk, r[0]);
1228 M(chk, chk, den);
1229 if (!neq25519(chk, num)) M(r[0], r[0], I);
1231 S(chk, r[0]);
1232 M(chk, chk, den);
1233 if (!neq25519(chk, num)) return false;
1235 if (par25519(r[0]) == (p[31]>>7)) Z(r[0], gf0, r[0]);
1237 M(r[3], r[0], r[1]);
1238 return true;
1242 * The crypto_sign_open() function verifies the signature in
1243 * 'sm' using the receiver's public key 'pk'.
1245 * Params:
1246 * msg = decrypted message, last 64 bytes are useless zeroes, must be of size at least sm.length
1247 * sm == signed message
1248 * pk == public key, slice size must be at least crypto_sign_PUBLICKEYBYTES, extra ignored
1250 * Returns:
1251 * success flag
1253 bool crypto_sign_open() (ubyte[] msg, const(ubyte)[] sm, const(ubyte)[] pk) @safe nothrow
1254 in {
1255 assert(pk.length >= crypto_sign_PUBLICKEYBYTES);
1256 assert(msg.length >= sm.length);
1258 body {
1259 ubyte[32] t = void;
1260 ubyte[64] h = void;
1261 long[16][4] p = void, q = void;
1262 size_t n = sm.length;
1264 if (n < 64) return false;
1266 if (!unpackneg(q, pk)) return false;
1267 for (auto i = 0; i < n; ++i) msg[i] = sm[i];
1268 for (auto i = 0; i < 32; ++i) msg[i+32] = pk[i];
1269 crypto_hash(h, msg/*, n*/);
1270 reduce(h);
1271 scalarmult(p, q, h);
1273 scalarbase(q, sm[32..$]);
1274 add(p, q);
1275 pack(t, p);
1277 n -= 64;
1278 if (!crypto_verify_32(sm, t)) {
1279 for (auto i = 0; i < n; ++i) msg[i] = 0;
1280 return false;
1283 for (auto i = 0; i < n; ++i) msg[i] = sm[i+64];
1284 for (auto i = n; i < n+64; ++i) msg[i] = 0;
1286 return true;
1291 * The crypto_sign_open() function verifies the signature in
1292 * 'sm' using the receiver's public key 'pk'.
1293 * The crypto_sign_open() function returns the message.
1295 * WARNING! This function allocates!
1297 * Params:
1298 * sm == signed message
1299 * pk == public key, slice size must be at least crypto_sign_PUBLICKEYBYTES, extra ignored
1301 * Returns:
1302 * decrypted message or null on error
1304 ubyte[] crypto_sign_open() (const(ubyte)[] sm, const(ubyte)[] pk) @safe nothrow {
1305 ubyte[] msg;
1306 msg.length = sm.length;
1307 if (!crypto_sign_open(msg, sm, pk)) return null;
1308 return msg[0..sm.length-64]; // remove signature
1312 unittest {
1313 import std.exception;
1314 import std.random;
1315 import std.range;
1316 import std.stdio;
1319 private extern(C) int open(const(char)* filename, int flags, ...);
1320 void randombytes (ubyte[] dest, size_t len) {
1321 import core.sys.posix.unistd;
1322 static int fd = -1;
1323 if (fd == -1) {
1324 for (;;) {
1325 fd = open("/dev/urandom", /*O_RDONLY*/0);
1326 if (fd != -1) break;
1327 sleep(1);
1330 size_t pos = 0;
1331 while (len > 0) {
1332 ssize_t i = read(fd, cast(void*)(&dest[pos]), (len < 1048576 ? len : 1048576));
1333 if (i < 1) {
1334 sleep(1);
1335 continue;
1337 pos += i;
1338 len -= i;
1343 static void rnd (ubyte[] dest, size_t len) {
1344 for (size_t f = 0; f < len; ++f) dest[f] = cast(ubyte)uniform(0, 256);
1346 randombytes = &rnd;
1349 randombytes = (ubyte[] dest, size_t len) {
1350 for (size_t f = 0; f < len; ++f) dest[f] = cast(ubyte)uniform(0, 256);
1353 void dumpArray(T) (T[] arr) @trusted {
1354 writefln("============================= (%s)", arr.length);
1355 for (auto f = 0; f < arr.length; ++f) {
1356 if (f && f%16 == 0) writeln();
1357 static if (T.sizeof == 1) writef(" 0x%02x", arr[f]);
1358 else static if (T.sizeof == 2) writef(" 0x%04x", arr[f]);
1359 else static if (T.sizeof == 4) writef(" 0x%08x", arr[f]);
1360 else writef(" 0x%08x", arr[f]);
1362 writeln();
1363 writeln("-----------------------------");
1366 string hashToString (const(ubyte)[] hash) {
1367 char[] s;
1368 s.length = hash.length*2;
1369 char toHex(int a) { return cast(char)(a < 10 ? a+'0' : a+'a'-10); }
1370 for (int a = 0; a < hash.length; ++a) {
1371 s[a*2] = toHex(hash[a]>>4);
1372 s[a*2+1] = toHex(hash[a]&0x0f);
1374 return assumeUnique(s);
1377 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];
1378 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];
1379 static immutable ubyte[5] m = [0x61,0x68,0x6f,0x6a,0x0a];
1380 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];
1381 ubyte[] smres, t;
1383 writeln("crypto_sign");
1384 smres = crypto_sign(m, sk);
1385 assert(smres.length == sm.length);
1386 assert(smres == sm);
1388 writeln("crypto_sign_open");
1389 t = crypto_sign_open(smres, pk);
1390 assert(t !is null);
1391 assert(t.length == m.length);
1392 assert(t == m);
1395 // based on the code by Adam D. Ruppe
1396 // 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
1397 template SHARange(T) if (isInputRange!(T)) {
1398 struct SHARange {
1399 T r;
1401 bool empty () { return state == 5; }
1403 void popFront () {
1404 if (state == 0) {
1405 r.popFront;
1406 ++length; // FIXME
1407 if (r.empty) {
1408 state = 1;
1409 position = 2;
1410 current = 0x80;
1412 } else {
1413 bool hackforward = false;
1414 if (state == 1) {
1415 current = 0x0;
1416 state = 2;
1417 if (((position+length+8)*8)%512 == 8) {
1418 --position;
1419 hackforward = true;
1421 goto proceed;
1422 //++position;
1423 } else if (state == 2) {
1424 proceed:
1425 if (!(((position+length+8)*8)%512)) {
1426 state = 3;
1427 position = 7;
1428 length *= 8;
1429 if (hackforward) goto proceedmoar;
1430 } else {
1431 ++position;
1433 } else if (state == 3) {
1434 proceedmoar:
1435 current = (length>>(position*8))&0xff;
1436 if (position == 0) state = 4; else --position;
1437 } else if (state == 4) {
1438 current = 0xff;
1439 state = 5;
1444 ubyte front () {
1445 if (state == 0) return cast(ubyte)r.front();
1446 assert(state != 5);
1447 //writefln("%x", current);
1448 return current;
1451 ubyte current;
1452 uint position;
1453 ulong length;
1454 int state = 0; // reading range, reading appended bit, reading padding, reading length, done
1459 immutable(ubyte)[] SHA256(T) (T data) if (isInputRange!(T)) {
1460 uint[8] h = [0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19];
1461 static immutable(uint[64]) k = [
1462 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
1463 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
1464 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
1465 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
1466 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
1467 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
1468 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
1469 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
1473 SHARange!(T) range;
1474 static if (is(data == SHARange)) range = data; else range.r = data;
1477 while(!range.empty) {
1478 uint[64] words;
1480 for(int a = 0; a < 16; ++a) {
1481 for(int b = 3; b >= 0; --b) {
1482 words[a] |= cast(uint)(range.front())<<(b*8);
1483 range.popFront;
1487 uint ror (uint n, int cnt) {
1488 return cast(uint)(n>>cnt)|cast(uint)(n<<(32-(cnt)));
1491 uint xrot00 (uint reax, int r0, int r1, int r2) {
1492 uint rebx = reax, recx = reax;
1493 reax = ror(reax, r0);
1494 rebx = ror(rebx, r1);
1495 recx >>= r2;
1496 reax ^= rebx;
1497 reax ^= recx;
1498 return reax;
1501 for(int a = 16; a < 64; ++a) {
1502 uint t1 = xrot00(words[a-15], 7, 18, 3);
1503 uint t2 = xrot00(words[a-2], 17, 19, 10);
1504 words[a] = words[a-16]+t1+words[a-7]+t2;
1507 uint A = h[0];
1508 uint B = h[1];
1509 uint C = h[2];
1510 uint D = h[3];
1511 uint E = h[4];
1512 uint F = h[5];
1513 uint G = h[6];
1514 uint H = h[7];
1516 uint xrot01 (uint reax, int r0, int r1, int r2) {
1517 uint rebx = reax, recx = reax;
1518 reax = ror(reax, r0);
1519 rebx = ror(rebx, r1);
1520 recx = ror(recx, r2);
1521 reax ^= rebx;
1522 reax ^= recx;
1523 return reax;
1526 for(int i = 0; i < 64; ++i) {
1527 uint s0 = xrot01(A, 2, 13, 22);
1528 uint maj = (A&B)^(A&C)^(B&C);
1529 uint t2 = s0+maj;
1530 uint s1 = xrot01(E, 6, 11, 25);
1531 uint ch = (E&F)^((~E)&G);
1532 uint t1 = H+s1+ch+k[i]+words[i];
1534 H = G;
1535 G = F;
1536 F = E;
1537 E = D+t1;
1538 D = C;
1539 C = B;
1540 B = A;
1541 A = t1+t2;
1544 h[0] += A;
1545 h[1] += B;
1546 h[2] += C;
1547 h[3] += D;
1548 h[4] += E;
1549 h[5] += F;
1550 h[6] += G;
1551 h[7] += H;
1554 ubyte[] hash;
1555 for(int j = 0; j < 8; ++j)
1556 for(int i = 3; i >= 0; --i) {
1557 hash ~= cast(ubyte)(h[j]>>(i*8))&0xff;
1560 return hash.idup;
1564 void box () {
1565 writeln("box");
1567 static immutable ubyte[32] alicesk = [
1568 0x77,0x07,0x6d,0x0a,0x73,0x18,0xa5,0x7d
1569 ,0x3c,0x16,0xc1,0x72,0x51,0xb2,0x66,0x45
1570 ,0xdf,0x4c,0x2f,0x87,0xeb,0xc0,0x99,0x2a
1571 ,0xb1,0x77,0xfb,0xa5,0x1d,0xb9,0x2c,0x2a
1574 static immutable ubyte[32] bobpk = [
1575 0xde,0x9e,0xdb,0x7d,0x7b,0x7d,0xc1,0xb4
1576 ,0xd3,0x5b,0x61,0xc2,0xec,0xe4,0x35,0x37
1577 ,0x3f,0x83,0x43,0xc8,0x5b,0x78,0x67,0x4d
1578 ,0xad,0xfc,0x7e,0x14,0x6f,0x88,0x2b,0x4f
1581 static immutable ubyte[24] nonce = [
1582 0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73
1583 ,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6
1584 ,0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37
1587 // API requires first 32 bytes to be 0
1588 static immutable ubyte[163] m = [
1589 0, 0, 0, 0, 0, 0, 0, 0
1590 , 0, 0, 0, 0, 0, 0, 0, 0
1591 , 0, 0, 0, 0, 0, 0, 0, 0
1592 , 0, 0, 0, 0, 0, 0, 0, 0
1593 ,0xbe,0x07,0x5f,0xc5,0x3c,0x81,0xf2,0xd5
1594 ,0xcf,0x14,0x13,0x16,0xeb,0xeb,0x0c,0x7b
1595 ,0x52,0x28,0xc5,0x2a,0x4c,0x62,0xcb,0xd4
1596 ,0x4b,0x66,0x84,0x9b,0x64,0x24,0x4f,0xfc
1597 ,0xe5,0xec,0xba,0xaf,0x33,0xbd,0x75,0x1a
1598 ,0x1a,0xc7,0x28,0xd4,0x5e,0x6c,0x61,0x29
1599 ,0x6c,0xdc,0x3c,0x01,0x23,0x35,0x61,0xf4
1600 ,0x1d,0xb6,0x6c,0xce,0x31,0x4a,0xdb,0x31
1601 ,0x0e,0x3b,0xe8,0x25,0x0c,0x46,0xf0,0x6d
1602 ,0xce,0xea,0x3a,0x7f,0xa1,0x34,0x80,0x57
1603 ,0xe2,0xf6,0x55,0x6a,0xd6,0xb1,0x31,0x8a
1604 ,0x02,0x4a,0x83,0x8f,0x21,0xaf,0x1f,0xde
1605 ,0x04,0x89,0x77,0xeb,0x48,0xf5,0x9f,0xfd
1606 ,0x49,0x24,0xca,0x1c,0x60,0x90,0x2e,0x52
1607 ,0xf0,0xa0,0x89,0xbc,0x76,0x89,0x70,0x40
1608 ,0xe0,0x82,0xf9,0x37,0x76,0x38,0x48,0x64
1609 ,0x5e,0x07,0x05
1612 ubyte[163] c;
1615 static immutable ubyte[] res = [
1616 0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5
1617 ,0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9
1618 ,0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73
1619 ,0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce
1620 ,0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4
1621 ,0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a
1622 ,0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b
1623 ,0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72
1624 ,0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2
1625 ,0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38
1626 ,0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a
1627 ,0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae
1628 ,0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea
1629 ,0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda
1630 ,0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde
1631 ,0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3
1632 ,0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6
1633 ,0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74
1634 ,0xe3,0x55,0xa5];
1635 /*crypto_box_curve25519xsalsa20poly1305*/crypto_box(c,m,nonce,bobpk,alicesk);
1636 for (auto f = 16; f < 163; ++f) assert(c[f] == res[f-16]);
1638 box();
1640 void box2 () {
1641 writeln("box2");
1642 static immutable ubyte[32] bobsk = [
1643 0x5d,0xab,0x08,0x7e,0x62,0x4a,0x8a,0x4b
1644 ,0x79,0xe1,0x7f,0x8b,0x83,0x80,0x0e,0xe6
1645 ,0x6f,0x3b,0xb1,0x29,0x26,0x18,0xb6,0xfd
1646 ,0x1c,0x2f,0x8b,0x27,0xff,0x88,0xe0,0xeb
1649 static immutable ubyte[32] alicepk = [
1650 0x85,0x20,0xf0,0x09,0x89,0x30,0xa7,0x54
1651 ,0x74,0x8b,0x7d,0xdc,0xb4,0x3e,0xf7,0x5a
1652 ,0x0d,0xbf,0x3a,0x0d,0x26,0x38,0x1a,0xf4
1653 ,0xeb,0xa4,0xa9,0x8e,0xaa,0x9b,0x4e,0x6a
1656 static immutable ubyte[24] nonce = [
1657 0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73
1658 ,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6
1659 ,0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37
1662 // API requires first 16 bytes to be 0
1663 static immutable ubyte[163] c = [
1664 0, 0, 0, 0, 0, 0, 0, 0
1665 , 0, 0, 0, 0, 0, 0, 0, 0
1666 ,0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5
1667 ,0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9
1668 ,0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73
1669 ,0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce
1670 ,0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4
1671 ,0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a
1672 ,0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b
1673 ,0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72
1674 ,0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2
1675 ,0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38
1676 ,0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a
1677 ,0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae
1678 ,0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea
1679 ,0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda
1680 ,0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde
1681 ,0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3
1682 ,0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6
1683 ,0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74
1684 ,0xe3,0x55,0xa5
1687 ubyte m[163];
1689 static immutable ubyte[] res = [
1690 0xbe,0x07,0x5f,0xc5,0x3c,0x81,0xf2,0xd5
1691 ,0xcf,0x14,0x13,0x16,0xeb,0xeb,0x0c,0x7b
1692 ,0x52,0x28,0xc5,0x2a,0x4c,0x62,0xcb,0xd4
1693 ,0x4b,0x66,0x84,0x9b,0x64,0x24,0x4f,0xfc
1694 ,0xe5,0xec,0xba,0xaf,0x33,0xbd,0x75,0x1a
1695 ,0x1a,0xc7,0x28,0xd4,0x5e,0x6c,0x61,0x29
1696 ,0x6c,0xdc,0x3c,0x01,0x23,0x35,0x61,0xf4
1697 ,0x1d,0xb6,0x6c,0xce,0x31,0x4a,0xdb,0x31
1698 ,0x0e,0x3b,0xe8,0x25,0x0c,0x46,0xf0,0x6d
1699 ,0xce,0xea,0x3a,0x7f,0xa1,0x34,0x80,0x57
1700 ,0xe2,0xf6,0x55,0x6a,0xd6,0xb1,0x31,0x8a
1701 ,0x02,0x4a,0x83,0x8f,0x21,0xaf,0x1f,0xde
1702 ,0x04,0x89,0x77,0xeb,0x48,0xf5,0x9f,0xfd
1703 ,0x49,0x24,0xca,0x1c,0x60,0x90,0x2e,0x52
1704 ,0xf0,0xa0,0x89,0xbc,0x76,0x89,0x70,0x40
1705 ,0xe0,0x82,0xf9,0x37,0x76,0x38,0x48,0x64
1706 ,0x5e,0x07,0x05
1709 assert(/*crypto_box_curve25519xsalsa20poly1305_open*/crypto_box_open(m,c,nonce,alicepk,bobsk));
1710 for (auto f = 32; f < 163; ++f) assert(m[f] == res[f-32]);
1712 box2();
1714 void box7 () {
1715 writeln("box7");
1716 ubyte[crypto_box_SECRETKEYBYTES] alicesk;
1717 ubyte[crypto_box_PUBLICKEYBYTES] alicepk;
1718 ubyte[crypto_box_SECRETKEYBYTES] bobsk;
1719 ubyte[crypto_box_PUBLICKEYBYTES] bobpk;
1720 ubyte[crypto_box_NONCEBYTES] n;
1721 ubyte[10000] m, c, m2;
1722 for (auto mlen = 0; mlen < 1000 && mlen+crypto_box_ZEROBYTES < m.length; ++mlen) {
1723 crypto_box_keypair(alicepk,alicesk);
1724 crypto_box_keypair(bobpk,bobsk);
1725 randombytes(n,crypto_box_NONCEBYTES);
1726 randombytes(m[crypto_box_ZEROBYTES..$],mlen);
1727 crypto_box(c[0..mlen+crypto_box_ZEROBYTES],m,n,bobpk,alicesk);
1728 assert(crypto_box_open(m2[0..mlen+crypto_box_ZEROBYTES],c,n,alicepk,bobsk));
1729 for (auto i = 0; i < mlen+crypto_box_ZEROBYTES; ++i) assert(m2[i] == m[i]);
1732 version(unittest_full) box7(); // it's slow
1734 void box8 () {
1735 writeln("box8");
1736 ubyte[crypto_box_SECRETKEYBYTES] alicesk;
1737 ubyte[crypto_box_PUBLICKEYBYTES] alicepk;
1738 ubyte[crypto_box_SECRETKEYBYTES] bobsk;
1739 ubyte[crypto_box_PUBLICKEYBYTES] bobpk;
1740 ubyte[crypto_box_NONCEBYTES] n;
1741 ubyte[10000] m, c, m2;
1742 for (auto mlen = 0; mlen < 1000 && mlen+crypto_box_ZEROBYTES < m.length; ++mlen) {
1743 crypto_box_keypair(alicepk,alicesk);
1744 crypto_box_keypair(bobpk,bobsk);
1745 randombytes(n,crypto_box_NONCEBYTES);
1746 randombytes(m[crypto_box_ZEROBYTES..$],mlen);
1747 crypto_box(c[0..mlen+crypto_box_ZEROBYTES],m,n,bobpk,alicesk);
1748 int caught = 0;
1749 while (caught < 10) {
1750 c[uniform(0, mlen+crypto_box_ZEROBYTES)] = cast(ubyte)uniform(0, 256);
1751 if (crypto_box_open(m2[0..mlen+crypto_box_ZEROBYTES],c,n,alicepk,bobsk)) {
1752 for (auto i = 0; i < mlen+crypto_box_ZEROBYTES; ++i) assert(m2[i] == m[i]);
1753 } else {
1754 ++caught;
1757 assert(caught == 10);
1760 version(unittest_full) box8(); // it's slow
1762 void core1 () {
1763 writeln("core1");
1764 static immutable ubyte[32] shared_ = [
1765 0x4a,0x5d,0x9d,0x5b,0xa4,0xce,0x2d,0xe1
1766 ,0x72,0x8e,0x3b,0xf4,0x80,0x35,0x0f,0x25
1767 ,0xe0,0x7e,0x21,0xc9,0x47,0xd1,0x9e,0x33
1768 ,0x76,0xf0,0x9b,0x3c,0x1e,0x16,0x17,0x42
1771 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];
1773 static immutable ubyte[16] c = [
1774 0x65,0x78,0x70,0x61,0x6e,0x64,0x20,0x33
1775 ,0x32,0x2d,0x62,0x79,0x74,0x65,0x20,0x6b
1778 ubyte[32] firstkey;
1780 static immutable ubyte[32] res = [
1781 0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4
1782 ,0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7
1783 ,0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2
1784 ,0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89
1787 crypto_core_hsalsa20(firstkey,zero,shared_,c);
1788 assert(firstkey == res);
1790 core1();
1792 void core2 () {
1793 writeln("core2");
1794 static immutable ubyte[32]firstkey = [
1795 0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4
1796 ,0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7
1797 ,0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2
1798 ,0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89
1801 static immutable ubyte[16]nonceprefix = [
1802 0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73
1803 ,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6
1806 static immutable ubyte[16] c = [
1807 0x65,0x78,0x70,0x61,0x6e,0x64,0x20,0x33
1808 ,0x32,0x2d,0x62,0x79,0x74,0x65,0x20,0x6b
1811 ubyte[32] secondkey;
1813 static immutable ubyte[32] res = [
1814 0xdc,0x90,0x8d,0xda,0x0b,0x93,0x44,0xa9
1815 ,0x53,0x62,0x9b,0x73,0x38,0x20,0x77,0x88
1816 ,0x80,0xf3,0xce,0xb4,0x21,0xbb,0x61,0xb9
1817 ,0x1c,0xbd,0x4c,0x3e,0x66,0x25,0x6c,0xe4
1820 crypto_core_hsalsa20(secondkey,nonceprefix,firstkey,c);
1821 assert(secondkey == res);
1823 core2();
1825 void core3 () {
1826 writeln("core3");
1827 static immutable ubyte[32] secondkey = [
1828 0xdc,0x90,0x8d,0xda,0x0b,0x93,0x44,0xa9
1829 ,0x53,0x62,0x9b,0x73,0x38,0x20,0x77,0x88
1830 ,0x80,0xf3,0xce,0xb4,0x21,0xbb,0x61,0xb9
1831 ,0x1c,0xbd,0x4c,0x3e,0x66,0x25,0x6c,0xe4
1834 static immutable ubyte[8] noncesuffix = [
1835 0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37
1838 static immutable ubyte[16] c = [
1839 0x65,0x78,0x70,0x61,0x6e,0x64,0x20,0x33
1840 ,0x32,0x2d,0x62,0x79,0x74,0x65,0x20,0x6b
1843 static ubyte[16] input = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] ;
1845 static ubyte output[64*256*256];
1847 static ubyte[64] h;
1849 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];
1851 int pos = 0;
1852 for (auto i = 0; i < 8; ++i) input[i] = noncesuffix[i];
1853 do {
1854 do {
1855 crypto_core_salsa20(output[pos..$],input,secondkey,c);
1856 pos += 64;
1857 } while (++input[8]);
1858 } while (++input[9]);
1859 crypto_hash(h,output);
1860 assert(h == res);
1862 version(unittest_full) core3(); // it's slow
1864 void core4 () {
1865 writeln("core4");
1866 static immutable ubyte[32] k = [
1867 1, 2, 3, 4, 5, 6, 7, 8
1868 , 9, 10, 11, 12, 13, 14, 15, 16
1869 ,201,202,203,204,205,206,207,208
1870 ,209,210,211,212,213,214,215,216
1873 static immutable ubyte[16] input = [
1874 101,102,103,104,105,106,107,108
1875 ,109,110,111,112,113,114,115,116
1878 static immutable ubyte[16] c = [
1879 101,120,112, 97,110,100, 32, 51
1880 , 50, 45, 98,121,116,101, 32,107
1883 ubyte[64] output;
1885 static immutable ubyte[64] res = [
1886 69, 37, 68, 39, 41, 15,107,193
1887 ,255,139,122, 6,170,233,217, 98
1888 , 89,144,182,106, 21, 51,200, 65
1889 ,239, 49,222, 34,215,114, 40,126
1890 ,104,197, 7,225,197,153, 31, 2
1891 ,102, 78, 76,176, 84,245,246,184
1892 ,177,160,133,130, 6, 72,149,119
1893 ,192,195,132,236,234,103,246, 74
1896 crypto_core_salsa20(output,input,k,c);
1897 assert(output == res);
1899 core4();
1901 void core5 () {
1902 writeln("core5");
1903 static immutable ubyte[32] k = [
1904 0xee,0x30,0x4f,0xca,0x27,0x00,0x8d,0x8c
1905 ,0x12,0x6f,0x90,0x02,0x79,0x01,0xd8,0x0f
1906 ,0x7f,0x1d,0x8b,0x8d,0xc9,0x36,0xcf,0x3b
1907 ,0x9f,0x81,0x96,0x92,0x82,0x7e,0x57,0x77
1910 static immutable ubyte[16] input = [
1911 0x81,0x91,0x8e,0xf2,0xa5,0xe0,0xda,0x9b
1912 ,0x3e,0x90,0x60,0x52,0x1e,0x4b,0xb3,0x52
1915 static immutable ubyte[16] c = [
1916 101,120,112, 97,110,100, 32, 51
1917 , 50, 45, 98,121,116,101, 32,107
1920 ubyte output[32];
1922 static immutable ubyte[32] res = [
1923 0xbc,0x1b,0x30,0xfc,0x07,0x2c,0xc1,0x40
1924 ,0x75,0xe4,0xba,0xa7,0x31,0xb5,0xa8,0x45
1925 ,0xea,0x9b,0x11,0xe9,0xa5,0x19,0x1f,0x94
1926 ,0xe1,0x8c,0xba,0x8f,0xd8,0x21,0xa7,0xcd
1929 crypto_core_hsalsa20(output,input,k,c);
1930 assert(output == res);
1932 core5();
1934 void core6 () {
1935 writeln("core6");
1936 static immutable ubyte[32] k = [
1937 0xee,0x30,0x4f,0xca,0x27,0x00,0x8d,0x8c
1938 ,0x12,0x6f,0x90,0x02,0x79,0x01,0xd8,0x0f
1939 ,0x7f,0x1d,0x8b,0x8d,0xc9,0x36,0xcf,0x3b
1940 ,0x9f,0x81,0x96,0x92,0x82,0x7e,0x57,0x77
1943 static immutable ubyte[16] input = [
1944 0x81,0x91,0x8e,0xf2,0xa5,0xe0,0xda,0x9b
1945 ,0x3e,0x90,0x60,0x52,0x1e,0x4b,0xb3,0x52
1948 static immutable ubyte[16] c = [
1949 101,120,112, 97,110,100, 32, 51
1950 , 50, 45, 98,121,116,101, 32,107
1953 ubyte output[64];
1955 static immutable ubyte[32] res = [
1956 0xbc,0x1b,0x30,0xfc,0x07,0x2c,0xc1,0x40
1957 ,0x75,0xe4,0xba,0xa7,0x31,0xb5,0xa8,0x45
1958 ,0xea,0x9b,0x11,0xe9,0xa5,0x19,0x1f,0x94
1959 ,0xe1,0x8c,0xba,0x8f,0xd8,0x21,0xa7,0xcd
1962 ubyte[32] pp;
1963 uint pppos = 0;
1965 void print(const(ubyte)[] x, const(ubyte)[] y)
1967 uint borrow = 0;
1968 for (auto i = 0; i < 4; ++i) {
1969 uint xi = x[i];
1970 uint yi = y[i];
1971 //printf(",0x%02x",255&(xi-yi-borrow));
1972 pp[pppos++] = cast(ubyte)(255&(xi-yi-borrow));
1973 borrow = (xi < yi+borrow);
1977 crypto_core_salsa20(output,input,k,c);
1978 print(output,c);
1979 print(output[20..$],c[4..$]);
1980 print(output[40..$],c[8..$]);
1981 print(output[60..$],c[12..$]);
1982 print(output[24..$],input);
1983 print(output[28..$],input[4..$]);
1984 print(output[32..$],input[8..$]);
1985 print(output[36..$],input[12..$]);
1986 assert(pp == res);
1988 core6();
1990 void hash () {
1991 writeln("hash");
1992 static immutable ubyte x[8] = ['t','e','s','t','i','n','g','\n'];
1993 static ubyte[crypto_hash_BYTES] h;
1994 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];
1995 crypto_hash(h,x);
1996 //for (auto f = 0; f < crypto_hash_BYTES; ++f) assert(h[f] == res[f]);
1997 assert(h == res);
1999 hash();
2001 void onetimeauth () {
2002 writeln("onetimeauth");
2003 static immutable ubyte rs[32] = [
2004 0xee,0xa6,0xa7,0x25,0x1c,0x1e,0x72,0x91
2005 ,0x6d,0x11,0xc2,0xcb,0x21,0x4d,0x3c,0x25
2006 ,0x25,0x39,0x12,0x1d,0x8e,0x23,0x4e,0x65
2007 ,0x2d,0x65,0x1f,0xa4,0xc8,0xcf,0xf8,0x80
2010 static immutable ubyte c[131] = [
2011 0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73
2012 ,0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce
2013 ,0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4
2014 ,0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a
2015 ,0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b
2016 ,0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72
2017 ,0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2
2018 ,0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38
2019 ,0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a
2020 ,0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae
2021 ,0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea
2022 ,0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda
2023 ,0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde
2024 ,0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3
2025 ,0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6
2026 ,0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74
2027 ,0xe3,0x55,0xa5
2030 ubyte a[16];
2032 static immutable ubyte[16] res = [0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5,0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9];
2034 /*crypto_onetimeauth_poly1305*/crypto_onetimeauth(a,c,rs);
2035 assert(a == res);
2037 onetimeauth();
2039 void onetimeauth2 () {
2040 writeln("onetimeauth2");
2041 static immutable ubyte[32] rs = [
2042 0xee,0xa6,0xa7,0x25,0x1c,0x1e,0x72,0x91
2043 ,0x6d,0x11,0xc2,0xcb,0x21,0x4d,0x3c,0x25
2044 ,0x25,0x39,0x12,0x1d,0x8e,0x23,0x4e,0x65
2045 ,0x2d,0x65,0x1f,0xa4,0xc8,0xcf,0xf8,0x80
2048 static immutable ubyte[131] c = [
2049 0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73
2050 ,0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce
2051 ,0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4
2052 ,0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a
2053 ,0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b
2054 ,0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72
2055 ,0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2
2056 ,0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38
2057 ,0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a
2058 ,0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae
2059 ,0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea
2060 ,0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda
2061 ,0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde
2062 ,0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3
2063 ,0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6
2064 ,0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74
2065 ,0xe3,0x55,0xa5
2068 static immutable ubyte[16] a = [
2069 0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5
2070 ,0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9
2073 assert(/*crypto_onetimeauth_poly1305_verify*/crypto_onetimeauth_verify(a,c,rs));
2075 onetimeauth2();
2077 void onetimeauth7 () {
2078 writeln("onetimeauth7");
2079 static ubyte[32] key;
2080 static ubyte[10000] c;
2081 static ubyte[16] a;
2083 for (auto clen = 0; clen < 10000; ++clen) {
2084 //if (clen%512 == 0) { writef("\r%s", clen); stdout.flush(); }
2085 randombytes(key, key.length);
2086 randombytes(c, clen);
2087 crypto_onetimeauth(a,c[0..clen],key);
2088 assert(crypto_onetimeauth_verify(a,c[0..clen],key));
2089 if (clen > 0) {
2090 c[uniform(0, clen)] += 1+(uniform(0, 255));
2091 assert(!crypto_onetimeauth_verify(a,c[0..clen],key));
2092 a[uniform(0, a.length)] += 1+(uniform(0, 255));
2093 assert(!crypto_onetimeauth_verify(a,c[0..clen],key));
2097 version(unittest_full) onetimeauth7(); // it's slow
2099 void scalarmult () {
2100 writeln("scalarmult");
2101 static immutable ubyte[32] alicesk = [
2102 0x77,0x07,0x6d,0x0a,0x73,0x18,0xa5,0x7d
2103 ,0x3c,0x16,0xc1,0x72,0x51,0xb2,0x66,0x45
2104 ,0xdf,0x4c,0x2f,0x87,0xeb,0xc0,0x99,0x2a
2105 ,0xb1,0x77,0xfb,0xa5,0x1d,0xb9,0x2c,0x2a
2108 ubyte[32] alicepk;
2110 static immutable ubyte[32] res = [
2111 0x85,0x20,0xf0,0x09,0x89,0x30,0xa7,0x54
2112 ,0x74,0x8b,0x7d,0xdc,0xb4,0x3e,0xf7,0x5a
2113 ,0x0d,0xbf,0x3a,0x0d,0x26,0x38,0x1a,0xf4
2114 ,0xeb,0xa4,0xa9,0x8e,0xaa,0x9b,0x4e,0x6a
2117 /*crypto_scalarmult_curve25519_base*/crypto_scalarmult_base(alicepk,alicesk);
2118 assert(alicepk == res);
2120 scalarmult();
2122 void scalarmult2 () {
2123 writeln("scalarmult2");
2124 static immutable ubyte[32] bobsk = [
2125 0x5d,0xab,0x08,0x7e,0x62,0x4a,0x8a,0x4b
2126 ,0x79,0xe1,0x7f,0x8b,0x83,0x80,0x0e,0xe6
2127 ,0x6f,0x3b,0xb1,0x29,0x26,0x18,0xb6,0xfd
2128 ,0x1c,0x2f,0x8b,0x27,0xff,0x88,0xe0,0xeb
2131 ubyte[32] bobpk;
2133 static immutable ubyte[32] res = [
2134 0xde,0x9e,0xdb,0x7d,0x7b,0x7d,0xc1,0xb4
2135 ,0xd3,0x5b,0x61,0xc2,0xec,0xe4,0x35,0x37
2136 ,0x3f,0x83,0x43,0xc8,0x5b,0x78,0x67,0x4d
2137 ,0xad,0xfc,0x7e,0x14,0x6f,0x88,0x2b,0x4f
2140 /*crypto_scalarmult_curve25519_base*/crypto_scalarmult_base(bobpk,bobsk);
2141 assert(bobpk == res);
2143 scalarmult2();
2145 void scalarmult5 () {
2146 writeln("scalarmult5");
2147 static immutable ubyte[32] alicesk = [
2148 0x77,0x07,0x6d,0x0a,0x73,0x18,0xa5,0x7d
2149 ,0x3c,0x16,0xc1,0x72,0x51,0xb2,0x66,0x45
2150 ,0xdf,0x4c,0x2f,0x87,0xeb,0xc0,0x99,0x2a
2151 ,0xb1,0x77,0xfb,0xa5,0x1d,0xb9,0x2c,0x2a
2154 static immutable ubyte[32] bobpk = [
2155 0xde,0x9e,0xdb,0x7d,0x7b,0x7d,0xc1,0xb4
2156 ,0xd3,0x5b,0x61,0xc2,0xec,0xe4,0x35,0x37
2157 ,0x3f,0x83,0x43,0xc8,0x5b,0x78,0x67,0x4d
2158 ,0xad,0xfc,0x7e,0x14,0x6f,0x88,0x2b,0x4f
2161 ubyte[32] k;
2163 static immutable ubyte[32] res = [
2164 0x4a,0x5d,0x9d,0x5b,0xa4,0xce,0x2d,0xe1
2165 ,0x72,0x8e,0x3b,0xf4,0x80,0x35,0x0f,0x25
2166 ,0xe0,0x7e,0x21,0xc9,0x47,0xd1,0x9e,0x33
2167 ,0x76,0xf0,0x9b,0x3c,0x1e,0x16,0x17,0x42
2170 crypto_scalarmult(k,alicesk,bobpk);
2171 assert(k == res);
2173 scalarmult5();
2175 void scalarmult6 () {
2176 writeln("scalarmult6");
2177 static immutable ubyte[32] bobsk = [
2178 0x5d,0xab,0x08,0x7e,0x62,0x4a,0x8a,0x4b
2179 ,0x79,0xe1,0x7f,0x8b,0x83,0x80,0x0e,0xe6
2180 ,0x6f,0x3b,0xb1,0x29,0x26,0x18,0xb6,0xfd
2181 ,0x1c,0x2f,0x8b,0x27,0xff,0x88,0xe0,0xeb
2184 static immutable ubyte[32] alicepk = [
2185 0x85,0x20,0xf0,0x09,0x89,0x30,0xa7,0x54
2186 ,0x74,0x8b,0x7d,0xdc,0xb4,0x3e,0xf7,0x5a
2187 ,0x0d,0xbf,0x3a,0x0d,0x26,0x38,0x1a,0xf4
2188 ,0xeb,0xa4,0xa9,0x8e,0xaa,0x9b,0x4e,0x6a
2191 ubyte[32] k;
2193 static immutable ubyte[32] res = [
2194 0x4a,0x5d,0x9d,0x5b,0xa4,0xce,0x2d,0xe1
2195 ,0x72,0x8e,0x3b,0xf4,0x80,0x35,0x0f,0x25
2196 ,0xe0,0x7e,0x21,0xc9,0x47,0xd1,0x9e,0x33
2197 ,0x76,0xf0,0x9b,0x3c,0x1e,0x16,0x17,0x42
2200 crypto_scalarmult(k,bobsk,alicepk);
2201 assert(k == res);
2203 scalarmult6();
2205 void secretbox () {
2206 writeln("secretbox");
2207 static immutable ubyte[32] firstkey = [
2208 0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4
2209 ,0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7
2210 ,0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2
2211 ,0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89
2214 static immutable ubyte[24] nonce = [
2215 0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73
2216 ,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6
2217 ,0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37
2220 // API requires first 32 bytes to be 0
2221 static immutable ubyte[163] m = [
2222 0, 0, 0, 0, 0, 0, 0, 0
2223 , 0, 0, 0, 0, 0, 0, 0, 0
2224 , 0, 0, 0, 0, 0, 0, 0, 0
2225 , 0, 0, 0, 0, 0, 0, 0, 0
2226 ,0xbe,0x07,0x5f,0xc5,0x3c,0x81,0xf2,0xd5
2227 ,0xcf,0x14,0x13,0x16,0xeb,0xeb,0x0c,0x7b
2228 ,0x52,0x28,0xc5,0x2a,0x4c,0x62,0xcb,0xd4
2229 ,0x4b,0x66,0x84,0x9b,0x64,0x24,0x4f,0xfc
2230 ,0xe5,0xec,0xba,0xaf,0x33,0xbd,0x75,0x1a
2231 ,0x1a,0xc7,0x28,0xd4,0x5e,0x6c,0x61,0x29
2232 ,0x6c,0xdc,0x3c,0x01,0x23,0x35,0x61,0xf4
2233 ,0x1d,0xb6,0x6c,0xce,0x31,0x4a,0xdb,0x31
2234 ,0x0e,0x3b,0xe8,0x25,0x0c,0x46,0xf0,0x6d
2235 ,0xce,0xea,0x3a,0x7f,0xa1,0x34,0x80,0x57
2236 ,0xe2,0xf6,0x55,0x6a,0xd6,0xb1,0x31,0x8a
2237 ,0x02,0x4a,0x83,0x8f,0x21,0xaf,0x1f,0xde
2238 ,0x04,0x89,0x77,0xeb,0x48,0xf5,0x9f,0xfd
2239 ,0x49,0x24,0xca,0x1c,0x60,0x90,0x2e,0x52
2240 ,0xf0,0xa0,0x89,0xbc,0x76,0x89,0x70,0x40
2241 ,0xe0,0x82,0xf9,0x37,0x76,0x38,0x48,0x64
2242 ,0x5e,0x07,0x05
2245 static immutable ubyte[] res = [
2246 0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5
2247 ,0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9
2248 ,0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73
2249 ,0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce
2250 ,0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4
2251 ,0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a
2252 ,0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b
2253 ,0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72
2254 ,0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2
2255 ,0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38
2256 ,0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a
2257 ,0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae
2258 ,0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea
2259 ,0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda
2260 ,0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde
2261 ,0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3
2262 ,0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6
2263 ,0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74
2264 ,0xe3,0x55,0xa5
2267 ubyte c[163];
2268 crypto_secretbox(c,m,nonce,firstkey);
2269 for (auto i = 16; i < 163; ++i) assert(c[i] == res[i-16]);
2271 secretbox();
2273 void secretbox2 () {
2274 writeln("secretbox2");
2275 static immutable ubyte[32] firstkey = [
2276 0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4
2277 ,0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7
2278 ,0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2
2279 ,0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89
2282 static immutable ubyte[24] nonce = [
2283 0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73
2284 ,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6
2285 ,0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37
2288 // API requires first 16 bytes to be 0
2289 static immutable ubyte[163] c = [
2290 0, 0, 0, 0, 0, 0, 0, 0
2291 , 0, 0, 0, 0, 0, 0, 0, 0
2292 ,0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5
2293 ,0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9
2294 ,0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73
2295 ,0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce
2296 ,0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4
2297 ,0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a
2298 ,0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b
2299 ,0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72
2300 ,0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2
2301 ,0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38
2302 ,0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a
2303 ,0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae
2304 ,0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea
2305 ,0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda
2306 ,0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde
2307 ,0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3
2308 ,0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6
2309 ,0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74
2310 ,0xe3,0x55,0xa5
2313 static immutable ubyte[] res = [
2314 0xbe,0x07,0x5f,0xc5,0x3c,0x81,0xf2,0xd5
2315 ,0xcf,0x14,0x13,0x16,0xeb,0xeb,0x0c,0x7b
2316 ,0x52,0x28,0xc5,0x2a,0x4c,0x62,0xcb,0xd4
2317 ,0x4b,0x66,0x84,0x9b,0x64,0x24,0x4f,0xfc
2318 ,0xe5,0xec,0xba,0xaf,0x33,0xbd,0x75,0x1a
2319 ,0x1a,0xc7,0x28,0xd4,0x5e,0x6c,0x61,0x29
2320 ,0x6c,0xdc,0x3c,0x01,0x23,0x35,0x61,0xf4
2321 ,0x1d,0xb6,0x6c,0xce,0x31,0x4a,0xdb,0x31
2322 ,0x0e,0x3b,0xe8,0x25,0x0c,0x46,0xf0,0x6d
2323 ,0xce,0xea,0x3a,0x7f,0xa1,0x34,0x80,0x57
2324 ,0xe2,0xf6,0x55,0x6a,0xd6,0xb1,0x31,0x8a
2325 ,0x02,0x4a,0x83,0x8f,0x21,0xaf,0x1f,0xde
2326 ,0x04,0x89,0x77,0xeb,0x48,0xf5,0x9f,0xfd
2327 ,0x49,0x24,0xca,0x1c,0x60,0x90,0x2e,0x52
2328 ,0xf0,0xa0,0x89,0xbc,0x76,0x89,0x70,0x40
2329 ,0xe0,0x82,0xf9,0x37,0x76,0x38,0x48,0x64
2330 ,0x5e,0x07,0x05
2333 ubyte m[163];
2335 assert(crypto_secretbox_open(m,c,nonce,firstkey));
2336 for (auto i = 32; i < 163; ++i) assert(m[i] == res[i-32]);
2338 secretbox2();
2340 void secretbox7 () {
2341 writeln("secretbox7");
2342 static ubyte[crypto_secretbox_KEYBYTES] k;
2343 static ubyte[crypto_secretbox_NONCEBYTES] n;
2344 static ubyte[10000] m, c, m2;
2345 for (auto mlen = 0; mlen < 1000 && mlen+crypto_secretbox_ZEROBYTES < m.length; ++mlen) {
2346 randombytes(k,crypto_secretbox_KEYBYTES);
2347 randombytes(n,crypto_secretbox_NONCEBYTES);
2348 randombytes(m[crypto_secretbox_ZEROBYTES..$],mlen);
2349 crypto_secretbox(c[0..mlen+crypto_secretbox_ZEROBYTES],m,n,k);
2350 assert(crypto_secretbox_open(m2[0..mlen+crypto_secretbox_ZEROBYTES],c,n,k));
2351 for (auto i = 0; i < mlen+crypto_secretbox_ZEROBYTES; ++i) assert(m2[i] == m[i]);
2354 secretbox7();
2356 void secretbox8 () {
2357 writeln("secretbox8");
2358 static ubyte[crypto_secretbox_KEYBYTES] k;
2359 static ubyte[crypto_secretbox_NONCEBYTES] n;
2360 static ubyte[10000] m, c, m2;
2361 for (auto mlen = 0; mlen < 1000 && mlen+crypto_secretbox_ZEROBYTES < m.length; ++mlen) {
2362 randombytes(k,crypto_secretbox_KEYBYTES);
2363 randombytes(n,crypto_secretbox_NONCEBYTES);
2364 randombytes(m[crypto_secretbox_ZEROBYTES..$],mlen);
2365 crypto_secretbox(c[0..mlen+crypto_secretbox_ZEROBYTES],m,n,k);
2366 auto caught = 0;
2367 while (caught < 10) {
2368 c[uniform(0, mlen+crypto_secretbox_ZEROBYTES)] = cast(ubyte)uniform(0, 256);
2369 if (crypto_secretbox_open(m2[0..mlen+crypto_secretbox_ZEROBYTES],c,n,k)) {
2370 for (auto i = 0; i < mlen+crypto_secretbox_ZEROBYTES; ++i) assert(m2[i] == m[i]);
2372 ++caught;
2374 assert(caught == 10);
2377 version(unittest_full) secretbox8(); // it's slow
2379 void stream () {
2380 writeln("stream");
2381 static immutable ubyte[32] firstkey = [
2382 0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4
2383 ,0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7
2384 ,0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2
2385 ,0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89
2388 static immutable ubyte[24] nonce = [
2389 0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73
2390 ,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6
2391 ,0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37
2394 static ubyte[4194304] output;
2396 //ubyte h[32];
2397 //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];
2399 crypto_stream(output,nonce,firstkey);
2400 //crypto_hash_sha256(h,output,sizeof output);
2401 assert(hashToString(SHA256(output[0..$])) == "662b9d0e3463029156069b12f918691a98f7dfb2ca0393c96bbfc6b1fbd630a2");
2403 stream();
2405 void stream2 () {
2406 writeln("stream2");
2407 static immutable ubyte[32] secondkey = [
2408 0xdc,0x90,0x8d,0xda,0x0b,0x93,0x44,0xa9
2409 ,0x53,0x62,0x9b,0x73,0x38,0x20,0x77,0x88
2410 ,0x80,0xf3,0xce,0xb4,0x21,0xbb,0x61,0xb9
2411 ,0x1c,0xbd,0x4c,0x3e,0x66,0x25,0x6c,0xe4
2414 static immutable ubyte[8] noncesuffix = [
2415 0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37
2418 static ubyte[4194304] output;
2420 crypto_stream_salsa20(output,noncesuffix,secondkey);
2421 assert(hashToString(SHA256(output[0..$])) == "662b9d0e3463029156069b12f918691a98f7dfb2ca0393c96bbfc6b1fbd630a2");
2423 stream2();
2425 void stream3 () {
2426 writeln("stream3");
2427 static immutable ubyte[32] firstkey = [
2428 0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4
2429 ,0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7
2430 ,0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2
2431 ,0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89
2434 static immutable ubyte[24] nonce = [
2435 0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73
2436 ,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6
2437 ,0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37
2440 ubyte rs[32];
2442 static immutable ubyte[32] res = [
2443 0xee,0xa6,0xa7,0x25,0x1c,0x1e,0x72,0x91
2444 ,0x6d,0x11,0xc2,0xcb,0x21,0x4d,0x3c,0x25
2445 ,0x25,0x39,0x12,0x1d,0x8e,0x23,0x4e,0x65
2446 ,0x2d,0x65,0x1f,0xa4,0xc8,0xcf,0xf8,0x80
2449 crypto_stream/*_xsalsa20*/(rs,nonce,firstkey);
2450 assert(rs == res);
2452 stream3();
2454 void stream4 () {
2455 writeln("stream4");
2456 static immutable ubyte[32] firstkey = [
2457 0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4
2458 ,0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7
2459 ,0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2
2460 ,0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89
2463 static immutable ubyte[24] nonce = [
2464 0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73
2465 ,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6
2466 ,0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37
2469 static immutable ubyte[163] m = [
2470 0, 0, 0, 0, 0, 0, 0, 0
2471 , 0, 0, 0, 0, 0, 0, 0, 0
2472 , 0, 0, 0, 0, 0, 0, 0, 0
2473 , 0, 0, 0, 0, 0, 0, 0, 0
2474 ,0xbe,0x07,0x5f,0xc5,0x3c,0x81,0xf2,0xd5
2475 ,0xcf,0x14,0x13,0x16,0xeb,0xeb,0x0c,0x7b
2476 ,0x52,0x28,0xc5,0x2a,0x4c,0x62,0xcb,0xd4
2477 ,0x4b,0x66,0x84,0x9b,0x64,0x24,0x4f,0xfc
2478 ,0xe5,0xec,0xba,0xaf,0x33,0xbd,0x75,0x1a
2479 ,0x1a,0xc7,0x28,0xd4,0x5e,0x6c,0x61,0x29
2480 ,0x6c,0xdc,0x3c,0x01,0x23,0x35,0x61,0xf4
2481 ,0x1d,0xb6,0x6c,0xce,0x31,0x4a,0xdb,0x31
2482 ,0x0e,0x3b,0xe8,0x25,0x0c,0x46,0xf0,0x6d
2483 ,0xce,0xea,0x3a,0x7f,0xa1,0x34,0x80,0x57
2484 ,0xe2,0xf6,0x55,0x6a,0xd6,0xb1,0x31,0x8a
2485 ,0x02,0x4a,0x83,0x8f,0x21,0xaf,0x1f,0xde
2486 ,0x04,0x89,0x77,0xeb,0x48,0xf5,0x9f,0xfd
2487 ,0x49,0x24,0xca,0x1c,0x60,0x90,0x2e,0x52
2488 ,0xf0,0xa0,0x89,0xbc,0x76,0x89,0x70,0x40
2489 ,0xe0,0x82,0xf9,0x37,0x76,0x38,0x48,0x64
2490 ,0x5e,0x07,0x05
2493 ubyte c[163];
2495 static immutable ubyte[] res = [
2496 0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73
2497 ,0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce
2498 ,0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4
2499 ,0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a
2500 ,0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b
2501 ,0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72
2502 ,0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2
2503 ,0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38
2504 ,0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a
2505 ,0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae
2506 ,0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea
2507 ,0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda
2508 ,0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde
2509 ,0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3
2510 ,0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6
2511 ,0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74
2512 ,0xe3,0x55,0xa5
2515 /*crypto_stream_xsalsa20_xor*/crypto_stream_xor(c,m,nonce,firstkey);
2516 for (auto i = 32; i < 163; ++i) assert(c[i] == res[i-32]);
2518 stream4();
2520 version(unittest) {
2521 version(unittest_main) {
2522 void main () {}