Skip to content

Instantly share code, notes, and snippets.

@secp8x32
Forked from nlitsme/messagehash.md
Created October 12, 2021 08:17
Show Gist options
  • Save secp8x32/54aafbe1b74686636d90d18c280e3361 to your computer and use it in GitHub Desktop.
Save secp8x32/54aafbe1b74686636d90d18c280e3361 to your computer and use it in GitHub Desktop.
How to calculate the bitcoin messagehash

Demonstrate how to calculate the messagehash for the two signatures in this transaction

See ecdsa_demo.py for code showing how to use this to crack the bitcoin secret key.

These are the values extracted from the example transaction below:

pk="04 db d0 c6 15 32 27 9c f7 29 81 c3 58 4f c3 22 16 e0 12 76 99 63 5c 27 89 f5 49 e0 73 0c 05 9b 81 ae 13 30 16 a6 9c 21 e2 3f 18 59 a9 5f 06 d5 2b 7b f1 49 a8 f2 fe 4e 85 35 c8 a8 29 b4 49 c5 ff"
r="d4 7c e4 c0 25 c3 5e c4 40 bc 81 d9 98 34 a6 24 87 51 61 a2 6b f5 6e f7 fd c0 f5 d5 2f 84 3a d1"
s1="44 e1 ff 2d fd 81 02 cf 7a 47 c2 1d 5c 9f d5 70 16 10 d0 49 53 c6 83 65 96 b4 fe 9d d2 f5 3e 3e"
s2="9a 5f 1c 75 e4 61 d7 ce b1 cf 3c ab 90 13 eb 2d c8 5b 6d 0d a8 c3 c6 e2 7e 3a 5a 5b 3f aa 5b ab"
m1="c0 e2 d0 a8 9a 34 8d e8 8f da 08 21 1c 70 d1 d7 e5 2c ce f2 eb 94 59 91 1b f9 77 d5 87 78 4c 6e"
m2="17 b0 f4 1c 8c 33 7a c1 e1 8c 98 75 9e 83 a8 cc cb c3 68 dd 9d 89 e5 f0 3c b6 33 c2 65 fd 0d dc"
eccalc crack2 "$pk" "$r" "$s1" "$s2" "$m1" "$m2"


note that the output script for both inputs is the same in this case: 19 76 a9 14 70 79 2f b7 4a 5d f7 45 ba c0 7d f6 fe 02 0f 87 1c bb 29 3b 88 ac


----- hexdump of https://bitaps.com/9ec4bc49e828d924af1d1029cacf709431abbde46d59554b62bc270e3b29c4b1

 01 00 00 00
 02  -- inputs
 f6 4c 60 3e 2f 9f 4d af 70 c2 f4 25 2b 2d cd b0 7c c0 19 2b 72 38 bc 9c 3d ac ba e5 55 ba f7 01 01 00 00 00
    8a
       47 30 44
          02 20 d4 7c e4 c0 25 c3 5e c4 40 bc 81 d9 98 34 a6 24 87 51 61 a2 6b f5 6e f7 fd c0 f5 d5 2f 84 3a d1  -- r
          02 20 44 e1 ff 2d fd 81 02 cf 7a 47 c2 1d 5c 9f d5 70 16 10 d0 49 53 c6 83 65 96 b4 fe 9d d2 f5 3e 3e  -- s1
          01
       41 04 db d0 c6 15 32 27 9c f7 29 81 c3 58 4f c3 22 16 e0 12 76 99 63 5c 27 89 f5 49 e0 73 0c 05 9b 81 ae 13 30 16 a6 9c 21 e2 3f 18 59 a9 5f 06 d5 2b 7b f1 49 a8 f2 fe 4e 85 35 c8 a8 29 b4 49 c5 ff   -- the public key
    ff ff ff ff
 29 f8 41 db 2b a0 ca fa 3a 2a 89 3c d1 d8 c3 e9 62 e8 67 8f c6 1e be 89 f4 15 a4 6b c8 d9 85 4a 01 00 00 00
    8a
       47 30 44
          02 20 d4 7c e4 c0 25 c3 5e c4 40 bc 81 d9 98 34 a6 24 87 51 61 a2 6b f5 6e f7 fd c0 f5 d5 2f 84 3a d1  -- r
          02 20 9a 5f 1c 75 e4 61 d7 ce b1 cf 3c ab 90 13 eb 2d c8 5b 6d 0d a8 c3 c6 e2 7e 3a 5a 5b 3f aa 5b ab  -- s2
          01
       41 04 db d0 c6 15 32 27 9c f7 29 81 c3 58 4f c3 22 16 e0 12 76 99 63 5c 27 89 f5 49 e0 73 0c 05 9b 81 ae 13 30 16 a6 9c 21 e2 3f 18 59 a9 5f 06 d5 2b 7b f1 49 a8 f2 fe 4e 85 35 c8 a8 29 b4 49 c5 ff   -- the public key
    ff ff ff ff
 01  -- outputs
     a0 86 01 00 00 00 00 00  19 76 a9 14 70 79 2f b7 4a 5d f7 45 ba c0 7d f6 fe 02 0f 87 1c bb 29 3b 88 ac
 00 00 00 00

