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