Beispiel #1
0
def breakDownWallet(walletPath, fragSize):
    print 'breaking down wallet in packs of %d addresses' % fragSize
    print 'reading wallet'
    theWallet = PyBtcWallet().readWalletFile(walletPath)

    nAddresses = len(theWallet.addrMap)

    addrIndex = 0
    wltIndex = 1

    if walletPath[-7:] == '.wallet':
        newDir = walletPath[:-7]
    else:
        newDir = os.path.dirname(walletPath)

    if not os.path.exists(newDir):
        os.mkdir(newDir)

    rootAddr = theWallet.addrMap['ROOT']
    withEncrypt = theWallet.useEncryption
    addrIter = theWallet.addrMap.iteritems()

    while nAddresses > 0:

        print 'breaking down wallet from address #%d to #%d' % (
            addrIndex, addrIndex + fragSize - 1)
        nAddresses -= fragSize

        newWalletPath = os.path.join(newDir,
                                     'armory_wlt_%05d_.wallet' % wltIndex)
        wltIndex += 1

        walletFragment = PyBtcWallet()
        createNewWallet(walletFragment, rootAddr, newWalletPath, withEncrypt,
                        theWallet.kdf)

        fileData = BinaryPacker()
        i = 0

        try:
            while i < fragSize:
                addrItem = addrIter.next()[1]
                addrItem.chainIndex = -2

                fileData.put(
                    BINARY_CHUNK,
                    '\x00' + addrItem.addrStr20 + addrItem.serialize())
                #walletFragment.walletFileSafeUpdate([[WLT_UPDATE_ADD, \
                #WLT_DATATYPE_KEYDATA, addrItem.addrStr20, addrItem]])
                i += 1

        except StopIteration:
            pass

        walletFile = open(newWalletPath, 'ab')
        walletFile.write(fileData.getBinaryString())
        walletFile.close()

        addrIndex += i
    print 'Done'
Beispiel #2
0
    def createNewWalletFromWizard(self):
        entropy = None
        if self.walletCreationPage.isManualEncryption():
            entropy = SecureBinaryData(
                int_to_binary(self.manualEntropyPage.pageFrame.getEntropy()))
        else:
            entropy = self.main.getExtraEntropyForKeyGen()
        self.newWallet = PyBtcWallet().createNewWallet(
            securePassphrase=self.setPassphrasePage.pageFrame.getPassphrase(),
            kdfTargSec=self.walletCreationPage.pageFrame.getKdfSec(),
            kdfMaxMem=self.walletCreationPage.pageFrame.getKdfBytes(),
            shortLabel=self.walletCreationPage.pageFrame.getName(),
            longLabel=self.walletCreationPage.pageFrame.getDescription(),
            doRegisterWithBDM=False,
            extraEntropy=entropy,
        )

        self.newWallet.unlock(securePassphrase=SecureBinaryData(
            self.setPassphrasePage.pageFrame.getPassphrase()))
        # We always want to fill the address pool, right away.
        fillPoolProgress = DlgProgress(self, self.main, HBar=1, \
                                       Title="Creating Wallet")
        fillPoolProgress.exec_(self.newWallet.fillAddressPool,
                               doRegister=False,
                               Progress=fillPoolProgress.UpdateHBar)

        # Reopening from file helps make sure everything is correct -- don't
        # let the user use a wallet that triggers errors on reading it
        wltpath = self.newWallet.walletPath
        walletFromDisk = PyBtcWallet().readWalletFile(wltpath)
        self.main.addWalletToApplication(walletFromDisk, walletIsNew=True)
Beispiel #3
0
    def createNewWalletFromWizard(self):
        self.newWallet = PyBtcWallet().createNewWallet( \
                       securePassphrase=self.setPassphrasePage.pageFrame.getPassphrase(), \
                       kdfTargSec=self.walletCreationPage.pageFrame.getKdfSec(), \
                       kdfMaxMem=self.walletCreationPage.pageFrame.getKdfBytes(), \
                       shortLabel=self.walletCreationPage.pageFrame.getName(), \
                       longLabel=self.walletCreationPage.pageFrame.getDescription(), \
                       doRegisterWithBDM=False, \
                       extraEntropy=self.main.getExtraEntropyForKeyGen())

        self.newWallet.unlock(securePassphrase=SecureBinaryData(
            self.setPassphrasePage.pageFrame.getPassphrase()))
        # We always want to fill the address pool, right away.
        fillpool = lambda: self.newWallet.fillAddressPool(doRegister=False)
        DlgExecLongProcess(fillpool, 'Creating Wallet...', self, self).exec_()

        # Reopening from file helps make sure everything is correct -- don't
        # let the user use a wallet that triggers errors on reading it
        wltpath = self.newWallet.walletPath
        walletFromDisk = PyBtcWallet().readWalletFile(wltpath)
        self.main.addWalletToApplication(walletFromDisk, walletIsNew=True)
        if TheBDM.getBDMState() in ('Uninitialized', 'Offline'):
            TheBDM.registerWallet(walletFromDisk, isFresh=True, wait=False)
        else:
            self.main.newWalletList.append([walletFromDisk, True])
