-
Notifications
You must be signed in to change notification settings - Fork 172
/
crypter.h
127 lines (105 loc) · 4.31 KB
/
crypter.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
// Copyright (c) 2009-2012 The Bitcoin Developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or https://opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_CRYPTER_H
#define BITCOIN_CRYPTER_H
#include "support/allocators/secure.h" /* for SecureString */
#include "key.h"
const unsigned int WALLET_CRYPTO_KEY_SIZE = 32;
const unsigned int WALLET_CRYPTO_SALT_SIZE = 8;
/*
Private key encryption is done based on a CMasterKey,
which holds a salt and random encryption key.
CMasterKeys are encrypted using AES-256-CBC using a key
derived using derivation method nDerivationMethod
(0 == EVP_sha512()) and derivation iterations nDeriveIterations.
vchOtherDerivationParameters is provided for alternative algorithms
which may require more parameters (such as scrypt).
Wallet Private Keys are then encrypted using AES-256-CBC
with the double-sha256 of the public key as the IV, and the
master key's key as the encryption key (see keystore.[ch]).
*/
/** Master key for wallet encryption */
class CMasterKey
{
public:
std::vector<unsigned char> vchCryptedKey;
std::vector<unsigned char> vchSalt;
// 0 = EVP_sha512()
// 1 = scrypt()
unsigned int nDerivationMethod;
unsigned int nDeriveIterations;
// Use this for more parameters to key derivation,
// such as the various parameters to scrypt
std::vector<unsigned char> vchOtherDerivationParameters;
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
{
READWRITE(vchCryptedKey);
READWRITE(vchSalt);
READWRITE(nDerivationMethod);
READWRITE(nDeriveIterations);
READWRITE(vchOtherDerivationParameters);
}
CMasterKey()
{
// 25000 rounds is just under 0.1 seconds on a 1.86 GHz Pentium M
// ie slightly lower than the lowest hardware we need bother supporting
nDeriveIterations = 25000;
nDerivationMethod = 1;
vchOtherDerivationParameters = std::vector<unsigned char>(0);
}
CMasterKey(unsigned int nDerivationMethodIndex)
{
switch (nDerivationMethodIndex)
{
case 0: // sha512
default:
nDeriveIterations = 25000;
nDerivationMethod = 0;
vchOtherDerivationParameters = std::vector<unsigned char>(0);
break;
case 1: // scrypt+sha512
nDeriveIterations = 10000;
nDerivationMethod = 1;
vchOtherDerivationParameters = std::vector<unsigned char>(0);
break;
}
}
};
typedef std::vector<unsigned char, secure_allocator<unsigned char> > CKeyingMaterial;
/** Encryption/decryption context with key information */
class CCrypter
{
private:
std::vector<unsigned char, secure_allocator<unsigned char>> vchKey;
std::vector<unsigned char, secure_allocator<unsigned char>> vchIV;
bool fKeySet;
public:
bool SetKeyFromPassphrase(const SecureString &strKeyData, const std::vector<unsigned char>& chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod);
bool Encrypt(const CKeyingMaterial& vchPlaintext, std::vector<unsigned char> &vchCiphertext) const;
bool Decrypt(const std::vector<unsigned char>& vchCiphertext, CKeyingMaterial& vchPlaintext) const;
bool SetKey(const CKeyingMaterial& chNewKey, const std::vector<unsigned char>& chNewIV);
void CleanKey()
{
memory_cleanse(vchKey.data(), vchKey.size());
memory_cleanse(vchIV.data(), vchIV.size());
fKeySet = false;
}
CCrypter()
{
fKeySet = false;
vchKey.resize(WALLET_CRYPTO_KEY_SIZE);
// TODO: Bitcoin uses an IV size of 16 defined by WALLET_CRYPTO_IV_SIZE.
vchIV.resize(WALLET_CRYPTO_KEY_SIZE);
}
~CCrypter()
{
CleanKey();
}
};
bool EncryptSecret(const CKeyingMaterial& vMasterKey, const CKeyingMaterial &vchPlaintext, const uint256& nIV, std::vector<unsigned char> &vchCiphertext);
bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector<unsigned char> &vchCiphertext, const uint256& nIV, CKeyingMaterial& vchPlaintext);
bool DecryptKey(const CKeyingMaterial& vMasterKey, const std::vector<unsigned char>& vchCryptedSecret, const CPubKey& vchPubKey, CKey& key);
#endif // BITCOIN_CRYPTER_H