Bitcoin ABC  0.22.12
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 <crypto/aes.h>
8 #include <crypto/sha512.h>
9 #include <util/system.h>
10 
11 #include <vector>
12 
13 int 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 
65 bool 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 
79 bool 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 
100 bool 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 
121 bool 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 
134 bool 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,
144  *((CKeyingMaterial *)&vchPlaintext));
145 }
146 
147 bool DecryptKey(const CKeyingMaterial &vMasterKey,
148  const std::vector<uint8_t> &vchCryptedSecret,
149  const CPubKey &vchPubKey, CKey &key) {
150  CKeyingMaterial vchSecret;
151  if (!DecryptSecret(vMasterKey, vchCryptedSecret, vchPubKey.GetHash(),
152  vchSecret)) {
153  return false;
154  }
155 
156  if (vchSecret.size() != 32) {
157  return false;
158  }
159 
160  key.Set(vchSecret.begin(), vchSecret.end(), vchPubKey.IsCompressed());
161  return key.VerifyPubKey(vchPubKey);
162 }
CSHA512 & Write(const uint8_t *data, size_t len)
Definition: sha512.cpp:248
bool SetKey(const CKeyingMaterial &chNewKey, const std::vector< uint8_t > &chNewIV)
Definition: crypter.cpp:65
const unsigned int WALLET_CRYPTO_KEY_SIZE
Definition: crypter.h:12
Encryption/decryption context with key information.
Definition: crypter.h:70
bool VerifyPubKey(const CPubKey &vchPubKey) const
Verify thoroughly whether a private key and a public key match.
Definition: key.cpp:303
std::vector< uint8_t, secure_allocator< uint8_t > > CKeyingMaterial
Definition: crypter.h:63
std::basic_string< char, std::char_traits< char >, secure_allocator< char > > SecureString
Definition: secure.h:56
uint256 GetHash() const
Get the 256-bit hash of this public key.
Definition: pubkey.h:140
bool DecryptKey(const CKeyingMaterial &vMasterKey, const std::vector< uint8_t > &vchCryptedSecret, const CPubKey &vchPubKey, CKey &key)
Definition: crypter.cpp:147
const unsigned int WALLET_CRYPTO_IV_SIZE
Definition: crypter.h:14
bool Encrypt(const CKeyingMaterial &vchPlaintext, std::vector< uint8_t > &vchCiphertext) const
Definition: crypter.cpp:79
void memory_cleanse(void *ptr, size_t len)
Secure overwrite a buffer (possibly containing secret data) with zero-bytes.
Definition: cleanse.cpp:14
bool SetKeyFromPassphrase(const SecureString &strKeyData, const std::vector< uint8_t > &chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod)
Definition: crypter.cpp:41
bool fKeySet
Definition: crypter.h:77
CSHA512 & Reset()
Definition: sha512.cpp:289
An encapsulated public key.
Definition: pubkey.h:31
int Decrypt(const uint8_t *data, int size, uint8_t *out) const
Definition: aes.cpp:174
void Finalize(uint8_t hash[OUTPUT_SIZE])
Definition: sha512.cpp:273
int Encrypt(const uint8_t *data, int size, uint8_t *out) const
Definition: aes.cpp:158
static constexpr size_t OUTPUT_SIZE
Definition: sha512.h:19
void Set(const T pbegin, const T pend, bool fCompressedIn)
Initialize using begin and end iterators to byte data.
Definition: key.h:69
bool DecryptSecret(const CKeyingMaterial &vMasterKey, const std::vector< uint8_t > &vchCiphertext, const uint256 &nIV, CKeyingMaterial &vchPlaintext)
Definition: crypter.cpp:134
int BytesToKeySHA512AES(const std::vector< uint8_t > &chSalt, const SecureString &strKeyData, int count, uint8_t *key, uint8_t *iv) const
Definition: crypter.cpp:13
256-bit opaque blob.
Definition: uint256.h:120
const unsigned int WALLET_CRYPTO_SALT_SIZE
Definition: crypter.h:13
bool Decrypt(const std::vector< uint8_t > &vchCiphertext, CKeyingMaterial &vchPlaintext) const
Definition: crypter.cpp:100
static int count
Definition: tests.c:35
bool EncryptSecret(const CKeyingMaterial &vMasterKey, const CKeyingMaterial &vchPlaintext, const uint256 &nIV, std::vector< uint8_t > &vchCiphertext)
Definition: crypter.cpp:121
std::vector< uint8_t, secure_allocator< uint8_t > > vchKey
Definition: crypter.h:75
An encapsulated secp256k1 private key.
Definition: key.h:25
A hasher class for SHA-512.
Definition: sha512.h:12
static const int AES_BLOCKSIZE
Definition: aes.h:14
std::vector< uint8_t, secure_allocator< uint8_t > > vchIV
Definition: crypter.h:76
bool IsCompressed() const
Check whether this is a compressed public key.
Definition: pubkey.h:154