diff --git a/src/examples/ecc_raw_private_key.cpp b/src/examples/ecc_raw_private_key.cpp index a3961ee75cf..4f418d6ab58 100644 --- a/src/examples/ecc_raw_private_key.cpp +++ b/src/examples/ecc_raw_private_key.cpp @@ -13,13 +13,12 @@ int main() { const auto private_scalar_bytes = Botan::hex_decode("D2AC61C35CAEE918E47B0BD5E61DA9B3A5C2964AB317647DEF6DFC042A06C829"); - Botan::Null_RNG null_rng; const auto domain = Botan::EC_Group::from_name(curve_name); const auto private_scalar = Botan::BigInt(private_scalar_bytes); // This loads the private scalar into an ECDH_PrivateKey. Creating an // ECDSA_PrivateKey would work the same way. - const auto private_key = Botan::ECDH_PrivateKey(null_rng, domain, private_scalar); + const auto private_key = Botan::ECDH_PrivateKey(domain, private_scalar); const auto public_key = private_key.public_key(); std::cout << "Private Key (PEM):\n\n" << Botan::PKCS8::PEM_encode(private_key) << '\n'; diff --git a/src/lib/pubkey/ecc_key/ec_key_data.cpp b/src/lib/pubkey/ecc_key/ec_key_data.cpp index 7247276b7e0..47072d6b804 100644 --- a/src/lib/pubkey/ecc_key/ec_key_data.cpp +++ b/src/lib/pubkey/ecc_key/ec_key_data.cpp @@ -13,9 +13,6 @@ namespace Botan { EC_PublicKey_Data::EC_PublicKey_Data(EC_Group group, std::span bytes) : m_group(std::move(group)), m_point(m_group, bytes), m_legacy_point(m_point.to_legacy_point()) {} -EC_PrivateKey_Data::EC_PrivateKey_Data(EC_Group group, RandomNumberGenerator& rng) : - m_group(std::move(group)), m_scalar(EC_Scalar::random(m_group, rng)), m_legacy_x(m_scalar.to_bigint()) {} - EC_PrivateKey_Data::EC_PrivateKey_Data(EC_Group group, const BigInt& x) : m_group(std::move(group)), m_scalar(EC_Scalar::from_bigint(m_group, x)), m_legacy_x(m_scalar.to_bigint()) {} diff --git a/src/lib/pubkey/ecc_key/ec_key_data.h b/src/lib/pubkey/ecc_key/ec_key_data.h index f58cffe7f24..33650f59271 100644 --- a/src/lib/pubkey/ecc_key/ec_key_data.h +++ b/src/lib/pubkey/ecc_key/ec_key_data.h @@ -39,8 +39,6 @@ class EC_PublicKey_Data final { class EC_PrivateKey_Data final { public: - EC_PrivateKey_Data(EC_Group group, RandomNumberGenerator& rng); - EC_PrivateKey_Data(EC_Group group, const BigInt& x); EC_PrivateKey_Data(EC_Group group, EC_Scalar x); diff --git a/src/lib/pubkey/ecc_key/ecc_key.cpp b/src/lib/pubkey/ecc_key/ecc_key.cpp index 65e35a6ff6b..1238883568e 100644 --- a/src/lib/pubkey/ecc_key/ecc_key.cpp +++ b/src/lib/pubkey/ecc_key/ecc_key.cpp @@ -124,22 +124,26 @@ EC_PrivateKey::EC_PrivateKey(RandomNumberGenerator& rng, EC_Group ec_group, const BigInt& x, bool with_modular_inverse) { - if(x == 0) { - m_private_key = std::make_shared(std::move(ec_group), rng); - } else { - m_private_key = std::make_shared(std::move(ec_group), x); - } - + auto scalar = (x.is_zero()) ? EC_Scalar::random(ec_group, rng) : EC_Scalar::from_bigint(ec_group, x); + m_private_key = std::make_shared(std::move(ec_group), std::move(scalar)); m_public_key = m_private_key->public_key(rng, with_modular_inverse); m_domain_encoding = default_encoding_for(domain()); } EC_PrivateKey::EC_PrivateKey(RandomNumberGenerator& rng, EC_Group ec_group, bool with_modular_inverse) { - m_private_key = std::make_shared(std::move(ec_group), rng); + auto scalar = EC_Scalar::random(ec_group, rng); + m_private_key = std::make_shared(std::move(ec_group), std::move(scalar)); m_public_key = m_private_key->public_key(rng, with_modular_inverse); m_domain_encoding = default_encoding_for(domain()); } +EC_PrivateKey::EC_PrivateKey(EC_Group group, const BigInt& bn_scalar, bool with_modular_inverse) { + auto scalar = EC_Scalar::from_bigint(group, bn_scalar); + m_private_key = std::make_shared(std::move(group), std::move(scalar)); + m_public_key = m_private_key->public_key(with_modular_inverse); + m_domain_encoding = default_encoding_for(domain()); +} + EC_PrivateKey::EC_PrivateKey(EC_Group ec_group, EC_Scalar x, bool with_modular_inverse) { m_private_key = std::make_shared(std::move(ec_group), std::move(x)); m_public_key = m_private_key->public_key(with_modular_inverse); diff --git a/src/lib/pubkey/ecc_key/ecc_key.h b/src/lib/pubkey/ecc_key/ecc_key.h index 3578c94169c..822ff446eaf 100644 --- a/src/lib/pubkey/ecc_key/ecc_key.h +++ b/src/lib/pubkey/ecc_key/ecc_key.h @@ -173,6 +173,9 @@ class BOTAN_PUBLIC_API(2, 0) EC_PrivateKey : public virtual EC_PublicKey, * the base point with the modular inverse of * x (as in ECGDSA and ECKCDSA), otherwise by * multiplying directly with x (as in ECDSA). + * + * TODO: Remove, once the respective deprecated constructors of the + * concrete ECC algorithms is removed. */ EC_PrivateKey(RandomNumberGenerator& rng, EC_Group domain, const BigInt& x, bool with_modular_inverse = false); @@ -185,6 +188,15 @@ class BOTAN_PUBLIC_API(2, 0) EC_PrivateKey : public virtual EC_PublicKey, */ EC_PrivateKey(RandomNumberGenerator& rng, EC_Group group, bool with_modular_inverse = false); + /** + * Load a EC private key from the secret scalar + * + * If @p with_modular_inverse is set, the public key will be calculated by + * multiplying the base point with the modular inverse of x (as in ECGDSA + * and ECKCDSA), otherwise by multiplying directly with x (as in ECDSA). + */ + EC_PrivateKey(EC_Group group, const BigInt& scalar, bool with_modular_inverse = false); + /** * Load a EC private key from the secret scalar * diff --git a/src/lib/pubkey/ecdh/ecdh.h b/src/lib/pubkey/ecdh/ecdh.h index 2c43cc7565d..0175d105e5a 100644 --- a/src/lib/pubkey/ecdh/ecdh.h +++ b/src/lib/pubkey/ecdh/ecdh.h @@ -77,13 +77,28 @@ class BOTAN_PUBLIC_API(2, 0) ECDH_PrivateKey final : public ECDH_PublicKey, ECDH_PrivateKey(const AlgorithmIdentifier& alg_id, std::span key_bits) : EC_PrivateKey(alg_id, key_bits) {} + /** + * Create a private key from a given secret @p x + * @param domain curve parameters to bu used for this key + * @param x the private key + */ + ECDH_PrivateKey(EC_Group domain, const BigInt& x) : EC_PrivateKey(std::move(domain), x) {} + + /** + * Create a new private key + * @param rng a random number generator + * @param domain parameters to used for this key + */ + ECDH_PrivateKey(RandomNumberGenerator& rng, EC_Group domain) : EC_PrivateKey(rng, std::move(domain)) {} + /** * Generate a new private key * @param rng a random number generator * @param domain parameters to used for this key * @param x the private key; if zero, a new random key is generated */ - ECDH_PrivateKey(RandomNumberGenerator& rng, const EC_Group& domain, const BigInt& x = BigInt::zero()) : + BOTAN_DEPRECATED("Use one of the other constructors") + ECDH_PrivateKey(RandomNumberGenerator& rng, const EC_Group& domain, const BigInt& x) : EC_PrivateKey(rng, domain, x) {} std::unique_ptr public_key() const override; diff --git a/src/lib/pubkey/ecdsa/ecdsa.h b/src/lib/pubkey/ecdsa/ecdsa.h index 9376938a9d9..85a48c03c97 100644 --- a/src/lib/pubkey/ecdsa/ecdsa.h +++ b/src/lib/pubkey/ecdsa/ecdsa.h @@ -90,13 +90,28 @@ class BOTAN_PUBLIC_API(2, 0) ECDSA_PrivateKey final : public ECDSA_PublicKey, ECDSA_PrivateKey(const AlgorithmIdentifier& alg_id, std::span key_bits) : EC_PrivateKey(alg_id, key_bits) {} + /** + * Create a private key from a given secret @p x + * @param domain curve parameters to bu used for this key + * @param x the private key + */ + ECDSA_PrivateKey(EC_Group domain, const BigInt& x) : EC_PrivateKey(std::move(domain), x) {} + + /** + * Create a new private key + * @param rng a random number generator + * @param domain parameters to used for this key + */ + ECDSA_PrivateKey(RandomNumberGenerator& rng, EC_Group domain) : EC_PrivateKey(rng, std::move(domain)) {} + /** * Create a private key. * @param rng a random number generator * @param domain parameters to used for this key * @param x the private key (if zero, generate a new random key) */ - ECDSA_PrivateKey(RandomNumberGenerator& rng, const EC_Group& domain, const BigInt& x = BigInt::zero()) : + BOTAN_DEPRECATED("Use one of the other constructors") + ECDSA_PrivateKey(RandomNumberGenerator& rng, const EC_Group& domain, const BigInt& x) : EC_PrivateKey(rng, domain, x) {} bool check_key(RandomNumberGenerator& rng, bool) const override; diff --git a/src/lib/pubkey/ecgdsa/ecgdsa.h b/src/lib/pubkey/ecgdsa/ecgdsa.h index 7b176c6c173..838a6c12f1a 100644 --- a/src/lib/pubkey/ecgdsa/ecgdsa.h +++ b/src/lib/pubkey/ecgdsa/ecgdsa.h @@ -74,13 +74,29 @@ class BOTAN_PUBLIC_API(2, 0) ECGDSA_PrivateKey final : public ECGDSA_PublicKey, ECGDSA_PrivateKey(const AlgorithmIdentifier& alg_id, std::span key_bits) : EC_PrivateKey(alg_id, key_bits, true) {} + /** + * Create a private key from a given secret @p x + * @param domain curve parameters to bu used for this key + * @param x the private key + */ + ECGDSA_PrivateKey(EC_Group domain, const BigInt& x) : EC_PrivateKey(std::move(domain), x, true) {} + + /** + * Create a new private key + * @param rng a random number generator + * @param domain parameters to used for this key + */ + ECGDSA_PrivateKey(RandomNumberGenerator& rng, EC_Group domain) : + EC_PrivateKey(rng, std::move(domain), BigInt::zero(), true) {} + /** * Generate a new private key. * @param rng a random number generator * @param domain parameters to used for this key * @param x the private key (if zero, generate a new random key) */ - ECGDSA_PrivateKey(RandomNumberGenerator& rng, const EC_Group& domain, const BigInt& x = BigInt::zero()) : + BOTAN_DEPRECATED("Use one of the other constructors") + ECGDSA_PrivateKey(RandomNumberGenerator& rng, const EC_Group& domain, const BigInt& x) : EC_PrivateKey(rng, domain, x, true) {} std::unique_ptr public_key() const override; diff --git a/src/lib/pubkey/eckcdsa/eckcdsa.h b/src/lib/pubkey/eckcdsa/eckcdsa.h index 365481539df..3ecc6e10585 100644 --- a/src/lib/pubkey/eckcdsa/eckcdsa.h +++ b/src/lib/pubkey/eckcdsa/eckcdsa.h @@ -73,13 +73,29 @@ class BOTAN_PUBLIC_API(2, 0) ECKCDSA_PrivateKey final : public ECKCDSA_PublicKey ECKCDSA_PrivateKey(const AlgorithmIdentifier& alg_id, std::span key_bits) : EC_PrivateKey(alg_id, key_bits, true) {} + /** + * Create a private key from a given secret @p x + * @param domain curve parameters to bu used for this key + * @param x the private key + */ + ECKCDSA_PrivateKey(EC_Group domain, const BigInt& x) : EC_PrivateKey(std::move(domain), x, true) {} + + /** + * Create a new private key + * @param rng a random number generator + * @param domain parameters to used for this key + */ + ECKCDSA_PrivateKey(RandomNumberGenerator& rng, EC_Group domain) : + EC_PrivateKey(rng, std::move(domain), BigInt::zero(), true) {} + /** * Create a private key. * @param rng a random number generator * @param domain parameters to used for this key * @param x the private key (if zero, generate a new random key) */ - ECKCDSA_PrivateKey(RandomNumberGenerator& rng, const EC_Group& domain, const BigInt& x = BigInt::zero()) : + BOTAN_DEPRECATED("Use one of the other constructors") + ECKCDSA_PrivateKey(RandomNumberGenerator& rng, const EC_Group& domain, const BigInt& x) : EC_PrivateKey(rng, domain, x, true) {} bool check_key(RandomNumberGenerator& rng, bool) const override; diff --git a/src/lib/pubkey/gost_3410/gost_3410.cpp b/src/lib/pubkey/gost_3410/gost_3410.cpp index 1747b321fd3..53619e665d4 100644 --- a/src/lib/pubkey/gost_3410/gost_3410.cpp +++ b/src/lib/pubkey/gost_3410/gost_3410.cpp @@ -17,6 +17,18 @@ namespace Botan { +namespace { + +EC_Group check_domain(EC_Group domain) { + const size_t p_bits = domain.get_p_bits(); + if(p_bits != 256 && p_bits != 512) { + throw Decoding_Error(fmt("GOST-34.10-2012 is not defined for parameters of size {}", p_bits)); + } + return domain; +} + +} // namespace + std::vector GOST_3410_PublicKey::public_key_bits() const { auto bits = public_point().xy_bytes(); @@ -60,17 +72,12 @@ GOST_3410_PublicKey::GOST_3410_PublicKey(const AlgorithmIdentifier& alg_id, std: // The parameters also includes hash and cipher OIDs BER_Decoder(alg_id.parameters()).start_sequence().decode(ecc_param_id); - auto group = EC_Group::from_OID(ecc_param_id); - - const size_t p_bits = group.get_p_bits(); - if(p_bits != 256 && p_bits != 512) { - throw Decoding_Error(fmt("GOST-34.10-2012 is not defined for parameters of size {}", p_bits)); - } + auto group = check_domain(EC_Group::from_OID(ecc_param_id)); std::vector bits; BER_Decoder(key_bits).decode(bits, ASN1_Type::OctetString); - if(bits.size() != 2 * (p_bits / 8)) { + if(bits.size() != 2 * (group.get_p_bits() / 8)) { throw Decoding_Error("GOST-34.10-2012 invalid encoding of public key"); } @@ -86,13 +93,14 @@ GOST_3410_PublicKey::GOST_3410_PublicKey(const AlgorithmIdentifier& alg_id, std: m_public_key = std::make_shared(std::move(group), encoding); } +GOST_3410_PrivateKey::GOST_3410_PrivateKey(const EC_Group& domain, const BigInt& x) : + EC_PrivateKey(check_domain(domain), EC_Scalar::from_bigint(domain, x)) {} + +GOST_3410_PrivateKey::GOST_3410_PrivateKey(RandomNumberGenerator& rng, EC_Group domain) : + EC_PrivateKey(rng, check_domain(std::move(domain))) {} + GOST_3410_PrivateKey::GOST_3410_PrivateKey(RandomNumberGenerator& rng, const EC_Group& domain, const BigInt& x) : - EC_PrivateKey(rng, domain, x) { - const size_t p_bits = domain.get_p_bits(); - if(p_bits != 256 && p_bits != 512) { - throw Decoding_Error(fmt("GOST-34.10-2012 is not defined for parameters of size {}", p_bits)); - } -} + EC_PrivateKey(rng, check_domain(domain), x) {} std::unique_ptr GOST_3410_PrivateKey::public_key() const { return std::make_unique(domain(), public_point()); diff --git a/src/lib/pubkey/gost_3410/gost_3410.h b/src/lib/pubkey/gost_3410/gost_3410.h index 74283ff83fb..45e89d0f3df 100644 --- a/src/lib/pubkey/gost_3410/gost_3410.h +++ b/src/lib/pubkey/gost_3410/gost_3410.h @@ -82,13 +82,28 @@ class BOTAN_PUBLIC_API(2, 0) GOST_3410_PrivateKey final : public GOST_3410_Publi GOST_3410_PrivateKey(const AlgorithmIdentifier& alg_id, std::span key_bits) : EC_PrivateKey(alg_id, key_bits) {} + /** + * Create a private key from a given secret @p x + * @param domain curve parameters to bu used for this key + * @param x the private key + */ + GOST_3410_PrivateKey(const EC_Group& domain, const BigInt& x); + + /** + * Create a new private key + * @param rng a random number generator + * @param domain parameters to used for this key + */ + GOST_3410_PrivateKey(RandomNumberGenerator& rng, EC_Group domain); + /** * Generate a new private key * @param rng a random number generator * @param domain parameters to used for this key * @param x the private key; if zero, a new random key is generated */ - GOST_3410_PrivateKey(RandomNumberGenerator& rng, const EC_Group& domain, const BigInt& x = BigInt::zero()); + BOTAN_DEPRECATED("Use one of the other constructors") + GOST_3410_PrivateKey(RandomNumberGenerator& rng, const EC_Group& domain, const BigInt& x); std::unique_ptr public_key() const override; diff --git a/src/lib/pubkey/sm2/sm2.cpp b/src/lib/pubkey/sm2/sm2.cpp index 8f1db0ad8d3..dfcc9c80ef5 100644 --- a/src/lib/pubkey/sm2/sm2.cpp +++ b/src/lib/pubkey/sm2/sm2.cpp @@ -51,6 +51,16 @@ SM2_PrivateKey::SM2_PrivateKey(const AlgorithmIdentifier& alg_id, std::span_private_key() + EC_Scalar::one(domain())).invert()), m_da_inv_legacy(m_da_inv.to_bigint()) {} +SM2_PrivateKey::SM2_PrivateKey(EC_Group group, const BigInt& x) : + EC_PrivateKey(std::move(group), x), + m_da_inv((this->_private_key() + EC_Scalar::one(domain())).invert()), + m_da_inv_legacy(m_da_inv.to_bigint()) {} + +SM2_PrivateKey::SM2_PrivateKey(RandomNumberGenerator& rng, EC_Group group) : + EC_PrivateKey(rng, std::move(group)), + m_da_inv((this->_private_key() + EC_Scalar::one(domain())).invert()), + m_da_inv_legacy(m_da_inv.to_bigint()) {} + SM2_PrivateKey::SM2_PrivateKey(RandomNumberGenerator& rng, EC_Group group, const BigInt& x) : EC_PrivateKey(rng, std::move(group), x), m_da_inv((this->_private_key() + EC_Scalar::one(domain())).invert()), diff --git a/src/lib/pubkey/sm2/sm2.h b/src/lib/pubkey/sm2/sm2.h index 2f4e540ac7a..3dde593d634 100644 --- a/src/lib/pubkey/sm2/sm2.h +++ b/src/lib/pubkey/sm2/sm2.h @@ -76,13 +76,28 @@ class BOTAN_PUBLIC_API(2, 2) SM2_PrivateKey final : public SM2_PublicKey, */ SM2_PrivateKey(const AlgorithmIdentifier& alg_id, std::span key_bits); + /** + * Create a private key from a given secret @p x + * @param domain curve parameters to bu used for this key + * @param x the private key + */ + SM2_PrivateKey(EC_Group domain, const BigInt& x); + + /** + * Create a new private key + * @param rng a random number generator + * @param domain parameters to used for this key + */ + SM2_PrivateKey(RandomNumberGenerator& rng, EC_Group domain); + /** * Create a private key. * @param rng a random number generator * @param domain parameters to used for this key * @param x the private key (if zero, generate a new random key) */ - SM2_PrivateKey(RandomNumberGenerator& rng, EC_Group domain, const BigInt& x = BigInt::zero()); + BOTAN_DEPRECATED("Use one of the other constructors") + SM2_PrivateKey(RandomNumberGenerator& rng, EC_Group domain, const BigInt& x); bool check_key(RandomNumberGenerator& rng, bool) const override;