diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cli/pubkey.cpp | 89 | ||||
-rw-r--r-- | src/cli/speed.cpp | 6 | ||||
-rw-r--r-- | src/lib/ffi/ffi.cpp | 31 | ||||
-rw-r--r-- | src/lib/ffi/ffi.h | 7 | ||||
-rw-r--r-- | src/lib/pubkey/info.txt | 2 | ||||
-rw-r--r-- | src/lib/pubkey/pk_algs.cpp | 217 | ||||
-rw-r--r-- | src/lib/pubkey/pk_algs.h | 29 | ||||
-rw-r--r-- | src/lib/pubkey/pkcs8.cpp | 4 | ||||
-rw-r--r-- | src/lib/pubkey/x509_key.cpp | 4 |
9 files changed, 236 insertions, 153 deletions
diff --git a/src/cli/pubkey.cpp b/src/cli/pubkey.cpp index 1c3f948d1..cb23ddb66 100644 --- a/src/cli/pubkey.cpp +++ b/src/cli/pubkey.cpp @@ -12,6 +12,7 @@ #include <botan/base64.h> #include <botan/pk_keys.h> +#include <botan/pk_algs.h> #include <botan/pkcs8.h> #include <botan/pubkey.h> @@ -19,26 +20,6 @@ #include <botan/dl_group.h> #endif -#if defined(BOTAN_HAS_RSA) - #include <botan/rsa.h> -#endif - -#if defined(BOTAN_HAS_DSA) - #include <botan/dsa.h> -#endif - -#if defined(BOTAN_HAS_ECDSA) - #include <botan/ecdsa.h> -#endif - -#if defined(BOTAN_HAS_CURVE_25519) - #include <botan/curve25519.h> -#endif - -#if defined(BOTAN_HAS_MCELIECE) - #include <botan/mceliece.h> -#endif - namespace Botan_CLI { class PK_Keygen final : public Command @@ -46,75 +27,19 @@ class PK_Keygen final : public Command public: PK_Keygen() : Command("keygen --algo=RSA --params= --passphrase= --pbe= --pbe-millis=300 --der-out") {} - static std::unique_ptr<Botan::Private_Key> do_keygen(const std::string& algo, - const std::string& params, - Botan::RandomNumberGenerator& rng) + void go() override { - typedef std::function<std::unique_ptr<Botan::Private_Key> (std::string)> gen_fn; - std::map<std::string, gen_fn> generators; - -#if defined(BOTAN_HAS_RSA) - generators["RSA"] = [&rng](std::string param) -> std::unique_ptr<Botan::Private_Key> { - if(param.empty()) - param = "2048"; - return std::unique_ptr<Botan::Private_Key>( - new Botan::RSA_PrivateKey(rng, Botan::to_u32bit(param))); - }; -#endif + const std::string algo = get_arg("algo"); + const std::string params = get_arg("params"); -#if defined(BOTAN_HAS_DSA) - generators["DSA"] = [&rng](std::string param) -> std::unique_ptr<Botan::Private_Key> { - if(param.empty()) - param = "dsa/botan/2048"; - return std::unique_ptr<Botan::Private_Key>( - new Botan::DSA_PrivateKey(rng, Botan::DL_Group(param))); - }; -#endif + std::unique_ptr<Botan::Private_Key> + key(Botan::create_private_key(algo, rng(), params)); -#if defined(BOTAN_HAS_ECDSA) - generators["ECDSA"] = [&rng](std::string param) { - if(param.empty()) - param = "secp256r1"; - Botan::EC_Group grp(param); - return std::unique_ptr<Botan::Private_Key>( - new Botan::ECDSA_PrivateKey(rng, grp)); - }; -#endif - -#if defined(BOTAN_HAS_CURVE_25519) - generators["Curve25519"] = [&rng](std::string /*ignored*/) { - return std::unique_ptr<Botan::Private_Key>( - new Botan::Curve25519_PrivateKey(rng)); - }; -#endif - -#if defined(BOTAN_HAS_MCELIECE) - generators["McEliece"] = [&rng](std::string param) { - if(param.empty()) - param = "2280,45"; - std::vector<std::string> param_parts = Botan::split_on(param, ','); - if(param_parts.size() != 2) - throw CLI_Usage_Error("Bad McEliece parameters " + param); - return std::unique_ptr<Botan::Private_Key>( - new Botan::McEliece_PrivateKey(rng, - Botan::to_u32bit(param_parts[0]), - Botan::to_u32bit(param_parts[1]))); - }; -#endif - - auto gen = generators.find(algo); - if(gen == generators.end()) + if(!key) { throw CLI_Error_Unsupported("keygen", algo); } - return gen->second(params); - } - - void go() override - { - std::unique_ptr<Botan::Private_Key> key(do_keygen(get_arg("algo"), get_arg("params"), rng())); - const std::string pass = get_arg("passphrase"); const bool der_out = flag_set("der-out"); diff --git a/src/cli/speed.cpp b/src/cli/speed.cpp index b44c6df99..e6d4a6b7f 100644 --- a/src/cli/speed.cpp +++ b/src/cli/speed.cpp @@ -596,16 +596,18 @@ class Speed final : public Command ks_timer.run([&] { enc.set_key(key); }); ks_timer.run([&] { dec.set_key(key); }); + Botan::secure_vector<uint8_t> iv = rng().random_vec(enc.default_nonce_length()); + while(encrypt_timer.under(runtime) && decrypt_timer.under(runtime)) { - const Botan::secure_vector<uint8_t> iv = rng().random_vec(enc.default_nonce_length()); - // Must run in this order, or AEADs will reject the ciphertext iv_timer.run([&] { enc.start(iv); }); encrypt_timer.run([&] { enc.finish(buffer); }); iv_timer.run([&] { dec.start(iv); }); decrypt_timer.run([&] { dec.finish(buffer); }); + + iv[0] += 1; } output() << Timer::result_string_ops(ks_timer); diff --git a/src/lib/ffi/ffi.cpp b/src/lib/ffi/ffi.cpp index aaa89ff5d..88a34c3cc 100644 --- a/src/lib/ffi/ffi.cpp +++ b/src/lib/ffi/ffi.cpp @@ -21,6 +21,7 @@ #include <botan/hex.h> #include <botan/mem_ops.h> #include <botan/x509_key.h> +#include <botan/pk_algs.h> #include <cstring> #include <memory> @@ -730,6 +731,36 @@ int botan_bcrypt_is_valid(const char* pass, const char* hash) return BOTAN_FFI_ERROR_EXCEPTION_THROWN; } +int botan_privkey_create(botan_privkey_t* key_obj, + const char* algo_name, + const char* algo_params, + botan_rng_t rng_obj) + { + try + { + if(key_obj == nullptr || rng_obj == nullptr) + return -1; + if(algo_name == nullptr) + algo_name = "RSA"; + if(algo_params == nullptr) + algo_name = ""; + + *key_obj = nullptr; + + Botan::RandomNumberGenerator& rng = safe_get(rng_obj); + std::unique_ptr<Botan::Private_Key> key( + Botan::create_private_key(algo_name, rng, algo_params)); + *key_obj = new botan_privkey_struct(key.release()); + return 0; + } + catch(std::exception& e) + { + log_exception(BOTAN_CURRENT_FUNCTION, e.what()); + } + + return BOTAN_FFI_ERROR_EXCEPTION_THROWN; + } + int botan_privkey_create_rsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n_bits) { try diff --git a/src/lib/ffi/ffi.h b/src/lib/ffi/ffi.h index 165554105..83aa9545d 100644 --- a/src/lib/ffi/ffi.h +++ b/src/lib/ffi/ffi.h @@ -295,9 +295,12 @@ BOTAN_DLL int botan_bcrypt_is_valid(const char* pass, const char* hash); */ typedef struct botan_privkey_struct* botan_privkey_t; +BOTAN_DLL int botan_privkey_create(botan_privkey_t* key, + const char* algo_name, + const char* algo_params, + botan_rng_t rng); + BOTAN_DLL int botan_privkey_create_rsa(botan_privkey_t* key, botan_rng_t rng, size_t n_bits); -//BOTAN_DLL int botan_privkey_create_dsa(botan_privkey_t* key, botan_rng_t rng, size_t p_bits, size_t q_bits); -//BOTAN_DLL int botan_privkey_create_dh(botan_privkey_t* key, botan_rng_t rng, size_t p_bits); BOTAN_DLL int botan_privkey_create_ecdsa(botan_privkey_t* key, botan_rng_t rng, const char* params); BOTAN_DLL int botan_privkey_create_ecdh(botan_privkey_t* key, botan_rng_t rng, const char* params); BOTAN_DLL int botan_privkey_create_mceliece(botan_privkey_t* key, botan_rng_t rng, size_t n, size_t t); diff --git a/src/lib/pubkey/info.txt b/src/lib/pubkey/info.txt index 0e799f372..7692b0614 100644 --- a/src/lib/pubkey/info.txt +++ b/src/lib/pubkey/info.txt @@ -13,6 +13,7 @@ x509_key.cpp <header:public> blinding.h +pk_algs.h pk_keys.h pk_ops_fwd.h pkcs8.h @@ -22,7 +23,6 @@ x509_key.h </header:public> <header:internal> -pk_algs.h pk_ops.h pk_ops_impl.h </header:internal> diff --git a/src/lib/pubkey/pk_algs.cpp b/src/lib/pubkey/pk_algs.cpp index ac6f4a11f..f04f189f7 100644 --- a/src/lib/pubkey/pk_algs.cpp +++ b/src/lib/pubkey/pk_algs.cpp @@ -1,11 +1,11 @@ /* * PK Key -* (C) 1999-2010 Jack Lloyd +* (C) 1999-2010,2016 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ -#include <botan/internal/pk_algs.h> +#include <botan/pk_algs.h> #include <botan/oids.h> #if defined(BOTAN_HAS_RSA) @@ -54,8 +54,9 @@ namespace Botan { -Public_Key* make_public_key(const AlgorithmIdentifier& alg_id, - const secure_vector<byte>& key_bits) +std::unique_ptr<Public_Key> +load_public_key(const AlgorithmIdentifier& alg_id, + const secure_vector<byte>& key_bits) { const std::string alg_name = OIDS::lookup(alg_id.oid); if(alg_name == "") @@ -63,65 +64,66 @@ Public_Key* make_public_key(const AlgorithmIdentifier& alg_id, #if defined(BOTAN_HAS_RSA) if(alg_name == "RSA") - return new RSA_PublicKey(alg_id, key_bits); + return std::unique_ptr<Public_Key>(new RSA_PublicKey(alg_id, key_bits)); #endif -#if defined(BOTAN_HAS_DSA) - if(alg_name == "DSA") - return new DSA_PublicKey(alg_id, key_bits); +#if defined(BOTAN_HAS_CURVE_25519) + if(alg_name == "Curve25519") + return std::unique_ptr<Public_Key>(new Curve25519_PublicKey(alg_id, key_bits)); +#endif + +#if defined(BOTAN_HAS_MCELIECE) + if(alg_name == "McEliece") + return std::unique_ptr<Public_Key>(new McEliece_PublicKey(unlock(key_bits))); +#endif + +#if defined(BOTAN_HAS_ECDSA) + if(alg_name == "ECDSA") + return std::unique_ptr<Public_Key>(new ECDSA_PublicKey(alg_id, key_bits)); +#endif + +#if defined(BOTAN_HAS_ECDH) + if(alg_name == "ECDH") + return std::unique_ptr<Public_Key>(new ECDH_PublicKey(alg_id, key_bits)); #endif #if defined(BOTAN_HAS_DIFFIE_HELLMAN) if(alg_name == "DH") - return new DH_PublicKey(alg_id, key_bits); + return std::unique_ptr<Public_Key>(new DH_PublicKey(alg_id, key_bits)); #endif -#if defined(BOTAN_HAS_ELGAMAL) - if(alg_name == "ElGamal") - return new ElGamal_PublicKey(alg_id, key_bits); +#if defined(BOTAN_HAS_DSA) + if(alg_name == "DSA") + return std::unique_ptr<Public_Key>(new DSA_PublicKey(alg_id, key_bits)); #endif -#if defined(BOTAN_HAS_ECDSA) - if(alg_name == "ECDSA") - return new ECDSA_PublicKey(alg_id, key_bits); +#if defined(BOTAN_HAS_ELGAMAL) + if(alg_name == "ElGamal") + return std::unique_ptr<Public_Key>(new ElGamal_PublicKey(alg_id, key_bits)); #endif #if defined(BOTAN_HAS_ECGDSA) if(alg_name == "ECGDSA") - return new ECGDSA_PublicKey(alg_id, key_bits); + return std::unique_ptr<Public_Key>(new ECGDSA_PublicKey(alg_id, key_bits)); #endif #if defined(BOTAN_HAS_ECKCDSA) if(alg_name == "ECKCDSA") - return new ECKCDSA_PublicKey(alg_id, key_bits); + return std::unique_ptr<Public_Key>(new ECKCDSA_PublicKey(alg_id, key_bits)); #endif #if defined(BOTAN_HAS_GOST_34_10_2001) if(alg_name == "GOST-34.10") - return new GOST_3410_PublicKey(alg_id, key_bits); -#endif - -#if defined(BOTAN_HAS_ECDH) - if(alg_name == "ECDH") - return new ECDH_PublicKey(alg_id, key_bits); -#endif - -#if defined(BOTAN_HAS_CURVE_25519) - if(alg_name == "Curve25519") - return new Curve25519_PublicKey(alg_id, key_bits); -#endif - -#if defined(BOTAN_HAS_MCELIECE) - if(alg_name == "McEliece") - return new McEliece_PublicKey(unlock(key_bits)); + return std::unique_ptr<Public_Key>(new GOST_3410_PublicKey(alg_id, key_bits)); #endif throw Decoding_Error("Unhandled PK algorithm " + alg_name); } -Private_Key* make_private_key(const AlgorithmIdentifier& alg_id, - const secure_vector<byte>& key_bits, - RandomNumberGenerator& rng) +std::unique_ptr<Private_Key> +load_private_key(const AlgorithmIdentifier& alg_id, + const secure_vector<byte>& key_bits, + RandomNumberGenerator& rng) { const std::string alg_name = OIDS::lookup(alg_id.oid); if(alg_name == "") @@ -129,60 +131,163 @@ Private_Key* make_private_key(const AlgorithmIdentifier& alg_id, #if defined(BOTAN_HAS_RSA) if(alg_name == "RSA") - return new RSA_PrivateKey(alg_id, key_bits, rng); + return std::unique_ptr<Private_Key>(new RSA_PrivateKey(alg_id, key_bits, rng)); #endif -#if defined(BOTAN_HAS_DSA) - if(alg_name == "DSA") - return new DSA_PrivateKey(alg_id, key_bits, rng); +#if defined(BOTAN_HAS_CURVE_25519) + if(alg_name == "Curve25519") + return std::unique_ptr<Private_Key>(new Curve25519_PrivateKey(alg_id, key_bits, rng)); +#endif + +#if defined(BOTAN_HAS_ECDSA) + if(alg_name == "ECDSA") + return std::unique_ptr<Private_Key>(new ECDSA_PrivateKey(alg_id, key_bits)); +#endif + +#if defined(BOTAN_HAS_ECDH) + if(alg_name == "ECDH") + return std::unique_ptr<Private_Key>(new ECDH_PrivateKey(alg_id, key_bits)); #endif #if defined(BOTAN_HAS_DIFFIE_HELLMAN) if(alg_name == "DH") - return new DH_PrivateKey(alg_id, key_bits, rng); + return std::unique_ptr<Private_Key>(new DH_PrivateKey(alg_id, key_bits, rng)); #endif -#if defined(BOTAN_HAS_ELGAMAL) - if(alg_name == "ElGamal") - return new ElGamal_PrivateKey(alg_id, key_bits, rng); +#if defined(BOTAN_HAS_DSA) + if(alg_name == "DSA") + return std::unique_ptr<Private_Key>(new DSA_PrivateKey(alg_id, key_bits, rng)); #endif -#if defined(BOTAN_HAS_ECDSA) - if(alg_name == "ECDSA") - return new ECDSA_PrivateKey(alg_id, key_bits); +#if defined(BOTAN_HAS_MCELIECE) + if(alg_name == "McEliece") + return std::unique_ptr<Private_Key>(new McEliece_PrivateKey(key_bits)); #endif #if defined(BOTAN_HAS_ECGDSA) if(alg_name == "ECGDSA") - return new ECGDSA_PrivateKey(alg_id, key_bits); + return std::unique_ptr<Private_Key>(new ECGDSA_PrivateKey(alg_id, key_bits)); #endif #if defined(BOTAN_HAS_ECKCDSA) if(alg_name == "ECKCDSA") - return new ECKCDSA_PrivateKey(alg_id, key_bits); + return std::unique_ptr<Private_Key>(new ECKCDSA_PrivateKey(alg_id, key_bits)); #endif #if defined(BOTAN_HAS_GOST_34_10_2001) if(alg_name == "GOST-34.10") - return new GOST_3410_PrivateKey(alg_id, key_bits); + return std::unique_ptr<Private_Key>(new GOST_3410_PrivateKey(alg_id, key_bits)); #endif -#if defined(BOTAN_HAS_ECDH) - if(alg_name == "ECDH") - return new ECDH_PrivateKey(alg_id, key_bits); +#if defined(BOTAN_HAS_ELGAMAL) + if(alg_name == "ElGamal") + return std::unique_ptr<Private_Key>(new ElGamal_PrivateKey(alg_id, key_bits, rng)); #endif + throw Decoding_Error("Unhandled PK algorithm " + alg_name); + } + +std::unique_ptr<Private_Key> +create_private_key(const std::string& alg_name, + RandomNumberGenerator& rng, + const std::string& params) + { + /* + * Default paramaters are chosen for work factor > 2**128 where possible + */ + #if defined(BOTAN_HAS_CURVE_25519) if(alg_name == "Curve25519") - return new Curve25519_PrivateKey(alg_id, key_bits, rng); + return std::unique_ptr<Private_Key>(new Curve25519_PrivateKey(rng)); +#endif + +#if defined(BOTAN_HAS_RSA) + if(alg_name == "RSA") + { + const size_t rsa_bits = (params.empty() ? 3072 : to_u32bit(params)); + return std::unique_ptr<Private_Key>(new RSA_PrivateKey(rng, rsa_bits)); + } #endif #if defined(BOTAN_HAS_MCELIECE) if(alg_name == "McEliece") - return new McEliece_PrivateKey(key_bits); + { + std::vector<std::string> mce_param = + Botan::split_on(params.empty() ? "2960,57" : params, ','); + + if(mce_param.size() != 2) + throw Invalid_Argument("create_private_key bad McEliece parameters " + params); + + size_t mce_n = Botan::to_u32bit(mce_param[0]); + size_t mce_t = Botan::to_u32bit(mce_param[1]); + + return std::unique_ptr<Botan::Private_Key>(new Botan::McEliece_PrivateKey(rng, mce_n, mce_t)); + } #endif - throw Decoding_Error("Unhandled PK algorithm " + alg_name); + // ECC crypto +#if defined(BOTAN_HAS_ECC_CRYPTO) + + if(alg_name == "ECDSA" || + alg_name == "ECDH" || + alg_name == "ECKCDSA" || + alg_name == "ECGDSA" || + alg_name == "GOST-34.10") + { + const EC_Group ec_group(params.empty() ? "secp256r1" : params); + +#if defined(BOTAN_HAS_ECDSA) + if(alg_name == "ECDSA") + return std::unique_ptr<Private_Key>(new ECDSA_PrivateKey(rng, ec_group)); +#endif + +#if defined(BOTAN_HAS_ECDH) + if(alg_name == "ECDH") + return std::unique_ptr<Private_Key>(new ECDH_PrivateKey(rng, ec_group)); +#endif + +#if defined(BOTAN_HAS_ECKCDSA) + if(alg_name == "ECKCDSA") + return std::unique_ptr<Private_Key>(new ECKCDSA_PrivateKey(rng, ec_group)); +#endif + +#if defined(BOTAN_HAS_GOST_34_10_2001) + if(alg_name == "GOST-34.10") + return std::unique_ptr<Private_Key>(new GOST_3410_PrivateKey(rng, ec_group)); +#endif + +#if defined(BOTAN_HAS_ECGDSA) + if(alg_name == "ECGDSA") + return std::unique_ptr<Private_Key>(new ECGDSA_PrivateKey(rng, ec_group)); +#endif + } +#endif + + // DL crypto +#if defined(BOTAN_HAS_DL_GROUP) + if(alg_name == "DH" || alg_name == "DSA" || alg_name == "ElGamal") + { + std::string default_group = (alg_name == "DSA") ? "dsa/botan/2048" : "modp/ietf/2048"; + DL_Group modp_group(params.empty() ? default_group : params); + +#if defined(BOTAN_HAS_DIFFIE_HELLMAN) + if(alg_name == "DH") + return std::unique_ptr<Private_Key>(new DH_PrivateKey(rng, modp_group)); +#endif + +#if defined(BOTAN_HAS_DSA) + if(alg_name == "DSA") + return std::unique_ptr<Private_Key>(new DSA_PrivateKey(rng, modp_group)); +#endif + +#if defined(BOTAN_HAS_ELGAMAL) + if(alg_name == "ElGamal") + return std::unique_ptr<Private_Key>(new ElGamal_PrivateKey(rng, modp_group)); +#endif + } +#endif + + return std::unique_ptr<Private_Key>(); } } diff --git a/src/lib/pubkey/pk_algs.h b/src/lib/pubkey/pk_algs.h index 804860ed1..c73f5365e 100644 --- a/src/lib/pubkey/pk_algs.h +++ b/src/lib/pubkey/pk_algs.h @@ -1,6 +1,6 @@ /* * PK Key Factory -* (C) 1999-2010 Jack Lloyd +* (C) 1999-2010,2016 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -9,15 +9,32 @@ #define BOTAN_PK_KEY_FACTORY_H__ #include <botan/pk_keys.h> +#include <botan/alg_id.h> +#include <memory> namespace Botan { -Public_Key* make_public_key(const AlgorithmIdentifier& alg_id, - const secure_vector<byte>& key_bits); +BOTAN_DLL std::unique_ptr<Public_Key> +load_public_key(const AlgorithmIdentifier& alg_id, + const secure_vector<byte>& key_bits); -Private_Key* make_private_key(const AlgorithmIdentifier& alg_id, - const secure_vector<byte>& key_bits, - RandomNumberGenerator& rng); +BOTAN_DLL std::unique_ptr<Private_Key> +load_private_key(const AlgorithmIdentifier& alg_id, + const secure_vector<byte>& key_bits, + RandomNumberGenerator& rng); + +/** +* Create a new key +* For ECC keys, algo_params specifies EC group (eg, "secp256r1") +* For DH/DSA/ElGamal keys, algo_params is DL group (eg, "modp/ietf/2048") +* For RSA, algo_params is integer keylength +* For McEliece, algo_params is n,t +* If algo_params is left empty, suitable default parameters are chosen. +*/ +BOTAN_DLL std::unique_ptr<Private_Key> +create_private_key(const std::string& algo_name, + RandomNumberGenerator& rng, + const std::string& algo_params = ""); } diff --git a/src/lib/pubkey/pkcs8.cpp b/src/lib/pubkey/pkcs8.cpp index 96dfd5e44..26cafdc4f 100644 --- a/src/lib/pubkey/pkcs8.cpp +++ b/src/lib/pubkey/pkcs8.cpp @@ -13,7 +13,7 @@ #include <botan/pem.h> #include <botan/pbes2.h> #include <botan/scan_name.h> -#include <botan/internal/pk_algs.h> +#include <botan/pk_algs.h> namespace Botan { @@ -227,7 +227,7 @@ Private_Key* load_key(DataSource& source, throw PKCS8_Exception("Unknown algorithm OID: " + alg_id.oid.as_string()); - return make_private_key(alg_id, pkcs8_key, rng); + return load_private_key(alg_id, pkcs8_key, rng).release(); } } diff --git a/src/lib/pubkey/x509_key.cpp b/src/lib/pubkey/x509_key.cpp index 08e17bfed..f4cfe805e 100644 --- a/src/lib/pubkey/x509_key.cpp +++ b/src/lib/pubkey/x509_key.cpp @@ -10,7 +10,7 @@ #include <botan/ber_dec.h> #include <botan/pem.h> #include <botan/alg_id.h> -#include <botan/internal/pk_algs.h> +#include <botan/pk_algs.h> namespace Botan { @@ -70,7 +70,7 @@ Public_Key* load_key(DataSource& source) if(key_bits.empty()) throw Decoding_Error("X.509 public key decoding failed"); - return make_public_key(alg_id, key_bits); + return load_public_key(alg_id, key_bits).release(); } catch(Decoding_Error& e) { |