/* * Create a RSA private key */ RSA_PrivateKey::RSA_PrivateKey(RandomNumberGenerator& rng, size_t bits, size_t exp) { if(bits < 1024) throw Invalid_Argument(algo_name() + ": Can't make a key that is only " + std::to_string(bits) + " bits long"); if(exp < 3 || exp % 2 == 0) throw Invalid_Argument(algo_name() + ": Invalid encryption exponent"); e = exp; do { p = random_prime(rng, (bits + 1) / 2, e); q = random_prime(rng, bits - p.bits(), e); n = p * q; } while(n.bits() != bits); d = inverse_mod(e, lcm(p - 1, q - 1)); d1 = d % (p - 1); d2 = d % (q - 1); c = inverse_mod(q, p); gen_check(rng); }
/** * EC_PrivateKey constructor */ EC_PrivateKey::EC_PrivateKey(RandomNumberGenerator& rng, const EC_Group& ec_group, const BigInt& x, bool with_modular_inverse) { m_domain_params = ec_group; if (!ec_group.get_oid().empty()) m_domain_encoding = EC_DOMPAR_ENC_OID; else m_domain_encoding = EC_DOMPAR_ENC_EXPLICIT; if(x == 0) { m_private_key = BigInt::random_integer(rng, 1, domain().get_order()); } else { m_private_key = x; } m_public_key = domain().get_base_point() * ((with_modular_inverse) ? inverse_mod(m_private_key, m_domain_params.get_order()) : m_private_key); BOTAN_ASSERT(m_public_key.on_the_curve(), "Generated public key point was on the curve"); }
SecureVector<byte> ECDSA_Signature_Operation::sign(const byte msg[], size_t msg_len, RandomNumberGenerator& rng) { rng.add_entropy(msg, msg_len); BigInt m(msg, msg_len); BigInt r = 0, s = 0; while(r == 0 || s == 0) { // This contortion is necessary for the tests BigInt k; k.randomize(rng, order.bits()); while(k >= order) k.randomize(rng, order.bits() - 1); PointGFp k_times_P = base_point * k; r = mod_order.reduce(k_times_P.get_affine_x()); s = mod_order.multiply(inverse_mod(k, order), mul_add(x, r, m)); } SecureVector<byte> output(2*order.bytes()); r.binary_encode(&output[output.size() / 2 - r.bytes()]); s.binary_encode(&output[output.size() - s.bytes()]); return output; }
/* * Default ElGamal Decrypt Operation */ BigInt Default_ELG_Op::decrypt(const BigInt& a, const BigInt& b) const { if(a >= p || b >= p) throw Invalid_Argument("Default_ELG_Op: Invalid message"); return mod_p.multiply(b, inverse_mod(powermod_x_p(a), p)); }
EC_PrivateKey::EC_PrivateKey(const AlgorithmIdentifier& alg_id, const secure_vector<uint8_t>& key_bits, bool with_modular_inverse) { m_domain_params = EC_Group(alg_id.parameters); m_domain_encoding = EC_DOMPAR_ENC_EXPLICIT; OID key_parameters; secure_vector<uint8_t> public_key_bits; BER_Decoder(key_bits) .start_cons(SEQUENCE) .decode_and_check<size_t>(1, "Unknown version code for ECC key") .decode_octet_string_bigint(m_private_key) .decode_optional(key_parameters, ASN1_Tag(0), PRIVATE) .decode_optional_string(public_key_bits, BIT_STRING, 1, PRIVATE) .end_cons(); if(!key_parameters.empty() && key_parameters != alg_id.oid) throw Decoding_Error("EC_PrivateKey - inner and outer OIDs did not match"); if(public_key_bits.empty()) { m_public_key = domain().get_base_point() * ((with_modular_inverse) ? inverse_mod(m_private_key, m_domain_params.get_order()) : m_private_key); BOTAN_ASSERT(m_public_key.on_the_curve(), "Public point derived from loaded key was on the curve"); } else { m_public_key = OS2ECP(public_key_bits, domain().get_curve()); // OS2ECP verifies that the point is on the curve } }
void SshKeyGenerator::generateOpenSslPrivateKeyString(const KeyPtr &key) { QList<BigInt> params; QByteArray keyId; const char *label; if (m_type == Rsa) { const QSharedPointer<RSA_PrivateKey> rsaKey = key.dynamicCast<RSA_PrivateKey>(); params << rsaKey->get_n() << rsaKey->get_e() << rsaKey->get_d() << rsaKey->get_p() << rsaKey->get_q(); const BigInt dmp1 = rsaKey->get_d() % (rsaKey->get_p() - 1); const BigInt dmq1 = rsaKey->get_d() % (rsaKey->get_q() - 1); const BigInt iqmp = inverse_mod(rsaKey->get_q(), rsaKey->get_p()); params << dmp1 << dmq1 << iqmp; keyId = SshCapabilities::PubKeyRsa; label = "RSA PRIVATE KEY"; } else { const QSharedPointer<DSA_PrivateKey> dsaKey = key.dynamicCast<DSA_PrivateKey>(); params << dsaKey->group_p() << dsaKey->group_q() << dsaKey->group_g() << dsaKey->get_y() << dsaKey->get_x(); keyId = SshCapabilities::PubKeyDss; label = "DSA PRIVATE KEY"; } DER_Encoder encoder; encoder.start_cons(SEQUENCE).encode(size_t(0)); foreach (const BigInt &b, params) encoder.encode(b); encoder.end_cons(); m_privateKey = QByteArray(PEM_Code::encode (encoder.get_contents(), label).c_str()); }
SecureVector<byte> DSA_Signature_Operation::sign(const byte msg[], size_t msg_len, RandomNumberGenerator& rng) { rng.add_entropy(msg, msg_len); BigInt i(msg, msg_len); BigInt r = 0, s = 0; while(r == 0 || s == 0) { BigInt k; do k.randomize(rng, q.bits()); while(k >= q); r = mod_q.reduce(powermod_g_p(k)); s = mod_q.multiply(inverse_mod(k, q), mul_add(x, r, i)); } SecureVector<byte> output(2*q.bytes()); r.binary_encode(&output[output.size() / 2 - r.bytes()]); s.binary_encode(&output[output.size() - s.bytes()]); return output; }
BigInt PointGFp::get_affine_y() const { if(is_zero()) throw Illegal_Transformation("Cannot convert zero point to affine"); BigInt z3 = curve_mult(m_coord_z, curve_sqr(m_coord_z)); z3 = inverse_mod(z3, m_curve.get_p()); m_curve.to_rep(z3, m_monty_ws); return curve_mult(z3, m_coord_y); }
BigInt PointGFp::get_affine_x() const { if(is_zero()) throw Illegal_Transformation("Cannot convert zero point to affine"); BigInt z2 = curve_sqr(m_coord_z); m_curve.from_rep(z2, m_monty_ws); z2 = inverse_mod(z2, m_curve.get_p()); return curve_mult(z2, m_coord_x); }
ticks Invmod_Timing_Test::measure_critical_function(std::vector<uint8_t> input) { const Botan::BigInt k(input.data(), input.size()); ticks start = get_ticks(); const Botan::BigInt inv = inverse_mod(k, m_p); ticks end = get_ticks(); return (end - start); }
BigInt PointGFp::get_affine_y() const { if(is_zero()) throw Illegal_Transformation("Cannot convert zero point to affine"); const BigInt& r2 = curve.get_r2(); BigInt z3 = monty_mult(coord_z, monty_sqr(coord_z)); z3 = inverse_mod(z3, curve.get_p()); z3 = monty_mult(z3, r2); return monty_mult(coord_y, z3); }
/************************************************* * DH_Core Constructor * *************************************************/ DH_Core::DH_Core(RandomNumberGenerator& rng, const DL_Group& group, const BigInt& x) { op = Engine_Core::dh_op(group, x); const BigInt& p = group.get_p(); BigInt k(rng, std::min(p.bits()-1, BLINDING_BITS)); if(k != 0) blinder = Blinder(k, power_mod(inverse_mod(k, p), x, p), p); }
BigInt PointGFp::get_affine_y() const { if(is_zero()) throw Illegal_Transformation("Cannot convert zero point to affine"); secure_vector<word> monty_ws; BigInt z3 = m_curve.mul_to_tmp(m_coord_z, m_curve.sqr_to_tmp(m_coord_z, monty_ws), monty_ws); z3 = inverse_mod(z3, m_curve.get_p()); m_curve.to_rep(z3, monty_ws); return m_curve.mul_to_tmp(z3, m_coord_y, monty_ws); }
/************************************************* * IF_Core Constructor * *************************************************/ IF_Core::IF_Core(RandomNumberGenerator& rng, const BigInt& e, const BigInt& n, const BigInt& d, const BigInt& p, const BigInt& q, const BigInt& d1, const BigInt& d2, const BigInt& c) { op = Engine_Core::if_op(e, n, d, p, q, d1, d2, c); if(BLINDING_BITS) { BigInt k(rng, std::min(n.bits()-1, BLINDING_BITS)); blinder = Blinder(power_mod(k, e, n), inverse_mod(k, n), n); } }
ticks ECDSA_Timing_Test::measure_critical_function(std::vector<uint8_t> input) { const Botan::BigInt k(input.data(), input.size()); const Botan::BigInt msg(Timing_Test::timing_test_rng(), m_order.bits()); ticks start = get_ticks(); //The following ECDSA operations involve and should not leak any information about k. const Botan::PointGFp k_times_P = m_base_point.blinded_multiply(k, Timing_Test::timing_test_rng()); const Botan::BigInt r = m_mod_order.reduce(k_times_P.get_affine_x()); const Botan::BigInt s = m_mod_order.multiply(inverse_mod(k, m_order), mul_add(m_x, r, msg)); ticks end = get_ticks(); return (end - start); }
IF_Scheme_PrivateKey::IF_Scheme_PrivateKey(RandomNumberGenerator& rng, const BigInt& prime1, const BigInt& prime2, const BigInt& exp, const BigInt& d_exp, const BigInt& mod) { m_p = prime1; m_q = prime2; m_e = exp; m_d = d_exp; m_n = mod.is_nonzero() ? mod : m_p * m_q; if(m_d == 0) { BigInt inv_for_d = lcm(m_p - 1, m_q - 1); if(m_e.is_even()) inv_for_d >>= 1; m_d = inverse_mod(m_e, inv_for_d); }
bool DSA_Verification_Operation::verify(const byte msg[], size_t msg_len, const byte sig[], size_t sig_len) { const BigInt& q = mod_q.get_modulus(); if(sig_len != 2*q.bytes() || msg_len > q.bytes()) return false; BigInt r(sig, q.bytes()); BigInt s(sig + q.bytes(), q.bytes()); BigInt i(msg, msg_len); if(r <= 0 || r >= q || s <= 0 || s >= q) return false; s = inverse_mod(s, q); s = mod_p.multiply(powermod_g_p(mod_q.multiply(s, i)), powermod_y_p(mod_q.multiply(s, r))); return (mod_q.reduce(s) == r); }
IF_Scheme_PrivateKey::IF_Scheme_PrivateKey(RandomNumberGenerator& rng, const BigInt& prime1, const BigInt& prime2, const BigInt& exp, const BigInt& d_exp, const BigInt& mod) { p = prime1; q = prime2; e = exp; d = d_exp; n = mod.is_nonzero() ? mod : p * q; if(d == 0) { BigInt inv_for_d = lcm(p - 1, q - 1); if(e.is_even()) inv_for_d >>= 1; d = inverse_mod(e, inv_for_d); }
void SshKeyGenerator::generateOpenSslPrivateKeyString(const KeyPtr &key) { QList<BigInt> params; const char *label = ""; switch (m_type) { case Rsa: { const QSharedPointer<RSA_PrivateKey> rsaKey = key.dynamicCast<RSA_PrivateKey>(); params << rsaKey->get_n() << rsaKey->get_e() << rsaKey->get_d() << rsaKey->get_p() << rsaKey->get_q(); const BigInt dmp1 = rsaKey->get_d() % (rsaKey->get_p() - 1); const BigInt dmq1 = rsaKey->get_d() % (rsaKey->get_q() - 1); const BigInt iqmp = inverse_mod(rsaKey->get_q(), rsaKey->get_p()); params << dmp1 << dmq1 << iqmp; label = "RSA PRIVATE KEY"; break; } case Dsa: { const QSharedPointer<DSA_PrivateKey> dsaKey = key.dynamicCast<DSA_PrivateKey>(); params << dsaKey->group_p() << dsaKey->group_q() << dsaKey->group_g() << dsaKey->get_y() << dsaKey->get_x(); label = "DSA PRIVATE KEY"; break; } case Ecdsa: params << key.dynamicCast<ECDSA_PrivateKey>()->private_value(); label = "EC PRIVATE KEY"; break; } DER_Encoder encoder; encoder.start_cons(SEQUENCE).encode(size_t(0)); foreach (const BigInt &b, params) encoder.encode(b); encoder.end_cons(); m_privateKey = QByteArray(PEM_Code::encode (encoder.get_contents(), label).c_str()); }
bool ECDSA_Verification_Operation::verify(const byte msg[], size_t msg_len, const byte sig[], size_t sig_len) { if(sig_len != order.bytes()*2) return false; BigInt e(msg, msg_len); BigInt r(sig, sig_len / 2); BigInt s(sig + sig_len / 2, sig_len / 2); if(r <= 0 || r >= order || s <= 0 || s >= order) return false; BigInt w = inverse_mod(s, order); PointGFp R = w * multi_exponentiate(base_point, e, public_point, r); if(R.is_zero()) return false; return (R.get_affine_x() % order == r); }
m_e = exp; m_d = d_exp; m_n = mod.is_nonzero() ? mod : m_p * m_q; if(m_d == 0) { BigInt inv_for_d = lcm(m_p - 1, m_q - 1); if(m_e.is_even()) inv_for_d >>= 1; m_d = inverse_mod(m_e, inv_for_d); } m_d1 = m_d % (m_p - 1); m_d2 = m_d % (m_q - 1); m_c = inverse_mod(m_q, m_p); load_check(rng); } /* * Check IF Scheme Private Parameters */ bool IF_Scheme_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const { if(m_n < 35 || m_n.is_even() || m_e < 2 || m_d < 2 || m_p < 3 || m_q < 3 || m_p*m_q != m_n) return false; if(m_d1 != m_d % (m_p - 1) || m_d2 != m_d % (m_q - 1) || m_c != inverse_mod(m_q, m_p)) return false;
DH_KA_Operation::DH_KA_Operation(const DH_PrivateKey& dh) : p(dh.group_p()), powermod_x_p(dh.get_x(), p) { BigInt k(global_state().global_rng(), p.bits() - 1); blinder = Blinder(k, powermod_x_p(inverse_mod(k, p)), p); }
e = exp; d = d_exp; n = mod.is_nonzero() ? mod : p * q; if(d == 0) { BigInt inv_for_d = lcm(p - 1, q - 1); if(e.is_even()) inv_for_d >>= 1; d = inverse_mod(e, inv_for_d); } d1 = d % (p - 1); d2 = d % (q - 1); c = inverse_mod(q, p); load_check(rng); } /* * Check IF Scheme Private Parameters */ bool IF_Scheme_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const { if(n < 35 || n.is_even() || e < 2 || d < 2 || p < 3 || q < 3 || p*q != n) return false; if(d1 != d % (p - 1) || d2 != d % (q - 1) || c != inverse_mod(q, p)) return false;