Beispiel #4
0
 def testIsWltSigningAnyLockbox(self):
    lockboxList = readLockboxesFile(os.path.join(self.armoryHomeDir, MULTISIG_FILE_NAME))
    self.assertFalse(self.wlt.isWltSigningAnyLockbox(lockboxList))
    
    lboxWltAFile   = os.path.join(self.armoryHomeDir,'armory_%s_.wallet' % FIRST_WLT_NAME)
    lboxWltA = PyBtcWallet().readWalletFile(lboxWltAFile, doScanNow=True)
    self.assertTrue(lboxWltA.isWltSigningAnyLockbox(lockboxList))
    
    lboxWltBFile   = os.path.join(self.armoryHomeDir,'armory_%s_.wallet' % SECOND_WLT_NAME)
    lboxWltB = PyBtcWallet().readWalletFile(lboxWltBFile, doScanNow=True)
    self.assertTrue(lboxWltB.isWltSigningAnyLockbox(lockboxList))
Beispiel #5
0
    def setUp(self):
        self.shortlabel = 'TestWallet1'
        self.wltID = '3VB8XSoY' if USE_TESTNET else '3VB8XSmd'

        self.fileA = os.path.join(ARMORY_HOME_DIR,
                                  'armory_%s_.wallet' % self.wltID)
        self.fileB = os.path.join(ARMORY_HOME_DIR,
                                  'armory_%s_backup.wallet' % self.wltID)
        self.fileAupd = os.path.join(
            ARMORY_HOME_DIR,
            'armory_%s_backup_unsuccessful.wallet' % self.wltID)
        self.fileBupd = os.path.join(
            ARMORY_HOME_DIR,
            'armory_%s_update_unsuccessful.wallet' % self.wltID)

        self.removeFileList(
            [self.fileA, self.fileB, self.fileAupd, self.fileBupd])

        # We need a controlled test, so we script the all the normally-random stuff
        self.privKey = SecureBinaryData('\xaa' * 32)
        self.privKey2 = SecureBinaryData('\x33' * 32)
        self.chainstr = SecureBinaryData('\xee' * 32)
        theIV = SecureBinaryData(hex_to_binary('77' * 16))
        self.passphrase = SecureBinaryData('A self.passphrase')
        self.passphrase2 = SecureBinaryData('A new self.passphrase')

        self.wlt = PyBtcWallet().createNewWallet(withEncrypt=False, \
                                            plainRootKey=self.privKey, \
                                            chaincode=self.chainstr,   \
                                            IV=theIV, \
                                            shortLabel=self.shortlabel)
    def setUp(self):
        self.fileA = os.path.join(ARMORY_HOME_DIR,
                                  'armory_%s_.wallet' % TEST_WALLET_ID)
        self.fileB = os.path.join(ARMORY_HOME_DIR,
                                  'armory_%s_backup.wallet' % TEST_WALLET_ID)
        self.fileAupd = os.path.join(
            ARMORY_HOME_DIR,
            'armory_%s_backup_unsuccessful.wallet' % TEST_WALLET_ID)
        self.fileBupd = os.path.join(
            ARMORY_HOME_DIR,
            'armory_%s_update_unsuccessful.wallet' % TEST_WALLET_ID)

        self.removeFileList(
            [self.fileA, self.fileB, self.fileAupd, self.fileBupd])

        # We need a controlled test, so we script the all the normally-random stuff
        self.privKey = SecureBinaryData('\xaa' * 32)
        self.privKey2 = SecureBinaryData('\x33' * 32)
        self.chainstr = SecureBinaryData('\xee' * 32)
        theIV = SecureBinaryData(hex_to_binary('77' * 16))
        self.passphrase = SecureBinaryData('A self.passphrase')
        self.passphrase2 = SecureBinaryData('A new self.passphrase')

        self.wallet = PyBtcWallet().createNewWallet(withEncrypt=False, \
                                            plainRootKey=self.privKey, \
                                            chaincode=self.chainstr,   \
                                            IV=theIV, \
                                            shortLabel=TEST_WALLET_NAME, \
                                            longLabel=TEST_WALLET_DESCRIPTION)
        self.jsonServer = Armory_Json_Rpc_Server(self.wallet)
        TheBDM.registerWallet(self.wallet)
Beispiel #7
0
 def __init__(self, wallet=None, walletPath=''):
     if wallet != None:
         self.wallet = wallet
     else:
         if not os.path.exists(walletPath):
             print 'Wallet does not exist:'
             print '  ', walletPath
             raise WalletNotFound
         self.wallet = PyBtcWallet().readWalletFile(walletPath)
