我正试图使gpg代理签名用于加密货币用途。我尝试过签名几个散列,其中一个的签名得到了一个不同的r
,同时得到了与其他实现相同的s
。
我已经将结果与c中的elliptic
nodejs库和libsecp256k1
进行了比较,这两个库之间的结果是一致的。
这大概是我自己的一个明显而愚蠢的错误,这就是原因,但我自己也找不到。
以下是libsecp256k1
版本的c#源代码:
#include
#include
#include
#include
#include
const unsigned char msg[32] = {0xc3, 0xaf, 0xca, 0x60, 0x84, 0xa5, 0x8f, 0x5b, 0x06, 0x0d, 0x0a, 0x4a, 0xaa, 0x6e, 0xd9, 0x06, 0x3a, 0x9b, 0xa7, 0x0f, 0x2b, 0xd4, 0xa7, 0x68, 0xf4, 0xad, 0x41, 0x41, 0x74, 0x28, 0xf8, 0x02};
const unsigned char pk[32] = {0xEC, 0x5D, 0xCC, 0xE1, 0x3E, 0xA0, 0xC5, 0xF4, 0x50, 0x0C, 0x31, 0x5C, 0x96, 0x4C, 0xDE, 0xE1, 0x0A, 0x05, 0x53, 0x13, 0xEA, 0x71, 0xB7, 0x55, 0x82, 0x00, 0xE9, 0x8B, 0x1D, 0xF7, 0x7F, 0x38};
int main() {
int r;
int fd;
secp256k1_context *ctx;
secp256k1_ecdsa_signature sig;
unsigned char *serialized_signature;
ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
r = secp256k1_ecdsa_sign(ctx, &sig, (const unsigned char*)msg, (const unsigned char*)pk, NULL, NULL);
if (r != 1) {
return 1;
}
serialized_signature = malloc(64);
r = secp256k1_ecdsa_signature_serialize_compact(ctx, serialized_signature, &sig);
if (r != 1) {
return 1;
}
fwrite(serialized_signature, 1, 64, stdout);
free(serialized_signature);
secp256k1_context_destroy(ctx);
return 0;
}
---
outputs:
$ ./a.out | hexdump -C
00000000 26 0d c8 ab 01 f0 79 64 0b dd 8d 5b 5b 43 76 bd |&.....yd...[[Cv.|
00000010 d2 db 1d 66 fa ce 87 57 6e f1 1f 04 df 54 24 67 |...f...Wn....T$g|
00000020 0f 50 01 c3 3c 17 b5 5e a1 c7 dc cb 2a 38 af 69 |.P..<..^....*8.i|
00000030 7c a1 8e 38 48 6c b4 7a 9b d7 f3 24 c9 99 17 b3 ||..8Hl.z...$....|
下面是使用gnupg的尝试:
keyid=D5C4AD7CC2A40CA64860ACA504450BED5A1D56D6
keygrip=A6D4B5C57143CE15C07D0DDEA5986B13B5F7ED72
hsh=c3afca6084a58f5b060d0a4aaa6ed9063a9ba70f2bd4a768f4ad41417428f802
cat <" not changed
gpg: key 04450BED5A1D56D6: secret key imported
gpg: Total number processed: 1
gpg: unchanged: 1
gpg: secret keys read: 1
gpg: secret keys unchanged: 1
00000000 4f 4b 0a 4f 4b 0a 44 20 28 37 3a 73 69 67 2d 76 |OK.OK.D (7:sig-v|
00000010 61 6c 28 35 3a 65 63 64 73 61 28 31 3a 72 33 32 |al(5:ecdsa(1:r32|
00000020 3a 26 25 30 44 c8 ab 01 f0 79 64 0b dd 8d 5b 5b |:&%0D....yd...[[|
00000030 43 76 bd d2 db 1d 66 fa ce 87 57 6e f1 1f 04 df |Cv....f...Wn....|
00000040 54 24 67 29 28 31 3a 73 33 32 3a 0f 50 01 c3 3c |T$g)(1:s32:.P..<|
00000050 17 b5 5e a1 c7 dc cb 2a 38 af 69 7c a1 8e 38 48 |..^....*8.i|..8H|
00000060 6c b4 7a 9b d7 f3 24 c9 99 17 b3 29 29 29 0a 4f |l.z...$....))).O|
00000070 4b 0a |K.|
00000072
(signature itself; r at 0x21 and, s at `0x4b`)
发布于 2021-01-27 02:40:50
gpg secp256k1曲线符号表达式(S-EXP)输出结果显示在十六进制转储(来自gpg脚本,第二个程序在下面张贴的问题)。0x28 "(“和0x29 ")”表示括号,该括号为R&S签名组件的32字节S-EXP编码。
libsecp256k1 Code Output:
R签名组件= 26天c8 ab 01 f0 79 64 b dd 8d 5b 5b 43 76 bd d2 db 1d 66 fa ce 87 57 6e f1 1 f 04 df 54 24 67
S签名组件= 0f 50 01 c3 3c 17 b5 5e a1 c7 cb 2a 38 af 69 7c a1 8e 48 b4 7a b4 7b d7 f3 24 c9 99 17 b3
GPG Script S-EXP Output:
R签名组件= 26 25 30 44 c8 ab 01 f0 79 64 0b dd 8d 5b 43 b 43 d2 db 1d 66 fa ce 87 57 6e f1 1f 04 df 54 24 67
S签名组件= 0f 50 01 c3 3c 17 b5 5e a1 c7 cb 2a 38 af 69 7c a1 8e 48 b4 7a b4 7b d7 f3 24 c9 99 17 b3
S签名组件似乎与libsecp256k1输出的结果完全匹配。只有R组件的第二个字节似乎不同,但值得注意的是S-EXP中的"25 30 44“的%0D解码看起来像第一个程序的R组件的0x0d第二个输出字节输出。
% cat melvin_5a1d56d6.asc
-----BEGIN PGP PRIVATE KEY BLOCK-----
lHQEXs4mIhMFK4EEAAoCAwTZvUk3CNXg/KYqfIbkNkZZXeD+yBE5X7AJ7IEYkpA9
SSks1IOQqws0M3U7YhhJt6sgsBQSjR9y/kUHHSSXHjRjAAEA7F3M4T6gxfRQDDFc
lkze4QoFUxPqcbdVggDpix33fzgPtbQgTWVsdmluIGVyZCA8bWVsdmluQHNlY2hv
c3QuaW5mbz6IkAQTEwgAOBYhBNXErXzCpAymSGCspQRFC+1aHVbWBQJeziYiAhsD
BQsJCAcDBRUKCQgLBRYCAwEAAh4BAheAAAoJEARFC+1aHVbWTzoA/AqL6dSHIr0+
lfRNSSo1a2WiKZpnCna9j9Kiiv7UylMqAQDCXnK+2gZM9xPsXOe0jrCyvc2qhqMN
/X5TObkVg5f1jg==
=OhY5
-----END PGP PRIVATE KEY BLOCK-----
请注意,由gpg计算的最后一个输出(S签名组件)与以下应用比特币secp256k1签名的手工计算有何不同:
% cat melvin_5a1d56d6.asc \ gpg --列表-数据包-详细
# off=0 ctb=94 tag=5 hlen=2 plen=116
:secret key packet:
version 4, algo 19, created 1590568482, expires 0
pkey[0]: 052B8104000A secp256k1 (1.3.132.0.10)
pkey[1]: 04D9BD493708D5E0FCA62A7C86E43646595DE0FEC811395FB009EC811892903D49292CD48390AB0B3433753B621849B7AB20B014128D1F72FE45071D24971E3463
skey[2]: EC5DCCE13EA0C5F4500C315C964CDEE10A055313EA71B7558200E98B1DF77F38
checksum: 0fb5
keyid: 04450BED5A1D56D6
# off=118 ctb=b4 tag=13 hlen=2 plen=32
:user ID packet: "Melvin erd "
# off=152 ctb=88 tag=2 hlen=2 plen=144
:signature packet: algo 19, keyid 04450BED5A1D56D6
version 4, created 1590568482, md5len 0, sigclass 0x13
digest algo 8, begin of digest 4f 3a
hashed subpkt 33 len 21 (issuer fpr v4 D5C4AD7CC2A40CA64860ACA504450BED5A1D56D6)
hashed subpkt 2 len 4 (sig created 2020-05-27)
hashed subpkt 27 len 1 (key flags: 03)
hashed subpkt 11 len 4 (pref-sym-algos: 9 8 7 3)
hashed subpkt 21 len 4 (pref-hash-algos: 10 9 8 11)
hashed subpkt 22 len 4 (pref-zip-algos: 2 3 1 0)
hashed subpkt 30 len 1 (features: 01)
hashed subpkt 23 len 1 (keyserver preferences: 80)
subpkt 16 len 8 (issuer key ID 04450BED5A1D56D6)
data: 0A8BE9D48722BD3E95F44D492A356B65A2299A670A76BD8FD2A28AFED4CA532A
data: C25E72BEDA064CF713EC5CE7B48EB0B2BDCDAA86A30DFD7E5339B9158397F58E
% cat melvin_5a1d56d6.asc | sed 's/\[GNUPG:\].*$//' | sed 's/-----BEGIN PGP PRIVATE KEY BLOCK-----//' | sed 's/-----END PGP PRIVATE KEY BLOCK-----//' | sed 's/-----BEGIN PGP PUBLIC KEY BLOCK-----//' | sed 's/-----END PGP PUBLIC KEY BLOCK-----//' | sed 's/-----BEGIN PGP SIGNATURE-----//' | sed 's/-----END PGP SIGNATURE-----//' | sed '/^$/d' | sed '/^=.*$/d' | tr -d '\n' | bx base64-decode | bx base16-encode
9474045ece262213052b8104000a020304d9bd493708d5e0fca62a7c86e43646595de0fec811395fb009ec811892903d49292cd48390ab0b3433753b621849b7ab20b014128d1f72fe45071d24971e3463000100ec5dcce13ea0c5f4500c315c964cdee10a055313ea71b7558200e98b1df77f380fb5b4204d656c76696e20657264203c6d656c76696e40736563686f73742e696e666f3e8890041313080038162104d5c4ad7cc2a40ca64860aca504450bed5a1d56d605025ece2622021b03050b0908070305150a09080b051602030100021e01021780000a091004450bed5a1d56d64f3a00fc0a8be9d48722bd3e95f44d492a356b65a2299a670a76bd8fd2a28afed4ca532a0100c25e72beda064cf713ec5ce7b48eb0b2bdcdaa86a30dfd7e5339b9158397f58e
密钥包(标签5):0x94原始数据包: 9474045ece262213052b8104000a020304d9bd493708d5e0fca62a7c86e43646595de0fec811395fb009ec811892903d49292cd48390ab0b3433753b621849b7ab20b014128d1f72fe45071d24971e3463000100ec5dcce13ea0c5f4500c315c964cdee10a055313ea71b7558200e98b1df77f380fb5
% echo 045ece262213052b8104000a020304d9bd493708d5e0fca62a7c86e43646595de0fec811395fb009ec811892903d49292cd48390ab0b3433753b621849b7ab20b014128d1f72fe45071d24971e3463 -n wc -c
158 / 2 = 79 = 0x004f
99004f045ece262213052b8104000a020304d9bd493708d5e0fca62a7c86e43646595de0fec811395fb009ec811892903d49292cd48390ab0b3433753b621849b7ab20b014128d1f72fe45071d24971e3463 = $MasterFingerprintBasis
用户ID数据包(标签13):0xb4原始数据包: b4204d656c76696e20657264203c6d656c76696e40736563686f73742e696e666f3e
% echo 4d656c76696e20657264203c6d656c76696e40736563686f73742e696e666f3e -n wc -c
64 / 2 = 32 = 0x00000020
b4000000204d656c76696e20657264203c6d656c76696e40736563686f73742e696e666f3e = $UserIDFingerprintBasis
ECC签名包(标记2):0x88原始数据包: 8890041313080038162104d5c4ad7cc2a40ca64860aca504450bed5a1d56d605025ece2622021b03050b0908070305150a09080b051602030100021e01021780000a091004450bed5a1d56d64f3a00fc0a8be9d48722bd3e95f44d492a356b65a2299a670a76bd8fd2a28afed4ca532a0100c25e72beda064cf713ec5ce7b48eb0b2bdcdaa86a30dfd7e5339b9158397f58e
% echo 041313080038162104d5c4ad7cc2a40ca64860aca504450bed5a1d56d605025ece2622021b03050b0908070305150a09080b051602030100021e01021780 -n wc -c
124 / 2 = 62 = 0x0000003e
041313080038162104d5c4ad7cc2a40ca64860aca504450bed5a1d56d605025ece2622021b03050b0908070305150a09080b051602030100021e0102178004ff0000003e = $MasterMagicBasis
<#>4. SHA256( $MasterFingerprintBasis + $UserIDFingerprintBasis + $MasterMagicBasis )
% echo 99004f045ece262213052b8104000a020304d9bd493708d5e0fca62a7c86e43646595de0fec811395fb009ec811892903d49292cd48390ab0b3433753b621849b7ab20b014128d1f72fe45071d24971e3463b4000000204d656c76696e20657264203c6d656c76696e40736563686f73742e696e666f3e041313080038162104d5c4ad7cc2a40ca64860aca504450bed5a1d56d605025ece2622021b03050b0908070305150a09080b051602030100021e0102178004FF0000003e _ bx sha256 4f3a4cc1a8f4bea91ddca5688b73b9379edd80876a1b5ed47543f33939f3b7cf
5.符号计算哈希
./btc_sign_secp256k1 EC5DCCE13EA0C5F4500C315C964CDEE10A055313EA71B7558200E98B1DF77F38 -m 4f3a4cc1a8f4bea91ddca5688b73b9379edd80876a1b5ed47543f33939f3b7cf -k
secp256k1 Uncompressed Pubkey : 04d9bd493708d5e0fca62a7c86e43646595de0fec811395fb009ec811892903d49292cd48390ab0b3433753b621849b7ab20b014128d1f72fe45071d24971e3463
Message is binary encoded as HEX : 4f3a4cc1a8f4bea91ddca5688b73b9379edd80876a1b5ed47543f33939f3b7cf
secp256k1 R Signature Component : 0a8be9d48722bd3e95f44d492a356b65a2299a670a76bd8fd2a28afed4ca532a
secp256k1 S Signature Component : 3da18d4125f9b308ec13a3184b714f4bfce132600c3aa2bd6c98a5774c9e4bb3
现在,让我们计算不需要私钥才能计算的互补签名。(r1,s1)的补码签名将是(r1,s2),其中"s1+s2=n“和sep256k1曲线n=s2
% echo 3da18d4125f9b308ec13a3184b714f4bfce132600c3aa2bd6c98a5774c9e4bb3 \ tr“A”“A”
3DA18D4125F9B308EC13A3184B714F4BFCE132600C3AA2BD6C98A5774C9E4BB3
% echo "obase=16;ibase=16;3DA18D4125F9B308EC13A3184B714F4BFCE132600C3AA2BD6C98A5774C9E4BB3“- bc
C25E72BEDA064CF713EC5CE7B48EB0B2BDCDAA86A30DFD7E5339B9158397F58E
使用上面计算的s2值,可以使签名顺其自然,除非选择约定来消除数学签名的歧义,并指定一个传统上正确的签名,这样s1 < s2就像比特币那样。对于比特币,这是一种先前形式的“交易可延展性”。使用OpenPGP,这可能会导致一种“证书可塑性”的形式,由于多个签名是公钥块的一部分而加剧了这种情况。对于OpenPGP,互操作性协商一致规则被记录为IETF 正在开发中,它目前没有提到证书可伸缩性的对策。
附加信息:
下面的密钥可以在上面的秘密包的尾部找到。可以计算未压缩的公钥(实质上是相关的压缩公钥的两倍),结果的公钥是A%的阴影输出。删除"-u“参数会强制计算相关的未压缩公钥,这是一个当前不适用于GPG的较短的答案。
A%回波ec5dcce13ea0c5f4500c315c964cdee10a055313ea71b7558200e98b1df77f38 \ bxec对公众 -u
04d9bd493708d5e0fca62a7c86e43646595de0fec811395fb009ec811892903d49292cd48390ab0b3433753b621849b7ab20b014128d1f72fe45071d24971e3463
B%回波99004f045ece262213052b8104000a020304d9bd493708d5e0fca62a7c86e43646595de0fec811395fb009ec811892903d49292cd48390ab0b3433753b621849b7ab20b014128d1f72fe45071d24971e3463 \ bxbase16 16-解码 \ shasum -
d5c4ad7cc2a40ca64860aca504450bed5a1d56d6 -
https://unix.stackexchange.com/questions/589730
复制相似问题