Author Topic: Extract ECDSA parameters from Block  (Read 4 times)

Offline administrator

  • Administrator
  • Newbie
  • *****
  • Posts: 38326
    • View Profile
Extract ECDSA parameters from Block
« on: November 08, 2019, 11:43:48 AM »
I am trying to extract the parameters of ECDSA signature used in bitcoin to run some tests. For that i need to obtain :

      --- r and s ,  i.e., the ECDSA signature

      --- H(m) , the hash of the message used to generate the ECDSA signature

      --- the random integer k used in ECDSA signature generation,
          this is, the k such that  s = k*(H(m) + x*r) mod q  where x is
          the private key


I already was able to obtain the r and the s of a very specific type of block, the ones where len(inp.script_sig) == 214 ) and the public key as well.

So i need to obtain these parameters for all blocks.  Also if someone knows how to do this for Ethereum and LiteCoin i'd appreciate you tell me.

```python

from blockchain import blockexplorer
from binascii import unhexlify
from pyasn1.codec.der import decoder as asn1der
import time, os, codecs
import numpy as np
from bitcoin_tools.bitcoin_tools.core.transaction import TX


# returns the blocks of given day
# if day = 0 , returns blocks of today
# if day = 1 , returns blocks of yesterday , and so on ....
def getBlocksofDay( day ):

    # get blocks from blockchain from given day
    # if we want the day before just subtract 86400000
    return blockexplorer.get_blocks(int(round(time.time() * 1000)) - 86400000*day)


# print SimpleBlock
def printSimpleBlock( block ):

    print("\nHeight : ", block.height )
    print("Hash : ", block.hash )
    print("Time : ", block.time)
    print("Main Chain :",  block.main_chain, "\n" )


# print Block
def printBlock( block ):

    print("\nHash : ", block.hash )
    print("Version : ", block.version )
    print("Previous Block : ", block.previous_block )
    print("Merkle Root : ", block.merkle_root )
    print("Time : ", block.time)
    print("Bits : ", block.bits)
    print("Fee : ", block.fee)
    print("Nonce : ", block.nonce)
    print("Number of transaction : ", block.n_tx)
    print("Size : ", block.size )
    print("Block Index : " , block.block_index )
    print("Main Chain :",  block.main_chain )
    print("Height : ", block.height )
    print("Received Time : ", block.received_time )
    print("Relayed By : ", block.relayed_by )

    if( block.n_tx > 50):
        print("Transactions : NOT PRINTING TX TOO MANY \n"  )
    else:
        print("Transactions : ", block.transactions )


# print Transaction
def printTransaction( tx ):

    print("\nDouble Spend : ", tx.double_spend )
    print("Block height : ", tx.block_height )
    print("Time : ", tx.time )
    print("Relayed By : ", tx.relayed_by )
    print("Hash : ", tx.hash )
    print("Tx Index : " , tx.tx_index )
    print("Version : ", tx.version )
    print("Size : ", tx.size )
    print("Inputs : ", tx.inputs )
    print("Outputs : ", tx.outputs, "\n" )


# print Input
def printInput( inp ):

    try:
        if( len(inp.script_sig) == 214 ):
            '''
            print("\nN : ", inp.n )
            print("Value : ", inp.value )
            print("Address : ", inp.address )
            print("Tx_Index : ", inp.tx_index )
            print("Type : ", inp.type )
            print("Script : ", inp.script )
            print("Script_Sig : ", inp.script_sig )
            print("Sequence : ", inp.sequence )
            '''
            return 0
    except:
        return -1


# print XPub
def printXPub( xpub ):

    print("\nAddress : ", xpub.address)
    print("Number of Transaction : ", xpub.n_tx )
    print("Total Received : ", xpub.total_received / 100000000, "BTC" )
    print("Total Sent : ", xpub.total_sent / 100000000, "BTC" )
    print("Final Balance : ", xpub.final_balance )
    print("Change Index : ", xpub.change_index )
    print("Account Index : ", xpub.account_index, "\n\n" )

    for tx in xpub.transactions:
        printTransaction(tx)



def printR_S_PK(script_sig_hex):

    #script_sig_hex is the scriptsig hex
    values = asn1der.decode(unhexlify(script_sig_hex)[1:])
    '''
    #R Value in int form
    print( "\nR value:", values[0][0] )

    #S Value in int form
    print( "S value:", values[0][1]  )

    # X coordinate of Public Key
    print( "X coordinate of PK:",  int(values[1].hex()[4:],16) )
    '''

    return [ int(values[1].hex()[6:],16), int(values[1].hex()[4:6],16), int(values[0][0]), int(values[0][1]) ]






#if __name__ == "__main__":


def getThemBlocks(day):


    simpleBlocksofDay = getBlocksofDay(day)
    pubKeys = np.array([[-1], [-1], [-1], [-1], [-1], [-1]])

    print("LEN : ", len(simpleBlocksofDay), "\n")

    # run through all blocks of this day
    for block in [simpleBlocksofDay[0]]:
        blocksofDay = blockexplorer.get_block( block.hash )
        txs = blocksofDay.transactions

        # run through all tx of this day
        for txofDay in txs:
            inpofTx = txofDay.inputs

            # run through all inputs of this day
            for inp in inpofTx:

                # if input has format we want
                if( printInput(inp) == 0 ):

                    numLines, numColumns = len(pubKeys), pubKeys[0].size

                    script_sig_hex = inp.script_sig
                    xC, sig, r, s = printR_S_PK(script_sig_hex)

                    aux = np.where(pubKeys[2]==xC)

                    columnToAdd = [ -1 for i in range(0,numLines) ]
                    columnToAdd[0], columnToAdd[1], columnToAdd[2], columnToAdd[3] = 6, 1, xC, sig
                    columnToAdd[4], columnToAdd[5] = r, s

                    lineToAdd = [ -1 for i in range(0,numColumns) ]


                    # xC it's not repeated
                    if( aux[0].size == 0 ):
                        pubKeys = np.c_[pubKeys, np.array(columnToAdd)]

                    # again xC it's not repeated
                    elif( (aux[0].size == 1) and (pubKeys[3][aux[0][0]] != sig) ):
                        pubKeys = np.c_[pubKeys, np.array(columnToAdd)]

                    # xC it's repeated
                    else:
                        if( pubKeys[3][aux[0][0]] == sig ):
                            column = aux[0][0]
                        else:
                            column = aux[0][1]

                        # need to add 2 new lines
                        if( pubKeys[0][column]+1 > numLines ):
                            aux = np.array(lineToAdd)
                            pubKeys = np.r_[pubKeys, [aux]]
                            pubKeys = np.r_[pubKeys, [aux]]
                            pubKeys = np.r_[pubKeys, [aux]]

                        line = pubKeys[0][column]
                        pubKeys[line][column] = r
                        pubKeys[line+1][column] = s
                        pubKeys[line+2][column] = txofDay.hash

                        # increase the number of elements in that columns by 2
                        pubKeys[0][column] += 3

                        # increase the number of signatures by 1
                        pubKeys[1][column] += 1



    for j in range(1, pubKeys[0].size):

        if(pubKeys[1][j] > 40):
            for i in range(0, len(pubKeys)):

                print(pubKeys[j])

            print("\n\n")




if __name__ == "__main__":

    '''
    for i in range(0,3):
        getThemBlocks(i)
    '''

    # First a transaction object is created (through the deserialize constructor) by deserializing the hex transaction we have selected.
    hex_tx = "01000000013ca58d2f6fac36602d831ee0cf2bc80031c7472e80a322b57f614c5ce9142b7100000 0006b483045022100f0331d85cb7f7ec1bedc41f50c695d654489458e88aec0076fbad5d8aeda16 73022009e8ca2dda1d6a16bfd7133b0008720145dacccb35c0d5c9fc567e52f26ca5f7012103a16 4209a7c23227fcd6a71c51efc5b6eb25407f4faf06890f57908425255e42bffffffff0241a20000 000000001976a914e44839239ab36f5bc67b2079de00ecf587233ebe88ac7463000000000000197 6a914dc7016484646168d99e49f907c86c271299441c088ac00000000"

    tx = TX.deserialize(hex_tx)

    # Then, the transaction can be displayed using the display method to analyze how it's been constructed.
    tx.display()


```