Beispiel #8
0
 def setUp(self):
     self.verifyBlockHeight()
     # Load the primary file from the test net in a box
     self.fileA = os.path.join(self.tiab.tiabDirectory, 'tiab', 'armory', \
                               'armory_%s_.wallet' % FIRST_WLT_NAME)
     self.wltA = PyBtcWallet().readWalletFile(self.fileA, doScanNow=True)
     self.fileB = os.path.join(self.tiab.tiabDirectory, 'tiab', 'armory', \
                               'armory_%s_.wallet' % SECOND_WLT_NAME)
     self.wltB = PyBtcWallet().readWalletFile(self.fileB, doScanNow=True)
     self.fileC = os.path.join(self.tiab.tiabDirectory, 'tiab', 'armory', \
                               'armory_%s_.wallet' % THIRD_WLT_NAME)
     self.wltC = PyBtcWallet().readWalletFile(self.fileC, doScanNow=True)
     self.jsonServer = Armory_Json_Rpc_Server(self.wltA, \
                                   inWltMap={SECOND_WLT_NAME : self.wltB, \
                                             THIRD_WLT_NAME : self.wltC}, \
                      armoryHomeDir=os.path.join(self.tiab.tiabDirectory, \
                                                 'tiab','armory'))
     TheBDM.registerWallet(self.wltA)
Beispiel #9
0
def createWalletList(n, nameString):
   walletList = []
   for i in range(n):
      name = "%s #%d" % (nameString, i)
      newWallet = PyBtcWallet().createNewWallet( \
                                           withEncrypt=False, \
                                           shortLabel=name, \
                                           longLabel=name, \
                                           doRegisterWithBDM=False)
      walletList.append(newWallet)
   return walletList
    def setUp(self):
        self.verifyBlockHeight()
        # Load the primary file from the test net in a box
        self.fileA = os.path.join(self.tiab.tiabDirectory, 'tiab', 'armory', \
                                  'armory_%s_.wallet' % FIRST_WLT_NAME)
        self.wltA = PyBtcWallet().readWalletFile(self.fileA)
        self.fileB = os.path.join(self.tiab.tiabDirectory, 'tiab', 'armory', \
                                  'armory_%s_.wallet' % SECOND_WLT_NAME)
        self.wltB = PyBtcWallet().readWalletFile(self.fileB)
        self.fileC = os.path.join(self.tiab.tiabDirectory, 'tiab', 'armory', \
                                  'armory_%s_.wallet' % THIRD_WLT_NAME)
        self.wltC = PyBtcWallet().readWalletFile(self.fileC)
        self.jsonServer = Armory_Json_Rpc_Server(self.wltA, \
                                      inWltMap={SECOND_WLT_NAME : self.wltB, \
                                                THIRD_WLT_NAME : self.wltC}, \
                         armoryHomeDir=os.path.join(self.tiab.tiabDirectory, \
                                                    'tiab','armory'))

        self.wltIDs = [
            self.wltA.uniqueIDB58, self.wltB.uniqueIDB58, self.wltC.uniqueIDB58
        ]
        #register a callback
        TheBDM.registerCppNotification(self.armoryDTiabTestCallback)

        #flag to check on wallet scan status
        self.numberOfWalletsScanned = 0

        self.wltA.registerWallet()
        time.sleep(0.5)
        self.wltB.registerWallet()
        time.sleep(0.5)
        self.wltC.registerWallet()
        time.sleep(0.5)
        #wait on scan for 20sec then raise if the scan hasn't finished yet
        i = 0
        while self.numberOfWalletsScanned < 3:
            time.sleep(0.5)
            i += 1
            if i >= 40:
                raise RuntimeError("self.numberOfWalletsScanned = %d" %
                                   self.numberOfWalletsScanned)
Beispiel #11
0
    def setUp(self):

        self.verifyBlockHeight()
        self.fileA = os.path.join(self.armoryHomeDir,
                                  'armory_%s_.wallet' % TEST_WALLET_ID)
        self.fileB = os.path.join(self.armoryHomeDir,
                                  'armory_%s_backup.wallet' % TEST_WALLET_ID)
        self.fileAupd = os.path.join(
            self.armoryHomeDir,
            'armory_%s_backup_unsuccessful.wallet' % TEST_WALLET_ID)
        self.fileBupd = os.path.join(
            self.armoryHomeDir,
            'armory_%s_update_unsuccessful.wallet' % TEST_WALLET_ID)

        self.removeFileList(
            [self.fileA, self.fileB, self.fileAupd, self.fileBupd])

        # We need a controlled test, so we script the all the normally-random stuff
        self.privKey = SecureBinaryData('\xaa' * 32)
        self.privKey2 = SecureBinaryData('\x33' * 32)
        self.chainstr = SecureBinaryData('\xee' * 32)
        theIV = SecureBinaryData(hex_to_binary('77' * 16))
        self.passphrase = SecureBinaryData('A self.passphrase')
        self.passphrase2 = SecureBinaryData('A new self.passphrase')

        #register a callback
        TheBDM.registerCppNotification(self.armoryDTestCallback)

        #flag to check on wallet scan status
        self.walletIsScanned = False

        #create the wallet
        self.wallet = PyBtcWallet().createNewWallet(withEncrypt=False, \
                                            plainRootKey=self.privKey, \
                                            chaincode=self.chainstr,   \
                                            IV=theIV, \
                                            shortLabel=TEST_WALLET_NAME, \
                                            longLabel=TEST_WALLET_DESCRIPTION,
                                            armoryHomeDir = self.armoryHomeDir)
        self.jsonServer = Armory_Json_Rpc_Server(self.wallet)

        #register it
        self.wallet.registerWallet()

        #wait on scan for 2 min then raise if the scan hasn't finished yet
        i = 0
        while not self.walletIsScanned:
            time.sleep(0.5)
            i += 1
            if i >= 60 * 4:
                raise RuntimeError(
                    "Timeout waiting for TheBDM to register the wallet.")
