Bitcoin ABC 0.30.7
P2P Digital Currency
crypter.cpp
Go to the documentation of this file.
1// Copyright (c) 2009-2016 The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5#include <wallet/crypter.h>
6
7#include <common/system.h>
8#include <crypto/aes.h>
9#include <crypto/sha512.h>
10
11#include <vector>
12
13int CCrypter::BytesToKeySHA512AES(const std::vector<uint8_t> &chSalt,
14 const SecureString &strKeyData, int count,
15 uint8_t *key, uint8_t *iv) const {
16 // This mimics the behavior of openssl's EVP_BytesToKey with an aes256cbc
17 // cipher and sha512 message digest. Because sha512's output size (64b) is
18 // greater than the aes256 block size (16b) + aes256 key size (32b), there's
19 // no need to process more than once (D_0).
20 if (!count || !key || !iv) {
21 return 0;
22 }
23
24 uint8_t buf[CSHA512::OUTPUT_SIZE];
25 CSHA512 di;
26
27 di.Write((const uint8_t *)strKeyData.data(), strKeyData.size());
28 di.Write(chSalt.data(), chSalt.size());
29 di.Finalize(buf);
30
31 for (int i = 0; i != count - 1; i++) {
32 di.Reset().Write(buf, sizeof(buf)).Finalize(buf);
33 }
34
35 memcpy(key, buf, WALLET_CRYPTO_KEY_SIZE);
37 memory_cleanse(buf, sizeof(buf));
39}
40
42 const std::vector<uint8_t> &chSalt,
43 const unsigned int nRounds,
44 const unsigned int nDerivationMethod) {
45 if (nRounds < 1 || chSalt.size() != WALLET_CRYPTO_SALT_SIZE) {
46 return false;
47 }
48
49 int i = 0;
50 if (nDerivationMethod == 0) {
51 i = BytesToKeySHA512AES(chSalt, strKeyData, nRounds, vchKey.data(),
52 vchIV.data());
53 }
54
55 if (i != (int)WALLET_CRYPTO_KEY_SIZE) {
56 memory_cleanse(vchKey.data(), vchKey.size());
57 memory_cleanse(vchIV.data(), vchIV.size());
58 return false;
59 }
60
61 fKeySet = true;
62 return true;
63}
64
65bool CCrypter::SetKey(const CKeyingMaterial &chNewKey,
66 const std::vector<uint8_t> &chNewIV) {
67 if (chNewKey.size() != WALLET_CRYPTO_KEY_SIZE ||
68 chNewIV.size() != WALLET_CRYPTO_IV_SIZE) {
69 return false;
70 }
71
72 memcpy(vchKey.data(), chNewKey.data(), chNewKey.size());
73 memcpy(vchIV.data(), chNewIV.data(), chNewIV.size());
74
75 fKeySet = true;
76 return true;
77}
78
79bool CCrypter::Encrypt(const CKeyingMaterial &vchPlaintext,
80 std::vector<uint8_t> &vchCiphertext) const {
81 if (!fKeySet) {
82 return false;
83 }
84
85 // max ciphertext len for a n bytes of plaintext is
86 // n + AES_BLOCKSIZE bytes
87 vchCiphertext.resize(vchPlaintext.size() + AES_BLOCKSIZE);
88
89 AES256CBCEncrypt enc(vchKey.data(), vchIV.data(), true);
90 size_t nLen = enc.Encrypt(vchPlaintext.data(), vchPlaintext.size(),
91 vchCiphertext.data());
92 if (nLen < vchPlaintext.size()) {
93 return false;
94 }
95 vchCiphertext.resize(nLen);
96
97 return true;
98}
99
100bool CCrypter::Decrypt(const std::vector<uint8_t> &vchCiphertext,
101 CKeyingMaterial &vchPlaintext) const {
102 if (!fKeySet) {
103 return false;
104 }
105
106 // plaintext will always be equal to or lesser than length of ciphertext
107 int nLen = vchCiphertext.size();
108
109 vchPlaintext.resize(nLen);
110
111 AES256CBCDecrypt dec(vchKey.data(), vchIV.data(), true);
112 nLen = dec.Decrypt(vchCiphertext.data(), vchCiphertext.size(),
113 vchPlaintext.data());
114 if (nLen == 0) {
115 return false;
116 }
117 vchPlaintext.resize(nLen);
118 return true;
119}
120
121bool EncryptSecret(const CKeyingMaterial &vMasterKey,
122 const CKeyingMaterial &vchPlaintext, const uint256 &nIV,
123 std::vector<uint8_t> &vchCiphertext) {
124 CCrypter cKeyCrypter;
125 std::vector<uint8_t> chIV(WALLET_CRYPTO_IV_SIZE);
126 memcpy(chIV.data(), &nIV, WALLET_CRYPTO_IV_SIZE);
127 if (!cKeyCrypter.SetKey(vMasterKey, chIV)) {
128 return false;
129 }
130 return cKeyCrypter.Encrypt(*((const CKeyingMaterial *)&vchPlaintext),
131 vchCiphertext);
132}
133
134bool DecryptSecret(const CKeyingMaterial &vMasterKey,
135 const std::vector<uint8_t> &vchCiphertext,
136 const uint256 &nIV, CKeyingMaterial &vchPlaintext) {
137 CCrypter cKeyCrypter;
138 std::vector<uint8_t> chIV(WALLET_CRYPTO_IV_SIZE);
139 memcpy(chIV.data(), &nIV, WALLET_CRYPTO_IV_SIZE);
140 if (!cKeyCrypter.SetKey(vMasterKey, chIV)) {
141 return false;
142 }
143 return cKeyCrypter.Decrypt(vchCiphertext, vchPlaintext);
144}
145
146bool DecryptKey(const CKeyingMaterial &vMasterKey,
147 const std::vector<uint8_t> &vchCryptedSecret,
148 const CPubKey &vchPubKey, CKey &key) {
149 CKeyingMaterial vchSecret;
150 if (!DecryptSecret(vMasterKey, vchCryptedSecret, vchPubKey.GetHash(),
151 vchSecret)) {
152 return false;
153 }
154
155 if (vchSecret.size() != 32) {
156 return false;
157 }
158
159 key.Set(vchSecret.begin(), vchSecret.end(), vchPubKey.IsCompressed());
160 return key.VerifyPubKey(vchPubKey);
161}
static const int AES_BLOCKSIZE
Definition: aes.h:14
int Decrypt(const uint8_t *data, int size, uint8_t *out) const
Definition: aes.cpp:174
int Encrypt(const uint8_t *data, int size, uint8_t *out) const
Definition: aes.cpp:158
Encryption/decryption context with key information.
Definition: crypter.h:64
std::vector< uint8_t, secure_allocator< uint8_t > > vchKey
Definition: crypter.h:69
bool fKeySet
Definition: crypter.h:71
bool Encrypt(const CKeyingMaterial &vchPlaintext, std::vector< uint8_t > &vchCiphertext) const
Definition: crypter.cpp:79
bool SetKeyFromPassphrase(const SecureString &strKeyData, const std::vector< uint8_t > &chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod)
Definition: crypter.cpp:41
int BytesToKeySHA512AES(const std::vector< uint8_t > &chSalt, const SecureString &strKeyData, int count, uint8_t *key, uint8_t *iv) const
Definition: crypter.cpp:13
std::vector< uint8_t, secure_allocator< uint8_t > > vchIV
Definition: crypter.h:70
bool Decrypt(const std::vector< uint8_t > &vchCiphertext, CKeyingMaterial &vchPlaintext) const
Definition: crypter.cpp:100
bool SetKey(const CKeyingMaterial &chNewKey, const std::vector< uint8_t > &chNewIV)
Definition: crypter.cpp:65
An encapsulated secp256k1 private key.
Definition: key.h:28
void Set(const T pbegin, const T pend, bool fCompressedIn)
Initialize using begin and end iterators to byte data.
Definition: key.h:76
bool VerifyPubKey(const CPubKey &vchPubKey) const
Verify thoroughly whether a private key and a public key match.
Definition: key.cpp:302
An encapsulated public key.
Definition: pubkey.h:31
bool IsCompressed() const
Check whether this is a compressed public key.
Definition: pubkey.h:154
uint256 GetHash() const
Get the 256-bit hash of this public key.
Definition: pubkey.h:140
A hasher class for SHA-512.
Definition: sha512.h:12
CSHA512 & Write(const uint8_t *data, size_t len)
Definition: sha512.cpp:248
static constexpr size_t OUTPUT_SIZE
Definition: sha512.h:19
CSHA512 & Reset()
Definition: sha512.cpp:289
void Finalize(uint8_t hash[OUTPUT_SIZE])
Definition: sha512.cpp:273
256-bit opaque blob.
Definition: uint256.h:129
void memory_cleanse(void *ptr, size_t len)
Secure overwrite a buffer (possibly containing secret data) with zero-bytes.
Definition: cleanse.cpp:14
bool DecryptKey(const CKeyingMaterial &vMasterKey, const std::vector< uint8_t > &vchCryptedSecret, const CPubKey &vchPubKey, CKey &key)
Definition: crypter.cpp:146
bool EncryptSecret(const CKeyingMaterial &vMasterKey, const CKeyingMaterial &vchPlaintext, const uint256 &nIV, std::vector< uint8_t > &vchCiphertext)
Definition: crypter.cpp:121
bool DecryptSecret(const CKeyingMaterial &vMasterKey, const std::vector< uint8_t > &vchCiphertext, const uint256 &nIV, CKeyingMaterial &vchPlaintext)
Definition: crypter.cpp:134
const unsigned int WALLET_CRYPTO_IV_SIZE
Definition: crypter.h:14
const unsigned int WALLET_CRYPTO_SALT_SIZE
Definition: crypter.h:13
std::vector< uint8_t, secure_allocator< uint8_t > > CKeyingMaterial
Definition: crypter.h:57
const unsigned int WALLET_CRYPTO_KEY_SIZE
Definition: crypter.h:12
std::basic_string< char, std::char_traits< char >, secure_allocator< char > > SecureString
Definition: secure.h:55
static int count
Definition: tests.c:31