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