Beispiel #12
0
    def buildCorruptWallet(self, walletPath):
        crpWlt = PyBtcWallet()
        crpWlt.createNewWallet(walletPath,
                               securePassphrase='testing',
                               doRegisterWithBDM=False)
        #not registering with the BDM, have to fill the wallet address pool manually
        crpWlt.fillAddressPool(100)

        #grab the last computed address
        lastaddr = crpWlt.addrMap[crpWlt.lastComputedChainAddr160]

        #corrupt the pubkey
        PubKey = hex_to_binary(
            '0478d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71a1518063243acd4dfe96b66e3f2ec8013c8e072cd09b3834a19f81f659cc3455'
        )
        lastaddr.binPublicKey65 = SecureBinaryData(PubKey)
        crpWlt.addrMap[crpWlt.lastComputedChainAddr160] = lastaddr

        crpWlt.fillAddressPool(200)

        #insert a gap and inconsistent encryption
        newAddr = PyBtcAddress()
        newAddr.chaincode = lastaddr.chaincode
        newAddr.chainIndex = 250
        PrivKey = hex_to_binary(
            'e3b0c44298fc1c149afbf4c8996fb92427ae41e5978fe51ca495991b7852b855')
        newAddr.binPrivKey32_Plain = SecureBinaryData(PrivKey)
        newAddr.binPublicKey65 = CryptoECDSA().ComputePublicKey( \
                                                  newAddr.binPrivKey32_Plain)
        newAddr.addrStr20 = newAddr.binPublicKey65.getHash160()
        newAddr.isInitialized = True

        crpWlt.addrMap[newAddr.addrStr20] = newAddr
        crpWlt.lastComputedChainAddr160 = newAddr.addrStr20
        crpWlt.fillAddressPool(250)

        lastAddr = crpWlt.addrMap[crpWlt.lastComputedChainAddr160]
        PrivKey = hex_to_binary(
            'e3b0c44298fc1c149afbf4c8996fb92427ae41e5978fe51ca495991b00000000')
        lastAddr.binPrivKey32_Plain = SecureBinaryData(PrivKey)
        lastAddr.binPublicKey65 = CryptoECDSA().ComputePublicKey( \
                                                  lastAddr.binPrivKey32_Plain)
        lastAddr.keyChanged = True
        crpWlt.kdfKey = crpWlt.kdf.DeriveKey(SecureBinaryData('testing'))
        lastAddr.lock(secureKdfOutput=crpWlt.kdfKey)
        lastAddr.useEncryption = True

        crpWlt.fillAddressPool(350)

        #TODO: corrupt a private key
        #break an address entry at binary level
        return crpWlt.uniqueIDB58
Beispiel #13
0
   print '   or: %s --sweep <master wallet file path>' % sys.argv[0]
   exit(0)
   
# Main execution path
# Do not ever access the same wallet file from two different processes at the same time
print '\n'
raw_input('PLEASE CLOSE ARMORY BEFORE RUNNING THIS SCRIPT!  (press enter to continue)\n')

if len(promoKitArgList)<3:
   printHelp()

operation = promoKitArgList[1]
walletFile = promoKitArgList[2]
if not os.path.exists(walletFile):
   print 'Wallet file was not found: %s' % walletFile
masterWallet = PyBtcWallet().readWalletFile(walletFile, False)
if operation == '--create':
   if len(promoKitArgList)<6:
      printHelp()
   else:
      numWallets = int(promoKitArgList[3])
      addrsPerWallet = int(promoKitArgList[4])
      walletLabel = promoKitArgList[5]
      walletList = createWalletList(numWallets, walletLabel)
      masterWallet = importAddrsToMasterWallet( \
            masterWallet, walletList, addrsPerWallet, "Master Promo Wallet", )
      # Didn't want to fit these into the argument list. Need to edit based on event
      printWalletList(walletList, "$10 in Bitcoins. ", "November 1st, 2014")
