def checkSig(self,binSig, binPubKey, txOutScript, txInTx, txInIndex, lastOpCodeSep=None): """ Generic method for checking Bitcoin tx signatures. This needs to be used for both OP_CHECKSIG and OP_CHECKMULTISIG. Step 1 is to pop signature and public key off the stack, which must be done outside this method and passed in through the argument list. The remaining steps do not require access to the stack. """ # 2. Subscript is from latest OP_CODESEPARATOR until end... if DNE, use whole script subscript = txOutScript if lastOpCodeSep: subscript = subscript[lastOpCodeSep:] # 3. Signature is deleted from subscript # I'm not sure why this line is necessary - maybe for non-standard scripts? lengthInBinary = int_to_binary(len(binSig)) subscript = subscript.replace( lengthInBinary + binSig, "") # 4. Hashtype is popped and stored hashtype = binary_to_int(binSig[-1]) justSig = binSig[:-1] if not hashtype == 1: LOGERROR('Non-unity hashtypes not implemented yet! (hashtype = %d)', hashtype) assert(False) # 5. Make a copy of the transaction -- we will be hashing a modified version txCopy = PyTx().unserialize( txInTx.serialize() ) # 6. Remove all OP_CODESEPARATORs subscript.replace( int_to_binary(OP_CODESEPARATOR), '') # 7. All the TxIn scripts in the copy are blanked (set to empty string) for txin in txCopy.inputs: txin.binScript = '' # 8. Script for the current input in the copy is set to subscript txCopy.inputs[txInIndex].binScript = subscript # 9. Prepare the signature and public key senderAddr = PyBtcAddress().createFromPublicKey(binPubKey) binHashCode = int_to_binary(hashtype, widthBytes=4) toHash = txCopy.serialize() + binHashCode # Hashes are computed as part of CppBlockUtils::CryptoECDSA methods ##hashToVerify = hash256(toHash) ##hashToVerify = binary_switchEndian(hashToVerify) # 10. Apply ECDSA signature verification if senderAddr.verifyDERSignature(toHash, justSig): return True else: return False
def testSimpleAddress(self): # Execute the tests with Satoshi's public key from the Bitcoin specification page satoshiPubKeyHex = '04fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284' addrPiece1Hex = '65a4358f4691660849d9f235eb05f11fabbd69fa' addrPiece1Bin = hex_to_binary(addrPiece1Hex) satoshiAddrStr = hash160_to_addrStr(addrPiece1Bin) saddr = PyBtcAddress().createFromPublicKey( hex_to_binary(satoshiPubKeyHex) ) print '\tAddr calc from pubkey: ', saddr.calculateAddrStr() self.assertTrue(checkAddrStrValid(satoshiAddrStr)) testAddr = PyBtcAddress().createFromPlainKeyData(PRIVATE_KEY, ADDRESS_20, publicKey65=PUBLIC_KEY) msg = int_to_binary(39029348428) theHash = hash256(msg) derSig = testAddr.generateDERSignature(theHash) # Testing ECDSA signing & verification -- arbitrary binary strings: self.assertTrue(testAddr.verifyDERSignature( theHash, derSig))
def testSimpleAddress(self): # Execute the tests with Satoshi's public key from the Bitcoin specification page satoshiPubKeyHex = '04fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284' addrPiece1Hex = '65a4358f4691660849d9f235eb05f11fabbd69fa' addrPiece1Bin = hex_to_binary(addrPiece1Hex) satoshiAddrStr = hash160_to_addrStr(addrPiece1Bin) saddr = PyBtcAddress().createFromPublicKey( hex_to_binary(satoshiPubKeyHex)) print '\tAddr calc from pubkey: ', saddr.calculateAddrStr() self.assertTrue(checkAddrStrValid(satoshiAddrStr)) testAddr = PyBtcAddress().createFromPlainKeyData( PRIVATE_KEY, ADDRESS_20, publicKey65=PUBLIC_KEY) msg = int_to_binary(39029348428) theHash = hash256(msg) derSig = testAddr.generateDERSignature(theHash) # Testing ECDSA signing & verification -- arbitrary binary strings: self.assertTrue(testAddr.verifyDERSignature(theHash, derSig))