8 #include <botan/pkcs8.h>
9 #include <botan/der_enc.h>
10 #include <botan/ber_dec.h>
11 #include <botan/alg_id.h>
12 #include <botan/oids.h>
13 #include <botan/pem.h>
14 #include <botan/pbes2.h>
15 #include <botan/scan_name.h>
16 #include <botan/pk_algs.h>
46 std::function<std::string ()> get_passphrase,
58 key_data = PKCS8_extract(source, pbe_alg_id);
69 key_data.push_back( b );
80 if(label ==
"PRIVATE KEY")
82 else if(label ==
"ENCRYPTED PRIVATE KEY")
85 key_data = PKCS8_extract(key_source, pbe_alg_id);
118 catch(std::exception& e)
120 throw Decoding_Error(
"PKCS #8 private key decoding failed: " + std::string(e.what()));
146 std::pair<std::string, std::string>
147 choose_pbe_params(
const std::string& pbe_algo,
const std::string& key_algo)
152 if(key_algo ==
"Curve25519" || key_algo ==
"McEliece")
153 return std::make_pair(
"AES-256/GCM",
"SHA-512");
155 return std::make_pair(
"AES-256/CBC",
"SHA-256");
158 SCAN_Name request(pbe_algo);
159 if(request.algo_name() !=
"PBE-PKCS5v20" || request.arg_count() != 2)
160 throw Exception(
"Unsupported PBE " + pbe_algo);
161 return std::make_pair(request.arg(1), request.arg(0));
171 const std::string& pass,
172 std::chrono::milliseconds msec,
173 const std::string& pbe_algo)
175 const auto pbe_params = choose_pbe_params(pbe_algo, key.
algo_name());
177 const std::pair<AlgorithmIdentifier, std::vector<uint8_t>> pbe_info =
179 pbe_params.first, pbe_params.second, rng);
194 const std::string& pass,
195 std::chrono::milliseconds msec,
196 const std::string& pbe_algo)
202 "ENCRYPTED PRIVATE KEY");
210 const std::string& pass,
211 size_t pbkdf_iterations,
212 const std::string& cipher,
213 const std::string& pbkdf_hash)
215 const std::pair<AlgorithmIdentifier, std::vector<uint8_t>> pbe_info =
217 pass, pbkdf_iterations,
218 cipher.empty() ?
"AES-256/CBC" : cipher,
219 pbkdf_hash.empty() ?
"SHA-256" : pbkdf_hash,
235 const std::string& pass,
236 size_t pbkdf_iterations,
237 const std::string& cipher,
238 const std::string& pbkdf_hash)
242 "ENCRYPTED PRIVATE KEY");
250 const std::string& pass,
251 std::chrono::milliseconds pbkdf_msec,
252 size_t* pbkdf_iterations,
253 const std::string& cipher,
254 const std::string& pbkdf_hash)
256 const std::pair<AlgorithmIdentifier, std::vector<uint8_t>> pbe_info =
258 pbkdf_msec, pbkdf_iterations,
259 cipher.empty() ?
"AES-256/CBC" : cipher,
260 pbkdf_hash.empty() ?
"SHA-256" : pbkdf_hash,
276 const std::string& pass,
277 std::chrono::milliseconds pbkdf_msec,
278 size_t* pbkdf_iterations,
279 const std::string& cipher,
280 const std::string& pbkdf_hash)
284 "ENCRYPTED PRIVATE KEY");
294 std::function<std::string ()> get_pass,
301 if(alg_name.empty() || alg_name == alg_id.
oid.
as_string())
315 std::function<std::string ()> get_pass)
317 return load_key(source, rng, get_pass,
true);
325 const std::string& pass)
327 return load_key(source, rng, [pass]() {
return pass; },
true);
336 return load_key(source, rng, []() -> std::string {
337 throw PKCS8_Exception(
"Internal error: Attempt to read password for unencrypted key" );},
false);
340 #if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
347 std::function<std::string ()> get_pass)
350 return load_key(source, rng, get_pass,
true);
356 Private_Key*
load_key(
const std::string& fsname,
357 RandomNumberGenerator& rng,
358 const std::string& pass)
366 Private_Key*
load_key(
const std::string& fsname,
367 RandomNumberGenerator& rng)
369 DataSource_Stream source(fsname,
true);
370 return load_key(source, rng, []() -> std::string {
371 throw PKCS8_Exception(
"Internal error: Attempt to read password for unencrypted key" );},
false);
std::vector< uint8_t > BER_encode_encrypted_pbkdf_iter(const Private_Key &key, RandomNumberGenerator &rng, const std::string &pass, size_t pbkdf_iterations, const std::string &cipher, const std::string &pbkdf_hash)
secure_vector< uint8_t > decode(DataSource &source, std::string &label)
std::vector< uint8_t > get_contents_unlocked()
std::vector< uint8_t > parameters
std::string encode(const uint8_t der[], size_t length, const std::string &label, size_t width)
std::pair< AlgorithmIdentifier, std::vector< uint8_t > > pbes2_encrypt_iter(const secure_vector< uint8_t > &key_bits, const std::string &passphrase, size_t pbkdf_iter, const std::string &cipher, const std::string &digest, RandomNumberGenerator &rng)
BER_Decoder & decode_and_check(const T &expected, const std::string &error_msg)
secure_vector< uint8_t > BER_encode(const Private_Key &key)
std::string PEM_encode_encrypted_pbkdf_iter(const Private_Key &key, RandomNumberGenerator &rng, const std::string &pass, size_t pbkdf_iterations, const std::string &cipher, const std::string &pbkdf_hash)
virtual std::string algo_name() const =0
BER_Decoder & decode(bool &v)
bool maybe_BER(DataSource &source)
std::string PEM_encode(const Private_Key &key)
std::pair< AlgorithmIdentifier, std::vector< uint8_t > > pbes2_encrypt_msec(const secure_vector< uint8_t > &key_bits, const std::string &passphrase, std::chrono::milliseconds msec, size_t *out_iterations_if_nonnull, const std::string &cipher, const std::string &digest, RandomNumberGenerator &rng)
Private_Key * load_key(DataSource &source, RandomNumberGenerator &rng, std::function< std::string()> get_pass)
DER_Encoder & encode(bool b)
std::vector< T, secure_allocator< T >> secure_vector
std::string lookup(const OID &oid)
virtual bool end_of_data() const =0
const char * what() const BOTAN_NOEXCEPT override
BER_Decoder start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
Private_Key * copy_key(const Private_Key &key, RandomNumberGenerator &rng)
size_t read_byte(uint8_t &out)
secure_vector< uint8_t > pbes2_decrypt(const secure_vector< uint8_t > &key_bits, const std::string &passphrase, const std::vector< uint8_t > ¶ms)
bool matches(DataSource &source, const std::string &extra, size_t search_range)
secure_vector< uint8_t > private_key_info() const
std::vector< uint8_t > BER_encode_encrypted_pbkdf_msec(const Private_Key &key, RandomNumberGenerator &rng, const std::string &pass, std::chrono::milliseconds pbkdf_msec, size_t *pbkdf_iterations, const std::string &cipher, const std::string &pbkdf_hash)
BER_Decoder & verify_end()
std::string as_string() const
DER_Encoder & start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
std::unique_ptr< Private_Key > load_private_key(const AlgorithmIdentifier &alg_id, const secure_vector< uint8_t > &key_bits)
std::string PEM_encode_encrypted_pbkdf_msec(const Private_Key &key, RandomNumberGenerator &rng, const std::string &pass, std::chrono::milliseconds pbkdf_msec, size_t *pbkdf_iterations, const std::string &cipher, const std::string &pbkdf_hash)