now calculate the messagehash like this:
  - replace one inputscript by the corresponding output script
  - replace the other input scripts by '00'
  - append '01 00 00 00' for the hash type at the end of the transaction
  - calculate the 'shasha'

## calculate m1

shasha(
     01 00 00 00
     02  -- inputs
     f6 4c 60 3e 2f 9f 4d af 70 c2 f4 25 2b 2d cd b0 7c c0 19 2b 72 38 bc 9c 3d ac ba e5 55 ba f7 01 01 00 00 00
        19 76 a9 14 70 79 2f b7 4a 5d f7 45 ba c0 7d f6 fe 02 0f 87 1c bb 29 3b 88 ac  -- replaced the first with output script, see 'txnsrc 1' below
        ff ff ff ff
     29 f8 41 db 2b a0 ca fa 3a 2a 89 3c d1 d8 c3 e9 62 e8 67 8f c6 1e be 89 f4 15 a4 6b c8 d9 85 4a 01 00 00 00
        00  -- replaced the second with empty script
        ff ff ff ff
     01  -- outputs
         a0 86 01 00 00 00 00 00  19 76 a9 14 70 79 2f b7 4a 5d f7 45 ba c0 7d f6 fe 02 0f 87 1c bb 29 3b 88 ac
     00 00 00 00
    -- and the hashtype
     01 00 00 00
) = c0 e2 d0 a8 9a 34 8d e8 8f da 08 21 1c 70 d1 d7 e5 2c ce f2 eb 94 59 91 1b f9 77 d5 87 78 4c 6e

## calculate m2
shasha(
     01 00 00 00
     02  -- inputs
     f6 4c 60 3e 2f 9f 4d af 70 c2 f4 25 2b 2d cd b0 7c c0 19 2b 72 38 bc 9c 3d ac ba e5 55 ba f7 01 01 00 00 00
        00  -- replaced the first with empty script
        ff ff ff ff
     29 f8 41 db 2b a0 ca fa 3a 2a 89 3c d1 d8 c3 e9 62 e8 67 8f c6 1e be 89 f4 15 a4 6b c8 d9 85 4a 01 00 00 00
        19 76 a9 14 70 79 2f b7 4a 5d f7 45 ba c0 7d f6 fe 02 0f 87 1c bb 29 3b 88 ac -- replaced the second with output script, see 'txnsrc 2' below
        ff ff ff ff
     01  -- outputs
         a0 86 01 00 00 00 00 00  19 76 a9 14 70 79 2f b7 4a 5d f7 45 ba c0 7d f6 fe 02 0f 87 1c bb 29 3b 88 ac
     00 00 00 00
    -- and the hashtype
     01 00 00 00
) = 17 b0 f4 1c 8c 33 7a c1 e1 8c 98 75 9e 83 a8 cc cb c3 68 dd 9d 89 e5 f0 3c b6 33 c2 65 fd 0d dc


-------

