Line data Source code
1 : // Copyright (c) 2016-2020 The ZCash developers 2 : // Copyright (c) 2020-2021 The PIVX Core developers 3 : // Distributed under the MIT software license, see the accompanying 4 : // file COPYING or https://www.opensource.org/licenses/mit-license.php. 5 : 6 : #include "crypter.h" 7 : 8 : #include "script/script.h" 9 : #include "script/standard.h" 10 : #include "util/system.h" 11 : #include "uint256.h" 12 : 13 106 : bool CCryptoKeyStore::AddCryptedSaplingSpendingKey( 14 : const libzcash::SaplingExtendedFullViewingKey &extfvk, 15 : const std::vector<unsigned char> &vchCryptedSecret) 16 : { 17 212 : LOCK(cs_KeyStore); 18 106 : if (!SetCrypted()) { 19 : return false; 20 : } 21 : 22 : // if extfvk is not in SaplingFullViewingKeyMap, add it 23 106 : if (!AddSaplingFullViewingKey(extfvk)) { 24 : return false; 25 : } 26 : 27 106 : mapCryptedSaplingSpendingKeys[extfvk] = vchCryptedSecret; 28 : return true; 29 : } 30 : 31 112 : static bool DecryptSaplingSpendingKey(const CKeyingMaterial& vMasterKey, 32 : const std::vector<unsigned char>& vchCryptedSecret, 33 : const libzcash::SaplingExtendedFullViewingKey& extfvk, 34 : libzcash::SaplingExtendedSpendingKey& sk) 35 : { 36 224 : CKeyingMaterial vchSecret; 37 112 : if (!DecryptSecret(vMasterKey, vchCryptedSecret, extfvk.fvk.GetFingerprint(), vchSecret)) 38 : return false; 39 : 40 111 : if (vchSecret.size() != ZIP32_XSK_SIZE) 41 : return false; 42 : 43 223 : CSecureDataStream ss(vchSecret, SER_NETWORK, PROTOCOL_VERSION); 44 111 : ss >> sk; 45 111 : return sk.expsk.full_viewing_key() == extfvk.fvk; 46 : } 47 : 48 1148 : bool CCryptoKeyStore::GetSaplingSpendingKey( 49 : const libzcash::SaplingExtendedFullViewingKey& extfvk, 50 : libzcash::SaplingExtendedSpendingKey& skOut) const 51 : { 52 2296 : LOCK(cs_KeyStore); 53 1148 : if (!IsCrypted()) { 54 1143 : return CBasicKeyStore::GetSaplingSpendingKey(extfvk, skOut); 55 : } 56 : 57 5 : auto it = mapCryptedSaplingSpendingKeys.find(extfvk); 58 5 : if (it == mapCryptedSaplingSpendingKeys.end()) return false; 59 5 : const std::vector<unsigned char>& vchCryptedSecret = it->second; 60 5 : return DecryptSaplingSpendingKey(vMasterKey, vchCryptedSecret, it->first, skOut); 61 : } 62 : 63 8200 : bool CCryptoKeyStore::HaveSaplingSpendingKey(const libzcash::SaplingExtendedFullViewingKey& extfvk) const 64 : { 65 16400 : LOCK(cs_KeyStore); 66 8200 : if (!IsCrypted()) { 67 7989 : return CBasicKeyStore::HaveSaplingSpendingKey(extfvk); 68 : } 69 422 : return mapCryptedSaplingSpendingKeys.count(extfvk) > 0; 70 : } 71 : 72 24 : bool CCryptoKeyStore::UnlockSaplingKeys(const CKeyingMaterial& vMasterKeyIn, bool fDecryptionThoroughlyChecked) 73 : { 74 24 : if (mapCryptedSaplingSpendingKeys.empty()) { 75 17 : LogPrintf("%s: mapCryptedSaplingSpendingKeys empty. No need to unlock anything.\n", __func__); 76 17 : return true; 77 : } 78 : 79 7 : bool keyFail = false; 80 7 : bool keyPass = false; 81 7 : CryptedSaplingSpendingKeyMap::const_iterator miSapling = mapCryptedSaplingSpendingKeys.begin(); 82 111 : for (; miSapling != mapCryptedSaplingSpendingKeys.end(); ++miSapling) { 83 107 : const libzcash::SaplingExtendedFullViewingKey &extfvk = (*miSapling).first; 84 107 : const std::vector<unsigned char> &vchCryptedSecret = (*miSapling).second; 85 107 : libzcash::SaplingExtendedSpendingKey sk; 86 107 : if (!DecryptSaplingSpendingKey(vMasterKeyIn, vchCryptedSecret, extfvk, sk)) { 87 : keyFail = true; 88 3 : break; 89 : } 90 107 : keyPass = true; 91 107 : if (fDecryptionThoroughlyChecked) 92 : break; 93 : } 94 : 95 7 : if (keyPass && keyFail) { 96 0 : LogPrintf("Sapling wallet is probably corrupted: Some keys decrypt but not all.\n"); 97 0 : throw std::runtime_error("Error unlocking sapling wallet: some keys decrypt but not all. Your wallet file may be corrupt."); 98 : } 99 7 : if (keyFail || !keyPass) 100 0 : return false; 101 : 102 : return true; 103 : }