static void TestEncrypt(const CCrypter& crypt, const std::vector<unsigned char>& vchPlaintextIn, \ const std::vector<unsigned char>& vchCiphertextCorrect = std::vector<unsigned char>()) { TestEncryptSingle(crypt, CKeyingMaterial(vchPlaintextIn.begin(), vchPlaintextIn.end()), vchCiphertextCorrect); for(std::vector<unsigned char>::const_iterator i(vchPlaintextIn.begin()); i != vchPlaintextIn.end(); ++i) TestEncryptSingle(crypt, CKeyingMaterial(i, vchPlaintextIn.end())); }
bool CHDSeed::Encrypt(CKeyingMaterial& vMasterKeyIn) { assert(sizeof(m_UUID) == WALLET_CRYPTO_IV_SIZE); encryptedMnemonic.clear(); if (!EncryptSecret(vMasterKeyIn, CKeyingMaterial(unencryptedMnemonic.begin(), unencryptedMnemonic.end()), std::vector<unsigned char>(m_UUID.begin(), m_UUID.end()), encryptedMnemonic)) return false; SecureUnsignedCharVector masterKeyPrivEncoded(BIP32_EXTKEY_SIZE); masterKeyPriv.Encode(masterKeyPrivEncoded.data()); if (!EncryptSecret(vMasterKeyIn, CKeyingMaterial(masterKeyPrivEncoded.begin(), masterKeyPrivEncoded.end()), masterKeyPub.pubkey.GetHash(), masterKeyPrivEncrypted)) return false; SecureUnsignedCharVector purposeKeyPrivEncoded(BIP32_EXTKEY_SIZE); purposeKeyPriv.Encode(purposeKeyPrivEncoded.data()); if (!EncryptSecret(vMasterKeyIn, CKeyingMaterial(purposeKeyPrivEncoded.begin(), purposeKeyPrivEncoded.end()), purposeKeyPub.pubkey.GetHash(), purposeKeyPrivEncrypted)) return false; SecureUnsignedCharVector cointypeKeyPrivEncoded(BIP32_EXTKEY_SIZE); cointypeKeyPriv.Encode(cointypeKeyPrivEncoded.data()); if (!EncryptSecret(vMasterKeyIn, CKeyingMaterial(cointypeKeyPrivEncoded.begin(), cointypeKeyPrivEncoded.end()), cointypeKeyPub.pubkey.GetHash(), cointypeKeyPrivEncrypted)) return false; encrypted = true; vMasterKey = vMasterKeyIn; return true; }
bool CAccountHD::Encrypt(const CKeyingMaterial& vMasterKeyIn) { assert(sizeof(accountUUID) == WALLET_CRYPTO_IV_SIZE); if (IsReadOnly()) { return true; } // NB! We don't encrypt the keystores for HD accounts - as they only contain public keys. // Encrypt account key SecureUnsignedCharVector accountKeyPrivEncoded(BIP32_EXTKEY_SIZE); accountKeyPriv.Encode(accountKeyPrivEncoded.data()); if (!EncryptSecret(vMasterKeyIn, CKeyingMaterial(accountKeyPrivEncoded.begin(), accountKeyPrivEncoded.end()), std::vector<unsigned char>(accountUUID.begin(), accountUUID.end()), accountKeyPrivEncrypted)) return false; // Encrypt primary chain key SecureUnsignedCharVector primaryChainKeyPrivEncoded(BIP32_EXTKEY_SIZE); primaryChainKeyPriv.Encode(primaryChainKeyPrivEncoded.data()); if (!EncryptSecret(vMasterKeyIn, CKeyingMaterial(primaryChainKeyPrivEncoded.begin(), primaryChainKeyPrivEncoded.end()), primaryChainKeyPub.pubkey.GetHash(), primaryChainKeyEncrypted)) return false; // Encrypt change chain key SecureUnsignedCharVector changeChainKeyPrivEncoded(BIP32_EXTKEY_SIZE); changeChainKeyPriv.Encode(changeChainKeyPrivEncoded.data()); if (!EncryptSecret(vMasterKeyIn, CKeyingMaterial(changeChainKeyPrivEncoded.begin(), changeChainKeyPrivEncoded.end()), changeChainKeyPub.pubkey.GetHash(), changeChainKeyEncrypted)) return false; encrypted = true; return true; }
bool OldDecrypt(const std::vector<unsigned char>& vchCiphertext, CKeyingMaterial& vchPlaintext, const unsigned char chKey[32], const unsigned char chIV[16]) { // plaintext will always be equal to or lesser than length of ciphertext int nLen = vchCiphertext.size(); int nPLen = nLen, nFLen = 0; vchPlaintext = CKeyingMaterial(nPLen); EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); if (!ctx) return false; bool fOk = true; EVP_CIPHER_CTX_init(ctx); if (fOk) fOk = EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, chKey, chIV) != 0; if (fOk) fOk = EVP_DecryptUpdate(ctx, &vchPlaintext[0], &nPLen, &vchCiphertext[0], nLen) != 0; if (fOk) fOk = EVP_DecryptFinal_ex(ctx, (&vchPlaintext[0]) + nPLen, &nFLen) != 0; EVP_CIPHER_CTX_cleanup(ctx); EVP_CIPHER_CTX_free(ctx); if (!fOk) return false; vchPlaintext.resize(nPLen + nFLen); return true; }
bool CCrypter::Decrypt(const std::vector<unsigned char>& vchCiphertext, CKeyingMaterial& vchPlaintext) { if (!fKeySet) return false; // plaintext will always be equal to or lesser than length of ciphertext int nLen = vchCiphertext.size(); int nPLen = nLen, nFLen = 0; vchPlaintext = CKeyingMaterial(nPLen); EVP_CIPHER_CTX ctx; bool fOk = true; EVP_CIPHER_CTX_init(&ctx); if (fOk) fOk = EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, chKey, chIV); if (fOk) fOk = EVP_DecryptUpdate(&ctx, &vchPlaintext[0], &nPLen, &vchCiphertext[0], nLen); if (fOk) fOk = EVP_DecryptFinal_ex(&ctx, (&vchPlaintext[0])+nPLen, &nFLen); EVP_CIPHER_CTX_cleanup(&ctx); if (!fOk) return false; vchPlaintext.resize(nPLen + nFLen); return true; }
bool CCrypter::Decrypt(const std::vector<unsigned char>& vchCiphertext, CKeyingMaterial& vchPlaintext) { if (!fKeySet) return false; // plaintext will always be equal to or lesser than length of ciphertext int nLen = vchCiphertext.size(); int nPLen = nLen, nFLen = 0; vchPlaintext = CKeyingMaterial(nPLen); bool fOk = true; EVP_CIPHER_CTX *ctx= EVP_CIPHER_CTX_new(); if(!ctx) throw std::runtime_error("Error allocating cipher context"); if (fOk) fOk = EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, chKey, chIV); if (fOk) fOk = EVP_DecryptUpdate(ctx, &vchPlaintext[0], &nPLen, &vchCiphertext[0], nLen); if (fOk) fOk = EVP_DecryptFinal_ex(ctx, (&vchPlaintext[0])+nPLen, &nFLen); EVP_CIPHER_CTX_free(ctx); if (!fOk) return false; vchPlaintext.resize(nPLen + nFLen); return true; }
static void TestDecrypt(const CCrypter& crypt, const std::vector<unsigned char>& vchCiphertext, \ const std::vector<unsigned char>& vchPlaintext = std::vector<unsigned char>()) { CKeyingMaterial vchDecrypted; crypt.Decrypt(vchCiphertext, vchDecrypted); if (vchPlaintext.size()) BOOST_CHECK(CKeyingMaterial(vchPlaintext.begin(), vchPlaintext.end()) == vchDecrypted); }
bool CAccountHD::Encrypt(CKeyingMaterial& vMasterKeyIn) { assert(sizeof(accountUUID) == WALLET_CRYPTO_IV_SIZE); SecureUnsignedCharVector accountKeyPrivEncoded(BIP32_EXTKEY_SIZE); accountKeyPriv.Encode(accountKeyPrivEncoded.data()); if (!EncryptSecret(vMasterKeyIn, CKeyingMaterial(accountKeyPrivEncoded.begin(), accountKeyPrivEncoded.end()), std::vector<unsigned char>(accountUUID.begin(), accountUUID.end()), accountKeyPrivEncrypted)) return false; SecureUnsignedCharVector primaryChainKeyPrivEncoded(BIP32_EXTKEY_SIZE); primaryChainKeyPriv.Encode(primaryChainKeyPrivEncoded.data()); if (!EncryptSecret(vMasterKeyIn, CKeyingMaterial(primaryChainKeyPrivEncoded.begin(), primaryChainKeyPrivEncoded.end()), primaryChainKeyPub.pubkey.GetHash(), primaryChainKeyEncrypted)) return false; SecureUnsignedCharVector changeChainKeyPrivEncoded(BIP32_EXTKEY_SIZE); changeChainKeyPriv.Encode(changeChainKeyPrivEncoded.data()); if (!EncryptSecret(vMasterKeyIn, CKeyingMaterial(changeChainKeyPrivEncoded.begin(), changeChainKeyPrivEncoded.end()), changeChainKeyPub.pubkey.GetHash(), changeChainKeyEncrypted)) return false; encrypted = true; return true; }
static void TestDecrypt(const CCrypter& crypt, const std::vector<unsigned char>& vchCiphertext, \ const std::vector<unsigned char>& vchPlaintext = std::vector<unsigned char>()) { CKeyingMaterial vchDecrypted1; CKeyingMaterial vchDecrypted2; int result1, result2; result1 = crypt.Decrypt(vchCiphertext, vchDecrypted1); result2 = OldDecrypt(vchCiphertext, vchDecrypted2, crypt.vchKey.data(), crypt.vchIV.data()); BOOST_CHECK(result1 == result2); // These two should be equal. However, OpenSSL 1.0.1j introduced a change // that would zero all padding except for the last byte for failed decrypts. // This behavior was reverted for 1.0.1k. if (vchDecrypted1 != vchDecrypted2 && vchDecrypted1.size() >= AES_BLOCK_SIZE && SSLeay() == 0x100010afL) { for(CKeyingMaterial::iterator it = vchDecrypted1.end() - AES_BLOCK_SIZE; it != vchDecrypted1.end() - 1; it++) *it = 0; } BOOST_CHECK_MESSAGE(vchDecrypted1 == vchDecrypted2, HexStr(vchDecrypted1.begin(), vchDecrypted1.end()) + " != " + HexStr(vchDecrypted2.begin(), vchDecrypted2.end())); if (vchPlaintext.size()) BOOST_CHECK(CKeyingMaterial(vchPlaintext.begin(), vchPlaintext.end()) == vchDecrypted2); }