Ed25519.cpp
1 /* 2 * Copyright (c) 2013-2025, The PurpleI2P Project 3 * 4 * This file is part of Purple i2pd project and licensed under BSD3 5 * 6 * See full license text in LICENSE file at top of project tree 7 */ 8 9 #include <openssl/evp.h> 10 #include "Log.h" 11 #include "Crypto.h" 12 #include "Ed25519.h" 13 14 namespace i2p 15 { 16 namespace crypto 17 { 18 Ed25519::Ed25519 () 19 { 20 BN_CTX * ctx = BN_CTX_new (); 21 BIGNUM * tmp = BN_new (); 22 23 q = BN_new (); 24 // 2^255-19 25 BN_set_bit (q, 255); // 2^255 26 BN_sub_word (q, 19); 27 28 l = BN_new (); 29 // 2^252 + 27742317777372353535851937790883648493 30 BN_set_bit (l, 252); 31 two_252_2 = BN_dup (l); 32 BN_dec2bn (&tmp, "27742317777372353535851937790883648493"); 33 BN_add (l, l, tmp); 34 BN_sub_word (two_252_2, 2); // 2^252 - 2 35 36 // -121665*inv(121666) 37 d = BN_new (); 38 BN_set_word (tmp, 121666); 39 BN_mod_inverse (tmp, tmp, q, ctx); 40 BN_set_word (d, 121665); 41 BN_set_negative (d, 1); 42 BN_mod_mul (d, d, tmp, q, ctx); 43 44 // 2^((q-1)/4) 45 I = BN_new (); 46 BN_free (tmp); 47 tmp = BN_dup (q); 48 BN_sub_word (tmp, 1); 49 BN_div_word (tmp, 4); 50 BN_set_word (I, 2); 51 BN_mod_exp (I, I, tmp, q, ctx); 52 BN_free (tmp); 53 54 // 4*inv(5) 55 BIGNUM * By = BN_new (); 56 BN_set_word (By, 5); 57 BN_mod_inverse (By, By, q, ctx); 58 BN_mul_word (By, 4); 59 BIGNUM * Bx = RecoverX (By, ctx); 60 BN_mod (Bx, Bx, q, ctx); // % q 61 BN_mod (By, By, q, ctx); // % q 62 63 // precalculate Bi256 table 64 Bi256Carry = { Bx, By }; // B 65 for (int i = 0; i < 32; i++) 66 { 67 Bi256[i][0] = Bi256Carry; // first point 68 for (int j = 1; j < 128; j++) 69 Bi256[i][j] = Sum (Bi256[i][j-1], Bi256[i][0], ctx); // (256+j+1)^i*B 70 Bi256Carry = Bi256[i][127]; 71 for (int j = 0; j < 128; j++) // add first point 128 more times 72 Bi256Carry = Sum (Bi256Carry, Bi256[i][0], ctx); 73 } 74 75 BN_CTX_free (ctx); 76 } 77 78 Ed25519::Ed25519 (const Ed25519& other): q (BN_dup (other.q)), l (BN_dup (other.l)), 79 d (BN_dup (other.d)), I (BN_dup (other.I)), two_252_2 (BN_dup (other.two_252_2)), 80 Bi256Carry (other.Bi256Carry) 81 { 82 for (int i = 0; i < 32; i++) 83 for (int j = 0; j < 128; j++) 84 Bi256[i][j] = other.Bi256[i][j]; 85 } 86 87 Ed25519::~Ed25519 () 88 { 89 BN_free (q); 90 BN_free (l); 91 BN_free (d); 92 BN_free (I); 93 BN_free (two_252_2); 94 } 95 96 97 EDDSAPoint Ed25519::GeneratePublicKey (const uint8_t * expandedPrivateKey, BN_CTX * ctx) const 98 { 99 return MulB (expandedPrivateKey, ctx); // left half of expanded key, considered as Little Endian 100 } 101 102 EDDSAPoint Ed25519::DecodePublicKey (const uint8_t * buf, BN_CTX * ctx) const 103 { 104 return DecodePoint (buf, ctx); 105 } 106 107 void Ed25519::EncodePublicKey (const EDDSAPoint& publicKey, uint8_t * buf, BN_CTX * ctx) const 108 { 109 EncodePoint (Normalize (publicKey, ctx), buf); 110 } 111 112 bool Ed25519::Verify (const EDDSAPoint& publicKey, const uint8_t * digest, const uint8_t * signature) const 113 { 114 BN_CTX * ctx = BN_CTX_new (); 115 BIGNUM * h = DecodeBN<64> (digest); 116 // signature 0..31 - R, 32..63 - S 117 // B*S = R + PK*h => R = B*S - PK*h 118 // we don't decode R, but encode (B*S - PK*h) 119 auto Bs = MulB (signature + EDDSA25519_SIGNATURE_LENGTH/2, ctx); // B*S; 120 BN_mod (h, h, l, ctx); // public key is multiple of B, but B%l = 0 121 auto PKh = Mul (publicKey, h, ctx); // PK*h 122 uint8_t diff[32]; 123 EncodePoint (Normalize (Sum (Bs, -PKh, ctx), ctx), diff); // Bs - PKh encoded 124 bool passed = !memcmp (signature, diff, 32); // R 125 BN_free (h); 126 BN_CTX_free (ctx); 127 if (!passed) 128 LogPrint (eLogError, "25519 signature verification failed"); 129 return passed; 130 } 131 132 void Ed25519::Sign (const uint8_t * expandedPrivateKey, const uint8_t * publicKeyEncoded, 133 const uint8_t * buf, size_t len, uint8_t * signature) const 134 { 135 BN_CTX * bnCtx = BN_CTX_new (); 136 // calculate r 137 EVP_MD_CTX * ctx = EVP_MD_CTX_create (); 138 EVP_DigestInit_ex (ctx, EVP_sha512(), NULL); 139 EVP_DigestUpdate (ctx, expandedPrivateKey + EDDSA25519_PRIVATE_KEY_LENGTH, EDDSA25519_PRIVATE_KEY_LENGTH); // right half of expanded key 140 EVP_DigestUpdate (ctx, buf, len); // data 141 uint8_t digest[64]; 142 unsigned int dl = 64; 143 EVP_DigestFinal_ex (ctx, digest, &dl); 144 EVP_MD_CTX_destroy (ctx); 145 BIGNUM * r = DecodeBN<32> (digest); // DecodeBN<64> (digest); // for test vectors 146 // calculate R 147 uint8_t R[EDDSA25519_SIGNATURE_LENGTH/2]; // we must use separate buffer because signature might be inside buf 148 EncodePoint (Normalize (MulB (digest, bnCtx), bnCtx), R); // EncodePoint (Mul (B, r, bnCtx), R); // for test vectors 149 // calculate S 150 ctx = EVP_MD_CTX_create (); 151 EVP_DigestInit_ex (ctx, EVP_sha512(), NULL); 152 EVP_DigestUpdate (ctx, R, EDDSA25519_SIGNATURE_LENGTH/2); // R 153 EVP_DigestUpdate (ctx, publicKeyEncoded, EDDSA25519_PUBLIC_KEY_LENGTH); // public key 154 EVP_DigestUpdate (ctx, buf, len); // data 155 dl = 64; 156 EVP_DigestFinal_ex (ctx, digest, &dl); 157 EVP_MD_CTX_destroy (ctx); 158 BIGNUM * h = DecodeBN<64> (digest); 159 // S = (r + h*a) % l 160 BIGNUM * a = DecodeBN<EDDSA25519_PRIVATE_KEY_LENGTH> (expandedPrivateKey); // left half of expanded key 161 BN_mod_mul (h, h, a, l, bnCtx); // %l 162 BN_mod_add (h, h, r, l, bnCtx); // %l 163 memcpy (signature, R, EDDSA25519_SIGNATURE_LENGTH/2); 164 EncodeBN (h, signature + EDDSA25519_SIGNATURE_LENGTH/2, EDDSA25519_SIGNATURE_LENGTH/2); // S 165 BN_free (r); BN_free (h); BN_free (a); 166 BN_CTX_free (bnCtx); 167 } 168 169 void Ed25519::SignRedDSA (const uint8_t * privateKey, const uint8_t * publicKeyEncoded, 170 const uint8_t * buf, size_t len, uint8_t * signature) const 171 { 172 BN_CTX * bnCtx = BN_CTX_new (); 173 // T = 80 random bytes 174 uint8_t T[80]; 175 RAND_bytes (T, 80); 176 // calculate r = H*(T || publickey || data) 177 EVP_MD_CTX * ctx = EVP_MD_CTX_create (); 178 EVP_DigestInit_ex (ctx, EVP_sha512(), NULL); 179 EVP_DigestUpdate (ctx, T, 80); 180 EVP_DigestUpdate (ctx, publicKeyEncoded, 32); 181 EVP_DigestUpdate (ctx, buf, len); // data 182 uint8_t digest[64]; 183 unsigned int dl = 64; 184 EVP_DigestFinal_ex (ctx, digest, &dl); 185 EVP_MD_CTX_destroy (ctx); 186 BIGNUM * r = DecodeBN<64> (digest); 187 BN_mod (r, r, l, bnCtx); // % l 188 EncodeBN (r, digest, 32); 189 // calculate R 190 uint8_t R[EDDSA25519_SIGNATURE_LENGTH/2]; // we must use separate buffer because signature might be inside buf 191 EncodePoint (Normalize (MulB (digest, bnCtx), bnCtx), R); 192 // calculate S 193 ctx = EVP_MD_CTX_create (); 194 EVP_DigestInit_ex (ctx, EVP_sha512(), NULL); 195 EVP_DigestUpdate (ctx, R, EDDSA25519_SIGNATURE_LENGTH/2); // R 196 EVP_DigestUpdate (ctx, publicKeyEncoded, EDDSA25519_PUBLIC_KEY_LENGTH); // public key 197 EVP_DigestUpdate (ctx, buf, len); // data 198 dl = 64; 199 EVP_DigestFinal_ex (ctx, digest, &dl); 200 EVP_MD_CTX_destroy (ctx); 201 BIGNUM * h = DecodeBN<64> (digest); 202 // S = (r + h*a) % l 203 BIGNUM * a = DecodeBN<EDDSA25519_PRIVATE_KEY_LENGTH> (privateKey); 204 BN_mod_mul (h, h, a, l, bnCtx); // %l 205 BN_mod_add (h, h, r, l, bnCtx); // %l 206 memcpy (signature, R, EDDSA25519_SIGNATURE_LENGTH/2); 207 EncodeBN (h, signature + EDDSA25519_SIGNATURE_LENGTH/2, EDDSA25519_SIGNATURE_LENGTH/2); // S 208 BN_free (r); BN_free (h); BN_free (a); 209 BN_CTX_free (bnCtx); 210 } 211 212 EDDSAPoint Ed25519::Sum (const EDDSAPoint& p1, const EDDSAPoint& p2, BN_CTX * ctx) const 213 { 214 // x3 = (x1*y2+y1*x2)*(z1*z2-d*t1*t2) 215 // y3 = (y1*y2+x1*x2)*(z1*z2+d*t1*t2) 216 // z3 = (z1*z2-d*t1*t2)*(z1*z2+d*t1*t2) 217 // t3 = (y1*y2+x1*x2)*(x1*y2+y1*x2) 218 BIGNUM * x3 = BN_new (), * y3 = BN_new (), * z3 = BN_new (), * t3 = BN_new (); 219 220 BN_mul (x3, p1.x, p2.x, ctx); // A = x1*x2 221 BN_mul (y3, p1.y, p2.y, ctx); // B = y1*y2 222 223 BN_CTX_start (ctx); 224 BIGNUM * t1 = p1.t, * t2 = p2.t; 225 if (!t1) { t1 = BN_CTX_get (ctx); BN_mul (t1, p1.x, p1.y, ctx); } 226 if (!t2) { t2 = BN_CTX_get (ctx); BN_mul (t2, p2.x, p2.y, ctx); } 227 BN_mul (t3, t1, t2, ctx); 228 BN_mul (t3, t3, d, ctx); // C = d*t1*t2 229 230 if (p1.z) 231 { 232 if (p2.z) 233 BN_mul (z3, p1.z, p2.z, ctx); // D = z1*z2 234 else 235 BN_copy (z3, p1.z); // D = z1 236 } 237 else 238 { 239 if (p2.z) 240 BN_copy (z3, p2.z); // D = z2 241 else 242 BN_one (z3); // D = 1 243 } 244 245 BIGNUM * E = BN_CTX_get (ctx), * F = BN_CTX_get (ctx), * G = BN_CTX_get (ctx), * H = BN_CTX_get (ctx); 246 BN_add (E, p1.x, p1.y); 247 BN_add (F, p2.x, p2.y); 248 BN_mul (E, E, F, ctx); // (x1 + y1)*(x2 + y2) 249 BN_sub (E, E, x3); 250 BN_sub (E, E, y3); // E = (x1 + y1)*(x2 + y2) - A - B 251 BN_sub (F, z3, t3); // F = D - C 252 BN_add (G, z3, t3); // G = D + C 253 BN_add (H, y3, x3); // H = B + A 254 255 BN_mod_mul (x3, E, F, q, ctx); // x3 = E*F 256 BN_mod_mul (y3, G, H, q, ctx); // y3 = G*H 257 BN_mod_mul (z3, F, G, q, ctx); // z3 = F*G 258 BN_mod_mul (t3, E, H, q, ctx); // t3 = E*H 259 260 BN_CTX_end (ctx); 261 262 return EDDSAPoint {x3, y3, z3, t3}; 263 } 264 265 void Ed25519::Double (EDDSAPoint& p, BN_CTX * ctx) const 266 { 267 BN_CTX_start (ctx); 268 BIGNUM * x2 = BN_CTX_get (ctx), * y2 = BN_CTX_get (ctx), * z2 = BN_CTX_get (ctx), * t2 = BN_CTX_get (ctx); 269 270 BN_sqr (x2, p.x, ctx); // x2 = A = x^2 271 BN_sqr (y2, p.y, ctx); // y2 = B = y^2 272 if (p.t) 273 BN_sqr (t2, p.t, ctx); // t2 = t^2 274 else 275 { 276 BN_mul (t2, p.x, p.y, ctx); // t = x*y 277 BN_sqr (t2, t2, ctx); // t2 = t^2 278 } 279 BN_mul (t2, t2, d, ctx); // t2 = C = d*t^2 280 if (p.z) 281 BN_sqr (z2, p.z, ctx); // z2 = D = z^2 282 else 283 BN_one (z2); // z2 = 1 284 285 BIGNUM * E = BN_CTX_get (ctx), * F = BN_CTX_get (ctx), * G = BN_CTX_get (ctx), * H = BN_CTX_get (ctx); 286 // E = (x+y)*(x+y)-A-B = x^2+y^2+2xy-A-B = 2xy 287 BN_mul (E, p.x, p.y, ctx); 288 BN_lshift1 (E, E); // E =2*x*y 289 BN_sub (F, z2, t2); // F = D - C 290 BN_add (G, z2, t2); // G = D + C 291 BN_add (H, y2, x2); // H = B + A 292 293 BN_mod_mul (p.x, E, F, q, ctx); // x2 = E*F 294 BN_mod_mul (p.y, G, H, q, ctx); // y2 = G*H 295 if (!p.z) p.z = BN_new (); 296 BN_mod_mul (p.z, F, G, q, ctx); // z2 = F*G 297 if (!p.t) p.t = BN_new (); 298 BN_mod_mul (p.t, E, H, q, ctx); // t2 = E*H 299 300 BN_CTX_end (ctx); 301 } 302 303 EDDSAPoint Ed25519::Mul (const EDDSAPoint& p, const BIGNUM * e, BN_CTX * ctx) const 304 { 305 BIGNUM * zero = BN_new (), * one = BN_new (); 306 BN_zero (zero); BN_one (one); 307 EDDSAPoint res {zero, one}; 308 if (!BN_is_zero (e)) 309 { 310 int bitCount = BN_num_bits (e); 311 for (int i = bitCount - 1; i >= 0; i--) 312 { 313 Double (res, ctx); 314 if (BN_is_bit_set (e, i)) res = Sum (res, p, ctx); 315 } 316 } 317 return res; 318 } 319 320 EDDSAPoint Ed25519::MulB (const uint8_t * e, BN_CTX * ctx) const // B*e, e is 32 bytes Little Endian 321 { 322 BIGNUM * zero = BN_new (), * one = BN_new (); 323 BN_zero (zero); BN_one (one); 324 EDDSAPoint res {zero, one}; 325 bool carry = false; 326 for (int i = 0; i < 32; i++) 327 { 328 uint8_t x = e[i]; 329 if (carry) 330 { 331 if (x < 255) 332 { 333 x++; 334 carry = false; 335 } 336 else 337 x = 0; 338 } 339 if (x > 0) 340 { 341 if (x <= 128) 342 res = Sum (res, Bi256[i][x-1], ctx); 343 else 344 { 345 res = Sum (res, -Bi256[i][255-x], ctx); // -Bi[256-x] 346 carry = true; 347 } 348 } 349 } 350 if (carry) res = Sum (res, Bi256Carry, ctx); 351 return res; 352 } 353 354 EDDSAPoint Ed25519::Normalize (const EDDSAPoint& p, BN_CTX * ctx) const 355 { 356 if (p.z) 357 { 358 BIGNUM * x = BN_new (), * y = BN_new (); 359 BN_mod_inverse (y, p.z, q, ctx); 360 BN_mod_mul (x, p.x, y, q, ctx); // x = x/z 361 BN_mod_mul (y, p.y, y, q, ctx); // y = y/z 362 return EDDSAPoint{x, y}; 363 } 364 else 365 return EDDSAPoint{BN_dup (p.x), BN_dup (p.y)}; 366 } 367 368 bool Ed25519::IsOnCurve (const EDDSAPoint& p, BN_CTX * ctx) const 369 { 370 BN_CTX_start (ctx); 371 BIGNUM * x2 = BN_CTX_get (ctx), * y2 = BN_CTX_get (ctx), * tmp = BN_CTX_get (ctx); 372 BN_sqr (x2, p.x, ctx); // x^2 373 BN_sqr (y2, p.y, ctx); // y^2 374 // y^2 - x^2 - 1 - d*x^2*y^2 375 BN_mul (tmp, d, x2, ctx); 376 BN_mul (tmp, tmp, y2, ctx); 377 BN_sub (tmp, y2, tmp); 378 BN_sub (tmp, tmp, x2); 379 BN_sub_word (tmp, 1); 380 BN_mod (tmp, tmp, q, ctx); // % q 381 bool ret = BN_is_zero (tmp); 382 BN_CTX_end (ctx); 383 return ret; 384 } 385 386 BIGNUM * Ed25519::RecoverX (const BIGNUM * y, BN_CTX * ctx) const 387 { 388 BN_CTX_start (ctx); 389 BIGNUM * y2 = BN_CTX_get (ctx), * xx = BN_CTX_get (ctx); 390 BN_sqr (y2, y, ctx); // y^2 391 // xx = (y^2 -1)*inv(d*y^2 +1) 392 BN_mul (xx, d, y2, ctx); 393 BN_add_word (xx, 1); 394 BN_mod_inverse (xx, xx, q, ctx); 395 BN_sub_word (y2, 1); 396 BN_mul (xx, y2, xx, ctx); 397 // x = srqt(xx) = xx^(2^252-2) 398 BIGNUM * x = BN_new (); 399 BN_mod_exp (x, xx, two_252_2, q, ctx); 400 // check (x^2 -xx) % q 401 BN_sqr (y2, x, ctx); 402 BN_mod_sub (y2, y2, xx, q, ctx); 403 if (!BN_is_zero (y2)) 404 BN_mod_mul (x, x, I, q, ctx); 405 if (BN_is_odd (x)) 406 BN_sub (x, q, x); 407 BN_CTX_end (ctx); 408 return x; 409 } 410 411 EDDSAPoint Ed25519::DecodePoint (const uint8_t * buf, BN_CTX * ctx) const 412 { 413 // buf is 32 bytes Little Endian, convert it to Big Endian 414 uint8_t buf1[EDDSA25519_PUBLIC_KEY_LENGTH]; 415 for (size_t i = 0; i < EDDSA25519_PUBLIC_KEY_LENGTH/2; i++) // invert bytes 416 { 417 buf1[i] = buf[EDDSA25519_PUBLIC_KEY_LENGTH -1 - i]; 418 buf1[EDDSA25519_PUBLIC_KEY_LENGTH -1 - i] = buf[i]; 419 } 420 bool isHighestBitSet = buf1[0] & 0x80; 421 if (isHighestBitSet) 422 buf1[0] &= 0x7f; // clear highest bit 423 BIGNUM * y = BN_new (); 424 BN_bin2bn (buf1, EDDSA25519_PUBLIC_KEY_LENGTH, y); 425 BIGNUM * x = RecoverX (y, ctx); 426 if ((bool)BN_is_bit_set (x, 0) != isHighestBitSet) 427 BN_sub (x, q, x); // x = q - x 428 BIGNUM * z = BN_new (), * t = BN_new (); 429 BN_one (z); BN_mod_mul (t, x, y, q, ctx); // pre-calculate t 430 EDDSAPoint p {x, y, z, t}; 431 if (!IsOnCurve (p, ctx)) 432 LogPrint (eLogError, "Decoded point is not on 25519"); 433 return p; 434 } 435 436 void Ed25519::EncodePoint (const EDDSAPoint& p, uint8_t * buf) const 437 { 438 EncodeBN (p.y, buf,EDDSA25519_PUBLIC_KEY_LENGTH); 439 if (BN_is_bit_set (p.x, 0)) // highest bit 440 buf[EDDSA25519_PUBLIC_KEY_LENGTH - 1] |= 0x80; // set highest bit 441 } 442 443 template<int len> 444 BIGNUM * Ed25519::DecodeBN (const uint8_t * buf) const 445 { 446 // buf is Little Endian convert it to Big Endian 447 uint8_t buf1[len]; 448 for (size_t i = 0; i < len/2; i++) // invert bytes 449 { 450 buf1[i] = buf[len -1 - i]; 451 buf1[len -1 - i] = buf[i]; 452 } 453 BIGNUM * res = BN_new (); 454 BN_bin2bn (buf1, len, res); 455 return res; 456 } 457 458 void Ed25519::EncodeBN (const BIGNUM * bn, uint8_t * buf, size_t len) const 459 { 460 bn2buf (bn, buf, len); 461 // To Little Endian 462 for (size_t i = 0; i < len/2; i++) // invert bytes 463 { 464 uint8_t tmp = buf[i]; 465 buf[i] = buf[len -1 - i]; 466 buf[len -1 - i] = tmp; 467 } 468 } 469 470 void Ed25519::BlindPublicKey (const uint8_t * pub, const uint8_t * seed, uint8_t * blinded) 471 { 472 BN_CTX * ctx = BN_CTX_new (); 473 // calculate alpha = seed mod l 474 BIGNUM * alpha = DecodeBN<64> (seed); // seed is in Little Endian 475 BN_mod (alpha, alpha, l, ctx); // % l 476 uint8_t priv[32]; 477 EncodeBN (alpha, priv, 32); // back to Little Endian 478 BN_free (alpha); 479 // A' = BLIND_PUBKEY(A, alpha) = A + DERIVE_PUBLIC(alpha) 480 auto A1 = Sum (DecodePublicKey (pub, ctx), MulB (priv, ctx), ctx); // pub + B*alpha 481 EncodePublicKey (A1, blinded, ctx); 482 BN_CTX_free (ctx); 483 } 484 485 void Ed25519::BlindPrivateKey (const uint8_t * priv, const uint8_t * seed, uint8_t * blindedPriv, uint8_t * blindedPub) 486 { 487 BN_CTX * ctx = BN_CTX_new (); 488 // calculate alpha = seed mod l 489 BIGNUM * alpha = DecodeBN<64> (seed); // seed is in Little Endian 490 BN_mod (alpha, alpha, l, ctx); // % l 491 BIGNUM * p = DecodeBN<32> (priv); // priv is in Little Endian 492 BN_add (alpha, alpha, p); // alpha = alpha + priv 493 // a' = BLIND_PRIVKEY(a, alpha) = (a + alpha) mod L 494 BN_mod (alpha, alpha, l, ctx); // % l 495 EncodeBN (alpha, blindedPriv, 32); 496 // A' = DERIVE_PUBLIC(a') 497 auto A1 = MulB (blindedPriv, ctx); 498 EncodePublicKey (A1, blindedPub, ctx); 499 BN_free (alpha); BN_free (p); 500 BN_CTX_free (ctx); 501 } 502 503 void Ed25519::ExpandPrivateKey (const uint8_t * key, uint8_t * expandedKey) 504 { 505 SHA512 (key, EDDSA25519_PRIVATE_KEY_LENGTH, expandedKey); 506 expandedKey[0] &= 0xF8; // drop last 3 bits 507 expandedKey[EDDSA25519_PRIVATE_KEY_LENGTH - 1] &= 0x3F; // drop first 2 bits 508 expandedKey[EDDSA25519_PRIVATE_KEY_LENGTH - 1] |= 0x40; // set second bit 509 } 510 511 void Ed25519::CreateRedDSAPrivateKey (uint8_t * priv) 512 { 513 uint8_t seed[32]; 514 RAND_bytes (seed, 32); 515 BIGNUM * p = DecodeBN<32> (seed); 516 BN_CTX * ctx = BN_CTX_new (); 517 BN_mod (p, p, l, ctx); // % l 518 EncodeBN (p, priv, 32); 519 BN_CTX_free (ctx); 520 BN_free (p); 521 } 522 523 static std::unique_ptr<Ed25519> g_Ed25519; 524 std::unique_ptr<Ed25519>& GetEd25519 () 525 { 526 if (!g_Ed25519) 527 { 528 auto c = new Ed25519(); 529 if (!g_Ed25519) // make sure it was not created already 530 g_Ed25519.reset (c); 531 else 532 delete c; 533 } 534 return g_Ed25519; 535 } 536 } 537 }