/* * Set the passphrase to use */ void PBE_PKCS5v20::set_key(const std::string& passphrase) { PKCS5_PBKDF2 pbkdf(new HMAC(hash_function->clone())); key = pbkdf.derive_key(key_length, passphrase, &salt[0], salt.size(), iterations).bits_of(); }
void PBKDF::pbkdf_timed(byte out[], size_t out_len, const std::string& passphrase, const byte salt[], size_t salt_len, std::chrono::milliseconds msec, size_t& iterations) const { iterations = pbkdf(out, out_len, passphrase, salt, salt_len, 0, msec); }
void PBKDF::pbkdf_iterations(byte out[], size_t out_len, const std::string& passphrase, const byte salt[], size_t salt_len, size_t iterations) const { if(iterations == 0) throw std::invalid_argument(name() + ": Invalid iteration count"); const size_t iterations_run = pbkdf(out, out_len, passphrase, salt, salt_len, iterations, std::chrono::milliseconds(0)); BOTAN_ASSERT_EQUAL(iterations, iterations_run, "Expected PBKDF iterations"); }
void go() override { const uint64_t cc_number = std::stoull(get_arg("CC")); const std::vector<uint8_t> tweak = Botan::hex_decode(get_arg("tweak")); const std::string pass = get_arg("passphrase"); std::unique_ptr<Botan::PBKDF> pbkdf(Botan::PBKDF::create("PBKDF2(SHA-256)")); if(!pbkdf) throw CLI_Error_Unsupported("PBKDF", "PBKDF2(SHA-256)"); Botan::secure_vector<uint8_t> key = pbkdf->pbkdf_iterations(32, pass, tweak.data(), tweak.size(), 100000); output() << decrypt_cc_number(cc_number, key, tweak) << "\n"; }
// result = ENCODE_HEX(PBKDF(password, salt, index, rounds)) static void _simple(buffer password, buffer salt, word block_index, int rounds, char *result) { buffer result_buffer = buffer_calloc(32); pbkdf(password, salt, block_index, rounds, &result_buffer); buffer_encode(result_buffer, result); buffer_free(&result_buffer); }
secure_vector<uint8_t> pbes2_decrypt(const secure_vector<uint8_t>& key_bits, const std::string& passphrase, const std::vector<uint8_t>& params) { AlgorithmIdentifier kdf_algo, enc_algo; BER_Decoder(params) .start_cons(SEQUENCE) .decode(kdf_algo) .decode(enc_algo) .end_cons(); AlgorithmIdentifier prf_algo; if(kdf_algo.oid != OIDS::lookup("PKCS5.PBKDF2")) throw Decoding_Error("PBE-PKCS5 v2.0: Unknown KDF algorithm " + kdf_algo.oid.as_string()); secure_vector<uint8_t> salt; size_t iterations = 0, key_length = 0; BER_Decoder(kdf_algo.parameters) .start_cons(SEQUENCE) .decode(salt, OCTET_STRING) .decode(iterations) .decode_optional(key_length, INTEGER, UNIVERSAL) .decode_optional(prf_algo, SEQUENCE, CONSTRUCTED, AlgorithmIdentifier("HMAC(SHA-160)", AlgorithmIdentifier::USE_NULL_PARAM)) .end_cons(); const std::string cipher = OIDS::lookup(enc_algo.oid); const std::vector<std::string> cipher_spec = split_on(cipher, '/'); if(cipher_spec.size() != 2) throw Decoding_Error("PBE-PKCS5 v2.0: Invalid cipher spec " + cipher); if(cipher_spec[1] != "CBC" && cipher_spec[1] != "GCM") throw Decoding_Error("PBE-PKCS5 v2.0: Don't know param format for " + cipher); if(salt.size() < 8) throw Decoding_Error("PBE-PKCS5 v2.0: Encoded salt is too small"); secure_vector<uint8_t> iv; BER_Decoder(enc_algo.parameters).decode(iv, OCTET_STRING).verify_end(); const std::string prf = OIDS::lookup(prf_algo.oid); std::unique_ptr<PBKDF> pbkdf(get_pbkdf("PBKDF2(" + prf + ")")); std::unique_ptr<Cipher_Mode> dec(get_cipher_mode(cipher, DECRYPTION)); if(!dec) throw Decoding_Error("PBE-PKCS5 cannot decrypt no cipher " + cipher); if(key_length == 0) key_length = dec->key_spec().maximum_keylength(); dec->set_key(pbkdf->pbkdf_iterations(key_length, passphrase, salt.data(), salt.size(), iterations)); dec->start(iv); secure_vector<uint8_t> buf = key_bits; dec->finish(buf); return buf; }