Signature

使用 SSL 簽署交易 - PEM 的私鑰

  • August 29, 2019

給定一個 private key:3cd0560f5b27591916c643a0b7aa69d03839380a738d2e912990dcc573715d2c和一個 tx hash: 456f9e1b6184d770f1a240da9a3c4458e55b6b4ba2244dd21404db30b3131b94,我想使用 SSL 和 PHP 進行簽名。將私鑰轉換為 pem 格式(以便 SSL 可以使用它),我生成以下 base64 字元串:PNBWD1snWRkWxkOgt6pp0Dg5OApzjS6RKZDcxXNxXSw=. 所以一個有效的 pem 格式應該是:

-----BEGIN EC PRIVATE KEY----- PNBWD1snWRkWxkOgt6pp0Dg5OApzjS6RKZDcxXNxXSw= -----END EC PRIVATE KEY-----

但是,它似乎不起作用。我正在使用以下功能:openssl_sign($hash, $signature, $private_key, OPENSSL_ALGO_SHA256).

但是當我使用 SSL 生成隨機私鑰時,例如: -----BEGIN EC PRIVATE KEY----- MHcCAQEEINhhp8dYz31X+KWq3u/gutJthvW2puUbB9AOIul/v2SOoAoGCCqGSM49 AwEHoUQDQgAE0jE7TIszCklw//SGyYW0+z38PUxwfkip9WS4UUn68f7D78D6ZQ/O dlPisC1fQZrUrFrik/wq7E4Xwrqs3n3b5w== -----END EC PRIVATE KEY-----

該功能確實有效。我使用現有私鑰生成的 pem 格式有什麼問題?

當我驗證您自己創建的私鑰時,我收到此錯誤:

錯誤:0D07207B:asn1 編碼常式:ASN1_get_object:標頭太長

我看不出你是如何創建你的私鑰的,但要走的路是通過 ASN.1 結構,然後是 base64。使用 OpenSSL 進行簽名時,您還必須確保您簽名的是十六進制數據,而不是字元串(這在我在評論中提供的連結的答案中進行了解釋)。

私鑰的 ASN1 結構如下所示:

# ASN.1 STRUCTURE FOR PRIVATE KEY:
#   30  <-- declares the start of an ASN.1 sequence
#   74  <-- length of following sequence 
#   02  <-- declares the start of an integer
#   01  <-- length of integer in bytes (1 byte)
#   01  <-- value of integer (1)
#   04  <-- declares the start of an "octet string"
#   20  <-- length of string to follow (32 bytes)
#           3cd0560f5b27591916c643 ... a738d2e912990dcc573715d2c 
#           \--------------------------------------------------/
#            this is the private key 
#   a0   <-- declares the start of context-specific tag 0
#   07   <-- length of context-specific tag 
#   06   <-- declares the start of an object ID
#   05   <-- length of object ID to follow 
#   2b 81 04 00 0a <-- the object ID of the curve secp256k1
#   a1   <-- declares the start of context-specific tag 1
#   44   <-- declares the length of context-sepcifc tag (68 bytes)
#   03   <-- declares the start of a bit string
#   42   <-- length of bit string to follow (66 bytes)
#   00   <-- ??
#            04 f1 44 f0 dc 00 80 af d2 b7 3f 13 37 6c ... 05 49 cd 83 f4 58 56 1e
#            \-------------------------------------------------------------------/
#             this is the public key

使用您的 privkey,我派生了 pukey,並獲得了這種 pem 格式:

### use pre defined ASN.1 strings to concatenate PEM privkey
 a pre_string : 30740201010420
 the privkey  : 3cd0560f5b27591916c643a0b7aa69d03839380a738d2e912990dcc573715d2c
 a mid_string : a00706052b8104000aa144034200
 the pubkey   : 04BF350D2821375158A608B51E3E898E507FE47F2D2E8C774DE4A9A7EDECF74ED
                A24243CB992C5673A07FA5B3A66CD8E3ACEF2809D0E380A0C7929DAB1E5D5438B

### base64 privkey file and put some nice surroundings
-----BEGIN EC PRIVATE KEY-----
MHQCAQEEIDzQVg9bJ1kZFsZDoLeqadA4OTgKc40ukSmQ3MVzcV0soAcGBSuBBAAK
oUQDQgAEvzUNKCE3UVimCLUePomOUH/kfy0ujHdN5Kmn7ez3TtokJDy5ksVnOgf6
WzpmzY46zvKAnQ44Cgx5Kdqx5dVDiw==
-----END EC PRIVATE KEY-----

使用 asn1parse,結果如下所示:

openssl asn1parse -in privkey.pem
   0:d=0  hl=2 l= 116 cons: SEQUENCE          
   2:d=1  hl=2 l=   1 prim: INTEGER           :01
   5:d=1  hl=2 l=  32 prim: OCTET STRING      [HEX DUMP]:3CD0560F5B27591916C643A0B7AA69D03839380A738D2E912990DCC573715D2C
  39:d=1  hl=2 l=   7 cons: cont [ 0 ]        
  41:d=2  hl=2 l=   5 prim: OBJECT            :secp256k1
  48:d=1  hl=2 l=  68 cons: cont [ 1 ]        
  50:d=2  hl=2 l=  66 prim: BIT STRING 

放在一起:

#!/bin/sh 
###############################################
# convert from chars to hex
printf $( echo 456f9e1b6184d770f1a240da9a3c4458e55b6b4ba2244dd21404db30b3131b94 | sed 's/[[:xdigit:]]\{2\}/\\x&/g' ) > tmp_utx.hex

echo "The private key in HEX format: "
echo 3cd0560f5b27591916c643a0b7aa69d03839380a738d2e912990dcc573715d2c  
# The private key in PEM format:
echo "-----BEGIN EC PRIVATE KEY-----
MHQCAQEEIDzQVg9bJ1kZFsZDoLeqadA4OTgKc40ukSmQ3MVzcV0soAcGBSuBBAAK
oUQDQgAEvzUNKCE3UVimCLUePomOUH/kfy0ujHdN5Kmn7ez3TtokJDy5ksVnOgf6
WzpmzY46zvKAnQ44Cgx5Kdqx5dVDiw==
-----END EC PRIVATE KEY-----" > privkey.pem

# the signing process 
#  prepare pubkey:
   openssl ec -in privkey.pem -pubout -out pubkey.pem
#  sign:
   openssl dgst -sign privkey.pem  -sha256 -hex tmp_utx.hex
   openssl dgst -sign privkey.pem  -sha256 tmp_utx.hex > tmp_sig.hex
#  verify:
   openssl dgst -verify pubkey.pem -sha256 -signature tmp_sig.hex tmp_utx.hex

echo " "

返回:

驗證OK

引用自:https://bitcoin.stackexchange.com/questions/66594