I have an unsigned raw segwit transaction on my regtest network:
02000000011333183ddf384da83ed49296136c70d206ad2b19331bf25d390e69b222165e370000000000ffffffff0200e1f5050000000017a914a860f76561c85551594c18eecceffaee8c4822d787f0c1a4350000000017a914d8b6fcc85a383261df05423ddf068a8987bf02878700000000
Pretty format:
Version: 02000000 Flag: Input Count: 01 Input 1 Previous Output Hash: 1333183ddf384da83ed49296136c70d206ad2b19331bf25d390e69b222165e37 Input 1 Previous Output Index: 00000000 Input 1 script length: 00 (empty for now) Input 1 scriptSig: Input 1 sequence: feffffff Output Count: 02 Output 1 Value: 00e1f50500000000 (100M satoshis / 1 BTC) Output 1 public key script length: 0x17 (23 bytes) Output 1 public key script: a914a860f76561c85551594c18eecceffaee8c4822d787 Output 2 Value: F0C1A43500000000 (899990000 sats / 8.9999 BTC) Output 2 public key script length: 0x17 (23 bytes) Output 2 public key script: a914d8b6fcc85a383261df05423ddf068a8987bf028787 Witness Count: Witness 1 length: Witness 1: Witness 2 length: Witness 2: Locktime: 8c000000 (block 140) I can sign it using the above data (concatenated from top to bottom):
$ bitcoin-cli -regtest signrawtransaction 02000000011333183ddf384da83ed49296136c70d206ad2b19331bf25d390e69b222165e370000000000feffffff0200e1f5050000000017a914a860f76561c85551594c18eecceffaee8c4822d787F0C1A4350000000017a914d8b6fcc85a383261df05423ddf068a8987bf0287878c000000 { "hex": "020000000001011333183ddf384da83ed49296136c70d206ad2b19331bf25d390e69b222165e370000000017160014b93f973eb2bf0b614bddc0f47286788c98c535b4feffffff0200e1f5050000000017a914a860f76561c85551594c18eecceffaee8c4822d787f0c1a4350000000017a914d8b6fcc85a383261df05423ddf068a8987bf028787024730440220434caf5bb442cb6a251e8bce0ec493f9a1a9c4423bcfc029e542b0e8a89d1b3f022011090d4e98f79c62b188245a4aa4eb77e912bfd57e0a9b9a1c5e65f2b39f3ab401210223bec70d670d29a30d9bcee197910e37cf2a10f0dc3c5ac44d865aec0d7052fb8c000000", "complete": true } But, when I try to do it manually, I get a different result for the signature in witness. I think I may be signing the wrong data, so what would the serialized hex string look like that gets hashed (HASH256) and then signed to produce the signature in the Witness data (Witness 1 below)?
Final Tx (signed using signrawtransaction)
Version: 02000000 Flag: 0001 (indicates segwit) Input Count: 01 Input 1 Previous Output Hash: 1333183ddf384da83ed49296136c70d206ad2b19331bf25d390e69b222165e37 Input 1 Previous Output Index: 00000000 Input 1 script length: 0x17 (23 bytes) Input 1 scriptSig: 160014b93f973eb2bf0b614bddc0f47286788c98c535b4 Input 1 sequence: feffffff Output Count: 02 Output 1 Value: 00e1f50500000000 (100M satoshis / 1 BTC) Output 1 public key script length: 0x17 (23 bytes) Output 1 public key script: a914a860f76561c85551594c18eecceffaee8c4822d787 Output 2 Value: F0C1A43500000000 (899990000 sats / 8.9999 BTC) Output 2 public key script length: 0x17 (23 bytes) Output 2 public key script: a914d8b6fcc85a383261df05423ddf068a8987bf028787 Witness Count: 02 Witness 1 length: 0x47 (71 bytes) Witness 1: 30440220434caf5bb442cb6a251e8bce0ec493f9a1a9c4423bcfc029e542b0e8a89d1b3f022011090d4e98f79c62b188245a4aa4eb77e912bfd57e0a9b9a1c5e65f2b39f3ab401 Witness 2 length: 0x21 (33 bytes) Witness 2: 0223bec70d670d29a30d9bcee197910e37cf2a10f0dc3c5ac44d865aec0d7052fb Locktime: 8c000000 (block 140) Edit: Code for signing: GIST - ec_sign_hex.sh. This takes the final hashed hex string and a 32-byte hex private key as parameters. The private key I'm using is 72b90220501a0c27a499535c010de9e2fa190c0d287a940a3886bcb2cbcccdb8, and it's executed as:
$ ec_sign_hex 02000000011333183ddf384da83ed49296136c70d206ad2b19331bf25d390e69b222165e370000000000feffffff0200e1f5050000000017a914a860f76561c85551594c18eecceffaee8c4822d787F0C1A4350000000017a914d8b6fcc85a383261df05423ddf068a8987bf0287878c000000 72b90220501a0c27a499535c010de9e2fa190c0d287a940a3886bcb2cbcccdb8 #!/bin/bash ## Command Line parsing ####################### if [[ $# -lt 2 ]]; then echo "Usage: $ ec_sign_hex <input-hex> <priv-key-hex>" exit 1 fi inputHex=$1 privKeyHex=$2 ## Create .pem and .pub files ############################# pubKeyHex="$(openssl ec -inform DER -text -noout -in <(cat <(echo -n "302e0201010420") <(echo -n "${privKeyHex}") <(echo -n "a00706052b8104000a") | xxd -r -p) 2>/dev/null | tail -6 | head -5 | sed 's/[ :]//g' | tr -d '\n')" asnFormatKey="30740201010420${privKeyHex}a00706052b8104000aa144034200${pubKeyHex}" echo "-----BEGIN EC PRIVATE KEY-----" > tmp.pem echo $asnFormatKey | xxd -r -p | base64 | fold -w 64 >> tmp.pem echo "-----END EC PRIVATE KEY-----" >> tmp.pem openssl ec -in tmp.pem -pubout -out tmpPub.pem &>/dev/null ## Sign message # sign: openssl pkeyutl -sign -inkey tmp.pem -in <(printf $inputHex | xxd -r -p) -out tmp.sig echo "Signature" echo "####################" echo "" openssl pkeyutl -sign -inkey tmp.pem -in <(printf $inputHex | xxd -r -p) | xxd -p #-hexdump #| xxd -p echo "" echo "####################" # verify: openssl pkeyutl -verify -pubin -inkey tmpPub.pem -sigfile tmp.sig -in <(printf $inputHex | xxd -r -p) rm tmp.pem tmpPub.pem tmp.sig Update: I believe the above script isn't working because pkeyutl defaults to a sha1 fingerprint before signing.