1 // Copyright (c) 2009-2012 The Bitcoin Developers
2 // Distributed under the MIT/X11 software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 #include <openssl/aes.h>
6 #include <openssl/evp.h>
15 bool CCrypter::SetKeyFromPassphrase(const SecureString
& strKeyData
, const std::vector
<unsigned char>& chSalt
, const unsigned int nRounds
, const unsigned int nDerivationMethod
)
17 if (nRounds
< 1 || chSalt
.size() != WALLET_CRYPTO_SALT_SIZE
)
20 // Try to keep the keydata out of swap (and be a bit over-careful to keep the IV that we don't even use out of swap)
21 // Note that this does nothing about suspend-to-disk (which will put all our key data on disk)
22 // Note as well that at no point in this program is any attempt made to prevent stealing of keys by reading the memory of the running process.
23 mlock(&chKey
[0], sizeof chKey
);
24 mlock(&chIV
[0], sizeof chIV
);
27 if (nDerivationMethod
== 0)
28 i
= EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha512(), &chSalt
[0],
29 (unsigned char *)&strKeyData
[0], strKeyData
.size(), nRounds
, chKey
, chIV
);
31 if (i
!= (int)WALLET_CRYPTO_KEY_SIZE
)
33 memset(&chKey
, 0, sizeof chKey
);
34 memset(&chIV
, 0, sizeof chIV
);
42 bool CCrypter::SetKey(const CKeyingMaterial
& chNewKey
, const std::vector
<unsigned char>& chNewIV
)
44 if (chNewKey
.size() != WALLET_CRYPTO_KEY_SIZE
|| chNewIV
.size() != WALLET_CRYPTO_KEY_SIZE
)
47 // Try to keep the keydata out of swap
48 // Note that this does nothing about suspend-to-disk (which will put all our key data on disk)
49 // Note as well that at no point in this program is any attempt made to prevent stealing of keys by reading the memory of the running process.
50 mlock(&chKey
[0], sizeof chKey
);
51 mlock(&chIV
[0], sizeof chIV
);
53 memcpy(&chKey
[0], &chNewKey
[0], sizeof chKey
);
54 memcpy(&chIV
[0], &chNewIV
[0], sizeof chIV
);
60 bool CCrypter::Encrypt(const CKeyingMaterial
& vchPlaintext
, std::vector
<unsigned char> &vchCiphertext
)
65 // max ciphertext len for a n bytes of plaintext is
66 // n + AES_BLOCK_SIZE - 1 bytes
67 int nLen
= vchPlaintext
.size();
68 int nCLen
= nLen
+ AES_BLOCK_SIZE
, nFLen
= 0;
69 vchCiphertext
= std::vector
<unsigned char> (nCLen
);
75 EVP_CIPHER_CTX_init(&ctx
);
76 if (fOk
) fOk
= EVP_EncryptInit_ex(&ctx
, EVP_aes_256_cbc(), NULL
, chKey
, chIV
);
77 if (fOk
) fOk
= EVP_EncryptUpdate(&ctx
, &vchCiphertext
[0], &nCLen
, &vchPlaintext
[0], nLen
);
78 if (fOk
) fOk
= EVP_EncryptFinal_ex(&ctx
, (&vchCiphertext
[0])+nCLen
, &nFLen
);
79 EVP_CIPHER_CTX_cleanup(&ctx
);
81 if (!fOk
) return false;
83 vchCiphertext
.resize(nCLen
+ nFLen
);
87 bool CCrypter::Decrypt(const std::vector
<unsigned char>& vchCiphertext
, CKeyingMaterial
& vchPlaintext
)
92 // plaintext will always be equal to or lesser than length of ciphertext
93 int nLen
= vchCiphertext
.size();
94 int nPLen
= nLen
, nFLen
= 0;
96 vchPlaintext
= CKeyingMaterial(nPLen
);
102 EVP_CIPHER_CTX_init(&ctx
);
103 if (fOk
) fOk
= EVP_DecryptInit_ex(&ctx
, EVP_aes_256_cbc(), NULL
, chKey
, chIV
);
104 if (fOk
) fOk
= EVP_DecryptUpdate(&ctx
, &vchPlaintext
[0], &nPLen
, &vchCiphertext
[0], nLen
);
105 if (fOk
) fOk
= EVP_DecryptFinal_ex(&ctx
, (&vchPlaintext
[0])+nPLen
, &nFLen
);
106 EVP_CIPHER_CTX_cleanup(&ctx
);
108 if (!fOk
) return false;
110 vchPlaintext
.resize(nPLen
+ nFLen
);
115 bool EncryptSecret(CKeyingMaterial
& vMasterKey
, const CSecret
&vchPlaintext
, const uint256
& nIV
, std::vector
<unsigned char> &vchCiphertext
)
117 CCrypter cKeyCrypter
;
118 std::vector
<unsigned char> chIV(WALLET_CRYPTO_KEY_SIZE
);
119 memcpy(&chIV
[0], &nIV
, WALLET_CRYPTO_KEY_SIZE
);
120 if(!cKeyCrypter
.SetKey(vMasterKey
, chIV
))
122 return cKeyCrypter
.Encrypt((CKeyingMaterial
)vchPlaintext
, vchCiphertext
);
125 bool DecryptSecret(const CKeyingMaterial
& vMasterKey
, const std::vector
<unsigned char>& vchCiphertext
, const uint256
& nIV
, CSecret
& vchPlaintext
)
127 CCrypter cKeyCrypter
;
128 std::vector
<unsigned char> chIV(WALLET_CRYPTO_KEY_SIZE
);
129 memcpy(&chIV
[0], &nIV
, WALLET_CRYPTO_KEY_SIZE
);
130 if(!cKeyCrypter
.SetKey(vMasterKey
, chIV
))
132 return cKeyCrypter
.Decrypt(vchCiphertext
, *((CKeyingMaterial
*)&vchPlaintext
));