elif operation == '--distribute':
   if len(promoKitArgList)<4:
      printHelp()
Beispiel #14
0
    def testPyBtcWallet(self):

        self.wlt.addrPoolSize = 5
        # No block chain loaded so this should return -1
        # self.assertEqual(self.wlt.detectHighestUsedIndex(True), -1)
        self.assertEqual(self.wlt.kdfKey, None)
        self.assertEqual(binary_to_hex(self.wlt.addrMap['ROOT'].addrStr20),
                         WALLET_ROOT_ADDR)

        #############################################################################
        # (1) Getting a new address:
        newAddr = self.wlt.getNextUnusedAddress()
        self.wlt.pprint(indent=' ' * 5)
        self.assertEqual(binary_to_hex(newAddr.addrStr20), NEW_UNUSED_ADDR)

        # (1) Re-reading wallet from file, compare the two wallets
        wlt2 = PyBtcWallet().readWalletFile(self.wlt.walletPath)
        self.assertTrue(self.wlt.isEqualTo(wlt2))

        #############################################################################
        # (2)Testing unencrypted wallet import-address'
        originalLength = len(self.wlt.linearAddr160List)
        self.wlt.importExternalAddressData(privKey=self.privKey2)
        self.assertEqual(len(self.wlt.linearAddr160List), originalLength + 1)

        # (2) Re-reading wallet from file, compare the two wallets
        wlt2 = PyBtcWallet().readWalletFile(self.wlt.walletPath)
        self.assertTrue(self.wlt.isEqualTo(wlt2))

        # (2a)Testing deleteImportedAddress
        # Wallet size before delete:',  os.path.getsize(self.wlt.walletPath)
        # Addresses before delete:', len(self.wlt.linearAddr160List)
        toDelete160 = convertKeyDataToAddress(self.privKey2)
        self.wlt.deleteImportedAddress(toDelete160)
        self.assertEqual(len(self.wlt.linearAddr160List), originalLength)

        # (2a) Reimporting address for remaining tests
        # Wallet size before reimport:',  os.path.getsize(self.wlt.walletPath)
        self.wlt.importExternalAddressData(privKey=self.privKey2)
        self.assertEqual(len(self.wlt.linearAddr160List), originalLength + 1)

        # (2b)Testing ENCRYPTED wallet import-address
        privKey3 = SecureBinaryData('\xbb' * 32)
        privKey4 = SecureBinaryData('\x44' * 32)
        self.chainstr2 = SecureBinaryData('\xdd' * 32)
        theIV2 = SecureBinaryData(hex_to_binary('66' * 16))
        self.passphrase2 = SecureBinaryData('hello')
        wltE = PyBtcWallet().createNewWallet(withEncrypt=True, \
                                            plainRootKey=privKey3, \
                                            securePassphrase=self.passphrase2, \
                                            chaincode=self.chainstr2,   \
                                            IV=theIV2, \
                                            shortLabel=self.shortlabel)

        #  We should have thrown an error about importing into a  locked wallet...
        self.assertRaises(WalletLockError,
                          wltE.importExternalAddressData,
                          privKey=self.privKey2)

        wltE.unlock(securePassphrase=self.passphrase2)
        wltE.importExternalAddressData(privKey=self.privKey2)

        # (2b) Re-reading wallet from file, compare the two wallets
        wlt2 = PyBtcWallet().readWalletFile(wltE.walletPath)
        self.assertTrue(wltE.isEqualTo(wlt2))

        # (2b) Unlocking wlt2 after re-reading locked-import-wallet
        wlt2.unlock(securePassphrase=self.passphrase2)
        self.assertFalse(wlt2.isLocked)

        #############################################################################
        # Now play with encrypted wallets
        # *********************************************************************'
        # (3)Testing conversion to encrypted wallet

        kdfParams = self.wlt.computeSystemSpecificKdfParams(0.1)
        self.wlt.changeKdfParams(*kdfParams)

        self.assertEqual(self.wlt.kdf.getSalt(), kdfParams[2])
        self.wlt.changeWalletEncryption(securePassphrase=self.passphrase)
        self.assertEqual(self.wlt.kdf.getSalt(), kdfParams[2])

        # (3) Re-reading wallet from file, compare the two wallets'
        wlt2 = PyBtcWallet().readWalletFile(self.wlt.getWalletPath())
        self.assertTrue(self.wlt.isEqualTo(wlt2))
        # NOTE:  this isEqual operation compares the serializations
        #        of the wallet addresses, which only contains the
        #        encrypted versions of the private keys.  However,
        #        self.wlt is unlocked and contains the plaintext keys, too
        #        while wlt2 does not.
        self.wlt.lock()
        for key in self.wlt.addrMap:
            self.assertTrue(self.wlt.addrMap[key].isLocked)
            self.assertEqual(
                self.wlt.addrMap[key].binPrivKey32_Plain.toHexStr(), '')

        #############################################################################
        # (4)Testing changing self.passphrase on encrypted wallet',

        self.wlt.unlock(securePassphrase=self.passphrase)
        for key in self.wlt.addrMap:
            self.assertFalse(self.wlt.addrMap[key].isLocked)
            self.assertNotEqual(
                self.wlt.addrMap[key].binPrivKey32_Plain.toHexStr(), '')
        # ...to same self.passphrase'
        origKdfKey = self.wlt.kdfKey
        self.wlt.changeWalletEncryption(securePassphrase=self.passphrase)
        self.assertEqual(origKdfKey, self.wlt.kdfKey)

        # (4)And now testing new self.passphrase...'
        self.wlt.changeWalletEncryption(securePassphrase=self.passphrase2)
        self.assertNotEqual(origKdfKey, self.wlt.kdfKey)

        # (4) Re-reading wallet from file, compare the two wallets'
        wlt2 = PyBtcWallet().readWalletFile(self.wlt.getWalletPath())
        self.assertTrue(self.wlt.isEqualTo(wlt2))

        #############################################################################
        # (5)Testing changing KDF on encrypted wallet'

        self.wlt.unlock(securePassphrase=self.passphrase2)

        MEMORY_REQT_BYTES = 1024
        NUM_ITER = 999
        SALT_ALL_0 = '00' * 32
        self.wlt.changeKdfParams(MEMORY_REQT_BYTES, NUM_ITER,
                                 hex_to_binary(SALT_ALL_0), self.passphrase2)
        self.assertEqual(self.wlt.kdf.getMemoryReqtBytes(), MEMORY_REQT_BYTES)
        self.assertEqual(self.wlt.kdf.getNumIterations(), NUM_ITER)
        self.assertEqual(self.wlt.kdf.getSalt().toHexStr(), SALT_ALL_0)

        self.wlt.changeWalletEncryption(securePassphrase=self.passphrase2)
        # I don't know why this shouldn't be ''
        # Commenting out because it's a broken assertion
        # self.assertNotEqual(origKdfKey.toHexStr(), '')

        # (5) Get new address from locked wallet'
        # Locking wallet'
        self.wlt.lock()
        for i in range(10):
            self.wlt.getNextUnusedAddress()
        self.assertEqual(len(self.wlt.addrMap), originalLength + 13)

        # (5) Re-reading wallet from file, compare the two wallets'
        wlt2 = PyBtcWallet().readWalletFile(self.wlt.getWalletPath())
        self.assertTrue(self.wlt.isEqualTo(wlt2))

        #############################################################################
        # !!!  #forkOnlineWallet()
        # (6)Testing forking encrypted wallet for online mode'
        self.wlt.forkOnlineWallet('OnlineVersionOfEncryptedWallet.bin')
        wlt2.readWalletFile('OnlineVersionOfEncryptedWallet.bin')
        for key in wlt2.addrMap:
            self.assertTrue(self.wlt.addrMap[key].isLocked)
            self.assertEqual(
                self.wlt.addrMap[key].binPrivKey32_Plain.toHexStr(), '')
        # (6)Getting a new addresses from both wallets'
        for i in range(self.wlt.addrPoolSize * 2):
            self.wlt.getNextUnusedAddress()
            wlt2.getNextUnusedAddress()

        newaddr1 = self.wlt.getNextUnusedAddress()
        newaddr2 = wlt2.getNextUnusedAddress()
        self.assertTrue(newaddr1.getAddr160() == newaddr2.getAddr160())
        self.assertEqual(len(wlt2.addrMap), 3 * originalLength + 14)

        # (6) Re-reading wallet from file, compare the two wallets
        wlt3 = PyBtcWallet().readWalletFile(
            'OnlineVersionOfEncryptedWallet.bin')
        self.assertTrue(wlt3.isEqualTo(wlt2))
        #############################################################################
        # (7)Testing removing wallet encryption'
        # Wallet is locked?  ', self.wlt.isLocked
        self.wlt.unlock(securePassphrase=self.passphrase2)
        self.wlt.changeWalletEncryption(None)
        for key in self.wlt.addrMap:
            self.assertFalse(self.wlt.addrMap[key].isLocked)
            self.assertNotEqual(
                self.wlt.addrMap[key].binPrivKey32_Plain.toHexStr(), '')

        # (7) Re-reading wallet from file, compare the two wallets'
        wlt2 = PyBtcWallet().readWalletFile(self.wlt.getWalletPath())
        self.assertTrue(self.wlt.isEqualTo(wlt2))

        #############################################################################
        # \n'
        # *********************************************************************'
        # (8)Doing interrupt tests to test wallet-file-update recovery'
        def hashfile(fn):
            f = open(fn, 'r')
            d = hash256(f.read())
            f.close()
            return binary_to_hex(d[:8])

        def verifyFileStatus(fileAExists = True, fileBExists = True, \
                             fileAupdExists = True, fileBupdExists = True):
            self.assertEqual(os.path.exists(self.fileA), fileAExists)
            self.assertEqual(os.path.exists(self.fileB), fileBExists)
            self.assertEqual(os.path.exists(self.fileAupd), fileAupdExists)
            self.assertEqual(os.path.exists(self.fileBupd), fileBupdExists)

        correctMainHash = hashfile(self.fileA)
        try:
            self.wlt.interruptTest1 = True
            self.wlt.getNextUnusedAddress()
        except InterruptTestError:
            # Interrupted!'
            pass
        self.wlt.interruptTest1 = False

        # (8a)Interrupted getNextUnusedAddress on primary file update'
        verifyFileStatus(True, True, False, True)
        # (8a)Do consistency check on the wallet'
        self.wlt.doWalletFileConsistencyCheck()
        verifyFileStatus(True, True, False, False)
        self.assertEqual(correctMainHash, hashfile(self.fileA))

        try:
            self.wlt.interruptTest2 = True
            self.wlt.getNextUnusedAddress()
        except InterruptTestError:
            # Interrupted!'
            pass
        self.wlt.interruptTest2 = False

        # (8b)Interrupted getNextUnusedAddress on between primary/backup update'
        verifyFileStatus(True, True, True, True)
        # (8b)Do consistency check on the wallet'
        self.wlt.doWalletFileConsistencyCheck()
        verifyFileStatus(True, True, False, False)
        self.assertEqual(hashfile(self.fileA), hashfile(self.fileB))
        # (8c) Try interrupting at state 3'
        verifyFileStatus(True, True, False, False)

        try:
            self.wlt.interruptTest3 = True
            self.wlt.getNextUnusedAddress()
        except InterruptTestError:
            # Interrupted!'
            pass
        self.wlt.interruptTest3 = False

        # (8c)Interrupted getNextUnusedAddress on backup file update'
        verifyFileStatus(True, True, True, False)
        # (8c)Do consistency check on the wallet'
        self.wlt.doWalletFileConsistencyCheck()
        verifyFileStatus(True, True, False, False)
        self.assertEqual(hashfile(self.fileA), hashfile(self.fileB))

        #############################################################################
        # \n'
        # *********************************************************************'
        # (9)Checksum-based byte-error correction tests!'
        # (9)Start with a good primary and backup file...'

        # (9a)Open primary wallet, change second byte in KDF'
        wltfile = open(self.wlt.walletPath, 'r+b')
        wltfile.seek(326)
        wltfile.write('\xff')
        wltfile.close()
        # (9a)Byte changed, file hashes:'
        verifyFileStatus(True, True, False, False)

        # (9a)Try to read wallet from file, should correct KDF error, write fix'
        wlt2 = PyBtcWallet().readWalletFile(self.wlt.walletPath)
        verifyFileStatus(True, True, False, False)
        self.assertNotEqual(hashfile(self.fileA), hashfile(self.fileB))

        # \n'
        # *********************************************************************'
        # (9b)Change a byte in each checksummed field in root addr'
        wltfile = open(self.wlt.walletPath, 'r+b')
        wltfile.seek(838)
        wltfile.write('\xff')
        wltfile.seek(885)
        wltfile.write('\xff')
        wltfile.seek(929)
        wltfile.write('\xff')
        wltfile.seek(954)
        wltfile.write('\xff')
        wltfile.seek(1000)
        wltfile.write('\xff')
        wltfile.close()
        # (9b) New file hashes...'
        verifyFileStatus(True, True, False, False)

        # (9b)Try to read wallet from file, should correct address errors'
        wlt2 = PyBtcWallet().readWalletFile(self.wlt.walletPath)
        verifyFileStatus(True, True, False, False)
        self.assertNotEqual(hashfile(self.fileA), hashfile(self.fileB))

        # \n'
        # *********************************************************************'
        # (9c)Change a byte in each checksummed field, of first non-root addr'
        wltfile = open(self.wlt.walletPath, 'r+b')
        wltfile.seek(1261 + 21 + 838)
        wltfile.write('\xff')
        wltfile.seek(1261 + 21 + 885)
        wltfile.write('\xff')
        wltfile.seek(1261 + 21 + 929)
        wltfile.write('\xff')
        wltfile.seek(1261 + 21 + 954)
        wltfile.write('\xff')
        wltfile.seek(1261 + 21 + 1000)
        wltfile.write('\xff')
        wltfile.close()
        # (9c) New file hashes...'
        verifyFileStatus(True, True, False, False)

        # (9c)Try to read wallet from file, should correct address errors'
        wlt2 = PyBtcWallet().readWalletFile(self.wlt.walletPath)
        verifyFileStatus(True, True, False, False)
        self.assertNotEqual(hashfile(self.fileA), hashfile(self.fileB))

        # \n'
        # *********************************************************************'
        # (9d)Now butcher the CHECKSUM, see if correction works'
        wltfile = open(self.wlt.walletPath, 'r+b')
        wltfile.seek(977)
        wltfile.write('\xff')
        wltfile.close()
        # (9d) New file hashes...'
        verifyFileStatus(True, True, False, False)

        # (9d)Try to read wallet from file, should correct address errors'
        wlt2 = PyBtcWallet().readWalletFile(self.wlt.walletPath)
        verifyFileStatus(True, True, False, False)
        self.assertNotEqual(hashfile(self.fileA), hashfile(self.fileB))

        # *******'
        # (9z) Test comment I/O'
        comment1 = 'This is my normal unit-testing address.'
        comment2 = 'This is fake tx... no tx has this hash.'
        comment3 = comment1 + '  Corrected!'
        hash1 = '\x1f' * 20  # address160
        hash2 = '\x2f' * 32  # tx hash
        self.wlt.setComment(hash1, comment1)
        self.wlt.setComment(hash2, comment2)
        self.wlt.setComment(hash1, comment3)

        wlt2 = PyBtcWallet().readWalletFile(self.wlt.walletPath)
        c3 = wlt2.getComment(hash1)
        c2 = wlt2.getComment(hash2)
        self.assertEqual(c3, comment3)
        self.assertEqual(c2, comment2)
