首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Gnupg secp256k1签名与其他实现不匹配。

Gnupg secp256k1签名与其他实现不匹配。
EN

Unix & Linux用户
提问于 2020-05-29 12:37:07
回答 1查看 278关注 0票数 3

我正试图使gpg代理签名用于加密货币用途。我尝试过签名几个散列,其中一个的签名得到了一个不同的r,同时得到了与其他实现相同的s

我已经将结果与c中的elliptic nodejs库和libsecp256k1进行了比较,这两个库之间的结果是一致的。

这大概是我自己的一个明显而愚蠢的错误,这就是原因,但我自己也找不到。

以下是libsecp256k1版本的c#源代码:

代码语言:javascript
运行
复制
#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的尝试:

代码语言:javascript
运行
复制
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`)
EN

回答 1

Unix & Linux用户

发布于 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

代码语言:javascript
运行
复制
-----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 --列表-数据包-详细

代码语言:javascript
运行
复制
# 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
代码语言:javascript
运行
复制
% 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
代码语言:javascript
运行
复制
9474045ece262213052b8104000a020304d9bd493708d5e0fca62a7c86e43646595de0fec811395fb009ec811892903d49292cd48390ab0b3433753b621849b7ab20b014128d1f72fe45071d24971e3463000100ec5dcce13ea0c5f4500c315c964cdee10a055313ea71b7558200e98b1df77f380fb5b4204d656c76696e20657264203c6d656c76696e40736563686f73742e696e666f3e8890041313080038162104d5c4ad7cc2a40ca64860aca504450bed5a1d56d605025ece2622021b03050b0908070305150a09080b051602030100021e01021780000a091004450bed5a1d56d64f3a00fc0a8be9d48722bd3e95f44d492a356b65a2299a670a76bd8fd2a28afed4ca532a0100c25e72beda064cf713ec5ce7b48eb0b2bdcdaa86a30dfd7e5339b9158397f58e

密钥包(标签5):0x94原始数据包: 9474045ece262213052b8104000a020304d9bd493708d5e0fca62a7c86e43646595de0fec811395fb009ec811892903d49292cd48390ab0b3433753b621849b7ab20b014128d1f72fe45071d24971e3463000100ec5dcce13ea0c5f4500c315c964cdee10a055313ea71b7558200e98b1df77f380fb5

% echo 045ece262213052b8104000a020304d9bd493708d5e0fca62a7c86e43646595de0fec811395fb009ec811892903d49292cd48390ab0b3433753b621849b7ab20b014128d1f72fe45071d24971e3463 -n wc -c

代码语言:javascript
运行
复制
 158 / 2 = 79 = 0x004f

99004f045ece262213052b8104000a020304d9bd493708d5e0fca62a7c86e43646595de0fec811395fb009ec811892903d49292cd48390ab0b3433753b621849b7ab20b014128d1f72fe45071d24971e3463 = $MasterFingerprintBasis

用户ID数据包(标签13):0xb4原始数据包: b4204d656c76696e20657264203c6d656c76696e40736563686f73742e696e666f3e

% echo 4d656c76696e20657264203c6d656c76696e40736563686f73742e696e666f3e -n wc -c

代码语言:javascript
运行
复制
  64 / 2 = 32 = 0x00000020

b4000000204d656c76696e20657264203c6d656c76696e40736563686f73742e696e666f3e = $UserIDFingerprintBasis

ECC签名包(标记2):0x88原始数据包: 8890041313080038162104d5c4ad7cc2a40ca64860aca504450bed5a1d56d605025ece2622021b03050b0908070305150a09080b051602030100021e01021780000a091004450bed5a1d56d64f3a00fc0a8be9d48722bd3e95f44d492a356b65a2299a670a76bd8fd2a28afed4ca532a0100c25e72beda064cf713ec5ce7b48eb0b2bdcdaa86a30dfd7e5339b9158397f58e

% echo 041313080038162104d5c4ad7cc2a40ca64860aca504450bed5a1d56d605025ece2622021b03050b0908070305150a09080b051602030100021e01021780 -n wc -c

代码语言:javascript
运行
复制
 124 / 2 = 62 = 0x0000003e

041313080038162104d5c4ad7cc2a40ca64860aca504450bed5a1d56d605025ece2622021b03050b0908070305150a09080b051602030100021e0102178004ff0000003e = $MasterMagicBasis

<#>4. SHA256( $MasterFingerprintBasis + $UserIDFingerprintBasis + $MasterMagicBasis )

% echo 99004f045ece262213052b8104000a020304d9bd493708d5e0fca62a7c86e43646595de0fec811395fb009ec811892903d49292cd48390ab0b3433753b621849b7ab20b014128d1f72fe45071d24971e3463b4000000204d656c76696e20657264203c6d656c76696e40736563686f73742e696e666f3e041313080038162104d5c4ad7cc2a40ca64860aca504450bed5a1d56d605025ece2622021b03050b0908070305150a09080b051602030100021e0102178004FF0000003e _ bx sha256 4f3a4cc1a8f4bea91ddca5688b73b9379edd80876a1b5ed47543f33939f3b7cf

5.符号计算哈希

./btc_sign_secp256k1 EC5DCCE13EA0C5F4500C315C964CDEE10A055313EA71B7558200E98B1DF77F38 -m 4f3a4cc1a8f4bea91ddca5688b73b9379edd80876a1b5ed47543f33939f3b7cf -k

代码语言:javascript
运行
复制
 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 -

票数 3
EN
页面原文内容由Unix & Linux提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://unix.stackexchange.com/questions/589730

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档