1 module dcrypt.ecc.ed25519; 2 3 import dcrypt.ecc.curved25519.groupElement; 4 import dcrypt.ecc.curve25519: clamp; 5 import dcrypt.digests.sha2: SHA512; 6 import dcrypt.util; 7 8 /// Generate a ed25519 public key from a secret key. 9 unittest { 10 // draft-josefsson-eddsa-ed25519-03 11 // -----TEST 1 12 13 immutable ubyte[32] sk = cast(const ubyte[]) x"9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60"; 14 immutable ubyte[32] expectedPk = cast(const ubyte[]) x"d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a"; 15 16 immutable ubyte[32] pk = secret_to_public(sk); 17 18 assert(pk == expectedPk, "ed25519 crypto_sign_pubkey failed."); 19 } 20 21 /// Test signing and verifying. 22 /// Test vectors from http://ed25519.cr.yp.to/python/sign.input. 23 unittest { 24 25 immutable ubyte[32] sk = cast(const ubyte[]) x"9d61b19deffd5a60ba844af492ec2cc4 4449c5697b326919703bac031cae7f60"; 26 immutable ubyte[32] pk = secret_to_public(sk); 27 28 assert(pk == x"d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a", "Ed25519 generated unexpected public key."); 29 30 immutable ubyte[0] message = cast(const ubyte[]) ""; 31 32 immutable ubyte[64] signature = sign(message, sk); 33 34 immutable auto expectedSig = x"e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b"; 35 assert(signature[0..32] == expectedSig[0..32], "Ed25519 signature: wrong R."); 36 assert(signature[32..64] == expectedSig[32..64], "Ed25519 produced unexpected signature."); 37 38 immutable bool valid = verify(signature, message, pk); 39 assert(valid, "Ed25519 signature verificaton failed."); 40 41 assert(!verify(signature, cast(const ubyte[]) "asdf", pk), "Ed25519 signature verificaton failed."); 42 } 43 44 @safe nothrow @nogc: 45 46 /// Sign a message with your secret key. 47 /// 48 /// Params: 49 /// sig = buffer for signature 50 /// m = message 51 /// sk = secret key 52 /// pk = public key. Not necessary to provide it, but a bit faster. 53 public ubyte[64] sign( 54 in ubyte[] m, 55 in ubyte[] sk, 56 in ubyte[] publicKey = null 57 ) 58 in { 59 assert(sk.length == 32, "Secret key must be 32 bytes."); 60 if(publicKey !is null) { 61 assert(publicKey.length == 32, "Public key must be 32 bytes."); 62 } 63 } body { 64 ubyte[64] sig; 65 ubyte[32] r, h; 66 67 ge_p3 R; 68 69 immutable ubyte[64] expandedSecret = secret_expand(sk); 70 71 ubyte[32] pk; /// public key 72 73 if(publicKey !is null) { 74 pk = publicKey; 75 } else { 76 // shortcut for: pk = secret_to_public(sk); 77 pk = ge_scalarmult_base(expandedSecret[0..32]).toBytes; 78 } 79 80 81 // sha512_modq 82 SHA512 sha; 83 sha.put(expandedSecret[32..64]); 84 sha.put(m); 85 r = sc_reduce(sha.finish()); 86 87 R = ge_scalarmult_base(r); 88 sig[0..32] = R.toBytes; 89 90 // sha512modq 91 sha.put(sig[0..32]); 92 sha.put(pk[0..32]); 93 sha.put(m); 94 h = sc_reduce(sha.finish()); 95 96 sig[32..64] = sc_muladd(h, expandedSecret[0..32], r); 97 98 return sig; 99 } 100 101 102 /// Verify a signature `sig` of message `m` with public key `pk`. 103 /// Params: 104 /// signature = 64 bytes signature. 105 /// m = The signed message. 106 /// pk = The public key. 107 public bool verify( 108 in ubyte[] signature, 109 in ubyte[] m, 110 in ubyte[] pk 111 ) 112 in { 113 assert(signature.length == 64); 114 assert(pk.length == 32); 115 } body { 116 ubyte[32] rCopy, sCopy, rCheck; 117 ge_p3 A; 118 ge_p2 R; 119 120 if (signature[63] & 224) return false; // bad signature 121 if (!ge_frombytes_negate_vartime(A, pk)) return false; // bad signature 122 123 rCopy[] = signature[0..32]; 124 sCopy[] = signature[32..64]; 125 126 SHA512 sha; 127 sha.put(rCopy); 128 sha.put(pk[0..32]); 129 sha.put(m); 130 //crypto_hash_sha512_3(h, rcopy, 32, pkcopy, 32, m, mlen); 131 immutable ubyte[32] h = sc_reduce(sha.finish()); 132 133 R = ge_double_scalarmult_vartime(h, A, sCopy); 134 135 return crypto_equals(R.toBytes, rCopy); 136 } 137 138 /// Generate public key from secret key. 139 ubyte[32] secret_to_public(in ubyte[] sk) 140 in { 141 assert(sk.length == 32, "Invalid secret key length. Must be 32."); 142 //assert((sk[0] & ~248) == 0 || (sk[31] & ~63) == 0 || (sk[31] & 64) == 64, "Invalid secret key!"); 143 } body { 144 145 ubyte[32] secret = secret_expand(sk)[0..32]; 146 147 assert((secret[0] & ~248) == 0 || (secret[31] & ~63) == 0 || (secret[31] & 64) == 64, "Invalid secret key!"); 148 149 return ge_scalarmult_base(secret).toBytes; 150 } 151 152 private ubyte[64] secret_expand(in ubyte[] sk) 153 in { 154 assert(sk.length == 32, "Invalid secret key length. Must be 32."); 155 } body { 156 ubyte[64] secret; 157 158 SHA512 hash; 159 hash.put(sk[0..32]); 160 secret = hash.finish(); 161 162 clamp(secret[0..32]); 163 164 return secret; 165 } 166 167 // TODO: 168 //ubyte[32] ed25519_ref10_pubkey_from_curve25519_pubkey(in ubyte[] pk, 169 // in int signbit) 170 //in { 171 // assert(outp.length == 32, "Output buffer size must be 32."); 172 // assert(inp.length == 32, "Input size must be 32."); 173 // assert(signbit == 0 || signbit == 1, "signbit must be either 0 or 1."); 174 //} body { 175 // fe u; 176 // fe one; 177 // fe y; 178 // fe uplus1; 179 // fe uminus1; 180 // fe inv_uplus1; 181 // 182 // /* From prop228: 183 // 184 // Given a curve25519 x-coordinate (u), we can get the y coordinate 185 // of the ed25519 key using 186 // 187 // y = (u-1)/(u+1) 188 // */ 189 // u = fe.fromBytes(pk); 190 // uminus1 = u - fe.one; 191 // uplus1 = u + fe.one; 192 // y = uminus1 * uplus1.inverse; 193 // 194 // ubyte[32] outp = y.toBytes; 195 // /* propagate sign. */ 196 // outp[31] |= (!!signbit) << 7; // convert non zero values to 128 197 // 198 // return outp; 199 //} 200 201 private: 202 203 /** 204 Input: 205 s[0]+256*s[1]+...+256^63*s[63] = s 206 207 Output: 208 s[0]+256*s[1]+...+256^31*s[31] = s mod l 209 where l = 2^252 + 27742317777372353535851937790883648493. 210 Overwrites s in place. 211 */ 212 ubyte[32] sc_reduce(in ubyte[] inp) pure 213 in { 214 assert(inp.length == 64); 215 } body { 216 long s0 = 0x001FFFFF & load_3(inp[0..3]); 217 long s1 = 0x001FFFFF & (load_4(inp[2..6]) >> 5); 218 long s2 = 0x001FFFFF & (load_3(inp[5..8]) >> 2); 219 long s3 = 0x001FFFFF & (load_4(inp[7..11]) >> 7); 220 long s4 = 0x001FFFFF & (load_4(inp[10..14]) >> 4); 221 long s5 = 0x001FFFFF & (load_3(inp[13..16]) >> 1); 222 long s6 = 0x001FFFFF & (load_4(inp[15..19]) >> 6); 223 long s7 = 0x001FFFFF & (load_3(inp[18..21]) >> 3); 224 long s8 = 0x001FFFFF & load_3(inp[21..24]); 225 long s9 = 0x001FFFFF & (load_4(inp[23..27]) >> 5); 226 long s10 = 0x001FFFFF & (load_3(inp[26..29]) >> 2); 227 long s11 = 0x001FFFFF & (load_4(inp[28..32]) >> 7); 228 long s12 = 0x001FFFFF & (load_4(inp[31..35]) >> 4); 229 long s13 = 0x001FFFFF & (load_3(inp[34..37]) >> 1); 230 long s14 = 0x001FFFFF & (load_4(inp[36..40]) >> 6); 231 long s15 = 0x001FFFFF & (load_3(inp[39..42]) >> 3); 232 long s16 = 0x001FFFFF & load_3(inp[42..45]); 233 long s17 = 0x001FFFFF & (load_4(inp[44..48]) >> 5); 234 long s18 = 0x001FFFFF & (load_3(inp[47..50]) >> 2); 235 long s19 = 0x001FFFFF & (load_4(inp[49..53]) >> 7); 236 long s20 = 0x001FFFFF & (load_4(inp[52..56]) >> 4); 237 long s21 = 0x001FFFFF & (load_3(inp[55..58]) >> 1); 238 long s22 = 0x001FFFFF & (load_4(inp[57..61]) >> 6); 239 long s23 = (load_4(inp[60..64]) >> 3); 240 long carry0; 241 long carry1; 242 long carry2; 243 long carry3; 244 long carry4; 245 long carry5; 246 long carry6; 247 long carry7; 248 long carry8; 249 long carry9; 250 long carry10; 251 long carry11; 252 long carry12; 253 long carry13; 254 long carry14; 255 long carry15; 256 long carry16; 257 258 s11 += s23 * 666643; 259 s12 += s23 * 470296; 260 s13 += s23 * 654183; 261 s14 -= s23 * 997805; 262 s15 += s23 * 136657; 263 s16 -= s23 * 683901; 264 s23 = 0; 265 266 s10 += s22 * 666643; 267 s11 += s22 * 470296; 268 s12 += s22 * 654183; 269 s13 -= s22 * 997805; 270 s14 += s22 * 136657; 271 s15 -= s22 * 683901; 272 s22 = 0; 273 274 s9 += s21 * 666643; 275 s10 += s21 * 470296; 276 s11 += s21 * 654183; 277 s12 -= s21 * 997805; 278 s13 += s21 * 136657; 279 s14 -= s21 * 683901; 280 s21 = 0; 281 282 s8 += s20 * 666643; 283 s9 += s20 * 470296; 284 s10 += s20 * 654183; 285 s11 -= s20 * 997805; 286 s12 += s20 * 136657; 287 s13 -= s20 * 683901; 288 s20 = 0; 289 290 s7 += s19 * 666643; 291 s8 += s19 * 470296; 292 s9 += s19 * 654183; 293 s10 -= s19 * 997805; 294 s11 += s19 * 136657; 295 s12 -= s19 * 683901; 296 s19 = 0; 297 298 s6 += s18 * 666643; 299 s7 += s18 * 470296; 300 s8 += s18 * 654183; 301 s9 -= s18 * 997805; 302 s10 += s18 * 136657; 303 s11 -= s18 * 683901; 304 s18 = 0; 305 306 carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= SHL64(carry6,21); 307 carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= SHL64(carry8,21); 308 carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= SHL64(carry10,21); 309 carry12 = (s12 + (1<<20)) >> 21; s13 += carry12; s12 -= SHL64(carry12,21); 310 carry14 = (s14 + (1<<20)) >> 21; s15 += carry14; s14 -= SHL64(carry14,21); 311 carry16 = (s16 + (1<<20)) >> 21; s17 += carry16; s16 -= SHL64(carry16,21); 312 313 carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= SHL64(carry7,21); 314 carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= SHL64(carry9,21); 315 carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= SHL64(carry11,21); 316 carry13 = (s13 + (1<<20)) >> 21; s14 += carry13; s13 -= SHL64(carry13,21); 317 carry15 = (s15 + (1<<20)) >> 21; s16 += carry15; s15 -= SHL64(carry15,21); 318 319 s5 += s17 * 666643; 320 s6 += s17 * 470296; 321 s7 += s17 * 654183; 322 s8 -= s17 * 997805; 323 s9 += s17 * 136657; 324 s10 -= s17 * 683901; 325 s17 = 0; 326 327 s4 += s16 * 666643; 328 s5 += s16 * 470296; 329 s6 += s16 * 654183; 330 s7 -= s16 * 997805; 331 s8 += s16 * 136657; 332 s9 -= s16 * 683901; 333 s16 = 0; 334 335 s3 += s15 * 666643; 336 s4 += s15 * 470296; 337 s5 += s15 * 654183; 338 s6 -= s15 * 997805; 339 s7 += s15 * 136657; 340 s8 -= s15 * 683901; 341 s15 = 0; 342 343 s2 += s14 * 666643; 344 s3 += s14 * 470296; 345 s4 += s14 * 654183; 346 s5 -= s14 * 997805; 347 s6 += s14 * 136657; 348 s7 -= s14 * 683901; 349 s14 = 0; 350 351 s1 += s13 * 666643; 352 s2 += s13 * 470296; 353 s3 += s13 * 654183; 354 s4 -= s13 * 997805; 355 s5 += s13 * 136657; 356 s6 -= s13 * 683901; 357 s13 = 0; 358 359 s0 += s12 * 666643; 360 s1 += s12 * 470296; 361 s2 += s12 * 654183; 362 s3 -= s12 * 997805; 363 s4 += s12 * 136657; 364 s5 -= s12 * 683901; 365 s12 = 0; 366 367 carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= SHL64(carry0,21); 368 carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= SHL64(carry2,21); 369 carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= SHL64(carry4,21); 370 carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= SHL64(carry6,21); 371 carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= SHL64(carry8,21); 372 carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= SHL64(carry10,21); 373 374 carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= SHL64(carry1,21); 375 carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= SHL64(carry3,21); 376 carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= SHL64(carry5,21); 377 carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= SHL64(carry7,21); 378 carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= SHL64(carry9,21); 379 carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= SHL64(carry11,21); 380 381 s0 += s12 * 666643; 382 s1 += s12 * 470296; 383 s2 += s12 * 654183; 384 s3 -= s12 * 997805; 385 s4 += s12 * 136657; 386 s5 -= s12 * 683901; 387 s12 = 0; 388 389 carry0 = s0 >> 21; s1 += carry0; s0 -= SHL64(carry0,21); 390 carry1 = s1 >> 21; s2 += carry1; s1 -= SHL64(carry1,21); 391 carry2 = s2 >> 21; s3 += carry2; s2 -= SHL64(carry2,21); 392 carry3 = s3 >> 21; s4 += carry3; s3 -= SHL64(carry3,21); 393 carry4 = s4 >> 21; s5 += carry4; s4 -= SHL64(carry4,21); 394 carry5 = s5 >> 21; s6 += carry5; s5 -= SHL64(carry5,21); 395 carry6 = s6 >> 21; s7 += carry6; s6 -= SHL64(carry6,21); 396 carry7 = s7 >> 21; s8 += carry7; s7 -= SHL64(carry7,21); 397 carry8 = s8 >> 21; s9 += carry8; s8 -= SHL64(carry8,21); 398 carry9 = s9 >> 21; s10 += carry9; s9 -= SHL64(carry9,21); 399 carry10 = s10 >> 21; s11 += carry10; s10 -= SHL64(carry10,21); 400 carry11 = s11 >> 21; s12 += carry11; s11 -= SHL64(carry11,21); 401 402 s0 += s12 * 666643; 403 s1 += s12 * 470296; 404 s2 += s12 * 654183; 405 s3 -= s12 * 997805; 406 s4 += s12 * 136657; 407 s5 -= s12 * 683901; 408 s12 = 0; 409 410 carry0 = s0 >> 21; s1 += carry0; s0 -= SHL64(carry0,21); 411 carry1 = s1 >> 21; s2 += carry1; s1 -= SHL64(carry1,21); 412 carry2 = s2 >> 21; s3 += carry2; s2 -= SHL64(carry2,21); 413 carry3 = s3 >> 21; s4 += carry3; s3 -= SHL64(carry3,21); 414 carry4 = s4 >> 21; s5 += carry4; s4 -= SHL64(carry4,21); 415 carry5 = s5 >> 21; s6 += carry5; s5 -= SHL64(carry5,21); 416 carry6 = s6 >> 21; s7 += carry6; s6 -= SHL64(carry6,21); 417 carry7 = s7 >> 21; s8 += carry7; s7 -= SHL64(carry7,21); 418 carry8 = s8 >> 21; s9 += carry8; s8 -= SHL64(carry8,21); 419 carry9 = s9 >> 21; s10 += carry9; s9 -= SHL64(carry9,21); 420 carry10 = s10 >> 21; s11 += carry10; s10 -= SHL64(carry10,21); 421 422 ubyte[32] s; 423 s[0] = cast(ubyte) (s0 >> 0); 424 s[1] = cast(ubyte) (s0 >> 8); 425 s[2] = cast(ubyte) ((s0 >> 16) | SHL64(s1,5)); 426 s[3] = cast(ubyte) (s1 >> 3); 427 s[4] = cast(ubyte) (s1 >> 11); 428 s[5] = cast(ubyte) ((s1 >> 19) | SHL64(s2,2)); 429 s[6] = cast(ubyte) (s2 >> 6); 430 s[7] = cast(ubyte) ((s2 >> 14) | SHL64(s3,7)); 431 s[8] = cast(ubyte) (s3 >> 1); 432 s[9] = cast(ubyte) (s3 >> 9); 433 s[10] = cast(ubyte) ((s3 >> 17) | SHL64(s4,4)); 434 s[11] = cast(ubyte) (s4 >> 4); 435 s[12] = cast(ubyte) (s4 >> 12); 436 s[13] = cast(ubyte) ((s4 >> 20) | SHL64(s5,1)); 437 s[14] = cast(ubyte) (s5 >> 7); 438 s[15] = cast(ubyte) ((s5 >> 15) | SHL64(s6,6)); 439 s[16] = cast(ubyte) (s6 >> 2); 440 s[17] = cast(ubyte) (s6 >> 10); 441 s[18] = cast(ubyte) ((s6 >> 18) | SHL64(s7,3)); 442 s[19] = cast(ubyte) (s7 >> 5); 443 s[20] = cast(ubyte) (s7 >> 13); 444 s[21] = cast(ubyte) (s8 >> 0); 445 s[22] = cast(ubyte) (s8 >> 8); 446 s[23] = cast(ubyte) ((s8 >> 16) | SHL64(s9,5)); 447 s[24] = cast(ubyte) (s9 >> 3); 448 s[25] = cast(ubyte) (s9 >> 11); 449 s[26] = cast(ubyte) ((s9 >> 19) | SHL64(s10,2)); 450 s[27] = cast(ubyte) (s10 >> 6); 451 s[28] = cast(ubyte) ((s10 >> 14) | SHL64(s11,7)); 452 s[29] = cast(ubyte) (s11 >> 1); 453 s[30] = cast(ubyte) (s11 >> 9); 454 s[31] = cast(ubyte) (s11 >> 17); 455 456 return s; 457 } 458 459 460 /// Calculates (a*b + c) mod l 461 /// Input: 462 /// a[0]+256*a[1]+...+256^31*a[31] = a 463 /// b[0]+256*b[1]+...+256^31*b[31] = b 464 /// c[0]+256*c[1]+...+256^31*c[31] = c 465 /// 466 /// Returns: 467 /// (a*b + c) mod l 468 /// s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l 469 /// where l = 2^252 + 27742317777372353535851937790883648493. 470 ubyte[32] sc_muladd(in ubyte[] a, in ubyte[] b, in ubyte[] c) pure 471 in { 472 assert(a.length == 32); 473 assert(b.length == 32); 474 assert(c.length == 32); 475 } body { 476 // assign 21-bit slices to a*, b*, c* 477 long a0 = 0x001FFFFF & load_3(a[0..3]); 478 long a1 = 0x001FFFFF & (load_4(a[2..6]) >> 5); 479 long a2 = 0x001FFFFF & (load_3(a[5..8]) >> 2); 480 long a3 = 0x001FFFFF & (load_4(a[7..11]) >> 7); 481 long a4 = 0x001FFFFF & (load_4(a[10..14]) >> 4); 482 long a5 = 0x001FFFFF & (load_3(a[13..16]) >> 1); 483 long a6 = 0x001FFFFF & (load_4(a[15..19]) >> 6); 484 long a7 = 0x001FFFFF & (load_3(a[18..21]) >> 3); 485 long a8 = 0x001FFFFF & load_3(a[21..24]); 486 long a9 = 0x001FFFFF & (load_4(a[23..27]) >> 5); 487 long a10 = 0x001FFFFF & (load_3(a[26..29]) >> 2); 488 long a11 = (load_4(a[28..32]) >> 7); 489 490 long b0 = 0x001FFFFF & load_3(b[0..3]); 491 long b1 = 0x001FFFFF & (load_4(b[2..6]) >> 5); 492 long b2 = 0x001FFFFF & (load_3(b[5..8]) >> 2); 493 long b3 = 0x001FFFFF & (load_4(b[7..11]) >> 7); 494 long b4 = 0x001FFFFF & (load_4(b[10..14]) >> 4); 495 long b5 = 0x001FFFFF & (load_3(b[13..16]) >> 1); 496 long b6 = 0x001FFFFF & (load_4(b[15..19]) >> 6); 497 long b7 = 0x001FFFFF & (load_3(b[18..21]) >> 3); 498 long b8 = 0x001FFFFF & load_3(b[21..24]); 499 long b9 = 0x001FFFFF & (load_4(b[23..27]) >> 5); 500 long b10 = 0x001FFFFF & (load_3(b[26..29]) >> 2); 501 long b11 = (load_4(b[28..32]) >> 7); 502 503 long c0 = 0x001FFFFF & load_3(c[0..3]); 504 long c1 = 0x001FFFFF & (load_4(c[2..6]) >> 5); 505 long c2 = 0x001FFFFF & (load_3(c[5..8]) >> 2); 506 long c3 = 0x001FFFFF & (load_4(c[7..11]) >> 7); 507 long c4 = 0x001FFFFF & (load_4(c[10..14]) >> 4); 508 long c5 = 0x001FFFFF & (load_3(c[13..16]) >> 1); 509 long c6 = 0x001FFFFF & (load_4(c[15..19]) >> 6); 510 long c7 = 0x001FFFFF & (load_3(c[18..21]) >> 3); 511 long c8 = 0x001FFFFF & load_3(c[21..24]); 512 long c9 = 0x001FFFFF & (load_4(c[23..27]) >> 5); 513 long c10 = 0x001FFFFF & (load_3(c[26..29]) >> 2); 514 long c11 = (load_4(c[28..32]) >> 7); 515 516 long s0; 517 long s1; 518 long s2; 519 long s3; 520 long s4; 521 long s5; 522 long s6; 523 long s7; 524 long s8; 525 long s9; 526 long s10; 527 long s11; 528 long s12; 529 long s13; 530 long s14; 531 long s15; 532 long s16; 533 long s17; 534 long s18; 535 long s19; 536 long s20; 537 long s21; 538 long s22; 539 long s23; 540 long carry0; 541 long carry1; 542 long carry2; 543 long carry3; 544 long carry4; 545 long carry5; 546 long carry6; 547 long carry7; 548 long carry8; 549 long carry9; 550 long carry10; 551 long carry11; 552 long carry12; 553 long carry13; 554 long carry14; 555 long carry15; 556 long carry16; 557 long carry17; 558 long carry18; 559 long carry19; 560 long carry20; 561 long carry21; 562 long carry22; 563 564 s0 = c0 + a0*b0; 565 s1 = c1 + a0*b1 + a1*b0; 566 s2 = c2 + a0*b2 + a1*b1 + a2*b0; 567 s3 = c3 + a0*b3 + a1*b2 + a2*b1 + a3*b0; 568 s4 = c4 + a0*b4 + a1*b3 + a2*b2 + a3*b1 + a4*b0; 569 s5 = c5 + a0*b5 + a1*b4 + a2*b3 + a3*b2 + a4*b1 + a5*b0; 570 s6 = c6 + a0*b6 + a1*b5 + a2*b4 + a3*b3 + a4*b2 + a5*b1 + a6*b0; 571 s7 = c7 + a0*b7 + a1*b6 + a2*b5 + a3*b4 + a4*b3 + a5*b2 + a6*b1 + a7*b0; 572 s8 = c8 + a0*b8 + a1*b7 + a2*b6 + a3*b5 + a4*b4 + a5*b3 + a6*b2 + a7*b1 + a8*b0; 573 s9 = c9 + a0*b9 + a1*b8 + a2*b7 + a3*b6 + a4*b5 + a5*b4 + a6*b3 + a7*b2 + a8*b1 + a9*b0; 574 s10 = c10 + a0*b10 + a1*b9 + a2*b8 + a3*b7 + a4*b6 + a5*b5 + a6*b4 + a7*b3 + a8*b2 + a9*b1 + a10*b0; 575 s11 = c11 + a0*b11 + a1*b10 + a2*b9 + a3*b8 + a4*b7 + a5*b6 + a6*b5 + a7*b4 + a8*b3 + a9*b2 + a10*b1 + a11*b0; 576 s12 = a1*b11 + a2*b10 + a3*b9 + a4*b8 + a5*b7 + a6*b6 + a7*b5 + a8*b4 + a9*b3 + a10*b2 + a11*b1; 577 s13 = a2*b11 + a3*b10 + a4*b9 + a5*b8 + a6*b7 + a7*b6 + a8*b5 + a9*b4 + a10*b3 + a11*b2; 578 s14 = a3*b11 + a4*b10 + a5*b9 + a6*b8 + a7*b7 + a8*b6 + a9*b5 + a10*b4 + a11*b3; 579 s15 = a4*b11 + a5*b10 + a6*b9 + a7*b8 + a8*b7 + a9*b6 + a10*b5 + a11*b4; 580 s16 = a5*b11 + a6*b10 + a7*b9 + a8*b8 + a9*b7 + a10*b6 + a11*b5; 581 s17 = a6*b11 + a7*b10 + a8*b9 + a9*b8 + a10*b7 + a11*b6; 582 s18 = a7*b11 + a8*b10 + a9*b9 + a10*b8 + a11*b7; 583 s19 = a8*b11 + a9*b10 + a10*b9 + a11*b8; 584 s20 = a9*b11 + a10*b10 + a11*b9; 585 s21 = a10*b11 + a11*b10; 586 s22 = a11*b11; 587 s23 = 0; 588 589 590 carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= SHL64(carry0,21); 591 carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= SHL64(carry2,21); 592 carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= SHL64(carry4,21); 593 carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= SHL64(carry6,21); 594 carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= SHL64(carry8,21); 595 carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= SHL64(carry10,21); 596 carry12 = (s12 + (1<<20)) >> 21; s13 += carry12; s12 -= SHL64(carry12,21); 597 carry14 = (s14 + (1<<20)) >> 21; s15 += carry14; s14 -= SHL64(carry14,21); 598 carry16 = (s16 + (1<<20)) >> 21; s17 += carry16; s16 -= SHL64(carry16,21); 599 carry18 = (s18 + (1<<20)) >> 21; s19 += carry18; s18 -= SHL64(carry18,21); 600 carry20 = (s20 + (1<<20)) >> 21; s21 += carry20; s20 -= SHL64(carry20,21); 601 carry22 = (s22 + (1<<20)) >> 21; s23 += carry22; s22 -= SHL64(carry22,21); 602 603 carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= SHL64(carry1,21); 604 carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= SHL64(carry3,21); 605 carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= SHL64(carry5,21); 606 carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= SHL64(carry7,21); 607 carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= SHL64(carry9,21); 608 carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= SHL64(carry11,21); 609 carry13 = (s13 + (1<<20)) >> 21; s14 += carry13; s13 -= SHL64(carry13,21); 610 carry15 = (s15 + (1<<20)) >> 21; s16 += carry15; s15 -= SHL64(carry15,21); 611 carry17 = (s17 + (1<<20)) >> 21; s18 += carry17; s17 -= SHL64(carry17,21); 612 carry19 = (s19 + (1<<20)) >> 21; s20 += carry19; s19 -= SHL64(carry19,21); 613 carry21 = (s21 + (1<<20)) >> 21; s22 += carry21; s21 -= SHL64(carry21,21); 614 615 s11 += s23 * 666643; 616 s12 += s23 * 470296; 617 s13 += s23 * 654183; 618 s14 -= s23 * 997805; 619 s15 += s23 * 136657; 620 s16 -= s23 * 683901; 621 s23 = 0; 622 623 s10 += s22 * 666643; 624 s11 += s22 * 470296; 625 s12 += s22 * 654183; 626 s13 -= s22 * 997805; 627 s14 += s22 * 136657; 628 s15 -= s22 * 683901; 629 s22 = 0; 630 631 s9 += s21 * 666643; 632 s10 += s21 * 470296; 633 s11 += s21 * 654183; 634 s12 -= s21 * 997805; 635 s13 += s21 * 136657; 636 s14 -= s21 * 683901; 637 s21 = 0; 638 639 s8 += s20 * 666643; 640 s9 += s20 * 470296; 641 s10 += s20 * 654183; 642 s11 -= s20 * 997805; 643 s12 += s20 * 136657; 644 s13 -= s20 * 683901; 645 s20 = 0; 646 647 s7 += s19 * 666643; 648 s8 += s19 * 470296; 649 s9 += s19 * 654183; 650 s10 -= s19 * 997805; 651 s11 += s19 * 136657; 652 s12 -= s19 * 683901; 653 s19 = 0; 654 655 s6 += s18 * 666643; 656 s7 += s18 * 470296; 657 s8 += s18 * 654183; 658 s9 -= s18 * 997805; 659 s10 += s18 * 136657; 660 s11 -= s18 * 683901; 661 s18 = 0; 662 663 carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= SHL64(carry6,21); 664 carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= SHL64(carry8,21); 665 carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= SHL64(carry10,21); 666 carry12 = (s12 + (1<<20)) >> 21; s13 += carry12; s12 -= SHL64(carry12,21); 667 carry14 = (s14 + (1<<20)) >> 21; s15 += carry14; s14 -= SHL64(carry14,21); 668 carry16 = (s16 + (1<<20)) >> 21; s17 += carry16; s16 -= SHL64(carry16,21); 669 670 carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= SHL64(carry7,21); 671 carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= SHL64(carry9,21); 672 carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= SHL64(carry11,21); 673 carry13 = (s13 + (1<<20)) >> 21; s14 += carry13; s13 -= SHL64(carry13,21); 674 carry15 = (s15 + (1<<20)) >> 21; s16 += carry15; s15 -= SHL64(carry15,21); 675 676 s5 += s17 * 666643; 677 s6 += s17 * 470296; 678 s7 += s17 * 654183; 679 s8 -= s17 * 997805; 680 s9 += s17 * 136657; 681 s10 -= s17 * 683901; 682 s17 = 0; 683 684 s4 += s16 * 666643; 685 s5 += s16 * 470296; 686 s6 += s16 * 654183; 687 s7 -= s16 * 997805; 688 s8 += s16 * 136657; 689 s9 -= s16 * 683901; 690 s16 = 0; 691 692 s3 += s15 * 666643; 693 s4 += s15 * 470296; 694 s5 += s15 * 654183; 695 s6 -= s15 * 997805; 696 s7 += s15 * 136657; 697 s8 -= s15 * 683901; 698 s15 = 0; 699 700 s2 += s14 * 666643; 701 s3 += s14 * 470296; 702 s4 += s14 * 654183; 703 s5 -= s14 * 997805; 704 s6 += s14 * 136657; 705 s7 -= s14 * 683901; 706 s14 = 0; 707 708 s1 += s13 * 666643; 709 s2 += s13 * 470296; 710 s3 += s13 * 654183; 711 s4 -= s13 * 997805; 712 s5 += s13 * 136657; 713 s6 -= s13 * 683901; 714 s13 = 0; 715 716 s0 += s12 * 666643; 717 s1 += s12 * 470296; 718 s2 += s12 * 654183; 719 s3 -= s12 * 997805; 720 s4 += s12 * 136657; 721 s5 -= s12 * 683901; 722 s12 = 0; 723 724 carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= SHL64(carry0,21); 725 carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= SHL64(carry2,21); 726 carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= SHL64(carry4,21); 727 carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= SHL64(carry6,21); 728 carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= SHL64(carry8,21); 729 carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= SHL64(carry10,21); 730 731 carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= SHL64(carry1,21); 732 carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= SHL64(carry3,21); 733 carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= SHL64(carry5,21); 734 carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= SHL64(carry7,21); 735 carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= SHL64(carry9,21); 736 carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= SHL64(carry11,21); 737 738 s0 += s12 * 666643; 739 s1 += s12 * 470296; 740 s2 += s12 * 654183; 741 s3 -= s12 * 997805; 742 s4 += s12 * 136657; 743 s5 -= s12 * 683901; 744 s12 = 0; 745 746 carry0 = s0 >> 21; s1 += carry0; s0 -= SHL64(carry0,21); 747 carry1 = s1 >> 21; s2 += carry1; s1 -= SHL64(carry1,21); 748 carry2 = s2 >> 21; s3 += carry2; s2 -= SHL64(carry2,21); 749 carry3 = s3 >> 21; s4 += carry3; s3 -= SHL64(carry3,21); 750 carry4 = s4 >> 21; s5 += carry4; s4 -= SHL64(carry4,21); 751 carry5 = s5 >> 21; s6 += carry5; s5 -= SHL64(carry5,21); 752 carry6 = s6 >> 21; s7 += carry6; s6 -= SHL64(carry6,21); 753 carry7 = s7 >> 21; s8 += carry7; s7 -= SHL64(carry7,21); 754 carry8 = s8 >> 21; s9 += carry8; s8 -= SHL64(carry8,21); 755 carry9 = s9 >> 21; s10 += carry9; s9 -= SHL64(carry9,21); 756 carry10 = s10 >> 21; s11 += carry10; s10 -= SHL64(carry10,21); 757 carry11 = s11 >> 21; s12 += carry11; s11 -= SHL64(carry11,21); 758 759 s0 += s12 * 666643; 760 s1 += s12 * 470296; 761 s2 += s12 * 654183; 762 s3 -= s12 * 997805; 763 s4 += s12 * 136657; 764 s5 -= s12 * 683901; 765 s12 = 0; 766 767 carry0 = s0 >> 21; s1 += carry0; s0 -= SHL64(carry0,21); 768 carry1 = s1 >> 21; s2 += carry1; s1 -= SHL64(carry1,21); 769 carry2 = s2 >> 21; s3 += carry2; s2 -= SHL64(carry2,21); 770 carry3 = s3 >> 21; s4 += carry3; s3 -= SHL64(carry3,21); 771 carry4 = s4 >> 21; s5 += carry4; s4 -= SHL64(carry4,21); 772 carry5 = s5 >> 21; s6 += carry5; s5 -= SHL64(carry5,21); 773 carry6 = s6 >> 21; s7 += carry6; s6 -= SHL64(carry6,21); 774 carry7 = s7 >> 21; s8 += carry7; s7 -= SHL64(carry7,21); 775 carry8 = s8 >> 21; s9 += carry8; s8 -= SHL64(carry8,21); 776 carry9 = s9 >> 21; s10 += carry9; s9 -= SHL64(carry9,21); 777 carry10 = s10 >> 21; s11 += carry10; s10 -= SHL64(carry10,21); 778 779 ubyte[32] s; 780 s[0] = cast(ubyte) (s0 >> 0); 781 s[1] = cast(ubyte) (s0 >> 8); 782 s[2] = cast(ubyte) ((s0 >> 16) | SHL64(s1,5)); 783 s[3] = cast(ubyte) (s1 >> 3); 784 s[4] = cast(ubyte) (s1 >> 11); 785 s[5] = cast(ubyte) ((s1 >> 19) | SHL64(s2,2)); 786 s[6] = cast(ubyte) (s2 >> 6); 787 s[7] = cast(ubyte) ((s2 >> 14) | SHL64(s3,7)); 788 s[8] = cast(ubyte) (s3 >> 1); 789 s[9] = cast(ubyte) (s3 >> 9); 790 s[10] = cast(ubyte) ((s3 >> 17) | SHL64(s4,4)); 791 s[11] = cast(ubyte) (s4 >> 4); 792 s[12] = cast(ubyte) (s4 >> 12); 793 s[13] = cast(ubyte) ((s4 >> 20) | SHL64(s5,1)); 794 s[14] = cast(ubyte) (s5 >> 7); 795 s[15] = cast(ubyte) ((s5 >> 15) | SHL64(s6,6)); 796 s[16] = cast(ubyte) (s6 >> 2); 797 s[17] = cast(ubyte) (s6 >> 10); 798 s[18] = cast(ubyte) ((s6 >> 18) | SHL64(s7,3)); 799 s[19] = cast(ubyte) (s7 >> 5); 800 s[20] = cast(ubyte) (s7 >> 13); 801 s[21] = cast(ubyte) (s8 >> 0); 802 s[22] = cast(ubyte) (s8 >> 8); 803 s[23] = cast(ubyte) ((s8 >> 16) | SHL64(s9,5)); 804 s[24] = cast(ubyte) (s9 >> 3); 805 s[25] = cast(ubyte) (s9 >> 11); 806 s[26] = cast(ubyte) ((s9 >> 19) | SHL64(s10,2)); 807 s[27] = cast(ubyte) (s10 >> 6); 808 s[28] = cast(ubyte) ((s10 >> 14) | SHL64(s11,7)); 809 s[29] = cast(ubyte) (s11 >> 1); 810 s[30] = cast(ubyte) (s11 >> 9); 811 s[31] = cast(ubyte) (s11 >> 17); 812 813 return s; 814 } 815 816 // test sc_muladd 817 unittest { 818 immutable auto expected = x"4b1aa2e4462a167d92e224e89293eaa7809accfcf60ad08497350a206ce2ec04"; 819 immutable ubyte[32] a = cast(const ubyte[]) x"9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60"; 820 immutable ubyte[32] b = cast(const ubyte[]) x"d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a"; 821 immutable ubyte[32] c = cast(const ubyte[]) x"3e9a9575a249d64080e109b8851daa7026df4135a7195ad2d36252c5a90d0f03"; 822 823 // calculate (a*a + a) mod q 824 825 assert(sc_muladd(a, b, c) == expected, "sc_muladd failed."); 826 assert(sc_muladd(b, a, c) == expected, "sc_muladd failed."); 827 } 828 829 private: 830 831 version(unittest) { 832 /// Extended tests for ed25519 from http://ed25519.cr.yp.to/python/sign.input. 833 834 import dcrypt.ecc.ed25519; 835 import std.algorithm; 836 837 unittest { 838 foreach(v; testVectors) { 839 immutable ubyte[32] sk = cast(const ubyte[]) v[0][0..32]; 840 immutable ubyte[32] pk = cast(const ubyte[]) v[1]; 841 immutable ubyte[] msg = cast(immutable ubyte[]) v[2]; 842 immutable ubyte[64] signature = cast(const ubyte[]) v[3][0..64]; 843 844 assert(secret_to_public(sk) == pk, "Public key generation failed."); 845 assert(sign(msg, sk) == signature, "Ed25519 signature failed."); 846 assert(verify(signature, msg, pk), "Ed25519 signature verification failed."); 847 } 848 } 849 850 // test vectors from http://ed25519.cr.yp.to/python/sign.input 851 // Converted with this python script: 852 // 853 //#!/bin/python 854 //# use with http://ed25519.cr.yp.to/python/sign.input as input 855 //import fileinput 856 // 857 // print("immutable string[][] testVectors = ["); 858 //for line in fileinput.input(): 859 //fields = line.split(":") 860 // print("\t[x\""+fields[0]+"\", x\"" + fields[1] + "\", x\"" + fields[2] + "\", x\"" + fields[3] + "\"],") 861 // 862 // print("];"); 863 864 private immutable string[4][64] testVectors = [ 865 [x"9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a", x"d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a", x"", x"e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b"], 866 [x"4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c", x"3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c", x"72", x"92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c0072"], 867 [x"c5aa8df43f9f837bedb7442f31dcb7b166d38535076f094b85ce3a2e0b4458f7fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025", x"fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025", x"af82", x"6291d657deec24024827e69c3abe01a30ce548a284743a445e3680d7db5ac3ac18ff9b538d16f290ae67f760984dc6594a7c15e9716ed28dc027beceea1ec40aaf82"], 868 [x"0d4a05b07352a5436e180356da0ae6efa0345ff7fb1572575772e8005ed978e9e61a185bcef2613a6c7cb79763ce945d3b245d76114dd440bcf5f2dc1aa57057", x"e61a185bcef2613a6c7cb79763ce945d3b245d76114dd440bcf5f2dc1aa57057", x"cbc77b", x"d9868d52c2bebce5f3fa5a79891970f309cb6591e3e1702a70276fa97c24b3a8e58606c38c9758529da50ee31b8219cba45271c689afa60b0ea26c99db19b00ccbc77b"], 869 [x"6df9340c138cc188b5fe4464ebaa3f7fc206a2d55c3434707e74c9fc04e20ebbc0dac102c4533186e25dc43128472353eaabdb878b152aeb8e001f92d90233a7", x"c0dac102c4533186e25dc43128472353eaabdb878b152aeb8e001f92d90233a7", x"5f4c8989", x"124f6fc6b0d100842769e71bd530664d888df8507df6c56dedfdb509aeb93416e26b918d38aa06305df3095697c18b2aa832eaa52edc0ae49fbae5a85e150c075f4c8989"], 870 [x"b780381a65edf8b78f6945e8dbec7941ac049fd4c61040cf0c324357975a293ce253af0766804b869bb1595be9765b534886bbaab8305bf50dbc7f899bfb5f01", x"e253af0766804b869bb1595be9765b534886bbaab8305bf50dbc7f899bfb5f01", x"18b6bec097", x"b2fc46ad47af464478c199e1f8be169f1be6327c7f9a0a6689371ca94caf04064a01b22aff1520abd58951341603faed768cf78ce97ae7b038abfe456aa17c0918b6bec097"], 871 [x"78ae9effe6f245e924a7be63041146ebc670dbd3060cba67fbc6216febc44546fbcfbfa40505d7f2be444a33d185cc54e16d615260e1640b2b5087b83ee3643d", x"fbcfbfa40505d7f2be444a33d185cc54e16d615260e1640b2b5087b83ee3643d", x"89010d855972", x"6ed629fc1d9ce9e1468755ff636d5a3f40a5d9c91afd93b79d241830f7e5fa29854b8f20cc6eecbb248dbd8d16d14e99752194e4904d09c74d639518839d230089010d855972"], 872 [x"691865bfc82a1e4b574eecde4c7519093faf0cf867380234e3664645c61c5f7998a5e3a36e67aaba89888bf093de1ad963e774013b3902bfab356d8b90178a63", x"98a5e3a36e67aaba89888bf093de1ad963e774013b3902bfab356d8b90178a63", x"b4a8f381e70e7a", x"6e0af2fe55ae377a6b7a7278edfb419bd321e06d0df5e27037db8812e7e3529810fa5552f6c0020985ca17a0e02e036d7b222a24f99b77b75fdd16cb05568107b4a8f381e70e7a"], 873 [x"3b26516fb3dc88eb181b9ed73f0bcd52bcd6b4c788e4bcaf46057fd078bee073f81fb54a825fced95eb033afcd64314075abfb0abd20a970892503436f34b863", x"f81fb54a825fced95eb033afcd64314075abfb0abd20a970892503436f34b863", x"4284abc51bb67235", x"d6addec5afb0528ac17bb178d3e7f2887f9adbb1ad16e110545ef3bc57f9de2314a5c8388f723b8907be0f3ac90c6259bbe885ecc17645df3db7d488f805fa084284abc51bb67235"], 874 [x"edc6f5fbdd1cee4d101c063530a30490b221be68c036f5b07d0f953b745df192c1a49c66e617f9ef5ec66bc4c6564ca33de2a5fb5e1464062e6d6c6219155efd", x"c1a49c66e617f9ef5ec66bc4c6564ca33de2a5fb5e1464062e6d6c6219155efd", x"672bf8965d04bc5146", x"2c76a04af2391c147082e33faacdbe56642a1e134bd388620b852b901a6bc16ff6c9cc9404c41dea12ed281da067a1513866f9d964f8bdd24953856c50042901672bf8965d04bc5146"], 875 [x"4e7d21fb3b1897571a445833be0f9fd41cd62be3aa04040f8934e1fcbdcacd4531b2524b8348f7ab1dfafa675cc538e9a84e3fe5819e27c12ad8bbc1a36e4dff", x"31b2524b8348f7ab1dfafa675cc538e9a84e3fe5819e27c12ad8bbc1a36e4dff", x"33d7a786aded8c1bf691", x"28e4598c415ae9de01f03f9f3fab4e919e8bf537dd2b0cdf6e79b9e6559c9409d9151a4c40f083193937627c369488259e99da5a9f0a87497fa6696a5dd6ce0833d7a786aded8c1bf691"], 876 [x"a980f892db13c99a3e8971e965b2ff3d41eafd54093bc9f34d1fd22d84115bb644b57ee30cdb55829d0a5d4f046baef078f1e97a7f21b62d75f8e96ea139c35f", x"44b57ee30cdb55829d0a5d4f046baef078f1e97a7f21b62d75f8e96ea139c35f", x"3486f68848a65a0eb5507d", x"77d389e599630d934076329583cd4105a649a9292abc44cd28c40000c8e2f5ac7660a81c85b72af8452d7d25c070861dae91601c7803d656531650dd4e5c41003486f68848a65a0eb5507d"], 877 [x"5b5a619f8ce1c66d7ce26e5a2ae7b0c04febcd346d286c929e19d0d5973bfef96fe83693d011d111131c4f3fbaaa40a9d3d76b30012ff73bb0e39ec27ab18257", x"6fe83693d011d111131c4f3fbaaa40a9d3d76b30012ff73bb0e39ec27ab18257", x"5a8d9d0a22357e6655f9c785", x"0f9ad9793033a2fa06614b277d37381e6d94f65ac2a5a94558d09ed6ce922258c1a567952e863ac94297aec3c0d0c8ddf71084e504860bb6ba27449b55adc40e5a8d9d0a22357e6655f9c785"], 878 [x"940c89fe40a81dafbdb2416d14ae469119869744410c3303bfaa0241dac57800a2eb8c0501e30bae0cf842d2bde8dec7386f6b7fc3981b8c57c9792bb94cf2dd", x"a2eb8c0501e30bae0cf842d2bde8dec7386f6b7fc3981b8c57c9792bb94cf2dd", x"b87d3813e03f58cf19fd0b6395", x"d8bb64aad8c9955a115a793addd24f7f2b077648714f49c4694ec995b330d09d640df310f447fd7b6cb5c14f9fe9f490bcf8cfadbfd2169c8ac20d3b8af49a0cb87d3813e03f58cf19fd0b6395"], 879 [x"9acad959d216212d789a119252ebfe0c96512a23c73bd9f3b202292d6916a738cf3af898467a5b7a52d33d53bc037e2642a8da996903fc252217e9c033e2f291", x"cf3af898467a5b7a52d33d53bc037e2642a8da996903fc252217e9c033e2f291", x"55c7fa434f5ed8cdec2b7aeac173", x"6ee3fe81e23c60eb2312b2006b3b25e6838e02106623f844c44edb8dafd66ab0671087fd195df5b8f58a1d6e52af42908053d55c7321010092748795ef94cf0655c7fa434f5ed8cdec2b7aeac173"], 880 [x"d5aeee41eeb0e9d1bf8337f939587ebe296161e6bf5209f591ec939e1440c300fd2a565723163e29f53c9de3d5e8fbe36a7ab66e1439ec4eae9c0a604af291a5", x"fd2a565723163e29f53c9de3d5e8fbe36a7ab66e1439ec4eae9c0a604af291a5", x"0a688e79be24f866286d4646b5d81c", x"f68d04847e5b249737899c014d31c805c5007a62c0a10d50bb1538c5f35503951fbc1e08682f2cc0c92efe8f4985dec61dcbd54d4b94a22547d24451271c8b000a688e79be24f866286d4646b5d81c"], 881 [x"0a47d10452ae2febec518a1c7c362890c3fc1a49d34b03b6467d35c904a8362d34e5a8508c4743746962c066e4badea2201b8ab484de5c4f94476ccd2143955b", x"34e5a8508c4743746962c066e4badea2201b8ab484de5c4f94476ccd2143955b", x"c942fa7ac6b23ab7ff612fdc8e68ef39", x"2a3d27dc40d0a8127949a3b7f908b3688f63b7f14f651aacd715940bdbe27a0809aac142f47ab0e1e44fa490ba87ce5392f33a891539caf1ef4c367cae54500cc942fa7ac6b23ab7ff612fdc8e68ef39"], 882 [x"f8148f7506b775ef46fdc8e8c756516812d47d6cfbfa318c27c9a22641e56f170445e456dacc7d5b0bbed23c8200cdb74bdcb03e4c7b73f0a2b9b46eac5d4372", x"0445e456dacc7d5b0bbed23c8200cdb74bdcb03e4c7b73f0a2b9b46eac5d4372", x"7368724a5b0efb57d28d97622dbde725af", x"3653ccb21219202b8436fb41a32ba2618c4a133431e6e63463ceb3b6106c4d56e1d2ba165ba76eaad3dc39bffb130f1de3d8e6427db5b71938db4e272bc3e20b7368724a5b0efb57d28d97622dbde725af"], 883 [x"77f88691c4eff23ebb7364947092951a5ff3f10785b417e918823a552dab7c7574d29127f199d86a8676aec33b4ce3f225ccb191f52c191ccd1e8cca65213a6b", x"74d29127f199d86a8676aec33b4ce3f225ccb191f52c191ccd1e8cca65213a6b", x"bd8e05033f3a8bcdcbf4beceb70901c82e31", x"fbe929d743a03c17910575492f3092ee2a2bf14a60a3fcacec74a58c7334510fc262db582791322d6c8c41f1700adb80027ecabc14270b703444ae3ee7623e0abd8e05033f3a8bcdcbf4beceb70901c82e31"], 884 [x"ab6f7aee6a0837b334ba5eb1b2ad7fcecfab7e323cab187fe2e0a95d80eff1325b96dca497875bf9664c5e75facf3f9bc54bae913d66ca15ee85f1491ca24d2c", x"5b96dca497875bf9664c5e75facf3f9bc54bae913d66ca15ee85f1491ca24d2c", x"8171456f8b907189b1d779e26bc5afbb08c67a", x"73bca64e9dd0db88138eedfafcea8f5436cfb74bfb0e7733cf349baa0c49775c56d5934e1d38e36f39b7c5beb0a836510c45126f8ec4b6810519905b0ca07c098171456f8b907189b1d779e26bc5afbb08c67a"], 885 [x"8d135de7c8411bbdbd1b31e5dc678f2ac7109e792b60f38cd24936e8a898c32d1ca281938529896535a7714e3584085b86ef9fec723f42819fc8dd5d8c00817f", x"1ca281938529896535a7714e3584085b86ef9fec723f42819fc8dd5d8c00817f", x"8ba6a4c9a15a244a9c26bb2a59b1026f21348b49", x"a1adc2bc6a2d980662677e7fdff6424de7dba50f5795ca90fdf3e96e256f3285cac71d3360482e993d0294ba4ec7440c61affdf35fe83e6e04263937db93f1058ba6a4c9a15a244a9c26bb2a59b1026f21348b49"], 886 [x"0e765d720e705f9366c1ab8c3fa84c9a44370c06969f803296884b2846a652a47fae45dd0a05971026d410bc497af5be7d0827a82a145c203f625dfcb8b03ba8", x"7fae45dd0a05971026d410bc497af5be7d0827a82a145c203f625dfcb8b03ba8", x"1d566a6232bbaab3e6d8804bb518a498ed0f904986", x"bb61cf84de61862207c6a455258bc4db4e15eea0317ff88718b882a06b5cf6ec6fd20c5a269e5d5c805bafbcc579e2590af414c7c227273c102a10070cdfe80f1d566a6232bbaab3e6d8804bb518a498ed0f904986"], 887 [x"db36e326d676c2d19cc8fe0c14b709202ecfc761d27089eb6ea4b1bb021ecfa748359b850d23f0715d94bb8bb75e7e14322eaf14f06f28a805403fbda002fc85", x"48359b850d23f0715d94bb8bb75e7e14322eaf14f06f28a805403fbda002fc85", x"1b0afb0ac4ba9ab7b7172cddc9eb42bba1a64bce47d4", x"b6dcd09989dfbac54322a3ce87876e1d62134da998c79d24b50bd7a6a797d86a0e14dc9d7491d6c14a673c652cfbec9f962a38c945da3b2f0879d0b68a9213001b0afb0ac4ba9ab7b7172cddc9eb42bba1a64bce47d4"], 888 [x"c89955e0f7741d905df0730b3dc2b0ce1a13134e44fef3d40d60c020ef19df77fdb30673402faf1c8033714f3517e47cc0f91fe70cf3836d6c23636e3fd2287c", x"fdb30673402faf1c8033714f3517e47cc0f91fe70cf3836d6c23636e3fd2287c", x"507c94c8820d2a5793cbf3442b3d71936f35fe3afef316", x"7ef66e5e86f2360848e0014e94880ae2920ad8a3185a46b35d1e07dea8fa8ae4f6b843ba174d99fa7986654a0891c12a794455669375bf92af4cc2770b579e0c507c94c8820d2a5793cbf3442b3d71936f35fe3afef316"], 889 [x"4e62627fc221142478aee7f00781f817f662e3b75db29bb14ab47cf8e84104d6b1d39801892027d58a8c64335163195893bfc1b61dbeca3260497e1f30371107", x"b1d39801892027d58a8c64335163195893bfc1b61dbeca3260497e1f30371107", x"d3d615a8472d9962bb70c5b5466a3d983a4811046e2a0ef5", x"836afa764d9c48aa4770a4388b654e97b3c16f082967febca27f2fc47ddfd9244b03cfc729698acf5109704346b60b230f255430089ddc56912399d1122de70ad3d615a8472d9962bb70c5b5466a3d983a4811046e2a0ef5"], 890 [x"6b83d7da8908c3e7205b39864b56e5f3e17196a3fc9c2f5805aad0f5554c142dd0c846f97fe28585c0ee159015d64c56311c886eddcc185d296dbb165d2625d6", x"d0c846f97fe28585c0ee159015d64c56311c886eddcc185d296dbb165d2625d6", x"6ada80b6fa84f7034920789e8536b82d5e4678059aed27f71c", x"16e462a29a6dd498685a3718b3eed00cc1598601ee47820486032d6b9acc9bf89f57684e08d8c0f05589cda2882a05dc4c63f9d0431d6552710812433003bc086ada80b6fa84f7034920789e8536b82d5e4678059aed27f71c"], 891 [x"19a91fe23a4e9e33ecc474878f57c64cf154b394203487a7035e1ad9cd697b0d2bf32ba142ba4622d8f3e29ecd85eea07b9c47be9d64412c9b510b27dd218b23", x"2bf32ba142ba4622d8f3e29ecd85eea07b9c47be9d64412c9b510b27dd218b23", x"82cb53c4d5a013bae5070759ec06c3c6955ab7a4050958ec328c", x"881f5b8c5a030df0f75b6634b070dd27bd1ee3c08738ae349338b3ee6469bbf9760b13578a237d5182535ede121283027a90b5f865d63a6537dca07b44049a0f82cb53c4d5a013bae5070759ec06c3c6955ab7a4050958ec328c"], 892 [x"1d5b8cb6215c18141666baeefcf5d69dad5bea9a3493dddaa357a4397a13d4de94d23d977c33e49e5e4992c68f25ec99a27c41ce6b91f2bfa0cd8292fe962835", x"94d23d977c33e49e5e4992c68f25ec99a27c41ce6b91f2bfa0cd8292fe962835", x"a9a8cbb0ad585124e522abbfb40533bdd6f49347b55b18e8558cb0", x"3acd39bec8c3cd2b44299722b5850a0400c1443590fd4861d59aae7496acb3df73fc3fdf7969ae5f50ba47dddc435246e5fd376f6b891cd4c2caf5d614b6170ca9a8cbb0ad585124e522abbfb40533bdd6f49347b55b18e8558cb0"], 893 [x"6a91b3227c472299089bdce9356e726a40efd840f11002708b7ee55b64105ac29d084aa8b97a6b9bafa496dbc6f76f3306a116c9d917e681520a0f914369427e", x"9d084aa8b97a6b9bafa496dbc6f76f3306a116c9d917e681520a0f914369427e", x"5cb6f9aa59b80eca14f6a68fb40cf07b794e75171fba96262c1c6adc", x"f5875423781b66216cb5e8998de5d9ffc29d1d67107054ace3374503a9c3ef811577f269de81296744bd706f1ac478caf09b54cdf871b3f802bd57f9a6cb91015cb6f9aa59b80eca14f6a68fb40cf07b794e75171fba96262c1c6adc"], 894 [x"93eaa854d791f05372ce72b94fc6503b2ff8ae6819e6a21afe825e27ada9e4fb16cee8a3f2631834c88b670897ff0b08ce90cc147b4593b3f1f403727f7e7ad5", x"16cee8a3f2631834c88b670897ff0b08ce90cc147b4593b3f1f403727f7e7ad5", x"32fe27994124202153b5c70d3813fdee9c2aa6e7dc743d4d535f1840a5", x"d834197c1a3080614e0a5fa0aaaa808824f21c38d692e6ffbd200f7dfb3c8f44402a7382180b98ad0afc8eec1a02acecf3cb7fde627b9f18111f260ab1db9a0732fe27994124202153b5c70d3813fdee9c2aa6e7dc743d4d535f1840a5"], 895 [x"941cac69fb7b1815c57bb987c4d6c2ad2c35d5f9a3182a79d4ba13eab253a8ad23be323c562dfd71ce65f5bba56a74a3a6dfc36b573d2f94f635c7f9b4fd5a5b", x"23be323c562dfd71ce65f5bba56a74a3a6dfc36b573d2f94f635c7f9b4fd5a5b", x"bb3172795710fe00054d3b5dfef8a11623582da68bf8e46d72d27cece2aa", x"0f8fad1e6bde771b4f5420eac75c378bae6db5ac6650cd2bc210c1823b432b48e016b10595458ffab92f7a8989b293ceb8dfed6c243a2038fc06652aaaf16f02bb3172795710fe00054d3b5dfef8a11623582da68bf8e46d72d27cece2aa"], 896 [x"1acdbb793b0384934627470d795c3d1dd4d79cea59ef983f295b9b59179cbb283f60c7541afa76c019cf5aa82dcdb088ed9e4ed9780514aefb379dabc844f31a", x"3f60c7541afa76c019cf5aa82dcdb088ed9e4ed9780514aefb379dabc844f31a", x"7cf34f75c3dac9a804d0fcd09eba9b29c9484e8a018fa9e073042df88e3c56", x"be71ef4806cb041d885effd9e6b0fbb73d65d7cdec47a89c8a994892f4e55a568c4cc78d61f901e80dbb628b86a23ccd594e712b57fa94c2d67ec266348785077cf34f75c3dac9a804d0fcd09eba9b29c9484e8a018fa9e073042df88e3c56"], 897 [x"8ed7a797b9cea8a8370d419136bcdf683b759d2e3c6947f17e13e2485aa9d420b49f3a78b1c6a7fca8f3466f33bc0e929f01fba04306c2a7465f46c3759316d9", x"b49f3a78b1c6a7fca8f3466f33bc0e929f01fba04306c2a7465f46c3759316d9", x"a750c232933dc14b1184d86d8b4ce72e16d69744ba69818b6ac33b1d823bb2c3", x"04266c033b91c1322ceb3446c901ffcf3cc40c4034e887c9597ca1893ba7330becbbd8b48142ef35c012c6ba51a66df9308cb6268ad6b1e4b03e70102495790ba750c232933dc14b1184d86d8b4ce72e16d69744ba69818b6ac33b1d823bb2c3"], 898 [x"f2ab396fe8906e3e5633e99cabcd5b09df0859b516230b1e0450b580b65f616c8ea074245159a116aa7122a25ec16b891d625a68f33660423908f6bdc44f8c1b", x"8ea074245159a116aa7122a25ec16b891d625a68f33660423908f6bdc44f8c1b", x"5a44e34b746c5fd1898d552ab354d28fb4713856d7697dd63eb9bd6b99c280e187", x"a06a23d982d81ab883aae230adbc368a6a9977f003cebb00d4c2e4018490191a84d3a282fdbfb2fc88046e62de43e15fb575336b3c8b77d19ce6a009ce51f50c5a44e34b746c5fd1898d552ab354d28fb4713856d7697dd63eb9bd6b99c280e187"], 899 [x"550a41c013f79bab8f06e43ad1836d51312736a9713806fafe6645219eaa1f9daf6b7145474dc9954b9af93a9cdb34449d5b7c651c824d24e230b90033ce59c0", x"af6b7145474dc9954b9af93a9cdb34449d5b7c651c824d24e230b90033ce59c0", x"8bc4185e50e57d5f87f47515fe2b1837d585f0aae9e1ca383b3ec908884bb900ff27", x"16dc1e2b9fa909eefdc277ba16ebe207b8da5e91143cde78c5047a89f681c33c4e4e3428d5c928095903a811ec002d52a39ed7f8b3fe1927200c6dd0b9ab3e048bc4185e50e57d5f87f47515fe2b1837d585f0aae9e1ca383b3ec908884bb900ff27"], 900 [x"19ac3e272438c72ddf7b881964867cb3b31ff4c793bb7ea154613c1db068cb7ef85b80e050a1b9620db138bfc9e100327e25c257c59217b601f1f6ac9a413d3f", x"f85b80e050a1b9620db138bfc9e100327e25c257c59217b601f1f6ac9a413d3f", x"95872d5f789f95484e30cbb0e114028953b16f5c6a8d9f65c003a83543beaa46b38645", x"ea855d781cbea4682e350173cb89e8619ccfddb97cdce16f9a2f6f6892f46dbe68e04b12b8d88689a7a31670cdff409af98a93b49a34537b6aa009d2eb8b470195872d5f789f95484e30cbb0e114028953b16f5c6a8d9f65c003a83543beaa46b38645"], 901 [x"ca267de96c93c238fafb1279812059ab93ac03059657fd994f8fa5a09239c821017370c879090a81c7f272c2fc80e3aac2bc603fcb379afc98691160ab745b26", x"017370c879090a81c7f272c2fc80e3aac2bc603fcb379afc98691160ab745b26", x"e05f71e4e49a72ec550c44a3b85aca8f20ff26c3ee94a80f1b431c7d154ec9603ee02531", x"ac957f82335aa7141e96b59d63e3ccee95c3a2c47d026540c2af42dc9533d5fd81827d1679ad187aeaf37834915e75b147a9286806c8017516ba43dd051a5e0ce05f71e4e49a72ec550c44a3b85aca8f20ff26c3ee94a80f1b431c7d154ec9603ee02531"], 902 [x"3dff5e899475e7e91dd261322fab09980c52970de1da6e2e201660cc4fce7032f30162bac98447c4042fac05da448034629be2c6a58d30dfd578ba9fb5e3930b", x"f30162bac98447c4042fac05da448034629be2c6a58d30dfd578ba9fb5e3930b", x"938f0e77621bf3ea52c7c4911c5157c2d8a2a858093ef16aa9b107e69d98037ba139a3c382", x"5efe7a92ff9623089b3e3b78f352115366e26ba3fb1a416209bc029e9cadccd9f4affa333555a8f3a35a9d0f7c34b292cae77ec96fa3adfcaadee2d9ced8f805938f0e77621bf3ea52c7c4911c5157c2d8a2a858093ef16aa9b107e69d98037ba139a3c382"], 903 [x"9a6b847864e70cfe8ba6ab22fa0ca308c0cc8bec7141fbcaa3b81f5d1e1cfcfc34ad0fbdb2566507a81c2b1f8aa8f53dccaa64cc87ada91b903e900d07eee930", x"34ad0fbdb2566507a81c2b1f8aa8f53dccaa64cc87ada91b903e900d07eee930", x"838367471183c71f7e717724f89d401c3ad9863fd9cc7aa3cf33d3c529860cb581f3093d87da", x"2ab255169c489c54c732232e37c87349d486b1eba20509dbabe7fed329ef08fd75ba1cd145e67b2ea26cb5cc51cab343eeb085fe1fd7b0ec4c6afcd9b979f905838367471183c71f7e717724f89d401c3ad9863fd9cc7aa3cf33d3c529860cb581f3093d87da"], 904 [x"575be07afca5d063c238cd9b8028772cc49cda34471432a2e166e096e2219efc94e5eb4d5024f49d7ebf79817c8de11497dc2b55622a51ae123ffc749dbb16e0", x"94e5eb4d5024f49d7ebf79817c8de11497dc2b55622a51ae123ffc749dbb16e0", x"33e5918b66d33d55fe717ca34383eae78f0af82889caf6696e1ac9d95d1ffb32cba755f9e3503e", x"58271d44236f3b98c58fd7ae0d2f49ef2b6e3affdb225aa3ba555f0e11cc53c23ad19baf24346590d05d7d5390582082cf94d39cad6530ab93d13efb3927950633e5918b66d33d55fe717ca34383eae78f0af82889caf6696e1ac9d95d1ffb32cba755f9e3503e"], 905 [x"15ffb45514d43444d61fcb105e30e135fd268523dda20b82758b1794231104411772c5abc2d23fd2f9d1c3257be7bc3c1cd79cee40844b749b3a7743d2f964b8", x"1772c5abc2d23fd2f9d1c3257be7bc3c1cd79cee40844b749b3a7743d2f964b8", x"da9c5559d0ea51d255b6bd9d7638b876472f942b330fc0e2b30aea68d77368fce4948272991d257e", x"6828cd7624e793b8a4ceb96d3c2a975bf773e5ff6645f353614058621e58835289e7f31f42dfe6af6d736f2644511e320c0fa698582a79778d18730ed3e8cb08da9c5559d0ea51d255b6bd9d7638b876472f942b330fc0e2b30aea68d77368fce4948272991d257e"], 906 [x"fe0568642943b2e1afbfd1f10fe8df87a4236bea40dce742072cb21886eec1fa299ebd1f13177dbdb66a912bbf712038fdf73b06c3ac020c7b19126755d47f61", x"299ebd1f13177dbdb66a912bbf712038fdf73b06c3ac020c7b19126755d47f61", x"c59d0862ec1c9746abcc3cf83c9eeba2c7082a036a8cb57ce487e763492796d47e6e063a0c1feccc2d", x"d59e6dfcc6d7e3e2c58dec81e985d245e681acf6594a23c59214f7bed8015d813c7682b60b3583440311e72a8665ba2c96dec23ce826e160127e18132b030404c59d0862ec1c9746abcc3cf83c9eeba2c7082a036a8cb57ce487e763492796d47e6e063a0c1feccc2d"], 907 [x"5ecb16c2df27c8cf58e436a9d3affbd58e9538a92659a0f97c4c4f994635a8cada768b20c437dd3aa5f84bb6a077ffa34ab68501c5352b5cc3fdce7fe6c2398d", x"da768b20c437dd3aa5f84bb6a077ffa34ab68501c5352b5cc3fdce7fe6c2398d", x"56f1329d9a6be25a6159c72f12688dc8314e85dd9e7e4dc05bbecb7729e023c86f8e0937353f27c7ede9", x"1c723a20c6772426a670e4d5c4a97c6ebe9147f71bb0a415631e44406e290322e4ca977d348fe7856a8edc235d0fe95f7ed91aefddf28a77e2c7dbfd8f552f0a56f1329d9a6be25a6159c72f12688dc8314e85dd9e7e4dc05bbecb7729e023c86f8e0937353f27c7ede9"], 908 [x"d599d637b3c30a82a9984e2f758497d144de6f06b9fba04dd40fd949039d7c846791d8ce50a44689fc178727c5c3a1c959fbeed74ef7d8e7bd3c1ab4da31c51f", x"6791d8ce50a44689fc178727c5c3a1c959fbeed74ef7d8e7bd3c1ab4da31c51f", x"a7c04e8ba75d0a03d8b166ad7a1d77e1b91c7aaf7befdd99311fc3c54a684ddd971d5b3211c3eeaff1e54e", x"ebf10d9ac7c96108140e7def6fe9533d727646ff5b3af273c1df95762a66f32b65a09634d013f54b5dd6011f91bc336ca8b355ce33f8cfbec2535a4c427f8205a7c04e8ba75d0a03d8b166ad7a1d77e1b91c7aaf7befdd99311fc3c54a684ddd971d5b3211c3eeaff1e54e"], 909 [x"30ab8232fa7018f0ce6c39bd8f782fe2e159758bb0f2f4386c7f28cfd2c85898ecfb6a2bd42f31b61250ba5de7e46b4719afdfbc660db71a7bd1df7b0a3abe37", x"ecfb6a2bd42f31b61250ba5de7e46b4719afdfbc660db71a7bd1df7b0a3abe37", x"63b80b7956acbecf0c35e9ab06b914b0c7014fe1a4bbc0217240c1a33095d707953ed77b15d211adaf9b97dc", x"9af885344cc7239498f712df80bc01b80638291ed4a1d28baa5545017a72e2f65649ccf9603da6eb5bfab9f5543a6ca4a7af3866153c76bf66bf95def615b00c63b80b7956acbecf0c35e9ab06b914b0c7014fe1a4bbc0217240c1a33095d707953ed77b15d211adaf9b97dc"], 910 [x"0ddcdc872c7b748d40efe96c2881ae189d87f56148ed8af3ebbbc80324e38bdd588ddadcbcedf40df0e9697d8bb277c7bb1498fa1d26ce0a835a760b92ca7c85", x"588ddadcbcedf40df0e9697d8bb277c7bb1498fa1d26ce0a835a760b92ca7c85", x"65641cd402add8bf3d1d67dbeb6d41debfbef67e4317c35b0a6d5bbbae0e034de7d670ba1413d056f2d6f1de12", x"c179c09456e235fe24105afa6e8ec04637f8f943817cd098ba95387f9653b2add181a31447d92d1a1ddf1ceb0db62118de9dffb7dcd2424057cbdff5d41d040365641cd402add8bf3d1d67dbeb6d41debfbef67e4317c35b0a6d5bbbae0e034de7d670ba1413d056f2d6f1de12"], 911 [x"89f0d68299ba0a5a83f248ae0c169f8e3849a9b47bd4549884305c9912b46603aba3e795aab2012acceadd7b3bd9daeeed6ff5258bdcd7c93699c2a3836e3832", x"aba3e795aab2012acceadd7b3bd9daeeed6ff5258bdcd7c93699c2a3836e3832", x"4f1846dd7ad50e545d4cfbffbb1dc2ff145dc123754d08af4e44ecc0bc8c91411388bc7653e2d893d1eac2107d05", x"2c691fa8d487ce20d5d2fa41559116e0bbf4397cf5240e152556183541d66cf753582401a4388d390339dbef4d384743caa346f55f8daba68ba7b9131a8a6e0b4f1846dd7ad50e545d4cfbffbb1dc2ff145dc123754d08af4e44ecc0bc8c91411388bc7653e2d893d1eac2107d05"], 912 [x"0a3c1844e2db070fb24e3c95cb1cc6714ef84e2ccd2b9dd2f1460ebf7ecf13b172e409937e0610eb5c20b326dc6ea1bbbc0406701c5cd67d1fbde09192b07c01", x"72e409937e0610eb5c20b326dc6ea1bbbc0406701c5cd67d1fbde09192b07c01", x"4c8274d0ed1f74e2c86c08d955bde55b2d54327e82062a1f71f70d536fdc8722cdead7d22aaead2bfaa1ad00b82957", x"87f7fdf46095201e877a588fe3e5aaf476bd63138d8a878b89d6ac60631b3458b9d41a3c61a588e1db8d29a5968981b018776c588780922f5aa732ba6379dd054c8274d0ed1f74e2c86c08d955bde55b2d54327e82062a1f71f70d536fdc8722cdead7d22aaead2bfaa1ad00b82957"], 913 [x"c8d7a8818b98dfdb20839c871cb5c48e9e9470ca3ad35ba2613a5d3199c8ab2390d2efbba4d43e6b2b992ca16083dbcfa2b322383907b0ee75f3e95845d3c47f", x"90d2efbba4d43e6b2b992ca16083dbcfa2b322383907b0ee75f3e95845d3c47f", x"783e33c3acbdbb36e819f544a7781d83fc283d3309f5d3d12c8dcd6b0b3d0e89e38cfd3b4d0885661ca547fb9764abff", x"fa2e994421aef1d5856674813d05cbd2cf84ef5eb424af6ecd0dc6fdbdc2fe605fe985883312ecf34f59bfb2f1c9149e5b9cc9ecda05b2731130f3ed28ddae0b783e33c3acbdbb36e819f544a7781d83fc283d3309f5d3d12c8dcd6b0b3d0e89e38cfd3b4d0885661ca547fb9764abff"], 914 [x"b482703612d0c586f76cfcb21cfd2103c957251504a8c0ac4c86c9c6f3e429fffd711dc7dd3b1dfb9df9704be3e6b26f587fe7dd7ba456a91ba43fe51aec09ad", x"fd711dc7dd3b1dfb9df9704be3e6b26f587fe7dd7ba456a91ba43fe51aec09ad", x"29d77acfd99c7a0070a88feb6247a2bce9984fe3e6fbf19d4045042a21ab26cbd771e184a9a75f316b648c6920db92b87b", x"58832bdeb26feafc31b46277cf3fb5d7a17dfb7ccd9b1f58ecbe6feb979666828f239ba4d75219260ecac0acf40f0e5e2590f4caa16bbbcd8a155d347967a60729d77acfd99c7a0070a88feb6247a2bce9984fe3e6fbf19d4045042a21ab26cbd771e184a9a75f316b648c6920db92b87b"], 915 [x"84e50dd9a0f197e3893c38dbd91fafc344c1776d3a400e2f0f0ee7aa829eb8a22c50f870ee48b36b0ac2f8a5f336fb090b113050dbcc25e078200a6e16153eea", x"2c50f870ee48b36b0ac2f8a5f336fb090b113050dbcc25e078200a6e16153eea", x"f3992cde6493e671f1e129ddca8038b0abdb77bb9035f9f8be54bd5d68c1aeff724ff47d29344391dc536166b8671cbbf123", x"69e6a4491a63837316e86a5f4ba7cd0d731ecc58f1d0a264c67c89befdd8d3829d8de13b33cc0bf513931715c7809657e2bfb960e5c764c971d733746093e500f3992cde6493e671f1e129ddca8038b0abdb77bb9035f9f8be54bd5d68c1aeff724ff47d29344391dc536166b8671cbbf123"], 916 [x"b322d46577a2a991a4d1698287832a39c487ef776b4bff037a05c7f1812bdeeceb2bcadfd3eec2986baff32b98e7c4dbf03ff95d8ad5ff9aa9506e5472ff845f", x"eb2bcadfd3eec2986baff32b98e7c4dbf03ff95d8ad5ff9aa9506e5472ff845f", x"19f1bf5dcf1750c611f1c4a2865200504d82298edd72671f62a7b1471ac3d4a30f7de9e5da4108c52a4ce70a3e114a52a3b3c5", x"c7b55137317ca21e33489ff6a9bfab97c855dc6f85684a70a9125a261b56d5e6f149c5774d734f2d8debfc77b721896a8267c23768e9badb910eef83ec25880219f1bf5dcf1750c611f1c4a2865200504d82298edd72671f62a7b1471ac3d4a30f7de9e5da4108c52a4ce70a3e114a52a3b3c5"], 917 [x"960cab5034b9838d098d2dcbf4364bec16d388f6376d73a6273b70f82bbc98c05e3c19f2415acf729f829a4ebd5c40e1a6bc9fbca95703a9376087ed0937e51a", x"5e3c19f2415acf729f829a4ebd5c40e1a6bc9fbca95703a9376087ed0937e51a", x"f8b21962447b0a8f2e4279de411bea128e0be44b6915e6cda88341a68a0d818357db938eac73e0af6d31206b3948f8c48a447308", x"27d4c3a1811ef9d4360b3bdd133c2ccc30d02c2f248215776cb07ee4177f9b13fc42dd70a6c2fed8f225c7663c7f182e7ee8eccff20dc7b0e1d5834ec5b1ea01f8b21962447b0a8f2e4279de411bea128e0be44b6915e6cda88341a68a0d818357db938eac73e0af6d31206b3948f8c48a447308"], 918 [x"eb77b2638f23eebc82efe45ee9e5a0326637401e663ed029699b21e6443fb48e9ef27608961ac711de71a6e2d4d4663ea3ecd42fb7e4e8627c39622df4af0bbc", x"9ef27608961ac711de71a6e2d4d4663ea3ecd42fb7e4e8627c39622df4af0bbc", x"99e3d00934003ebafc3e9fdb687b0f5ff9d5782a4b1f56b9700046c077915602c3134e22fc90ed7e690fddd4433e2034dcb2dc99ab", x"18dc56d7bd9acd4f4daa78540b4ac8ff7aa9815f45a0bba370731a14eaabe96df8b5f37dbf8eae4cb15a64b244651e59d6a3d6761d9e3c50f2d0cbb09c05ec0699e3d00934003ebafc3e9fdb687b0f5ff9d5782a4b1f56b9700046c077915602c3134e22fc90ed7e690fddd4433e2034dcb2dc99ab"], 919 [x"b625aa89d3f7308715427b6c39bbac58effd3a0fb7316f7a22b99ee5922f2dc965a99c3e16fea894ec33c6b20d9105e2a04e2764a4769d9bbd4d8bacfeab4a2e", x"65a99c3e16fea894ec33c6b20d9105e2a04e2764a4769d9bbd4d8bacfeab4a2e", x"e07241dbd3adbe610bbe4d005dd46732a4c25086ecb8ec29cd7bca116e1bf9f53bfbf3e11fa49018d39ff1154a06668ef7df5c678e6a", x"01bb901d83b8b682d3614af46a807ba2691358feb775325d3423f549ff0aa5757e4e1a74e9c70f9721d8f354b319d4f4a1d91445c870fd0ffb94fed64664730de07241dbd3adbe610bbe4d005dd46732a4c25086ecb8ec29cd7bca116e1bf9f53bfbf3e11fa49018d39ff1154a06668ef7df5c678e6a"], 920 [x"b1c9f8bd03fe82e78f5c0fb06450f27dacdf716434db268275df3e1dc177af427fc88b1f7b3f11c629be671c21621f5c10672fafc8492da885742059ee6774cf", x"7fc88b1f7b3f11c629be671c21621f5c10672fafc8492da885742059ee6774cf", x"331da7a9c1f87b2ac91ee3b86d06c29163c05ed6f8d8a9725b471b7db0d6acec7f0f702487163f5eda020ca5b493f399e1c8d308c3c0c2", x"4b229951ef262f16978f7914bc672e7226c5f8379d2778c5a2dc0a2650869f7acfbd0bcd30fdb0619bb44fc1ae5939b87cc318133009c20395b6c7eb98107701331da7a9c1f87b2ac91ee3b86d06c29163c05ed6f8d8a9725b471b7db0d6acec7f0f702487163f5eda020ca5b493f399e1c8d308c3c0c2"], 921 [x"6d8cdb2e075f3a2f86137214cb236ceb89a6728bb4a200806bf3557fb78fac6957a04c7a5113cddfe49a4c124691d46c1f9cdc8f343f9dcb72a1330aeca71fda", x"57a04c7a5113cddfe49a4c124691d46c1f9cdc8f343f9dcb72a1330aeca71fda", x"7f318dbd121c08bfddfeff4f6aff4e45793251f8abf658403358238984360054f2a862c5bb83ed89025d2014a7a0cee50da3cb0e76bbb6bf", x"a6cbc947f9c87d1455cf1a708528c090f11ecee4855d1dbaadf47454a4de55fa4ce84b36d73a5b5f8f59298ccf21992df492ef34163d87753b7e9d32f2c3660b7f318dbd121c08bfddfeff4f6aff4e45793251f8abf658403358238984360054f2a862c5bb83ed89025d2014a7a0cee50da3cb0e76bbb6bf"], 922 [x"47adc6d6bf571ee9570ca0f75b604ac43e303e4ab339ca9b53cacc5be45b2ccba3f527a1c1f17dfeed92277347c9f98ab475de1755b0ab546b8a15d01b9bd0be", x"a3f527a1c1f17dfeed92277347c9f98ab475de1755b0ab546b8a15d01b9bd0be", x"ce497c5ff5a77990b7d8f8699eb1f5d8c0582f70cb7ac5c54d9d924913278bc654d37ea227590e15202217fc98dac4c0f3be2183d133315739", x"4e8c318343c306adbba60c92b75cb0569b9219d8a86e5d57752ed235fc109a43c2cf4e942cacf297279fbb28675347e08027722a4eb7395e00a17495d32edf0bce497c5ff5a77990b7d8f8699eb1f5d8c0582f70cb7ac5c54d9d924913278bc654d37ea227590e15202217fc98dac4c0f3be2183d133315739"], 923 [x"3c19b50b0fe47961719c381d0d8da9b9869d312f13e3298b97fb22f0af29cbbe0f7eda091499625e2bae8536ea35cda5483bd16a9c7e416b341d6f2c83343612", x"0f7eda091499625e2bae8536ea35cda5483bd16a9c7e416b341d6f2c83343612", x"8ddcd63043f55ec3bfc83dceae69d8f8b32f4cdb6e2aebd94b4314f8fe7287dcb62732c9052e7557fe63534338efb5b6254c5d41d2690cf5144f", x"efbd41f26a5d62685516f882b6ec74e0d5a71830d203c231248f26e99a9c6578ec900d68cdb8fa7216ad0d24f9ecbc9ffa655351666582f626645395a31fa7048ddcd63043f55ec3bfc83dceae69d8f8b32f4cdb6e2aebd94b4314f8fe7287dcb62732c9052e7557fe63534338efb5b6254c5d41d2690cf5144f"], 924 [x"34e1e9d539107eb86b393a5ccea1496d35bc7d5e9a8c5159d957e4e5852b3eb00ecb2601d5f7047428e9f909883a12420085f04ee2a88b6d95d3d7f2c932bd76", x"0ecb2601d5f7047428e9f909883a12420085f04ee2a88b6d95d3d7f2c932bd76", x"a6d4d0542cfe0d240a90507debacabce7cbbd48732353f4fad82c7bb7dbd9df8e7d9a16980a45186d8786c5ef65445bcc5b2ad5f660ffc7c8eaac0", x"32d22904d3e7012d6f5a441b0b4228064a5cf95b723a66b048a087ecd55920c31c204c3f2006891a85dd1932e3f1d614cfd633b5e63291c6d8166f3011431e09a6d4d0542cfe0d240a90507debacabce7cbbd48732353f4fad82c7bb7dbd9df8e7d9a16980a45186d8786c5ef65445bcc5b2ad5f660ffc7c8eaac0"], 925 [x"49dd473ede6aa3c866824a40ada4996c239a20d84c9365e4f0a4554f8031b9cf788de540544d3feb0c919240b390729be487e94b64ad973eb65b4669ecf23501", x"788de540544d3feb0c919240b390729be487e94b64ad973eb65b4669ecf23501", x"3a53594f3fba03029318f512b084a071ebd60baec7f55b028dc73bfc9c74e0ca496bf819dd92ab61cd8b74be3c0d6dcd128efc5ed3342cba124f726c", x"d2fde02791e720852507faa7c3789040d9ef86646321f313ac557f4002491542dd67d05c6990cdb0d495501fbc5d5188bfbb84dc1bf6098bee0603a47fc2690f3a53594f3fba03029318f512b084a071ebd60baec7f55b028dc73bfc9c74e0ca496bf819dd92ab61cd8b74be3c0d6dcd128efc5ed3342cba124f726c"], 926 [x"331c64da482b6b551373c36481a02d8136ecadbb01ab114b4470bf41607ac57152a00d96a3148b4726692d9eff89160ea9f99a5cc4389f361fed0bb16a42d521", x"52a00d96a3148b4726692d9eff89160ea9f99a5cc4389f361fed0bb16a42d521", x"20e1d05a0d5b32cc8150b8116cef39659dd5fb443ab15600f78e5b49c45326d9323f2850a63c3808859495ae273f58a51e9de9a145d774b40ba9d753d3", x"22c99aa946ead39ac7997562810c01c20b46bd610645bd2d56dcdcbaacc5452c74fbf4b8b1813b0e94c30d808ce5498e61d4f7ccbb4cc5f04dfc6140825a960020e1d05a0d5b32cc8150b8116cef39659dd5fb443ab15600f78e5b49c45326d9323f2850a63c3808859495ae273f58a51e9de9a145d774b40ba9d753d3"], 927 [x"5c0b96f2af8712122cf743c8f8dc77b6cd5570a7de13297bb3dde1886213cce20510eaf57d7301b0e1d527039bf4c6e292300a3a61b4765434f3203c100351b1", x"0510eaf57d7301b0e1d527039bf4c6e292300a3a61b4765434f3203c100351b1", x"54e0caa8e63919ca614b2bfd308ccfe50c9ea888e1ee4446d682cb5034627f97b05392c04e835556c31c52816a48e4fb196693206b8afb4408662b3cb575", x"06e5d8436ac7705b3a90f1631cdd38ec1a3fa49778a9b9f2fa5ebea4e7d560ada7dd26ff42fafa8ba420323742761aca6904940dc21bbef63ff72daab45d430b54e0caa8e63919ca614b2bfd308ccfe50c9ea888e1ee4446d682cb5034627f97b05392c04e835556c31c52816a48e4fb196693206b8afb4408662b3cb575"], 928 [x"de84f2435f78dedb87da18194ff6a336f08111150def901c1ac418146eb7b54ad3a92bbaa4d63af79c2226a7236e6427428df8b362427f873023b22d2f5e03f2", x"d3a92bbaa4d63af79c2226a7236e6427428df8b362427f873023b22d2f5e03f2", x"205135ec7f417c858072d5233fb36482d4906abd60a74a498c347ff248dfa2722ca74e879de33169fadc7cd44d6c94a17d16e1e630824ba3e0df22ed68eaab", x"471ebc973cfdaceec07279307368b73be35bc6f8d8312b70150567369096706dc471126c3576f9f0eb550df5ac6a525181110029dd1fc11174d1aaced48d630f205135ec7f417c858072d5233fb36482d4906abd60a74a498c347ff248dfa2722ca74e879de33169fadc7cd44d6c94a17d16e1e630824ba3e0df22ed68eaab"], 929 ]; 930 }