Beispiel #15
0
    def testWalletRecovery(self):
        #run recovery on broken wallet
        recThread = PyBtcWalletRecovery().RecoverWallet(self.corruptWallet, \
                                                        'testing', RECOVERMODE.Full, \
                                                        returnError = 'Dict')
        recThread.join()
        brkWltResult = recThread.output

        self.assertTrue(len(brkWltResult['sequenceGaps'])==1, \
                        "Sequence Gap Undetected")
        self.assertTrue(len(brkWltResult['forkedPublicKeyChain'])==3, \
                        "Address Chain Forks Undetected")
        self.assertTrue(len(brkWltResult['unmatchedPair'])==100, \
                        "Unmatched Priv/Pub Key Undetected")
        self.assertTrue(len(brkWltResult['misc'])==50, \
                        "Wallet Encryption Inconsistency Undetected")
        self.assertTrue(len(brkWltResult['importedErr'])==50, \
                        "Unexpected Errors Found")
        self.assertTrue(brkWltResult['nErrors']==204, \
                        "Unexpected Errors Found")

        #check obfuscated keys yield the valid key
        #grab root key
        badWlt = PyBtcWallet()
        badWlt.readWalletFile(self.corruptWallet, False, False)
        rootAddr = badWlt.addrMap['ROOT']

        SecurePassphrase = SecureBinaryData('testing')
        secureKdfOutput = badWlt.kdf.DeriveKey(SecurePassphrase)

        #HMAC Q
        rootAddr.unlock(secureKdfOutput)
        Q = rootAddr.binPrivKey32_Plain.toBinStr()

        nonce = 0
        while 1:
            hmacQ = HMAC256(Q, 'LogMult%d' % nonce)
            if binary_to_int(hmacQ, BIGENDIAN) < SECP256K1_ORDER:
                hmacQ = SecureBinaryData(hmacQ)
                break
            nonce = nonce + 1

        #Bad Private Keys
        import operator
        badKeys = [
            addrObj
            for addrObj in (sorted(badWlt.addrMap.values(),
                                   key=operator.attrgetter('chainIndex')))
        ]

        #run through obdsPrivKey
        for i in range(0, len(brkWltResult['privMult'])):
            obfsPKey = SecureBinaryData(
                hex_to_binary(brkWltResult['privMult'][i]))
            pKey = CryptoECDSA().ECMultiplyScalars(obfsPKey.toBinStr(), \
                                                   hmacQ.toBinStr())

            try:
                badKeys[i + 201].unlock(secureKdfOutput)
            except:
                continue

            self.assertTrue(binary_to_hex(pKey) == \
                            badKeys[i+201].binPrivKey32_Plain.toHexStr(), \
                            'key mult error')

        #run recovery on recovered wallet
        recThread = PyBtcWalletRecovery().RecoverWallet( \
                                   'armory_%s_RECOVERED.wallet' % self.wltID, \
                                   'testing', RECOVERMODE.Full, \
                                   returnError = 'Dict')
        recThread.join()
        rcvWltResult = recThread.output

        self.assertTrue(len(rcvWltResult['importedErr'])==50, \
                        "Unexpected Errors Found")
        self.assertTrue(rcvWltResult['nErrors']==50, \
                        "Unexpected Errors Found")
        self.assertTrue(len(rcvWltResult['negativeImports'])==99, \
                        "Missing neg Imports")


# Running tests with "python <module name>" will NOT work for any Armory tests
# You must run tests with "python -m unittest <module name>" or run all tests with "python -m unittest discover"
# if __name__ == "__main__":
#    unittest.main()