## txnsrc 1
shasha(
     01 00 00 00
     01
     c4 c8 6a e5 40 d3 40 47 1b 03 83 3c b6 73 86 b0 60 a7 a5 63 2f 1e e7 30 c7 1e f6 90 9e 90 eb 9c 00 00 00 00
        8b 48 30 45 02 21 00 87 87 14 0a 00 fd b0 5e 55 ef 66 0f 54 c3 f5 1d 84 99 35 d1 4b c2 e2 c6 0f b9 7a 05 1a 1d a3 c7 02 20 79 7b 5e b2 65 24 6e 63 cb 06 1a b2 77 c5 41 a3 ba 42 37 d5 b3 c5 fe 94 b6 af 94 00 72 3a 87 90 01 41 04 04 c6 d6 28 a1 2e 1c bf 01 b1 d8 31 6c b1 c0 9a 38 16 33 69 f1 11 3a 26 51 35 65 a1 a2 44 5e 2e 12 fd ac 74 8c ec 24 34 42 c6 18 5e 5e 2c 26 47 f9 93 c8 8a ff 95 d9 22 f6 51 17 d7 3d a5 66 cc
        ff ff ff ff
     02 -- outputs
         d0 dc f7 05 00 00 00 00  19 76 a9 14 fc 41 ce e3 55 d1 0b 86 31 37 00 63 82 c8 09 ae c1 dd f3 3c 88 ac  --- output #0
         d0 fb 01 00 00 00 00 00  19 76 a9 14 70 79 2f b7 4a 5d f7 45 ba c0 7d f6 fe 02 0f 87 1c bb 29 3b 88 ac  --- output #1
     00 00 00 00
) = f6 4c 60 3e 2f 9f 4d af 70 c2 f4 25 2b 2d cd b0 7c c0 19 2b 72 38 bc 9c 3d ac ba e5 55 ba f7 01

## txnsrc 2
shasha(
     01 00 00 00
     01
     c4 c8 6a e5 40 d3 40 47 1b 03 83 3c b6 73 86 b0 60 a7 a5 63 2f 1e e7 30 c7 1e f6 90 9e 90 eb 9c 01 00 00 00
        8a 47 30 44 02 20 d4 7c e4 c0 25 c3 5e c4 40 bc 81 d9 98 34 a6 24 87 51 61 a2 6b f5 6e f7 fd c0 f5 d5 2f 84 3a d1 02 20 12 a8 c1 d5 c6 02 e3 82 c1 78 fb fc b9 57 e8 ec c3 47 f1 ba f7 8a 20 6f 20 a9 7f f4 c4 33 e1 46 01 41 04 db d0 c6 15 32 27 9c f7 29 81 c3 58 4f c3 22 16 e0 12 76 99 63 5c 27 89 f5 49 e0 73 0c 05 9b 81 ae 13 30 16 a6 9c 21 e2 3f 18 59 a9 5f 06 d5 2b 7b f1 49 a8 f2 fe 4e 85 35 c8 a8 29 b4 49 c5 ff
        ff ff ff ff
     02 -- outputs
         50 c3 00 00 00 00 00 00  19 76 a9 14 01 94 53 ca 35 e7 cd c4 31 18 dd a7 bc 81 ee 98 1b d6 f9 24 88 ac  --- output #0
         20 4e 00 00 00 00 00 00  19 76 a9 14 70 79 2f b7 4a 5d f7 45 ba c0 7d f6 fe 02 0f 87 1c bb 29 3b 88 ac  --- output #1
     00 00 00 00
) = 29 f8 41 db 2b a0 ca fa 3a 2a 89 3c d1 d8 c3 e9 62 e8 67 8f c6 1e be 89 f4 15 a4 6b c8 d9 85 4a

A old (before witness) style transaction has the following structure:

  1. first a 4 byte version: 01 00 00 00
  2. a varint encoding the number of inputs: 02
  3. the inputs
  4. a varint encoding the number of outputs: 01
  5. the outputs
  6. a 4 byte locktime: 00 00 00 00

An input is structured like this:

  1. a 32 byte transaction hash
  2. a 4 byte zero-based output index
  3. a varint encoding the input script size
  4. the input script
  5. a 4 byte sequence number: ff ff ff ff

Note that the transaction hash as used on most blockexplorers is byte-reversed from the hash as it is stored in the input, or calculated using the shasha algorithm.

The input script commonly contains:

  1. a signature: a asn-1 BER encoded 'r' and 's' value followed by a 01.
  2. a public key.

An output is structured like this:

  1. a 8 byte bitcoin value
  2. a varint encoding the output script size
  3. the output script

The output script commonly contains:

  1. 76 - dup
  2. a9 - hash160
  3. 14 ... - the address hash
  4. 88 - equalverify
  5. ac - checksig

The asn1-BER encoded signature:

  1. 30 - a sequence tag
  2. a length, typically in range: 0x40 - 0x48
  3. 02 - a 'int' tag, the type of the 'r' value
  4. a length, typically in range: 0x1e - 0x21
  5. the bytes for the 'r' value
  6. 02 - a 'int' tag, the type of the 's' value
  7. a length, typically in range: 0x1e - 0x21
  8. the bytes for the 's' value

See wikipedia for details on the BER encoding.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment