cosmetix
[iv.d.git] / tweetNaCl.d
blobb0290a535c597ba44ae7c1ea37d06a0a9301bc5f
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 )
9 */
10 //k8: yes, i know that this code sux. i know that i should rewrite it to be more 'D-ish'.
11 // i won't do that. thank you for your understanding. hehe.
12 module iv.tweetNaCl /*is aliced*/;
14 //import iv.alice;
15 public nothrow:
17 static if (!is(typeof(usize))) private alias usize = size_t;
18 static if (!is(typeof(sptrdiff))) private alias sptrdiff = ptrdiff_t;
19 static if (!is(typeof(ssizediff))) private alias ssizediff = ptrdiff_t;
21 static if (!is(typeof(ssize))) {
22 static if (usize.sizeof == 8) private alias ssize = long; //k8
23 else static if (usize.sizeof == 4) private alias ssize = int; //k8
24 else static assert(0, "invalid usize size"); //k8
28 // ////////////////////////////////////////////////////////////////////////// //
29 enum {
30 crypto_auth_BYTES = 32,
31 crypto_auth_KEYBYTES = 32,
33 crypto_box_PUBLICKEYBYTES = 32,
34 crypto_box_SECRETKEYBYTES = 32,
35 crypto_box_BEFORENMBYTES = 32,
36 crypto_box_NONCEBYTES = 24,
37 crypto_box_ZEROBYTES = 32,
38 crypto_box_BOXZEROBYTES = 16,
40 crypto_core_salsa20_OUTPUTBYTES = 64,
41 crypto_core_salsa20_INPUTBYTES = 16,
42 crypto_core_salsa20_KEYBYTES = 32,
43 crypto_core_salsa20_CONSTBYTES = 16,
45 crypto_core_hsalsa20_OUTPUTBYTES = 32,
46 crypto_core_hsalsa20_INPUTBYTES = 16,
47 crypto_core_hsalsa20_KEYBYTES = 32,
48 crypto_core_hsalsa20_CONSTBYTES = 16,
50 crypto_hash_BYTES = 64,
52 crypto_onetimeauth_BYTES = 16,
53 crypto_onetimeauth_KEYBYTES = 32,
55 crypto_scalarmult_BYTES = 32,
56 crypto_scalarmult_SCALARBYTES = 32,
58 crypto_secretbox_KEYBYTES = 32,
59 crypto_secretbox_NONCEBYTES = 24,
60 crypto_secretbox_ZEROBYTES = 32,
61 crypto_secretbox_BOXZEROBYTES = 16,
63 crypto_sign_BYTES = 64,
64 crypto_sign_PUBLICKEYBYTES = 32,
65 crypto_sign_SECRETKEYBYTES = 64,
67 crypto_stream_xsalsa20_KEYBYTES = 32,
68 crypto_stream_xsalsa20_NONCEBYTES = 24,
70 crypto_stream_salsa20_KEYBYTES = 32,
71 crypto_stream_salsa20_NONCEBYTES = 8,
73 crypto_stream_KEYBYTES = 32,
74 crypto_stream_NONCEBYTES = 24,
76 crypto_verify_16_BYTES = 16,
77 crypto_verify_32_BYTES = 32,
81 // ////////////////////////////////////////////////////////////////////////// //
82 /// set this callback to good (cryptograpic strong) random bytes generator
83 /// you can use /dev/urandom as prng
84 public void delegate (ubyte[] dest) nothrow randombytes = null;
87 // ////////////////////////////////////////////////////////////////////////// //
88 /**
89 * This function signs a message 'msg' using the sender's secret key 'sk'.
90 * The function returns the resulting signed message.
92 * WARNING! This function allocates!
94 * Params:
95 * msg == message
96 * sk == secret key, slice size must be at least crypto_sign_SECRETKEYBYTES, extra ignored
97 * dest == destination buffer; leave `null` to allocate, or pass array of at least `msg.length+crypto_sign_BYTES` bytes
99 * Returns:
100 * signed message
102 public ubyte[] crypto_sign (const(ubyte)[] msg, const(ubyte)[] sk, ubyte[] dest=null) {
103 if (sk.length < crypto_sign_SECRETKEYBYTES) assert(0, "sk too small");
104 ubyte[] sm;
105 if (dest.length >= msg.length+crypto_sign_BYTES) sm = dest[0..msg.length+64]; else sm.length = msg.length+crypto_sign_BYTES;
106 crypto_sign(sm, msg, sk);
107 return sm;
112 * This function verifies the signature in 'sm' using the receiver's public key 'pk'.
113 * The function returns the message.
115 * WARNING! This function allocates!
117 * Params:
118 * sm == signed message
119 * pk == public key, slice size must be at least crypto_sign_PUBLICKEYBYTES, extra ignored
120 * dest == destination buffer; leave `null` to allocate, or pass array of at least `sm.length` bytes
122 * Returns:
123 * decrypted message or null on error
125 public ubyte[] crypto_sign_open (const(ubyte)[] sm, const(ubyte)[] pk, ubyte[] dest=null) {
126 if (sm.length < crypto_sign_SECRETKEYBYTES) assert(0, "sm too small");
127 ubyte[] msg;
128 if (dest.length >= sm.length) msg = dest; else msg.length = sm.length;
129 scope(exit) if (msg.length >= crypto_sign_BYTES) msg[$-crypto_sign_BYTES..$] = 0; else if (msg.length) msg[] = 0;
130 if (!crypto_sign_open(msg, sm, pk)) return null;
131 return msg[0..sm.length-crypto_sign_BYTES]; // remove signature
135 // ////////////////////////////////////////////////////////////////////////// //
137 * This function checks that strings 'x' and 'y' has same content.
139 * Params:
140 * x = first string, slice length must be at least crypto_verify_16_BYTES, extra ignored
141 * y = second string, slice length must be at least crypto_verify_16_BYTES, extra ignored
143 * Returns:
144 * success flag
146 public bool crypto_verify_16 (const(ubyte)[] x, const(ubyte)[] y) @nogc {
147 pragma(inline, true);
148 if (x.length < crypto_verify_16_BYTES) assert(0, "x too small");
149 if (y.length < crypto_verify_16_BYTES) assert(0, "y too small");
150 return vn(x.ptr[0..crypto_verify_16_BYTES], y.ptr[0..crypto_verify_16_BYTES]);
154 * This function checks that strings 'x' and 'y' has same content.
156 * Params:
157 * x = first string, slice length must be at least crypto_verify_32_BYTES, extra ignored
158 * y = second string, slice length must be at least crypto_verify_32_BYTES, extra ignored
160 * Returns:
161 * success flag
163 public bool crypto_verify_32 (const(ubyte)[] x, const(ubyte)[] y) @nogc {
164 pragma(inline, true);
165 if (x.length < crypto_verify_32_BYTES) assert(0, "x too small");
166 if (y.length < crypto_verify_32_BYTES) assert(0, "y too small");
167 return vn(x.ptr[0..crypto_verify_32_BYTES], y.ptr[0..crypto_verify_32_BYTES]);
171 * This function encrypts a message 'msg' using a secret key 'key' and a nonce 'nonce'.
172 * The function returns the ciphertext 'output'.
174 * Params:
175 * output = resulting ciphertext
176 * msg = message
177 * nonce = nonce
178 * key = secret key
180 * Returns:
181 * ciphertext in 'output'
183 public void crypto_stream_salsa20_xor (ubyte[] output, const(ubyte)[] msg, const(ubyte)[] nonce, const(ubyte)[] key) @trusted @nogc {
184 if (nonce.length < crypto_stream_salsa20_NONCEBYTES) assert(0, "invalid nonce size");
185 if (key.length < crypto_stream_salsa20_KEYBYTES) assert(0, "invalid key size");
186 if (msg.length > int.max/2) assert(0, "message too big");
187 //??? msg.length == 0 || output.length <= msg.length
188 ubyte[16] z = 0;
189 ubyte[64] x = void;
190 uint cpos = 0, mpos = 0;
191 auto b = output.length;
192 if (!b) return;
193 //if (b < (msg.length+63)/64*64) assert(0, "output buffer too small");
194 z.ptr[0..8] = nonce.ptr[0..8];
195 while (b >= 64) {
196 crypto_core_salsa20(x[], z[], key, sigma[]);
197 foreach (immutable v; x) output.ptr[cpos++] = (mpos < msg.length ? msg.ptr[mpos++] : 0)^v;
199 if (msg.length) {
200 foreach (immutable v; x) output[cpos++] = msg[mpos++]^v;
201 } else {
202 output[cpos..cpos+64] = x[];
203 cpos += 64;
206 uint u = 1;
207 foreach (immutable i; 8..16) {
208 u += cast(uint)z.ptr[i];
209 z.ptr[i] = u&0xff;
210 u >>= 8;
212 b -= 64;
214 if (b) {
215 crypto_core_salsa20(x[], z[], key, sigma[]);
217 if (msg.length) {
218 foreach (immutable i; 0..b) output[cpos++] = msg[mpos++]^x[i];
219 } else {
220 output[cpos..cpos+b] = x[0..b];
223 foreach (immutable i; 0..b) output.ptr[cpos++] = (mpos < msg.length ? msg.ptr[mpos++] : 0)^x.ptr[i];
228 * This function produces a stream 'c' as a function of a secret key 'key'
229 * and a nonce 'nonce'.
231 * Params:
232 * c = resulting stream
233 * nonce = nonce
234 * key = secret key
236 * Returns:
237 * ciphertext in 'c'
239 public void crypto_stream_salsa20 (ubyte[] c, const(ubyte)[] nonce, const(ubyte)[] key) @nogc {
240 if (nonce.length < crypto_stream_salsa20_NONCEBYTES) assert(0, "invalid nonce size");
241 if (key.length < crypto_stream_salsa20_KEYBYTES) assert(0, "invalid key size");
242 crypto_stream_salsa20_xor(c, null, nonce, key);
246 * This function produces a stream 'c' as a function of a secret key 'key'
247 * and a nonce 'nonce'.
249 * Params:
250 * c = output slice
251 * nonce = nonce
252 * key = secret key
254 * Returns:
255 * stream in 'c'
257 public void crypto_stream (ubyte[] c, const(ubyte)[] nonce, const(ubyte)[] key) @nogc {
258 if (c.length == 0) assert(0, "invalid c");
259 if (nonce.length < crypto_stream_NONCEBYTES) assert(0, "invalid nonce size");
260 if (key.length < crypto_stream_KEYBYTES) assert(0, "invalid key size");
261 ubyte[32] s = void;
262 crypto_core_hsalsa20(s[], nonce, key, sigma[]);
263 crypto_stream_salsa20(c, nonce[16..$], s[]);
267 * This function encrypts a message 'msg' using a secret key 'key' and a nonce 'nonce'.
268 * The function returns the ciphertext 'c'.
270 * Params:
271 * c = output slice
272 * msg = message
273 * nonce = nonce
274 * key = secret key
276 * Returns:
277 * ciphertext in 'c'
279 public void crypto_stream_xor (ubyte[] c, const(ubyte)[] msg, const(ubyte)[] nonce, const(ubyte)[] key) @nogc {
280 if (msg.length < c.length) assert(0, "invalid msg size");
281 if (nonce.length < crypto_stream_NONCEBYTES) assert(0, "invalid nonce size");
282 if (key.length < crypto_stream_KEYBYTES) assert(0, "invalid key size");
283 ubyte[32] s = void;
284 crypto_core_hsalsa20(s[], nonce, key, sigma[]);
285 crypto_stream_salsa20_xor(c, msg, nonce[16..$], s);
289 * This function authenticates a message 'msg' using a secret key 'key'.
290 * The function returns an authenticator 'output'.
292 * Params:
293 * output = authenticator, slice size must be at least crypto_onetimeauth_BYTES, extra ignored
294 * msg == message
295 * key == secret key, slice size must be at least crypto_onetimeauth_KEYBYTES, extra ignored
297 * Returns:
298 * authenticator in 'output'
300 public void crypto_onetimeauth (ubyte[] output, const(ubyte)[] msg, const(ubyte)[] key) @nogc {
301 if (key.length < crypto_onetimeauth_KEYBYTES) assert(0, "invalid key size");
302 if (output.length < crypto_onetimeauth_BYTES) assert(0, "invalid output size");
303 if (msg.length > int.max/2) assert(0, "invalid message size");
305 uint s, u;
306 uint[17] x = void, r = void, h/*autoclear*/, c = void, g = void;
307 uint mpos = 0;
308 auto n = msg.length;
310 foreach (immutable i; 0..16) r.ptr[i] = key.ptr[i];
311 r.ptr[16..17] = 0;
313 r.ptr[3] &= 15;
314 r.ptr[4] &= 252;
315 r.ptr[7] &= 15;
316 r.ptr[8] &= 252;
317 r.ptr[11] &= 15;
318 r.ptr[12] &= 252;
319 r.ptr[15] &= 15;
321 while (n > 0) {
322 c.ptr[0..17] = 0;
324 usize jj;
325 for (jj = 0; jj < 16 && jj < n; ++jj) c.ptr[jj] = (mpos+jj < msg.length ? msg.ptr[mpos+jj] : 0);
326 c.ptr[jj] = 1;
327 mpos += jj;
328 n -= jj;
330 add1305(h, c);
331 foreach (immutable i; 0..17) {
332 x.ptr[i] = 0;
333 foreach (immutable j; 0..17) x.ptr[i] += h.ptr[j]*(j <= i ? r.ptr[i-j] : 320*r.ptr[i+17-j]);
335 h[] = x[];
336 u = 0;
337 foreach (immutable j; 0..16) {
338 u += h.ptr[j];
339 h.ptr[j] = u&255;
340 u >>= 8;
342 u += h.ptr[16];
343 h.ptr[16] = u&3;
344 u = 5*(u>>2);
345 foreach (immutable j; 0..16) {
346 u += h.ptr[j];
347 h.ptr[j] = u&255;
348 u >>= 8;
350 u += h.ptr[16];
351 h.ptr[16] = u;
354 g[] = h[];
355 add1305(h, minusp);
356 s = -(h.ptr[16]>>7);
357 foreach (immutable j; 0..17) h.ptr[j] ^= s&(g.ptr[j]^h.ptr[j]);
359 foreach (immutable j; 0..16) c.ptr[j] = key.ptr[j+16];
360 c.ptr[16] = 0;
361 add1305(h, c);
362 foreach (immutable j; 0..16) output.ptr[j] = cast(ubyte)(h.ptr[j]&0xff);
366 * This function checks that 'h' is a correct authenticator of a message 'msg'
367 * under the secret key 'key'.
369 * Params:
370 * h = authenticator, slice size must be at least crypto_onetimeauth_BYTES, extra ignored
371 * msg == message
372 * key == secret key, slice size must be at least crypto_onetimeauth_KEYBYTES, extra ignored
374 * Returns:
375 * success flag
377 public bool crypto_onetimeauth_verify (const(ubyte)[] h, const(ubyte)[] msg, const(ubyte)[] key) @nogc {
378 if (h.length < crypto_onetimeauth_BYTES) assert(0, "invalid h size");
379 if (key.length < crypto_onetimeauth_KEYBYTES) assert(0, "invalid key size");
380 ubyte[16] x = void;
381 crypto_onetimeauth(x[], msg, key);
382 return crypto_verify_16(h, x[]);
386 * This function encrypts and authenticates a message 'msg' using a secret
387 * key 'key' and a nonce 'nonce'.
388 * The function returns the resulting ciphertext 'c'.
389 * Note that first 'crypto_secretbox_ZEROBYTES' in source buffer SHOULD always contains zeroes.
390 * Note that first 'crypto_secretbox_BOXZEROBYTES' in destination buffer will always contains zeroes.
392 * Params:
393 * c = resulting cyphertext ('c' size should be at least msg.length)
394 * msg = message
395 * key = secret key
396 * nonce = nonce
398 * Returns:
399 * success flag and cyphertext in 'c' (on success)
401 public bool crypto_secretbox (ubyte[] c, const(ubyte)[] msg, const(ubyte)[] nonce, const(ubyte)[] key) @nogc {
402 if (nonce.length < crypto_secretbox_NONCEBYTES) assert(0, "invalid nonce size");
403 if (key.length < crypto_secretbox_KEYBYTES) assert(0, "invalid key size");
404 if (msg.length > int.max/2) assert(0, "msg too big");
405 if (msg.length <= crypto_secretbox_BOXZEROBYTES) assert(0, "msg too small");
406 if (c.length < msg.length) return false;
407 ubyte b = 0;
408 foreach (immutable ubyte mb; msg.ptr[0..crypto_secretbox_ZEROBYTES]) b |= mb;
409 if (b != 0) return false;
410 crypto_stream_xor(c.ptr[0..msg.length], msg, nonce, key);
411 crypto_onetimeauth(c[16..$], c[32..$], c);
412 c.ptr[0..crypto_secretbox_BOXZEROBYTES] = 0;
413 return true;
417 * This function verifies and decrypts a ciphertext 'c' using a secret
418 * key 'key' and a nonce 'nonce'.
419 * The function returns the resulting plaintext 'output'.
420 * Note that first 'crypto_secretbox_BOXZEROBYTES' in source buffer SHOULD always contains zeroes.
421 * Note that first 'crypto_secretbox_ZEROBYTES' in destination buffer will always contains zeroes.
423 * Params:
424 * output = resulting message ('output' size should be at least msg.length)
425 * c = cyphertext
426 * key = secret key
427 * nonce = nonce
429 * Returns:
430 * success flag and message in 'output' (on success)
432 public bool crypto_secretbox_open (ubyte[] output, const(ubyte)[] c, const(ubyte)[] nonce, const(ubyte)[] key) @nogc {
433 if (nonce.length < crypto_secretbox_NONCEBYTES) assert(0, "invalid nonce size");
434 if (key.length < crypto_secretbox_KEYBYTES) assert(0, "invalid key size");
435 if (c.length > int.max/2) assert(0, "message too big");
436 if (c.length < crypto_secretbox_ZEROBYTES) return false;
437 if (output.length < c.length) return false;
438 ubyte b = 0;
439 foreach (immutable ubyte mb; c.ptr[0..crypto_secretbox_BOXZEROBYTES]) b |= mb;
440 if (b != 0) return false;
441 ubyte[32] x = void;
442 crypto_stream(x[], nonce, key);
443 if (!crypto_onetimeauth_verify(c[16..$], c[32../*$*/32+(output.length-32)], x)) return false;
444 crypto_stream_xor(output.ptr[0..c.length], c, nonce, key);
445 output.ptr[0..crypto_secretbox_ZEROBYTES] = 0;
446 return true;
450 * This function randomly generates a secret key and a corresponding public key.
452 * Params:
453 * pk = slice to put generated public key into
454 * sk = slice to put generated secret key into
456 * Returns:
457 * pair of new keys
459 public void crypto_box_keypair (ubyte[] pk, ubyte[] sk) {
460 if (pk.length < crypto_box_PUBLICKEYBYTES) assert(0, "invalid pk size");
461 if (sk.length < crypto_box_SECRETKEYBYTES) assert(0, "invalid sk size");
462 randombytes(sk.ptr[0..32]);
463 crypto_scalarmult_base(pk, sk);
467 * This function generates a public key from a given secret key.
469 * Params:
470 * pk = slice to put generated public key into
471 * sk = slice with secret key
473 * Returns:
474 * pair of new keys
476 public void crypto_box_pk_from_sk (ubyte[] pk, const(ubyte)[] sk) {
477 if (pk.length < crypto_box_PUBLICKEYBYTES) assert(0, "invalid pk size");
478 if (sk.length < crypto_box_SECRETKEYBYTES) assert(0, "invalid sk size");
479 crypto_scalarmult_base(pk, sk);
483 * This function computes a shared secret 's' from public key 'pk' and secret key 'sk'.
485 * Params:
486 * skey = slice to put secret into (crypto_box_BEFORENMBYTES)
487 * pk = public
488 * sk = secret
490 * Returns:
491 * generated secret
493 public void crypto_box_beforenm (ubyte[] skey, const(ubyte)[] pk, const(ubyte)[] sk) @nogc {
494 if (skey.length < crypto_box_BEFORENMBYTES) assert(0, "invalid skey size");
495 if (pk.length < crypto_box_PUBLICKEYBYTES) assert(0, "invalid pk size");
496 if (sk.length < crypto_box_SECRETKEYBYTES) assert(0, "invalid sk size");
497 ubyte[32] s = void;
498 crypto_scalarmult(s[], sk, pk);
499 crypto_core_hsalsa20(skey, zero_[], s[], sigma[]);
503 * This function encrypts and authenticates a message 'msg' using a secret
504 * key 'key' and a nonce 'nonce'.
505 * The function returns the resulting ciphertext 'c'.
506 * Note that first 'crypto_box_ZEROBYTES' in source buffer SHOULD always contains zeroes.
507 * Note that first 'crypto_box_BOXZEROBYTES' in destination buffer will always contains zeroes.
509 * Params:
510 * c = resulting cyphertext ('c' size should be at least msg.length)
511 * msg = message
512 * nonce = nonce
513 * key = secret
515 * Returns:
516 * success flag and cyphertext in 'c' (on success)
518 public bool crypto_box_afternm (ubyte[] c, const(ubyte)[] msg, const(ubyte)[] nonce, const(ubyte)[] key) @nogc {
519 pragma(inline, true);
520 if (nonce.length < crypto_box_NONCEBYTES) assert(0, "invalid nonce size");
521 if (key.length < crypto_box_BEFORENMBYTES) assert(0, "invalid key size");
522 return crypto_secretbox(c, msg, nonce, key);
526 * This function verifies and decrypts a ciphertext 'c' using a secret
527 * key 'key' and a nonce 'nonce'.
528 * The function returns the resulting message 'msg'.
529 * Note that first 'crypto_box_ZEROBYTES' in destination buffer will always contains zeroes.
531 * Params:
532 * msg = resulting message ('msg' size should be at least msg.length+crypto_box_ZEROBYTES)
533 * c = cyphertext
534 * nonce = nonce
535 * key = secret
537 * Returns:
538 * success flag and resulting message in 'msg'
540 public bool crypto_box_open_afternm (ubyte[] msg, const(ubyte)[] c, const(ubyte)[] nonce, const(ubyte)[] key) @nogc {
541 pragma(inline, true);
542 if (nonce.length < crypto_box_NONCEBYTES) assert(0, "invalid nonce size");
543 if (key.length < crypto_box_BEFORENMBYTES) assert(0, "invalid key size");
544 return crypto_secretbox_open(msg, c, nonce, key);
548 * This function encrypts and authenticates a message 'msg' using the sender's secret
549 * key 'sk', the receiver's public key 'pk', and a nonce 'nonce'.
550 * The function returns the resulting ciphertext 'c'.
551 * Note that first 'crypto_box_ZEROBYTES' in source buffer SHOULD always contains zeroes.
552 * Note that first 'crypto_box_BOXZEROBYTES' in destination buffer will always contains zeroes.
554 * usage: fill first `crypto_box_ZEROBYTES` of `msg` with zeroes, and other bytes with
555 * actual unencrypted message data.
556 * make `c` of exactly `msg` size.
557 * call `crypto_box()`.
558 * `c[crypto_box_BOXZEROBYTES..$]` will be your encrypted message, ready to send.
560 * Params:
561 * c = resulting cyphertext ('c' size should be at least msg.length)
562 * msg = message
563 * nonce = nonce
564 * pk = receiver's public key
565 * sk = sender's secret key
567 * Returns:
568 * success flag and cyphertext in 'c'
570 public bool crypto_box(bool doSanityChecks=true) (ubyte[] c, const(ubyte)[] msg, const(ubyte)[] nonce, const(ubyte)[] pk, const(ubyte)[] sk) @nogc {
571 if (nonce.length < crypto_box_NONCEBYTES) assert(0, "invalid nonce size");
572 if (pk.length < crypto_box_PUBLICKEYBYTES) assert(0, "invalid pk size");
573 if (sk.length < crypto_box_SECRETKEYBYTES) assert(0, "invalid sk size");
574 if (msg.length < crypto_box_ZEROBYTES) assert(0, "invalid msg size");
575 if (c.length < msg.length) assert(0, "invalid c size");
576 static if (crypto_box_BOXZEROBYTES > crypto_box_ZEROBYTES) {
577 if (c.length < crypto_box_BOXZEROBYTES) assert(0, "invalid c size");
579 static if (doSanityChecks) {
580 ubyte b = 0;
581 foreach (immutable ubyte bv; msg[0..crypto_box_ZEROBYTES]) b |= bv;
582 if (b != 0) assert(0, "invalid msg padding");
584 ubyte[32] k = void;
585 crypto_box_beforenm(k[], pk, sk);
586 c.ptr[0..crypto_box_BOXZEROBYTES] = 0; // why not?
587 return crypto_box_afternm(c[0..msg.length], msg, nonce, k[]);
591 * This function verifies and decrypts a ciphertext 'c' using the receiver's secret
592 * key 'sk', the sender's public key 'pk', and a nonce 'nonce'.
593 * The function returns the resulting message 'msg'.
594 * Note that first 'crypto_box_BOXZEROBYTES' in source buffer SHOULD always contains zeroes.
595 * Note that first 'crypto_box_ZEROBYTES' in destination buffer will always contains zeroes.
597 * usage: fill first `crypto_box_BOXZEROBYTES` of `c` with zeroes, and other bytes with
598 * actual encrypted message data.
599 * make `msg` of exactly `c` size.
600 * call `crypto_box_open()`.
601 * `msg[crypto_box_ZEROBYTES..$]` will be your decrypted message, ready to read.
603 * Params:
604 * msg = resulting message ('msg' size should be at least msg.length)
605 * c = cyphertext
606 * nonce = nonce
607 * pk = receiver's public key
608 * sk = sender's secret key
610 * Returns:
611 * success flag and message in 'msg'
613 public bool crypto_box_open(bool doSanityChecks=true) (ubyte[] msg, const(ubyte)[] c, const(ubyte)[] nonce, const(ubyte)[] pk, const(ubyte)[] sk) @nogc {
614 if (nonce.length < crypto_box_NONCEBYTES) assert(0, "invalid nonce size");
615 if (pk.length < crypto_box_PUBLICKEYBYTES) assert(0, "invalid pk size");
616 if (sk.length < crypto_box_SECRETKEYBYTES) assert(0, "invalid sk size");
617 if (c.length < crypto_box_BOXZEROBYTES) assert(0, "invalid c size");
618 if (msg.length < c.length) assert(0, "invalid msg size");
619 static if (crypto_box_ZEROBYTES > crypto_box_BOXZEROBYTES) {
620 if (msg.length < crypto_box_ZEROBYTES) assert(0, "invalid msg size");
622 static if (doSanityChecks) {
623 ubyte b = 0;
624 foreach (immutable ubyte bv; c[0..crypto_box_BOXZEROBYTES]) b |= bv;
625 if (b != 0) assert(0, "invalid c padding");
627 ubyte[32] k = void;
628 crypto_box_beforenm(k[], pk, sk);
629 msg.ptr[0..crypto_box_ZEROBYTES] = 0; // why not?
630 return crypto_box_open_afternm(msg[0..c.length], c, nonce, k[]);
634 // ////////////////////////////////////////////////////////////////////////// //
635 // Ketmar's utility functions
638 * Calculate buffer size to hold encrypted message; it is bigger than `msg` size.
640 * WARNING! doesn't do overflow checking!
642 * Params:
643 * msglength = input message length
645 * Returns:
646 * buffer size to hold encrypted message
648 public usize crypto_boxes_encsize(string boxmode) (usize msglength) pure nothrow @safe @nogc
649 if (boxmode == "box" || boxmode == "secretbox")
651 pragma(inline, true);
652 return msglength+mixin("crypto_"~boxmode~"_ZEROBYTES")-mixin("crypto_"~boxmode~"_BOXZEROBYTES");
655 alias crypto_box_encsize = crypto_boxes_encsize!"box"; /// ditto
656 alias crypto_secretbox_encsize = crypto_boxes_encsize!"secretbox"; /// ditto
659 * Calculate buffer size to hold decrypted message; it is smaller than `msg` size.
661 * WARNING! doesn't do overflow checking!
663 * Params:
664 * msglength = input message length
666 * Returns:
667 * buffer size to hold encrypted message
669 public usize crypto_boxes_decsize(string boxmode) (usize msglength) pure nothrow @safe @nogc
670 if (boxmode == "box" || boxmode == "secretbox")
672 pragma(inline, true);
673 return
674 (msglength > mixin("crypto_"~boxmode~"_ZEROBYTES")-mixin("crypto_"~boxmode~"_BOXZEROBYTES") ?
675 msglength-(mixin("crypto_"~boxmode~"_ZEROBYTES")-mixin("crypto_"~boxmode~"_BOXZEROBYTES")) : 0);
678 alias crypto_box_decsize = crypto_boxes_decsize!"box"; /// ditto
679 alias crypto_secretbox_decsize = crypto_boxes_decsize!"secretbox"; /// ditto
682 * Check if `msg` can contain encrypted and authenticated message (i.e. it has enough data for that).
684 * Params:
685 * msg = input message
687 * Returns:
688 * `true` if `msg` size is valid.
690 public bool crypto_boxes_valid_encsize(string boxmode) (const(ubyte)[] msg) pure nothrow @safe @nogc
691 if (boxmode == "box" || boxmode == "secretbox")
693 pragma(inline, true);
694 return (msg.length >= mixin("crypto_"~boxmode~"_ZEROBYTES")-mixin("crypto_"~boxmode~"_BOXZEROBYTES"));
697 alias crypto_box_valid_encsize = crypto_boxes_valid_encsize!"box"; /// ditto
698 alias crypto_secretbox_valid_encsize = crypto_boxes_valid_encsize!"secretbox"; /// ditto
702 * This function encrypts and authenticates a message 'msg' using the sender's secret
703 * key 'sk', the receiver's public key 'pk', and a nonce 'nonce'.
704 * The function returns the resulting ciphertext 'c'.
705 * Note that `c` must be of at least `crypto_box_encsize(msg)` bytes in size.
707 * WARNING! this function is using `malloc()` internally, but not GC.
709 * Params:
710 * c = resulting cyphertext
711 * msg = message
712 * nonce = nonce
713 * pk = receiver's public key for "box" mode, or the only key for "secretbox" mode
714 * sk = sender's secret key for "box" mode, unused (and can be `null`) for "secretbox" mode
716 * Returns:
717 * success flag and cyphertext in 'c'
719 public bool crypto_boxes_enc(string boxmode) (ubyte[] c, const(ubyte)[] msg, const(ubyte)[] nonce, const(ubyte)[] pk, const(ubyte)[] sk=null) @trusted @nogc
720 if (boxmode == "box" || boxmode == "secretbox")
722 enum ZeroBytes = mixin("crypto_"~boxmode~"_ZEROBYTES");
723 enum BoxZeroBytes = mixin("crypto_"~boxmode~"_BOXZEROBYTES");
725 if (c.length < crypto_boxes_encsize!boxmode(msg.length)) return false;
726 if (nonce.length < mixin("crypto_"~boxmode~"_NONCEBYTES")) return false;
727 static if (boxmode == "box") {
728 if (pk.length < crypto_box_PUBLICKEYBYTES) return false;
729 if (sk.length < crypto_box_SECRETKEYBYTES) return false;
730 } else {
731 if (pk.length < crypto_secretbox_KEYBYTES) return false;
734 // use stack buffer for small messages; assume that we can alloca at least 4kb+ZeroBytes*2
735 import core.stdc.stdlib : alloca, malloc, free;
736 import core.stdc.string : memset, memcpy;
737 ubyte* smem = null, dmem = null;
738 bool doFree = false;
739 scope(exit) if (doFree) { if (smem !is null) free(smem); if (dmem !is null) free(dmem); }
740 immutable memsz = msg.length+ZeroBytes;
741 if (msg.length <= 2048) {
742 smem = cast(ubyte*)alloca(memsz);
743 dmem = cast(ubyte*)alloca(memsz);
744 } else {
745 smem = cast(ubyte*)malloc(memsz);
746 dmem = cast(ubyte*)malloc(memsz);
747 doFree = true;
749 if (smem is null || dmem is null) return false;
750 memset(smem, 0, memsz);
751 memset(dmem, 0, memsz);
752 // copy `msg` to `smem`
753 if (msg.length) memcpy(smem+ZeroBytes, msg.ptr, msg.length);
754 // process
755 static if (boxmode == "box") {
756 auto res = crypto_box(dmem[0..memsz], smem[0..memsz], nonce, pk, sk);
757 } else static if (boxmode == "secretbox") {
758 auto res = crypto_secretbox(dmem[0..memsz], smem[0..memsz], nonce, pk);
759 } else {
760 static assert(0, "wtf?!");
762 ubyte b = 0;
763 foreach (immutable ubyte bv; dmem[0..BoxZeroBytes]) b |= bv;
764 // copy result to destination buffer
765 memcpy(c.ptr, dmem+BoxZeroBytes, crypto_boxes_encsize!boxmode(msg.length));
766 return (res && b == 0);
769 alias crypto_box_enc = crypto_boxes_enc!"box"; /// ditto
770 alias crypto_secretbox_enc = crypto_boxes_enc!"secretbox"; /// ditto
773 * This function verifies and decrypts a ciphertext 'c' using the receiver's secret
774 * key 'sk', the sender's public key 'pk', and a nonce 'nonce'.
775 * Note that `msg` must be of at least `crypto_box_decsize(msg)` bytes in size.
776 * Also note that key order for "box" mode is reverse of `crypto_box_XXX()` functions.
778 * WARNING! this function is using `malloc()` internally, but not GC.
780 * Params:
781 * msg = resulting message
782 * c = cyphertext
783 * nonce = nonce
784 * pk = receiver's public key for "box" mode, or the only key for "secretbox" mode
785 * sk = sender's secret key for "box" mode, unused (and can be `null`) for "secretbox" mode
787 * Returns:
788 * success flag and message in 'msg'
790 public bool crypto_boxes_dec(string boxmode) (ubyte[] msg, const(ubyte)[] c, const(ubyte)[] nonce, const(ubyte)[] pk, const(ubyte)[] sk=null) @trusted @nogc
791 if (boxmode == "box" || boxmode == "secretbox")
793 enum ZeroBytes = mixin("crypto_"~boxmode~"_ZEROBYTES");
794 enum BoxZeroBytes = mixin("crypto_"~boxmode~"_BOXZEROBYTES");
796 if (c.length < crypto_boxes_valid_encsize!boxmode(c)) return false;
797 if (msg.length < crypto_boxes_decsize!boxmode(c.length)) return false;
798 if (nonce.length < mixin("crypto_"~boxmode~"_NONCEBYTES")) return false;
799 static if (boxmode == "box") {
800 if (pk.length < crypto_box_PUBLICKEYBYTES) return false;
801 if (sk.length < crypto_box_SECRETKEYBYTES) return false;
802 } else {
803 if (pk.length < crypto_secretbox_KEYBYTES) return false;
806 // use stack buffer for small messages; assume that we can alloca at least 4kb+crypto_box_ZEROBYTES*2
807 import core.stdc.stdlib : alloca, malloc, free;
808 import core.stdc.string : memset, memcpy;
809 ubyte* smem = null, dmem = null;
810 bool doFree = false;
811 scope(exit) if (doFree) { if (smem !is null) free(smem); if (dmem !is null) free(dmem); }
812 immutable memsz = c.length+(ZeroBytes-BoxZeroBytes);
813 if (c.length <= 2048) {
814 smem = cast(ubyte*)alloca(memsz);
815 dmem = cast(ubyte*)alloca(memsz);
816 } else {
817 smem = cast(ubyte*)malloc(memsz);
818 dmem = cast(ubyte*)malloc(memsz);
819 doFree = true;
821 if (smem is null || dmem is null) return false;
822 memset(smem, 0, memsz);
823 memset(dmem, 0, memsz);
824 // copy `c` to `smem`
825 memcpy(smem+BoxZeroBytes, c.ptr, c.length);
826 // process
827 static if (boxmode == "box") {
828 auto res = crypto_box_open(dmem[0..memsz], smem[0..memsz], nonce, pk, sk);
829 } else {
830 auto res = crypto_secretbox_open(dmem[0..memsz], smem[0..memsz], nonce, pk);
832 ubyte b = 0;
833 foreach (immutable ubyte bv; dmem[0..ZeroBytes]) b |= bv;
834 // copy result to destination buffer
835 memcpy(msg.ptr, dmem+ZeroBytes, crypto_boxes_decsize!boxmode(c.length));
836 return (res && b == 0);
839 alias crypto_box_dec = crypto_boxes_dec!"box"; /// ditto
840 alias crypto_secretbox_dec = crypto_boxes_dec!"secretbox"; /// ditto
843 // ////////////////////////////////////////////////////////////////////////// //
845 * This function signs a message 'msg' using the sender's secret key 'sk'.
846 * The function returns the resulting signed message.
848 * Params:
849 * sm = buffer to receive signed message, must be of size at least msg.length+crypto_sign_BYTES
850 * msg = message
851 * sk = secret key, slice size must be at least crypto_sign_SECRETKEYBYTES, extra ignored
853 * Returns:
854 * signed message
856 public void crypto_sign (ubyte[] sm, const(ubyte)[] msg, const(ubyte)[] sk) @nogc {
857 if (sk.length < crypto_sign_SECRETKEYBYTES) assert(0, "invalid sk size");
858 if (sm.length < msg.length+64) assert(0, "invalid sm size");
860 ubyte[64] d = void, h = void, r = void;
861 ulong[64] x = 0;
862 long[16][4] p = void;
863 auto n = msg.length;
864 auto smlen = n+64;
866 crypto_hash(d, sk.ptr[0..32]);
867 d.ptr[0] &= 248;
868 d.ptr[31] &= 127;
869 d.ptr[31] |= 64;
871 sm.ptr[64..64+n] = msg[];
872 sm.ptr[32..64] = d.ptr[32..64];
874 crypto_hash(r, sm.ptr[32..32+n+32]);
875 reduce(r);
876 scalarbase(p, r);
877 pack(sm, p);
879 sm.ptr[32..64] = sk.ptr[32..64];
880 crypto_hash(h, sm.ptr[0..n+64]);
881 reduce(h);
883 foreach (immutable i; 0..32) x.ptr[i] = cast(ulong)r.ptr[i];
884 foreach (immutable i; 0..32) foreach (immutable j; 0..32) x.ptr[i+j] += h.ptr[i]*cast(ulong)d.ptr[j];
885 modL(sm[32..$], cast(long[])x);
889 * This function verifies the signature in 'sm' using the receiver's public key 'pk'.
891 * Params:
892 * msg = decrypted message, last crypto_sign_BYTES bytes are useless zeroes, must be of size at least sm.length-crypto_sign_BYTES
893 * sm = signed message
894 * pk = public key, slice size must be at least crypto_sign_PUBLICKEYBYTES, extra ignored
896 * Returns:
897 * success flag
899 public bool crypto_sign_open (ubyte[] msg, const(ubyte)[] sm, const(ubyte)[] pk) @nogc {
900 if (pk.length < crypto_sign_PUBLICKEYBYTES) assert(0, "invalid pk size");
901 if (msg.length < sm.length) assert(0, "invalid sm size");
902 if (sm.length < 64) assert(0, "invalid sm size");
904 ubyte[32] t = void;
905 ubyte[64] h = void;
906 long[16][4] p = void, q = void;
907 auto n = sm.length;
909 if (n < 64) return false;
911 if (!unpackneg(q, pk)) return false;
912 msg.ptr[0..n] = sm[];
913 msg.ptr[32..64] = pk.ptr[0..32];
914 crypto_hash(h, msg);
915 reduce(h);
916 scalarmult(p, q, h);
918 scalarbase(q, sm[32..$]);
919 add(p, q);
920 pack(t, p);
922 n -= 64;
923 if (!crypto_verify_32(sm, t)) {
924 msg[0..$/*n*/] = 0;
925 return false;
928 msg.ptr[0..n] = sm.ptr[64..64+n];
929 if (msg.length > n) msg[n..$] = 0;
931 return true;
935 * This function randomly generates a secret key and a corresponding public key.
937 * Params:
938 * pk = slice to put generated public key into (at least crypto_sign_PUBLICKEYBYTES)
939 * sk = slice to put generated secret key into (at least crypto_sign_SECRETKEYBYTES)
941 * Returns:
942 * pair of new keys (in pk and sk)
944 public void crypto_sign_keypair (ubyte[] pk, ubyte[] sk) {
945 if (pk.length < crypto_sign_PUBLICKEYBYTES) assert(0, "invalid pk size");
946 if (sk.length < crypto_sign_SECRETKEYBYTES) assert(0, "invalid sk size");
948 ubyte[64] d = void;
949 long[16][4] p = void;
951 randombytes(sk.ptr[0..32]);
952 crypto_hash(d, sk.ptr[0..32]);
953 d.ptr[0] &= 248;
954 d.ptr[31] &= 127;
955 d.ptr[31] |= 64;
957 scalarbase(p, d);
958 pack(pk, p);
960 sk.ptr[32..64] = pk.ptr[0..32];
964 * This function generates a public key from the given secret key.
966 * Params:
967 * pk = slice to put generated public key into (at least crypto_sign_PUBLICKEYBYTES)
968 * sk = slice to get secret key from (at least crypto_sign_SECRETKEYBYTES,
969 * crypto_sign_PUBLICKEYBYTES is secret key, won't be modified)
971 * Returns:
972 * pair of new keys (in pk and sk)
974 public void crypto_sign_pk_from_sk (ubyte[] pk, ubyte[] sk) {
975 if (pk.length < crypto_sign_PUBLICKEYBYTES) assert(0, "invalid pk size");
976 if (sk.length < crypto_sign_SECRETKEYBYTES) assert(0, "invalid sk size");
978 ubyte[64] d = void;
979 long[16][4] p = void;
981 //randombytes(sk.ptr[0..32]);
982 crypto_hash(d, sk.ptr[0..32]);
983 d.ptr[0] &= 248;
984 d.ptr[31] &= 127;
985 d.ptr[31] |= 64;
987 scalarbase(p, d);
988 pack(pk, p);
990 sk.ptr[32..64] = pk.ptr[0..32];
994 // ////////////////////////////////////////////////////////////////////////// //
995 private @trusted @nogc:
997 static immutable ubyte[16] zero_ = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
998 static 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];
1000 static immutable long[16]
1001 gf0 = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
1002 gf1 = [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
1003 xx121665 = [0xDB41,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
1004 D = [0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203],
1005 D2 =[0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406],
1006 X = [0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169],
1007 Y = [0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666],
1008 I = [0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83];
1010 uint ld32 (const(ubyte)[] x) {
1011 pragma(inline, true);
1012 assert(x.length >= 4);
1013 uint u = x.ptr[3];
1014 u = (u<<8)|x.ptr[2];
1015 u = (u<<8)|x.ptr[1];
1016 return (u<<8)|x.ptr[0];
1019 ulong dl64 (const(ubyte)[] x) {
1020 pragma(inline, true);
1021 assert(x.length >= 8);
1022 ulong u = x.ptr[0];
1023 u = (u<<8)|x.ptr[1];
1024 u = (u<<8)|x.ptr[2];
1025 u = (u<<8)|x.ptr[3];
1026 u = (u<<8)|x.ptr[4];
1027 u = (u<<8)|x.ptr[5];
1028 u = (u<<8)|x.ptr[6];
1029 return (u<<8)|x.ptr[7];
1032 void st32 (ubyte[] x, uint u) {
1033 pragma(inline, true);
1034 assert(x.length >= 4);
1035 x.ptr[0] = u&0xff;
1036 x.ptr[1] = (u>>8)&0xff;
1037 x.ptr[2] = (u>>16)&0xff;
1038 x.ptr[3] = (u>>24)&0xff;
1041 void ts64 (ubyte[] x, ulong u) {
1042 pragma(inline, true);
1043 assert(x.length >= 8);
1044 x.ptr[0] = (u>>56)&0xff;
1045 x.ptr[1] = (u>>48)&0xff;
1046 x.ptr[2] = (u>>40)&0xff;
1047 x.ptr[3] = (u>>32)&0xff;
1048 x.ptr[4] = (u>>24)&0xff;
1049 x.ptr[5] = (u>>16)&0xff;
1050 x.ptr[6] = (u>>8)&0xff;
1051 x.ptr[7] = u&0xff;
1054 bool vn (const(ubyte)[] x, const(ubyte)[] y) {
1055 assert(x.length >= y.length);
1056 uint d = 0;
1057 foreach (immutable i, immutable v; cast(const(ubyte)[])x) d |= v^y.ptr[i];
1058 return (1&((d-1)>>8)) != 0;
1061 private void salsa_core(string type) (ubyte[] output, const(ubyte)[] input, const(ubyte)[] key, const(ubyte)[] constant)
1062 if (type == "salsa" || type == "hsalsa") // constraint
1064 static uint ROTL32 (uint x, int c) pure nothrow @safe @nogc { pragma(inline, true); return (x<<c)|((x&0xffffffff)>>(32-c)); }
1066 // magic!
1067 assert(mixin(`output.length >= crypto_core_`~type~`20_OUTPUTBYTES`));
1068 assert(mixin(`input.length >= crypto_core_`~type~`20_INPUTBYTES`));
1069 assert(mixin(`key.length >= crypto_core_`~type~`20_KEYBYTES`));
1070 assert(mixin(`constant.length >= crypto_core_`~type~`20_CONSTBYTES`));
1072 uint[16] w = void, x = void, y = void;
1073 uint[4] t = void;
1075 foreach (immutable i; 0..4) {
1076 x.ptr[5*i] = ld32(constant[4*i..$]);
1077 x.ptr[1+i] = ld32(key[4*i..$]);
1078 x.ptr[6+i] = ld32(input[4*i..$]);
1079 x.ptr[11+i] = ld32(key[16+4*i..$]);
1082 y[] = x[];
1084 foreach (immutable i; 0..20) {
1085 foreach (immutable j; 0..4) {
1086 foreach (immutable m; 0..4) t.ptr[m] = x.ptr[(5*j+4*m)%16];
1087 t.ptr[1] ^= ROTL32(t.ptr[0]+t.ptr[3], 7);
1088 t.ptr[2] ^= ROTL32(t.ptr[1]+t.ptr[0], 9);
1089 t.ptr[3] ^= ROTL32(t.ptr[2]+t.ptr[1], 13);
1090 t.ptr[0] ^= ROTL32(t.ptr[3]+t.ptr[2], 18);
1091 for (auto m = 0; m < 4; ++m) w.ptr[4*j+(j+m)%4] = t.ptr[m];
1093 for (auto m = 0; m < 16; ++m) x.ptr[m] = w.ptr[m];
1096 static if (type == "hsalsa") {
1097 for (auto i = 0; i < 16; ++i) x.ptr[i] += y.ptr[i];
1098 for (auto i = 0; i < 4; ++i) {
1099 x.ptr[5*i] -= ld32(constant[4*i..$]);
1100 x.ptr[6+i] -= ld32(input[4*i..$]);
1102 for (auto i = 0; i < 4; ++i) {
1103 st32(output[4*i..$], x.ptr[5*i]);
1104 st32(output[16+4*i..$], x.ptr[6+i]);
1106 } else {
1107 for (auto i = 0; i < 16; ++i) st32(output[4*i..$], x.ptr[i]+y.ptr[i]);
1111 // public for testing
1112 public void crypto_core_salsa20 (ubyte[] output, const(ubyte)[] input, const(ubyte)[] key, const(ubyte)[] constant) {
1113 pragma(inline, true);
1114 salsa_core!"salsa"(output, input, key, constant);
1117 // public for testing
1118 public void crypto_core_hsalsa20 (ubyte[] output, const(ubyte)[] input, const(ubyte)[] key, const(ubyte)[] constant) {
1119 pragma(inline, true);
1120 salsa_core!"hsalsa"(output, input, key, constant);
1123 private immutable ubyte[] sigma = cast(immutable ubyte[])"expand 32-byte k";
1125 private void add1305 (uint[] h, const(uint)[] c) {
1126 uint u = 0;
1127 foreach (immutable j; 0..17) {
1128 u += h.ptr[j]+c.ptr[j];
1129 h.ptr[j] = u&255;
1130 u >>= 8;
1134 private immutable uint[17] minusp = [5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,252];
1136 void car25519 (long[] o) {
1137 foreach (immutable i; 0..16) {
1138 o.ptr[i] += (1<<16);
1139 long c = o.ptr[i]>>16;
1140 o.ptr[(i+1)*(i<15)] += c-1+37*(c-1)*(i==15);
1141 o.ptr[i] -= c<<16;
1145 void sel25519 (long[] p,long[] q, int b) {
1146 long c = ~(b-1);
1147 foreach (immutable i; 0..16) {
1148 long t = c&(p.ptr[i]^q.ptr[i]);
1149 p.ptr[i] ^= t;
1150 q.ptr[i] ^= t;
1154 void pack25519 (ubyte[] o, const(long)[] n) {
1155 int b;
1156 long[16] m = void, t = void;
1157 t.ptr[0..16] = n.ptr[0..16];
1158 car25519(t);
1159 car25519(t);
1160 car25519(t);
1161 foreach (immutable j; 0..2) {
1162 m.ptr[0] = t.ptr[0]-0xffed;
1163 foreach (immutable i; 1..15) {
1164 m.ptr[i] = t.ptr[i]-0xffff-((m.ptr[i-1]>>16)&1);
1165 m.ptr[i-1] &= 0xffff;
1167 m.ptr[15] = t.ptr[15]-0x7fff-((m.ptr[14]>>16)&1);
1168 b = (m.ptr[15]>>16)&1;
1169 m.ptr[14] &= 0xffff;
1170 sel25519(t, m, 1-b);
1172 foreach (immutable i; 0..16) {
1173 o.ptr[2*i] = t.ptr[i]&0xff;
1174 o.ptr[2*i+1] = (t.ptr[i]>>8)&0xff;
1178 bool neq25519 (const(long)[] a, const(long)[] b) {
1179 ubyte[32] c = void, d = void;
1180 pack25519(c, a);
1181 pack25519(d, b);
1182 return crypto_verify_32(c, d);
1185 ubyte par25519 (const(long)[] a) {
1186 ubyte[32] d = void;
1187 pack25519(d, a);
1188 return d.ptr[0]&1;
1191 void unpack25519 (long[] o, const(ubyte)[] n) {
1192 foreach (immutable i; 0..16) o.ptr[i] = n.ptr[2*i]+(cast(long)n.ptr[2*i+1]<<8);
1193 o.ptr[15] &= 0x7fff;
1196 void A (long[] o, const(long)[] a, const(long)[] b) {
1197 foreach (immutable i; 0..16) o.ptr[i] = a.ptr[i]+b.ptr[i];
1200 void Z (long[] o, const(long)[] a, const(long)[] b) {
1201 foreach (immutable i; 0..16) o.ptr[i] = a.ptr[i]-b.ptr[i];
1204 void M (long[] o, const(long)[] a, const(long)[] b) {
1205 long[31] t; // automatically becomes 0
1206 foreach (immutable i; 0..16) foreach (immutable j; 0..16) t.ptr[i+j] += a.ptr[i]*b.ptr[j];
1207 foreach (immutable i; 0..15) t.ptr[i] += 38*t.ptr[i+16];
1208 o.ptr[0..16] = t.ptr[0..16];
1209 car25519(o);
1210 car25519(o);
1213 void S (long[] o, const(long)[] a) {
1214 M(o, a, a);
1217 void inv25519 (long[] o, const(long)[] i) {
1218 long[16] c = void;
1219 c[] = i.ptr[0..16];
1220 for (auto a = 253; a >= 0; --a) {
1221 S(c, c);
1222 if (a != 2 && a != 4) M(c, c, i);
1224 o.ptr[0..16] = c[];
1227 void pow2523 (long[] o, const(long)[] i) {
1228 long[16] c = void;
1229 c[] = i.ptr[0..16];
1230 for(auto a = 250; a >= 0; --a) {
1231 S(c, c);
1232 if (a != 1) M(c, c, i);
1234 o.ptr[0..16] = c[];
1237 // public for testing
1238 /* FIXME!
1239 * This function multiplies a group element 'p' by an integer 'n'.
1241 * Params:
1242 * p = group element
1243 * n = number
1245 * Returns:
1246 * resulting group element 'q' of length crypto_scalarmult_BYTES.
1248 public void crypto_scalarmult (ubyte[] q, const(ubyte)[] n, const(ubyte)[] p) {
1249 assert(q.length == crypto_scalarmult_BYTES);
1250 assert(n.length == crypto_scalarmult_BYTES);
1251 assert(p.length == crypto_scalarmult_BYTES);
1253 ubyte[32] z = void;
1254 long[80] x = void;
1255 long r;
1256 long[16] a = void, b = void, c = void, d = void, e = void, f = void;
1257 z[] = n.ptr[0..32];
1258 z.ptr[31] = (n.ptr[31]&127)|64;
1259 z.ptr[0] &= 248;
1260 unpack25519(x, p);
1261 foreach (immutable i; 0..16) {
1262 b.ptr[i] = x.ptr[i];
1263 d.ptr[i] = a.ptr[i] = c.ptr[i] = 0;
1265 a.ptr[0] = d.ptr[0] = 1;
1266 for (int i = 254; i >= 0; --i) {
1267 r = (z.ptr[i>>3]>>(i&7))&1;
1268 sel25519(a, b, cast(int)r);
1269 sel25519(c, d, cast(int)r);
1270 A(e, a, c);
1271 Z(a, a, c);
1272 A(c, b, d);
1273 Z(b, b, d);
1274 S(d, e);
1275 S(f, a);
1276 M(a, c, a);
1277 M(c, b, e);
1278 A(e, a, c);
1279 Z(a, a, c);
1280 S(b, a);
1281 Z(c, d, f);
1282 M(a, c, xx121665);
1283 A(a, a, d);
1284 M(c, c, a);
1285 M(a, d, f);
1286 M(d, b, x);
1287 S(b, e);
1288 sel25519(a, b, cast(int)r);
1289 sel25519(c, d, cast(int)r);
1291 foreach (immutable i; 0..16) {
1292 x.ptr[i+16] = a.ptr[i];
1293 x.ptr[i+32] = c.ptr[i];
1294 x.ptr[i+48] = b.ptr[i];
1295 x.ptr[i+64] = d.ptr[i];
1297 inv25519(x[32..$], x[32..$]);
1298 M(x[16..$], x[16..$], x[32..$]);
1299 pack25519(q, x[16..$]);
1302 // public for testing
1303 /* FIXME!
1304 * This function computes the scalar product of a standard group element
1305 * and an integer 'n'.
1307 * Params:
1308 * n = number
1310 * Returns:
1311 * resulting group element 'q' of length crypto_scalarmult_BYTES.
1313 public void crypto_scalarmult_base (ubyte[] q, const(ubyte)[] n) {
1314 pragma(inline, true);
1315 assert(q.length == crypto_scalarmult_BYTES);
1316 assert(n.length == crypto_scalarmult_SCALARBYTES);
1317 crypto_scalarmult(q, n, nine_);
1320 private:
1321 ulong R (ulong x, int c) pure { pragma(inline, true); return (x>>c)|(x<<(64-c)); }
1322 ulong Ch (ulong x, ulong y, ulong z) pure { pragma(inline, true); return (x&y)^(~x&z); }
1323 ulong Maj (ulong x, ulong y, ulong z) pure { pragma(inline, true); return (x&y)^(x&z)^(y&z); }
1324 ulong Sigma0 (ulong x) pure { pragma(inline, true); return R(x, 28)^R(x, 34)^R(x, 39); }
1325 ulong Sigma1 (ulong x) pure { pragma(inline, true); return R(x, 14)^R(x, 18)^R(x, 41); }
1326 ulong sigma0 (ulong x) pure { pragma(inline, true); return R(x, 1)^R(x, 8)^(x>>7); }
1327 ulong sigma1 (ulong x) pure { pragma(inline, true); return R(x, 19)^R(x, 61)^(x>>6); }
1329 immutable ulong[80] K = [
1330 0x428a2f98d728ae22UL, 0x7137449123ef65cdUL, 0xb5c0fbcfec4d3b2fUL, 0xe9b5dba58189dbbcUL,
1331 0x3956c25bf348b538UL, 0x59f111f1b605d019UL, 0x923f82a4af194f9bUL, 0xab1c5ed5da6d8118UL,
1332 0xd807aa98a3030242UL, 0x12835b0145706fbeUL, 0x243185be4ee4b28cUL, 0x550c7dc3d5ffb4e2UL,
1333 0x72be5d74f27b896fUL, 0x80deb1fe3b1696b1UL, 0x9bdc06a725c71235UL, 0xc19bf174cf692694UL,
1334 0xe49b69c19ef14ad2UL, 0xefbe4786384f25e3UL, 0x0fc19dc68b8cd5b5UL, 0x240ca1cc77ac9c65UL,
1335 0x2de92c6f592b0275UL, 0x4a7484aa6ea6e483UL, 0x5cb0a9dcbd41fbd4UL, 0x76f988da831153b5UL,
1336 0x983e5152ee66dfabUL, 0xa831c66d2db43210UL, 0xb00327c898fb213fUL, 0xbf597fc7beef0ee4UL,
1337 0xc6e00bf33da88fc2UL, 0xd5a79147930aa725UL, 0x06ca6351e003826fUL, 0x142929670a0e6e70UL,
1338 0x27b70a8546d22ffcUL, 0x2e1b21385c26c926UL, 0x4d2c6dfc5ac42aedUL, 0x53380d139d95b3dfUL,
1339 0x650a73548baf63deUL, 0x766a0abb3c77b2a8UL, 0x81c2c92e47edaee6UL, 0x92722c851482353bUL,
1340 0xa2bfe8a14cf10364UL, 0xa81a664bbc423001UL, 0xc24b8b70d0f89791UL, 0xc76c51a30654be30UL,
1341 0xd192e819d6ef5218UL, 0xd69906245565a910UL, 0xf40e35855771202aUL, 0x106aa07032bbd1b8UL,
1342 0x19a4c116b8d2d0c8UL, 0x1e376c085141ab53UL, 0x2748774cdf8eeb99UL, 0x34b0bcb5e19b48a8UL,
1343 0x391c0cb3c5c95a63UL, 0x4ed8aa4ae3418acbUL, 0x5b9cca4f7763e373UL, 0x682e6ff3d6b2b8a3UL,
1344 0x748f82ee5defb2fcUL, 0x78a5636f43172f60UL, 0x84c87814a1f0ab72UL, 0x8cc702081a6439ecUL,
1345 0x90befffa23631e28UL, 0xa4506cebde82bde9UL, 0xbef9a3f7b2c67915UL, 0xc67178f2e372532bUL,
1346 0xca273eceea26619cUL, 0xd186b8c721c0c207UL, 0xeada7dd6cde0eb1eUL, 0xf57d4f7fee6ed178UL,
1347 0x06f067aa72176fbaUL, 0x0a637dc5a2c898a6UL, 0x113f9804bef90daeUL, 0x1b710b35131c471bUL,
1348 0x28db77f523047d84UL, 0x32caab7b40c72493UL, 0x3c9ebe0a15c9bebcUL, 0x431d67c49c100d4cUL,
1349 0x4cc5d4becb3e42b6UL, 0x597f299cfc657e2aUL, 0x5fcb6fab3ad6faecUL, 0x6c44198c4a475817UL
1352 void crypto_hashblocks (ubyte[] x, const(ubyte)[] m, ulong n) {
1353 ulong[8] z = void, b = void, a = void;
1354 ulong[16] w = void;
1355 ulong t;
1356 uint mpos = 0;
1357 foreach (immutable i; 0..8) z.ptr[i] = a.ptr[i] = dl64(x[8*i..$]);
1358 while (n >= 128) {
1359 foreach (immutable i; 0..16) w.ptr[i] = dl64(m[mpos+8*i..$]);
1360 foreach (immutable i; 0..80) {
1361 b.ptr[0..8] = a.ptr[0..8];
1362 t = a.ptr[7]+Sigma1(a.ptr[4])+Ch(a.ptr[4], a.ptr[5], a.ptr[6])+K[i]+w.ptr[i%16];
1363 b.ptr[7] = t+Sigma0(a.ptr[0])+Maj(a.ptr[0], a.ptr[1], a.ptr[2]);
1364 b.ptr[3] += t;
1365 //foreach (immutable j; 0..8) a.ptr[(j+1)%8] = b.ptr[j];
1366 a.ptr[1..8] = b.ptr[0..7];
1367 a.ptr[0] = b.ptr[7];
1368 if (i%16 == 15) {
1369 foreach (immutable j; 0..16) w.ptr[j] += w.ptr[(j+9)%16]+sigma0(w.ptr[(j+1)%16])+sigma1(w.ptr[(j+14)%16]);
1372 foreach (immutable i; 0..8) { a.ptr[i] += z.ptr[i]; z.ptr[i] = a.ptr[i]; }
1373 mpos += 128;
1374 n -= 128;
1376 foreach (immutable i; 0..8) ts64(x[8*i..$], z.ptr[i]);
1379 immutable ubyte[64] ivc = [
1380 0x6a, 0x09, 0xe6, 0x67, 0xf3, 0xbc, 0xc9, 0x08,
1381 0xbb, 0x67, 0xae, 0x85, 0x84, 0xca, 0xa7, 0x3b,
1382 0x3c, 0x6e, 0xf3, 0x72, 0xfe, 0x94, 0xf8, 0x2b,
1383 0xa5, 0x4f, 0xf5, 0x3a, 0x5f, 0x1d, 0x36, 0xf1,
1384 0x51, 0x0e, 0x52, 0x7f, 0xad, 0xe6, 0x82, 0xd1,
1385 0x9b, 0x05, 0x68, 0x8c, 0x2b, 0x3e, 0x6c, 0x1f,
1386 0x1f, 0x83, 0xd9, 0xab, 0xfb, 0x41, 0xbd, 0x6b,
1387 0x5b, 0xe0, 0xcd, 0x19, 0x13, 0x7e, 0x21, 0x79
1391 * This function hashes a message 'msg'.
1392 * It returns a hash 'output'. The output length of 'output'
1393 * should be at least crypto_hash_BYTES.
1395 * Params:
1396 * output = resulting hash
1397 * msg = message
1399 * Returns:
1400 * sha512 hash
1402 public void crypto_hash (ubyte[] output, const(ubyte)[] msg) {
1403 if (output.length < crypto_hash_BYTES) assert(0, "output too small");
1404 ubyte[64] h = void;
1405 ubyte[256] x = 0;
1406 auto n = msg.length;
1407 ulong b = n;
1408 uint mpos = 0;
1410 h[] = ivc[];
1412 crypto_hashblocks(h, msg, n);
1413 mpos += n;
1414 n &= 127;
1415 mpos -= n;
1417 x.ptr[0..n] = msg.ptr[mpos..mpos+n];
1418 x.ptr[n] = 128;
1420 n = 256-128*(n<112);
1421 x.ptr[n-9] = b>>61;
1422 ts64(x[n-8..$], b<<3);
1423 crypto_hashblocks(h, x, n);
1425 output.ptr[0..64] = h;
1428 private void add (ref long[16][4] p, ref long[16][4] q) {
1429 long[16] a = void, b = void, c = void, d = void, t = void, e = void, f = void, g = void, h = void;
1431 Z(a, p.ptr[1], p.ptr[0]);
1432 Z(t, q.ptr[1], q.ptr[0]);
1433 M(a, a, t);
1434 A(b, p.ptr[0], p.ptr[1]);
1435 A(t, q.ptr[0], q.ptr[1]);
1436 M(b, b, t);
1437 M(c, p.ptr[3], q.ptr[3]);
1438 M(c, c, D2);
1439 M(d, p.ptr[2], q.ptr[2]);
1440 A(d, d, d);
1441 Z(e, b, a);
1442 Z(f, d, c);
1443 A(g, d, c);
1444 A(h, b, a);
1446 M(p.ptr[0], e, f);
1447 M(p.ptr[1], h, g);
1448 M(p.ptr[2], g, f);
1449 M(p.ptr[3], e, h);
1452 void cswap (ref long[16][4] p, ref long[16][4] q, ubyte b) {
1453 pragma(inline, true);
1454 foreach (immutable i; 0..4) sel25519(p.ptr[i], q.ptr[i], b);
1457 void pack (ubyte[] r, ref long[16][4] p) {
1458 long[16] tx = void, ty = void, zi = void;
1459 inv25519(zi, p.ptr[2]);
1460 M(tx, p.ptr[0], zi);
1461 M(ty, p.ptr[1], zi);
1462 pack25519(r, ty);
1463 r.ptr[31] ^= par25519(tx)<<7;
1466 void scalarmult (ref long[16][4] p, ref long[16][4] q, const(ubyte)[] s) {
1467 p.ptr[0][] = gf0[];
1468 p.ptr[1][] = gf1[];
1469 p.ptr[2][] = gf1[];
1470 p.ptr[3][] = gf0[];
1471 for (int i = 255; i >= 0; --i) {
1472 ubyte b = (s.ptr[i/8]>>(i&7))&1;
1473 cswap(p, q, b);
1474 add(q, p);
1475 add(p, p);
1476 cswap(p, q, b);
1480 void scalarbase (ref long[16][4] p, const(ubyte)[] s) {
1481 long[16][4] q = void;
1482 q.ptr[0][] = X[];
1483 q.ptr[1][] = Y[];
1484 q.ptr[2][] = gf1[];
1485 M(q.ptr[3], X, Y);
1486 scalarmult(p, q, s);
1489 immutable ulong[32] L = [
1490 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
1493 void modL (ubyte[] r, long[] x) {
1494 long carry;
1495 for (auto i = 63; i >= 32; --i) {
1496 int j;
1497 carry = 0;
1498 for (j = i-32; j < i-12; ++j) {
1499 x.ptr[j] += carry-16*x.ptr[i]*L[j-(i-32)];
1500 carry = (x.ptr[j]+128)>>8;
1501 x.ptr[j] -= carry<<8;
1503 x.ptr[j] += carry;
1504 x.ptr[i] = 0;
1506 carry = 0;
1507 foreach (immutable j; 0..32) {
1508 x.ptr[j] += carry-(x.ptr[31]>>4)*L[j];
1509 carry = x.ptr[j]>>8;
1510 x.ptr[j] &= 255;
1512 foreach (immutable j; 0..32) x.ptr[j] -= carry*L[j];
1513 foreach (immutable i; 0..32) {
1514 x.ptr[i+1] += x.ptr[i]>>8;
1515 r.ptr[i] = x.ptr[i]&255;
1519 void reduce (ubyte[] r) {
1520 long[64] x = void;
1521 foreach (immutable i; 0..64) x.ptr[i] = cast(ulong)r.ptr[i];
1522 r.ptr[0..64] = 0;
1523 modL(r, x);
1526 private bool unpackneg (ref long[16][4] r, const(ubyte)[] p) {
1527 long[16] t = void, chk = void, num = void, den = void, den2 = void, den4 = void, den6 = void;
1528 r.ptr[2][] = gf1[];
1529 unpack25519(r.ptr[1], p);
1530 S(num, r.ptr[1]);
1531 M(den, num, D);
1532 Z(num, num, r.ptr[2]);
1533 A(den, r.ptr[2], den);
1535 S(den2, den);
1536 S(den4, den2);
1537 M(den6, den4, den2);
1538 M(t, den6, num);
1539 M(t, t, den);
1541 pow2523(t, t);
1542 M(t, t, num);
1543 M(t, t, den);
1544 M(t, t, den);
1545 M(r.ptr[0], t, den);
1547 S(chk, r.ptr[0]);
1548 M(chk, chk, den);
1549 if (!neq25519(chk, num)) M(r.ptr[0], r.ptr[0], I);
1551 S(chk, r.ptr[0]);
1552 M(chk, chk, den);
1553 if (!neq25519(chk, num)) return false;
1555 if (par25519(r.ptr[0]) == (p.ptr[31]>>7)) Z(r.ptr[0], gf0, r.ptr[0]);
1557 M(r.ptr[3], r.ptr[0], r.ptr[1]);
1558 return true;
1562 // ////////////////////////////////////////////////////////////////////////// //
1563 // Ketmar's additions
1565 /** Generate 32-byte secret key from the given passphase and salt.
1567 * This is very simple (and cryptographically weak) function to
1568 * generate crypto key from the given passphrase and salt.
1570 * WARNING! This function sux, and it is absolutely cryptographically weak
1571 * (hence the name). Only use it if you don't care about any
1572 * attacks. Heh.
1574 * Params:
1575 * sk = output buffer, should have room for at least 32 bytes
1576 * passphrase = passphrase, arbitrary length
1577 * salt = salt
1579 * Returns:
1580 * Generated key in first 32 bytes of sk.
1582 public void weak_crypto_key_from_passphrase (ubyte[] sk, const(void)[] passphrase, ulong salt) @trusted @nogc {
1583 if (sk.length < 32) assert(0, "invalid sk size");
1584 static assert(crypto_hash_BYTES == 64);
1585 ubyte[crypto_hash_BYTES+24/*nonce*/] hash = void;
1586 crypto_hash(hash[], cast(const(ubyte)[])passphrase[]);
1587 hash[crypto_hash_BYTES..$] = 0;
1588 hash.ptr[crypto_hash_BYTES+0] = cast(ubyte)(salt&0xff);
1589 hash.ptr[crypto_hash_BYTES+1] = cast(ubyte)((salt>>8)&0xff);
1590 hash.ptr[crypto_hash_BYTES+2] = cast(ubyte)((salt>>16)&0xff);
1591 hash.ptr[crypto_hash_BYTES+3] = cast(ubyte)((salt>>24)&0xff);
1592 hash.ptr[crypto_hash_BYTES+4] = cast(ubyte)((salt>>32)&0xff);
1593 hash.ptr[crypto_hash_BYTES+5] = cast(ubyte)((salt>>40)&0xff);
1594 hash.ptr[crypto_hash_BYTES+6] = cast(ubyte)((salt>>48)&0xff);
1595 hash.ptr[crypto_hash_BYTES+7] = cast(ubyte)((salt>>56)&0xff);
1596 crypto_stream_xor(sk[0..32], hash[0..32], hash[64..64+24], hash[32..64]);