使用 SSL 簽署交易 - PEM 的私鑰
給定一個 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