1 /** 2 * RSA 3 * 4 * Copyright: 5 * (C) 1999-2008 Jack Lloyd 6 * (C) 2014-2015 Etienne Cimon 7 * 8 * License: 9 * Botan is released under the Simplified BSD License (see LICENSE.md) 10 */ 11 module botan.pubkey.algo.rsa; 12 13 import botan.constants; 14 static if (BOTAN_HAS_PUBLIC_KEY_CRYPTO && BOTAN_HAS_RSA): 15 16 public import botan.pubkey.pubkey; 17 public import botan.pubkey.algo.if_algo; 18 import botan.pubkey.pk_ops; 19 import botan.math.numbertheory.reducer; 20 import botan.pubkey.blinding; 21 import botan.utils.parsing; 22 import botan.math.numbertheory.numthry; 23 import botan.pubkey.algo.keypair; 24 import botan.rng.rng; 25 import memutils.helpers : Embed; 26 import std.concurrency; 27 import core.thread; 28 import std.algorithm : max; 29 30 struct RSAOptions { 31 enum algoName = "RSA"; 32 33 /* 34 * Check Private RSA Parameters 35 */ 36 static bool checkKey(in IFSchemePrivateKey privkey, RandomNumberGenerator rng, bool strong) 37 { 38 if (!privkey.checkKeyImpl(rng, strong)) 39 return false; 40 41 if (!strong) 42 return true; 43 auto p_minus_1 = privkey.getP() - 1; 44 auto q_minus_1 = privkey.getQ() - 1; 45 if ((privkey.getE() * privkey.getD()) % lcm(&p_minus_1, &q_minus_1) != 1) 46 return false; 47 48 return signatureConsistencyCheck(rng, privkey, "EMSA4(SHA-1)"); 49 } 50 } 51 52 /** 53 * RSA Public Key 54 */ 55 struct RSAPublicKey 56 { 57 public: 58 alias Options = RSAOptions; 59 __gshared immutable string algoName = Options.algoName; 60 61 this(in AlgorithmIdentifier alg_id, const ref SecureVector!ubyte key_bits) 62 { 63 m_owned = true; 64 m_pub = new IFSchemePublicKey(Options(), alg_id, key_bits); 65 } 66 67 /** 68 * Create a RSAPublicKey 69 * @arg n the modulus 70 * @arg e the exponent 71 */ 72 this(BigInt n, BigInt e) 73 { 74 m_owned = true; 75 m_pub = new IFSchemePublicKey(Options(), n.move(), e.move()); 76 } 77 78 this(PrivateKey pkey) { m_pub = cast(IFSchemePublicKey) pkey; } 79 this(PublicKey pkey) { m_pub = cast(IFSchemePublicKey) pkey; } 80 81 mixin Embed!(m_pub, m_owned); 82 83 bool m_owned; 84 IFSchemePublicKey m_pub; 85 } 86 87 /** 88 * RSA Private Key 89 */ 90 struct RSAPrivateKey 91 { 92 public: 93 alias Options = RSAOptions; 94 __gshared immutable string algoName = Options.algoName; 95 96 this(in AlgorithmIdentifier alg_id, const ref SecureVector!ubyte key_bits, RandomNumberGenerator rng) 97 { 98 m_owned = true; 99 m_priv = new IFSchemePrivateKey(Options(), rng, alg_id, key_bits); 100 } 101 102 /** 103 * Construct a private key from the specified parameters. 104 * 105 * Params: 106 * rng = a random number generator 107 * p = the first prime 108 * q = the second prime 109 * e = the exponent 110 * d = if specified, this has to be d with exp * d = 1 mod (p - 1, q - 1). Leave it as 0 if you wish 111 * the constructor to calculate it. 112 * n = if specified, this must be n = p * q. Leave it as 0 113 * if you wish to the constructor to calculate it. 114 */ 115 this(RandomNumberGenerator rng, BigInt p, BigInt q, BigInt e, BigInt d = BigInt(0), BigInt n = BigInt(0)) 116 { 117 m_owned = true; 118 m_priv = new IFSchemePrivateKey(Options(), rng, p.move(), q.move(), e.move(), d.move(), n.move()); 119 } 120 121 /** 122 * Create a new private key with the specified bit length 123 * Params: 124 * rng = the random number generator to use 125 * bits = the desired bit length of the private key 126 * exp = the public exponent to be used 127 */ 128 this(RandomNumberGenerator rng, size_t bits, size_t exp = 65537) 129 { 130 if (bits < 1024) 131 throw new InvalidArgument(algoName ~ ": Can't make a key that is only " ~ to!string(bits) ~ " bits long"); 132 if (exp < 3 || exp % 2 == 0) 133 throw new InvalidArgument(algoName ~ ": Invalid encryption exponent"); 134 BigInt e = exp; 135 BigInt p, q, n, d, d1, d2, c; 136 137 do 138 { 139 p = randomPrime(rng, (bits + 1) / 2, &e); 140 q = randomPrime(rng, bits - p.bits(), &e); 141 n = p * q; 142 } while (n.bits() != bits); 143 auto one = BigInt(1); 144 auto p_1 = p - one; 145 auto q_1 = q - one; 146 auto d_0 = lcm(&p_1, &q_1); 147 d = inverseMod(&e, &d_0); 148 149 m_owned = true; 150 m_priv = new IFSchemePrivateKey(Options(), rng, p.move(), q.move(), e.move(), d.move(), n.move()); 151 genCheck(rng); 152 } 153 154 this(PrivateKey pkey) { m_priv = cast(IFSchemePrivateKey) pkey; } 155 156 mixin Embed!(m_priv, m_owned); 157 158 bool m_owned; 159 IFSchemePrivateKey m_priv; 160 } 161 162 /** 163 * RSA private (decrypt/sign) operation 164 */ 165 final class RSAPrivateOperation : Signature, Decryption 166 { 167 public: 168 this(in PrivateKey pkey, RandomNumberGenerator rng) { 169 this(cast(IFSchemePrivateKey) pkey, rng); 170 } 171 172 this(in RSAPrivateKey pkey, RandomNumberGenerator rng) { 173 this(pkey.m_priv, rng); 174 } 175 176 this(in IFSchemePrivateKey rsa_, RandomNumberGenerator rng) 177 { 178 rsa = rsa_; 179 assert(rsa.algoName == RSAPublicKey.algoName); 180 m_n = &rsa.getN(); 181 m_q = &rsa.getQ(); 182 m_c = &rsa.getC(); 183 m_d1 = &rsa.getD1(); 184 m_p = &rsa.getP(); 185 m_powermod_e_n = FixedExponentPowerMod(&rsa.getE(), &rsa.getN()); 186 m_powermod_d2_q = FixedExponentPowerMod(&rsa.getD2(), &rsa.getQ()); 187 m_mod_p = ModularReducer(rsa.getP()); 188 BigInt k = BigInt(rng, m_n.bits() - 1); 189 auto e = (cast()*m_powermod_e_n)(cast()&k); 190 m_blinder = Blinder(e, inverseMod(&k, m_n), *m_n); 191 } 192 override size_t messageParts() const { return 1; } 193 override size_t messagePartSize() const { return 0; } 194 override size_t maxInputBits() const { return (m_n.bits() - 1); } 195 196 override SecureVector!ubyte 197 sign(const(ubyte)* msg, size_t msg_len, RandomNumberGenerator rng) 198 { 199 rng.addEntropy(msg, msg_len); 200 201 /* We don't check signatures against powermod_e_n here because 202 PKSigner checks verification consistency for all signature 203 algorithms. 204 */ 205 BigInt m = BigInt(msg, msg_len); 206 m = m_blinder.blind(m.dup); 207 m = privateOp(m); 208 BigInt x = m_blinder.unblind(m); 209 return BigInt.encode1363(x, m_n.bytes()); 210 } 211 212 /* 213 * RSA Decryption Operation 214 */ 215 override SecureVector!ubyte decrypt(const(ubyte)* msg, size_t msg_len) 216 { 217 BigInt m = BigInt(msg, msg_len); 218 BigInt x = m_blinder.unblind(privateOp(m_blinder.blind(m))); 219 FixedExponentPowerModImpl powermod_e_n = cast(FixedExponentPowerModImpl) *m_powermod_e_n; 220 assert(m == powermod_e_n.opCall(&x), "RSA decrypt passed consistency check"); 221 222 return BigInt.encodeLocked(x); 223 } 224 private: 225 BigInt privateOp()(auto const ref BigInt m) const 226 { 227 //import core.memory : GC; GC.disable(); scope(exit) GC.enable(); 228 import core.sync.condition; 229 import core.sync.mutex; 230 import core.atomic; 231 import memutils.utils : ThreadMem; 232 Mutex mutex = ThreadMem.alloc!Mutex(); 233 scope(exit) { 234 ThreadMem.free(mutex); 235 } 236 if (m >= *m_n) 237 throw new InvalidArgument("RSA private op - input is too large"); 238 BigInt j1; 239 j1.reserve(max(m_q.bytes() + m_q.bytes() % 128, m_n.bytes() + m_n.bytes() % 128)); 240 241 struct Handler { 242 shared(Mutex) mtx; 243 shared(const BigInt*) d1; 244 shared(const BigInt*) p; 245 shared(const BigInt*) m2; 246 shared(BigInt*) j1_2; 247 void run() { 248 try { 249 import botan.libstate.libstate : modexpInit; 250 modexpInit(); // enable quick path for powermod 251 BigInt* ret = cast(BigInt*) j1_2; 252 { 253 import memutils.utils; 254 FixedExponentPowerMod powermod_d1_p = FixedExponentPowerMod(cast(BigInt*)d1, cast(BigInt*)p); 255 BigInt _res =(cast()*powermod_d1_p)( cast(BigInt*) m2); 256 synchronized(cast()mtx) ret.load(&_res); 257 } 258 } catch (Exception e) { logDebug("Error: ", e.toString()); } 259 } 260 } 261 262 auto handler = Handler(cast(shared)mutex, cast(shared)m_d1, cast(shared)m_p, cast(shared)&m, cast(shared)&j1); 263 Unique!Thread thr = new Thread(&handler.run); 264 thr.start(); 265 FixedExponentPowerModImpl powermod_d2_q = cast(FixedExponentPowerModImpl)*m_powermod_d2_q; 266 BigInt j2 = powermod_d2_q.opCall(&m); 267 thr.join(); 268 BigInt j3; 269 synchronized(mutex) j3 = m_mod_p.reduce(subMul(&j1, &j2, m_c)); 270 return mulAdd(&j3, m_q, &j2); 271 } 272 273 const IFSchemePrivateKey rsa; 274 const BigInt* m_n; 275 const BigInt* m_q; 276 const BigInt* m_c; 277 const BigInt* m_d1; 278 const BigInt* m_p; 279 FixedExponentPowerMod m_powermod_e_n, m_powermod_d2_q; 280 ModularReducer m_mod_p; 281 Blinder m_blinder; 282 } 283 284 /** 285 * RSA public (encrypt/verify) operation 286 */ 287 final class RSAPublicOperation : Verification, Encryption 288 { 289 public: 290 this(in PublicKey pkey) { 291 this(cast(IFSchemePublicKey) pkey); 292 } 293 294 this(in RSAPublicKey pkey) { 295 this(pkey.m_pub); 296 } 297 298 this(in IFSchemePublicKey rsa) 299 { 300 assert(rsa.algoName == RSAPublicKey.algoName); 301 m_rsa = rsa; 302 m_n = &m_rsa.getN(); 303 m_powermod_e_n = FixedExponentPowerMod(&m_rsa.getE(), &m_rsa.getN()); 304 } 305 override size_t messageParts() const { return 1; } 306 override size_t messagePartSize() const { return 0; } 307 override size_t maxInputBits() const { return (m_n.bits() - 1); } 308 override bool withRecovery() const { return true; } 309 310 override SecureVector!ubyte encrypt(const(ubyte)* msg, size_t msg_len, RandomNumberGenerator) 311 { 312 BigInt m = BigInt(msg, msg_len); 313 return BigInt.encode1363(publicOp(m), m_n.bytes()); 314 } 315 316 override bool verify(const(ubyte)*, size_t, const(ubyte)*, size_t) 317 { 318 throw new InvalidState("Message recovery required"); 319 } 320 321 override SecureVector!ubyte verifyMr(const(ubyte)* msg, size_t msg_len) 322 { 323 BigInt m = BigInt(msg, msg_len); 324 return BigInt.encodeLocked(publicOp(m)); 325 } 326 327 private: 328 BigInt publicOp(const ref BigInt m) const 329 { 330 if (m >= *m_n) 331 throw new InvalidArgument("RSA public op - input is too large"); 332 return (cast()*m_powermod_e_n)(cast(BigInt*)&m); 333 } 334 335 const IFSchemePublicKey m_rsa; 336 const BigInt* m_n; 337 FixedExponentPowerMod m_powermod_e_n; 338 } 339 340 static if (BOTAN_TEST): 341 342 import botan.test; 343 import botan.pubkey.test; 344 import botan.rng.auto_rng; 345 import botan.pubkey.pubkey; 346 import botan.codec.hex; 347 import core.atomic; 348 import memutils.hashmap; 349 350 shared size_t total_tests; 351 352 353 size_t rsaesKat(string e, 354 string p, 355 string q, 356 string msg, 357 string padding, 358 string nonce, 359 string output) 360 { 361 atomicOp!"+="(total_tests, 1); 362 Unique!AutoSeededRNG rng = new AutoSeededRNG; 363 364 auto privkey = RSAPrivateKey(*rng, BigInt(p), BigInt(q), BigInt(e)); 365 366 auto pubkey = RSAPublicKey(privkey); 367 368 if (padding == "") 369 padding = "Raw"; 370 371 auto enc = scoped!PKEncryptorEME(pubkey, padding); 372 auto dec = scoped!PKDecryptorEME(privkey, padding); 373 374 return validateEncryption(enc, dec, "RSAES/" ~ padding, msg, nonce, output); 375 } 376 377 size_t rsaSigKat(string e, 378 string p, 379 string q, 380 string msg, 381 string padding, 382 string nonce, 383 string output) 384 { 385 atomicOp!"+="(total_tests, 1); 386 Unique!AutoSeededRNG rng = new AutoSeededRNG; 387 388 auto privkey = RSAPrivateKey(*rng, BigInt(p), BigInt(q), BigInt(e)); 389 390 auto pubkey = RSAPublicKey(privkey); 391 392 if (padding == "") 393 padding = "Raw"; 394 395 PKVerifier verify = PKVerifier(pubkey, padding); 396 PKSigner sign = PKSigner(privkey, padding); 397 398 return validateSignature(verify, sign, "RSA/" ~ padding, msg, *rng, nonce, output); 399 } 400 401 size_t rsaSigVerify(string e, 402 string n, 403 string msg, 404 string padding, 405 string signature) 406 { 407 atomicOp!"+="(total_tests, 1); 408 409 BigInt e_bn = BigInt(e); 410 BigInt n_bn = BigInt(n); 411 412 auto key = RSAPublicKey(n_bn.move(), e_bn.move()); 413 414 if (padding == "") 415 padding = "Raw"; 416 417 PKVerifier verify = PKVerifier(key, padding); 418 419 if (!verify.verifyMessage(hexDecode(msg), hexDecode(signature))) 420 return 1; 421 return 0; 422 } 423 424 size_t testPkKeygen(RandomNumberGenerator rng) 425 { 426 size_t fails; 427 428 auto rsa1024 = RSAPrivateKey(rng, 1024); 429 rsa1024.checkKey(rng, true); 430 atomicOp!"+="(total_tests, 1); 431 432 fails += validateSaveAndLoad(rsa1024, rng); 433 434 auto rsa2048 = RSAPrivateKey(rng, 2048); 435 rsa2048.checkKey(rng, true); 436 atomicOp!"+="(total_tests, 1); 437 fails += validateSaveAndLoad(rsa2048, rng); 438 439 return fails; 440 } 441 442 static if (BOTAN_HAS_TESTS && !SKIP_RSA_TEST) unittest 443 { 444 logDebug("Testing rsa.d ..."); 445 size_t fails = 0; 446 447 Unique!AutoSeededRNG rng = new AutoSeededRNG; 448 449 450 File rsa_enc = File("test_data/pubkey/rsaes.vec", "r"); 451 File rsa_sig = File("test_data/pubkey/rsa_sig.vec", "r"); 452 File rsa_verify = File("test_data/pubkey/rsa_verify.vec", "r"); 453 454 fails += testPkKeygen(*rng); 455 456 fails += runTestsBb(rsa_enc, "RSA Encryption", "Ciphertext", true, 457 (ref HashMap!(string, string) m) 458 { 459 return rsaesKat(m["E"], m["P"], m["Q"], m["Msg"], m.get("Padding"), m.get("Nonce"), m["Ciphertext"]); 460 }); 461 462 fails += runTestsBb(rsa_sig, "RSA Signature", "Signature", true, 463 (ref HashMap!(string, string) m) 464 { 465 return rsaSigKat(m["E"], m["P"], m["Q"], m["Msg"], m.get("Padding"), m.get("Nonce"), m["Signature"]); 466 }); 467 468 fails += runTestsBb(rsa_verify, "RSA Verify", "Signature", true, 469 (ref HashMap!(string, string) m) 470 { 471 return rsaSigVerify(m["E"], m["N"], m["Msg"], m.get("Padding"), m["Signature"]); 472 }); 473 474 testReport("rsa", total_tests, fails); 475 }