bool CCrypter::SetKeyFromPassphrase(const SecureString& strKeyData, const std::vector<unsigned char>& chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod) { if (nRounds < 1 || chSalt.size() != WALLET_CRYPTO_SALT_SIZE) return false; int i = 0; if (nDerivationMethod == 0) { i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha512(), &chSalt[0], (unsigned char *)&strKeyData[0], strKeyData.size(), nRounds, chKey, chIV); } if (nDerivationMethod == 1) { // Passphrase conversion uint256 scryptHash = scrypt_salted_multiround_hash((const void*)strKeyData.c_str(), strKeyData.size(), &chSalt[0], 8, nRounds); i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha512(), &chSalt[0], (unsigned char *)&scryptHash, sizeof scryptHash, nRounds, chKey, chIV); OPENSSL_cleanse(&scryptHash, sizeof scryptHash); } if (i != (int)WALLET_CRYPTO_KEY_SIZE) { OPENSSL_cleanse(chKey, sizeof(chKey)); OPENSSL_cleanse(chIV, sizeof(chIV)); return false; } fKeySet = true; return true; }
int CCrypter::BytesToKeySHA512AES(const std::vector<unsigned char>& chSalt, const SecureString& strKeyData, int count, unsigned char *key,unsigned char *iv) const { // This mimics the behavior of openssl's EVP_BytesToKey with an aes256cbc // cipher and sha512 message digest. Because sha512's output size (64b) is // greater than the aes256 block size (16b) + aes256 key size (32b), // there's no need to process more than once (D_0). if(!count || !key || !iv) return 0; unsigned char buf[CSHA512::OUTPUT_SIZE]; CSHA512 di; di.Write((const unsigned char*)strKeyData.c_str(), strKeyData.size()); di.Write(chSalt.data(), chSalt.size()); di.Finalize(buf); for(int i = 0; i != count - 1; i++) di.Reset().Write(buf, sizeof(buf)).Finalize(buf); memcpy(key, buf, WALLET_CRYPTO_KEY_SIZE); memcpy(iv, buf + WALLET_CRYPTO_KEY_SIZE, WALLET_CRYPTO_IV_SIZE); memory_cleanse(buf, sizeof(buf)); return WALLET_CRYPTO_KEY_SIZE; }
// passphrase must be at most 256 characters or code may crash void CMnemonic::ToSeed(SecureString mnemonic, SecureString passphrase, SecureVector& seedRet) { SecureString ssSalt = SecureString("mnemonic") + passphrase; SecureVector vchSalt(ssSalt.begin(), ssSalt.end()); seedRet.resize(64); // int PKCS5_PBKDF2_HMAC(const char *pass, int passlen, // const unsigned char *salt, int saltlen, int iter, // const EVP_MD *digest, // int keylen, unsigned char *out); PKCS5_PBKDF2_HMAC(mnemonic.c_str(), mnemonic.size(), &vchSalt[0], vchSalt.size(), 2048, EVP_sha512(), 64, &seedRet[0]); }
int __pass_cb(char *buf, int size, int rwflag, void *u) { Key::PassphraseFunctor* pf = (Key::PassphraseFunctor*)u; bool verify = (rwflag == 1); SecureString ss = (*pf)(verify); int len; len = ss.size(); if (len <= 0) return 0; // if too long, truncate if (len > size) len = size; memcpy(buf, ss.c_str(), len); return len; }