Use SecureString for mnemonic phrase.
This commit is contained in:
parent
d09a0c44f3
commit
67557df165
|
@ -882,6 +882,7 @@ dependencies = [
|
|||
"zcash_note_encryption",
|
||||
"zcash_primitives",
|
||||
"zcash_proofs",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -48,6 +48,7 @@ zcash_note_encryption = "0.0"
|
|||
zcash_primitives = "0.5"
|
||||
zcash_proofs = "0.5"
|
||||
ed25519-zebra = "2.2.0"
|
||||
zeroize = "1.4.2"
|
||||
|
||||
# Metrics
|
||||
hyper = { version = "=0.14.2", default-features = false, features = ["server", "tcp", "http1"] }
|
||||
|
|
|
@ -4,6 +4,7 @@ use std::{
|
|||
ffi::{CStr, CString},
|
||||
ptr, slice,
|
||||
};
|
||||
use zeroize::Zeroize;
|
||||
|
||||
use zcash_primitives::zip339;
|
||||
|
||||
|
@ -63,7 +64,9 @@ pub extern "C" fn zip339_free_phrase(phrase: *const c_char) {
|
|||
if !phrase.is_null() {
|
||||
unsafe {
|
||||
// It is correct to cast away const here; the memory is not actually immutable.
|
||||
CString::from_raw(phrase as *mut c_char);
|
||||
CString::from_raw(phrase as *mut c_char)
|
||||
.into_bytes()
|
||||
.zeroize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -510,8 +510,11 @@ CVarInt<I> WrapVarInt(I& n) { return CVarInt<I>(n); }
|
|||
/**
|
||||
* string
|
||||
*/
|
||||
template<typename Stream, typename C> void Serialize(Stream& os, const std::basic_string<C>& str);
|
||||
template<typename Stream, typename C> void Unserialize(Stream& is, std::basic_string<C>& str);
|
||||
template<typename Stream, typename C, typename T, typename A>
|
||||
void Serialize(Stream& os, const std::basic_string<C>& str);
|
||||
|
||||
template<typename Stream, typename C, typename T, typename A>
|
||||
void Unserialize(Stream& is, std::basic_string<C>& str);
|
||||
|
||||
/**
|
||||
* prevector
|
||||
|
@ -625,16 +628,16 @@ inline void Unserialize(Stream& is, T& a)
|
|||
/**
|
||||
* string
|
||||
*/
|
||||
template<typename Stream, typename C>
|
||||
void Serialize(Stream& os, const std::basic_string<C>& str)
|
||||
template<typename Stream, typename C, typename T, typename A>
|
||||
void Serialize(Stream& os, const std::basic_string<C, T, A>& str)
|
||||
{
|
||||
WriteCompactSize(os, str.size());
|
||||
if (!str.empty())
|
||||
os.write((char*)&str[0], str.size() * sizeof(str[0]));
|
||||
}
|
||||
|
||||
template<typename Stream, typename C>
|
||||
void Unserialize(Stream& is, std::basic_string<C>& str)
|
||||
template<typename Stream, typename C, typename T, typename A>
|
||||
void Unserialize(Stream& is, std::basic_string<C, T, A>& str)
|
||||
{
|
||||
unsigned int nSize = ReadCompactSize(is);
|
||||
str.resize(nSize);
|
||||
|
|
|
@ -316,7 +316,7 @@ void RegtestDeactivateNU5() {
|
|||
}
|
||||
|
||||
libzcash::SaplingExtendedSpendingKey GetTestMasterSaplingSpendingKey() {
|
||||
std::string mnemonic("abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art");
|
||||
SecureString mnemonic("abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art");
|
||||
MnemonicSeed seed(English, mnemonic);
|
||||
return libzcash::SaplingExtendedSpendingKey::Master(seed);
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ TEST(WalletZkeysTest, StoreAndLoadSaplingZkeys) {
|
|||
EXPECT_ANY_THROW(wallet.GenerateNewLegacySaplingZKey());
|
||||
|
||||
// Load the all-zeroes seed
|
||||
std::string mnemonic("abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art");
|
||||
SecureString mnemonic("abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art");
|
||||
MnemonicSeed seed(English, mnemonic);
|
||||
// The legacy seed used to be automatically derived from randomness; since
|
||||
// non-mnemonic random generation has been removed we just use the
|
||||
|
@ -433,7 +433,7 @@ TEST(WalletZkeysTest, WriteCryptedSaplingZkeyDirectToDb) {
|
|||
ASSERT_FALSE(wallet.HaveMnemonicSeed());
|
||||
|
||||
// Load the all-zeroes seed as the legacy seed
|
||||
std::string mnemonic("abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art");
|
||||
SecureString mnemonic("abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art");
|
||||
MnemonicSeed seed(English, mnemonic);
|
||||
wallet.LoadMnemonicSeed(seed);
|
||||
ASSERT_TRUE(wallet.HaveMnemonicSeed());
|
||||
|
|
|
@ -1763,7 +1763,7 @@ UniValue walletconfirmbackup(const UniValue& params, bool fHelp)
|
|||
|
||||
EnsureWalletIsUnlocked();
|
||||
|
||||
auto strMnemonicPhrase = params[0].get_str();
|
||||
SecureString strMnemonicPhrase(params[0].get_str());
|
||||
boost::erase_all(strMnemonicPhrase, "\"");
|
||||
boost::trim(strMnemonicPhrase);
|
||||
if (strMnemonicPhrase.length() > 0) {
|
||||
|
|
|
@ -2355,7 +2355,7 @@ bool CWallet::SetCryptedMnemonicSeed(const uint256& seedFp, const std::vector<un
|
|||
return false;
|
||||
}
|
||||
|
||||
bool CWallet::VerifyMnemonicSeed(std::string mnemonic) {
|
||||
bool CWallet::VerifyMnemonicSeed(const SecureString& mnemonic) {
|
||||
LOCK(cs_wallet);
|
||||
|
||||
auto seed = GetMnemonicSeed();
|
||||
|
|
|
@ -1305,7 +1305,7 @@ public:
|
|||
bool SetCryptedMnemonicSeed(const uint256& seedFp, const std::vector<unsigned char> &vchCryptedSecret);
|
||||
/* Checks the wallet's seed against the specified mnemonic, and marks the
|
||||
* wallet's seed as having been backed up if the phrases match. */
|
||||
bool VerifyMnemonicSeed(std::string mnemonic);
|
||||
bool VerifyMnemonicSeed(const SecureString& mnemonic);
|
||||
bool MnemonicVerified();
|
||||
|
||||
/* Set the current HD seed, without saving it to disk (used by LoadWallet) */
|
||||
|
|
|
@ -28,7 +28,7 @@ MnemonicSeed MnemonicSeed::Random(uint32_t bip44CoinType, Language language, siz
|
|||
std::vector<unsigned char> entropy(entropyLen, 0);
|
||||
GetRandBytes(entropy.data(), entropyLen);
|
||||
const char* phrase = zip339_entropy_to_phrase(language, entropy.data(), entropyLen);
|
||||
std::string mnemonic(phrase);
|
||||
SecureString mnemonic(phrase);
|
||||
zip339_free_phrase(phrase);
|
||||
MnemonicSeed seed(language, mnemonic);
|
||||
|
||||
|
|
|
@ -66,21 +66,18 @@ public:
|
|||
class MnemonicSeed: public HDSeed {
|
||||
private:
|
||||
Language language;
|
||||
std::string mnemonic;
|
||||
SecureString mnemonic;
|
||||
|
||||
MnemonicSeed() {}
|
||||
|
||||
void Init() {
|
||||
unsigned char buf[64];
|
||||
zip339_phrase_to_seed(language, mnemonic.c_str(), &buf);
|
||||
seed.assign(buf, std::end(buf));
|
||||
void SetSeedFromMnemonic() {
|
||||
seed.resize(64);
|
||||
zip339_phrase_to_seed(language, mnemonic.c_str(), (uint8_t (*)[64])seed.data());
|
||||
}
|
||||
|
||||
public:
|
||||
MnemonicSeed(Language languageIn, std::string& mnemonicIn): language(languageIn), mnemonic(mnemonicIn) {
|
||||
unsigned char buf[64];
|
||||
zip339_phrase_to_seed(languageIn, mnemonicIn.c_str(), &buf);
|
||||
seed.assign(buf, std::end(buf));
|
||||
MnemonicSeed(Language languageIn, SecureString mnemonicIn): language(languageIn), mnemonic(mnemonicIn) {
|
||||
SetSeedFromMnemonic();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -127,7 +124,7 @@ public:
|
|||
READWRITE(language0);
|
||||
READWRITE(mnemonic);
|
||||
language = (Language) language0;
|
||||
Init();
|
||||
SetSeedFromMnemonic();
|
||||
} else {
|
||||
uint32_t language0 = (uint32_t) language;
|
||||
|
||||
|
@ -147,7 +144,7 @@ public:
|
|||
return language;
|
||||
}
|
||||
|
||||
const std::string GetMnemonic() const {
|
||||
const SecureString& GetMnemonic() const {
|
||||
return mnemonic;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue