Disabled by default. You can use -derivationmethod option to choose which method will be used for wallet encryption keys generation.
Possible values:
* sha512 - default, compatible with bitcoin;
* scrypt+sha512 - selects scrypt derivation function.
Please note that this option only allows you to select default method. If you are already using encrypted wallet then suitable derivation method will be selected automatically.
#endif
#include "crypter.h"
+#include "scrypt.h"
bool CCrypter::SetKeyFromPassphrase(const SecureString& strKeyData, const std::vector<unsigned char>& chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod)
{
int i = 0;
if (nDerivationMethod == 0)
+ {
i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha512(), &chSalt[0],
(unsigned char *)&strKeyData[0], strKeyData.size(), nRounds, chKey, chIV);
+ }
+
+ if (nDerivationMethod == 1)
+ {
+ // Passphrase conversion
+ uint256 scryptHash = scrypt_salted_multiround_hash((const void*)strKeyData.c_str(), strKeyData.size(), &chSalt[0], 8, nRounds);
+
+ i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha512(), &chSalt[0],
+ (unsigned char *)&scryptHash, sizeof scryptHash, nRounds, chKey, chIV);
+ memset(&scryptHash, 0, sizeof scryptHash);
+ }
+
if (i != (int)WALLET_CRYPTO_KEY_SIZE)
{
// 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 = 0;
+ 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;
CClientUIInterface uiInterface;
std::string strWalletFileName;
unsigned int nNodeLifespan;
+unsigned int nDerivationMethodIndex;
//////////////////////////////////////////////////////////////////////////////
//
" -dnsseed " + _("Find peers using DNS lookup (default: 1)") + "\n" +
" -nosynccheckpoints " + _("Disable sync checkpoints (default: 0)") + "\n" +
" -stakepooledkeys " + _("Use pooled pubkeys for the last coinstake output (default: 0)") + "\n" +
+ " -derivationmethod " + _("Which key derivation method to use by default (default: sha512)") + "\n" +
" -banscore=<n> " + _("Threshold for disconnecting misbehaving peers (default: 100)") + "\n" +
" -bantime=<n> " + _("Number of seconds to keep misbehaving peers from reconnecting (default: 86400)") + "\n" +
" -maxreceivebuffer=<n> " + _("Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000)") + "\n" +
nNodeLifespan = GetArg("-addrlifespan", 7);
fStakeUsePooledKeys = GetBoolArg("-stakepooledkeys", false);
+
+ if(GetArg("-derivationmethod", "sha512") == "scrypt+sha512")
+ nDerivationMethodIndex = 1;
+
fTestNet = GetBoolArg("-testnet");
if (fTestNet) {
SoftSetBoolArg("-irc", true);
// Settings
extern int64 nTransactionFee;
extern bool fStakeUsePooledKeys;
+extern unsigned int nDerivationMethodIndex;
// Minimum disk space required - used in CheckDiskSpace()
static const uint64 nMinDiskSpace = 52428800;
r = 1, p = 1, N = 1024
*/
-uint256 scrypt(const void* input, size_t inputlen, void *scratchpad)
+uint256 scrypt_nosalt(const void* input, size_t inputlen, void *scratchpad)
{
uint32_t *V;
uint32_t X[32];
return result;
}
+uint256 scrypt(const void* data, size_t datalen, const void* salt, size_t saltlen, void *scratchpad)
+{
+ uint32_t *V;
+ uint32_t X[32];
+ uint256 result = 0;
+ V = (uint32_t *)(((uintptr_t)(scratchpad) + 63) & ~ (uintptr_t)(63));
+
+ PBKDF2_SHA256((const uint8_t*)data, datalen, (const uint8_t*)salt, saltlen, 1, (uint8_t *)X, 128);
+ scrypt_core(X, V);
+ PBKDF2_SHA256((const uint8_t*)data, datalen, (uint8_t *)X, 128, 1, (uint8_t*)&result, 32);
+
+ return result;
+}
+
uint256 scrypt_hash(const void* input, size_t inputlen)
{
unsigned char scratchpad[SCRYPT_BUFFER_SIZE];
- return scrypt(input, inputlen, scratchpad);
+ return scrypt_nosalt(input, inputlen, scratchpad);
+}
+
+uint256 scrypt_salted_hash(const void* input, size_t inputlen, const void* salt, size_t saltlen)
+{
+ unsigned char scratchpad[SCRYPT_BUFFER_SIZE];
+ return scrypt(input, inputlen, salt, saltlen, scratchpad);
+}
+
+uint256 scrypt_salted_multiround_hash(const void* input, size_t inputlen, const void* salt, size_t saltlen, const unsigned int nRounds)
+{
+ uint256 resultHash = scrypt_salted_hash(input, inputlen, salt, saltlen);
+ uint256 transitionalHash = resultHash;
+
+ for(unsigned int i = 1; i < nRounds; i++)
+ {
+ resultHash = scrypt_salted_hash(input, inputlen, (const void*)&transitionalHash, 32);
+ transitionalHash = resultHash;
+ }
+
+ return resultHash;
}
uint256 scrypt_blockhash(const void* input)
{
unsigned char scratchpad[SCRYPT_BUFFER_SIZE];
- return scrypt(input, 80, scratchpad);
+ return scrypt_nosalt(input, 80, scratchpad);
}
+
#include "util.h"
#include "net.h"
+uint256 scrypt_salted_multiround_hash(const void* input, size_t inputlen, const void* salt, size_t saltlen, const unsigned int nRounds);
+uint256 scrypt_salted_hash(const void* input, size_t inputlen, const void* salt, size_t saltlen);
uint256 scrypt_hash(const void* input, size_t inputlen);
uint256 scrypt_blockhash(const void* input);
vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
RAND_bytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE);
- CMasterKey kMasterKey;
+ CMasterKey kMasterKey(nDerivationMethodIndex);
RandAddSeedPerfmon();
kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE);