8 #include <botan/pbes2.h>
9 #include <botan/cipher_mode.h>
10 #include <botan/pbkdf.h>
11 #include <botan/der_enc.h>
12 #include <botan/ber_dec.h>
13 #include <botan/parsing.h>
14 #include <botan/alg_id.h>
15 #include <botan/oids.h>
16 #include <botan/rng.h>
26 std::vector<uint8_t> encode_pbes2_params(
const std::string& cipher,
27 const std::string& prf,
28 const secure_vector<uint8_t>& salt,
29 const secure_vector<uint8_t>& iv,
36 AlgorithmIdentifier(
"PKCS5.PBKDF2",
43 prf !=
"HMAC(SHA-160)",
46 .get_contents_unlocked()
50 AlgorithmIdentifier(cipher,
55 .get_contents_unlocked();
61 std::pair<AlgorithmIdentifier, std::vector<uint8_t>>
62 pbes2_encrypt_shared(
const secure_vector<uint8_t>& key_bits,
63 const std::string& passphrase,
64 size_t* msec_in_iterations_out,
65 size_t iterations_if_msec_null,
66 const std::string& cipher,
67 const std::string& digest,
68 RandomNumberGenerator& rng)
70 const std::string prf =
"HMAC(" + digest +
")";
72 const std::vector<std::string> cipher_spec =
split_on(cipher,
'/');
73 if(cipher_spec.size() != 2)
74 throw Decoding_Error(
"PBE-PKCS5 v2.0: Invalid cipher spec " + cipher);
76 const secure_vector<uint8_t> salt = rng.random_vec(12);
78 if(cipher_spec[1] !=
"CBC" && cipher_spec[1] !=
"GCM")
79 throw Decoding_Error(
"PBE-PKCS5 v2.0: Don't know param format for " + cipher);
84 throw Decoding_Error(
"PBE-PKCS5 cannot encrypt no cipher " + cipher);
86 std::unique_ptr<PBKDF> pbkdf(
get_pbkdf(
"PBKDF2(" + prf +
")"));
88 const size_t key_length = enc->key_spec().maximum_keylength();
91 secure_vector<uint8_t> iv = rng.random_vec(enc->default_nonce_length());
93 size_t iterations = iterations_if_msec_null;
95 if(msec_in_iterations_out)
97 std::chrono::milliseconds msec(*msec_in_iterations_out);
98 enc->set_key(pbkdf->derive_key(key_length, passphrase, salt.data(), salt.size(), msec, iterations).bits_of());
99 *msec_in_iterations_out = iterations;
103 enc->set_key(pbkdf->pbkdf_iterations(key_length, passphrase, salt.data(), salt.size(), iterations));
107 secure_vector<uint8_t> buf = key_bits;
110 AlgorithmIdentifier id(
112 encode_pbes2_params(cipher, prf, salt, iv, iterations, key_length));
114 return std::make_pair(
id,
unlock(buf));
120 std::pair<AlgorithmIdentifier, std::vector<uint8_t>>
122 const std::string& passphrase,
123 std::chrono::milliseconds msec,
124 const std::string& cipher,
125 const std::string& digest,
128 size_t msec_in_iterations_out = msec.count();
129 return pbes2_encrypt_shared(key_bits, passphrase, &msec_in_iterations_out, 0, cipher, digest, rng);
133 std::pair<AlgorithmIdentifier, std::vector<uint8_t>>
135 const std::string& passphrase,
136 std::chrono::milliseconds msec,
137 size_t* out_iterations_if_nonnull,
138 const std::string& cipher,
139 const std::string& digest,
142 size_t msec_in_iterations_out = msec.count();
144 auto ret = pbes2_encrypt_shared(key_bits, passphrase, &msec_in_iterations_out, 0, cipher, digest, rng);
146 if(out_iterations_if_nonnull)
147 *out_iterations_if_nonnull = msec_in_iterations_out;
152 std::pair<AlgorithmIdentifier, std::vector<uint8_t>>
154 const std::string& passphrase,
156 const std::string& cipher,
157 const std::string& digest,
160 return pbes2_encrypt_shared(key_bits, passphrase,
nullptr, pbkdf_iter, cipher, digest, rng);
163 secure_vector<uint8_t>
165 const std::string& passphrase,
166 const std::vector<uint8_t>& params)
183 size_t iterations = 0, key_length = 0;
196 const std::vector<std::string> cipher_spec =
split_on(cipher,
'/');
197 if(cipher_spec.size() != 2)
198 throw Decoding_Error(
"PBE-PKCS5 v2.0: Invalid cipher spec " + cipher);
199 if(cipher_spec[1] !=
"CBC" && cipher_spec[1] !=
"GCM")
200 throw Decoding_Error(
"PBE-PKCS5 v2.0: Don't know param format for " + cipher);
203 throw Decoding_Error(
"PBE-PKCS5 v2.0: Encoded salt is too small");
210 std::unique_ptr<PBKDF> pbkdf(
get_pbkdf(
"PBKDF2(" + prf +
")"));
214 throw Decoding_Error(
"PBE-PKCS5 cannot decrypt no cipher " + cipher);
217 key_length = dec->key_spec().maximum_keylength();
219 dec->set_key(pbkdf->pbkdf_iterations(key_length, passphrase, salt.data(), salt.size(), iterations));
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)
Cipher_Mode * get_cipher_mode(const std::string &algo, Cipher_Dir direction)
std::vector< std::string > split_on(const std::string &str, char delim)
BER_Decoder & decode(bool &v)
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)
BER_Decoder & decode_optional(T &out, ASN1_Tag type_tag, ASN1_Tag class_tag, const T &default_value=T())
std::vector< T, secure_allocator< T >> secure_vector
std::string lookup(const OID &oid)
PBKDF * get_pbkdf(const std::string &algo_spec, const std::string &provider="")
BER_Decoder start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
secure_vector< uint8_t > pbes2_decrypt(const secure_vector< uint8_t > &key_bits, const std::string &passphrase, const std::vector< uint8_t > ¶ms)
std::vector< T > unlock(const secure_vector< T > &in)
std::pair< AlgorithmIdentifier, std::vector< uint8_t > > pbes2_encrypt(const secure_vector< uint8_t > &key_bits, const std::string &passphrase, std::chrono::milliseconds msec, const std::string &cipher, const std::string &digest, RandomNumberGenerator &rng)
BER_Decoder & verify_end()
std::string as_string() const