当前位置: 首页 > 知识库问答 >
问题:

ECDSA使用OpenSSL签名,使用加密验证

谷梁涵忍
2023-03-14

我在应用程序中用戴伟的加密技术创建了一个ECDSA密钥对(secp128r1)。签名和验证按预期工作。我没有将消息本身添加到签名中,以最小化签名长度(正好是32个字节)。

但是,当我使用openssl创建签名时:

$ cat test.txt | openssl dgst -ecdsa-with-SHA1 -sign sample.key -keyform DER > act.bin

显然,OpenSSL将消息本身放在签名中,导致更大的签名(例如39字节)。如果我设置< code > CryptoPP::SignatureVerificationFilter::PUT _ MESSAGE ,就可以用Crypto验证签名。

我可以告诉OpenSSL在不将消息放入签名的情况下对消息进行签名,以便生成的签名正好是32字节吗?

共有3个答案

相诚
2023-03-14

首先,您应该知道128位的EC提供了大约64位的安全性。其次,我不认为这是openssl添加的消息,因为5个字节不够。无论如何,您可以使用head或tail来删除额外的字节。

漆雕嘉平
2023-03-14

Divb

桑迪普

正如@CodesInChaos所述,问题在于签名编码。还可以看到OpenSSL ECDSA签名比预期的长。

正如@Sandeep在评论中建议的,另一个选择是让Crypto使用OpenSSL签名。

这是一个加密测试程序,用于从OpenSSL和Java使用的ASN.1/DER输出转换,并将其转换为加密使用的IEEE P1363。它主要取自加密维基上的椭圆曲线数字签名算法。

#include "cryptlib.h"
#include "eccrypto.h"
#include "files.h"
#include "oids.h"
#include "dsa.h"
#include "sha.h"
#include "hex.h"

#include <iostream>

using namespace CryptoPP;

int main(int argc, char* argv[])
{
    // Load DER encoded public key
    FileSource pubKey("secp256k1-pub.der", true /*binary*/);
    ECDSA<ECP, SHA1>::Verifier verifier(pubKey);

    // Java or OpenSSL created signature. Is is ANS.1
    //   SEQUENCE ::= { r INTEGER, s INTEGER }.
    const byte derSignature[] = {
        0x30, 0x44, 0x02, 0x20, 0x08, 0x66, 0xc8, 0xf1,
        0x6f, 0x15, 0x00, 0x40, 0x8a, 0xe2, 0x1b, 0x40,
        0x56, 0x28, 0x9c, 0x17, 0x8b, 0xca, 0x64, 0x99,
        0x37, 0xdc, 0x35, 0xad, 0xad, 0x60, 0x18, 0x4d,
        0x63, 0xcf, 0x4a, 0x06, 0x02, 0x20, 0x78, 0x4c,
        0xb7, 0x0b, 0xa3, 0xff, 0x4f, 0xce, 0xd3, 0x01,
        0x27, 0x5c, 0x6c, 0xed, 0x06, 0xf0, 0xd7, 0x63,
        0x6d, 0xc6, 0xbe, 0x06, 0x59, 0xe8, 0xc3, 0xa5,
        0xce, 0x8a, 0xf1, 0xde, 0x01, 0xd5
    };

    // P1363 'r || s' concatenation. The size is 32+32 due to field
    // size for r and s in secp-256. It is not 20+20 due to SHA-1.
    SecByteBlock signature(verifier.SignatureLength());
    DSAConvertSignatureFormat(signature, signature.size(), DSA_P1363,
                          derSignature, sizeof(derSignature), DSA_DER);

    // Message "Attack at dawn!"
    const byte message[] = {
        0x41, 0x74, 0x74, 0x61, 0x63, 0x6b, 0x20, 0x61,
        0x74, 0x20, 0x64, 0x61, 0x77, 0x6e, 0x21, 0x0a
    };

    // https://www.cryptopp.com/wiki/Elliptic_Curve_Digital_Signature_Algorithm
    bool result = verifier.VerifyMessage(message, sizeof(message), signature, signature.size());
    if (result)
        std::cout << "Verified message" << std::endl;
    else
        std::cout << "Failed to verify message" << std::endl;

    return 0;
}

这是运行测试程序的结果。

$ ./test.exe
Signature (64):
0866C8F16F1500408AE21B4056289C178BCA649937DC35ADAD60184D63CF4A06784CB70BA3FF4FCE
D301275C6CED06F0D7636DC6BE0659E8C3A5CE8AF1DE01D5
Verified message

下面是我用来重现< code > cat test . txt | OpenSSL dgst-ECD sa-with-SHA1符号sample.key -keyform DER的设置

$ cat test.txt
Attack at dawn!

$ hexdump -C test.txt
00000000  41 74 74 61 63 6b 20 61  74 20 64 61 77 6e 21 0a  |Attack at dawn!.|
00000010

# Create private key in PEM format
$ openssl ecparam -name secp256k1 -genkey -noout -out secp256k1-key.pem

$ cat secp256k1-key.pem
-----BEGIN EC PRIVATE KEY-----
MHQCAQEEIO0D5Rjmes/91Nb3dHY9dxmbM7gVfxmB2+OVuLmWMbGXoAcGBSuBBAAK
oUQDQgAEgVNEuirUNCEVdf7nLSBUgU1GXLrtIBeglIbK54s91HlWKOKjk4CkJ3/B
wGAfcYKa+DgJ2IUQSD15K1T/ghM9eQ==
-----END EC PRIVATE KEY-----

# Convert private key to ASN.1/DER format
$ openssl ec -in secp256k1-key.pem -inform PEM -out secp256k1-key.der -outform DER

$ dumpasn1 secp256k1-key.der
  0 116: SEQUENCE {
  2   1:   INTEGER 1
  5  32:   OCTET STRING
       :     ED 03 E5 18 E6 7A CF FD D4 D6 F7 74 76 3D 77 19
       :     9B 33 B8 15 7F 19 81 DB E3 95 B8 B9 96 31 B1 97
 39   7:   [0] {
 41   5:     OBJECT IDENTIFIER secp256k1 (1 3 132 0 10)
       :     }
 48  68:   [1] {
 50  66:     BIT STRING
       :       04 81 53 44 BA 2A D4 34 21 15 75 FE E7 2D 20 54
       :       81 4D 46 5C BA ED 20 17 A0 94 86 CA E7 8B 3D D4
       :       79 56 28 E2 A3 93 80 A4 27 7F C1 C0 60 1F 71 82
       :       9A F8 38 09 D8 85 10 48 3D 79 2B 54 FF 82 13 3D
       :       79
       :     }
       :   }

# Create public key from private key
$ openssl ec -in secp256k1-key.der -inform DER -pubout -out secp256k1-pub.der -outform DER

$ dumpasn1 secp256k1-pub.der
  0  86: SEQUENCE {
  2  16:   SEQUENCE {
  4   7:     OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1)
 13   5:     OBJECT IDENTIFIER secp256k1 (1 3 132 0 10)
       :     }
 20  66:   BIT STRING
       :     04 81 53 44 BA 2A D4 34 21 15 75 FE E7 2D 20 54
       :     81 4D 46 5C BA ED 20 17 A0 94 86 CA E7 8B 3D D4
       :     79 56 28 E2 A3 93 80 A4 27 7F C1 C0 60 1F 71 82
       :     9A F8 38 09 D8 85 10 48 3D 79 2B 54 FF 82 13 3D
       :     79
       :   }

# Sign the message using the private key
$ cat test.txt | openssl dgst -ecdsa-with-SHA1 -sign secp256k1-key.der -keyform DER > test.sig

# Dump the signature as hex
$ hexdump -C test.sig
00000000  30 44 02 20 08 66 c8 f1  6f 15 00 40 8a e2 1b 40  |0D. .f..o..@...@|
00000010  56 28 9c 17 8b ca 64 99  37 dc 35 ad ad 60 18 4d  |V(....d.7.5..`.M|
00000020  63 cf 4a 06 02 20 78 4c  b7 0b a3 ff 4f ce d3 01  |c.J.. xL....O...|
00000030  27 5c 6c ed 06 f0 d7 63  6d c6 be 06 59 e8 c3 a5  |'\l....cm...Y...|
00000040  ce 8a f1 de 01 d5                                 |......|
00000046

# Dump the signature as ASN.1/DER
$ dumpasn1 test.sig
  0  68: SEQUENCE {
  2  32:   INTEGER
       :     08 66 C8 F1 6F 15 00 40 8A E2 1B 40 56 28 9C 17
       :     8B CA 64 99 37 DC 35 AD AD 60 18 4D 63 CF 4A 06
 36  32:   INTEGER
       :     78 4C B7 0B A3 FF 4F CE D3 01 27 5C 6C ED 06 F0
       :     D7 63 6D C6 BE 06 59 E8 C3 A5 CE 8A F1 DE 01 D5
       :   }

在Crypto中可以使用PEM编码的密钥,而不是ASN.1/DER编码的密钥。要做到这一点,你需要PEM包。它是一个社区插件,不是图书馆的一部分。

如果您将PEM Pack添加到库中,那么您需要重建库。或者,您可以将其作为程序的一部分构建。

子车高超
2023-03-14

CodesInChaos是正确的。签名中的额外字节来自ASN.1编码,而不是正在签名的原始消息。例如,这是使用曲线secp128r1的ECDSA密钥生成的39字节签名:

30 25 02 10 4E 32 32 90 CA D9 BD D2 5F 8B BE 3B
F2 BF E9 7F 02 11 00 A7 83 A6 68 AD 74 7E 1A 0E
8F 73 BD DF 7A E8 B5

30 表示遵循序列。25 告诉您序列的长度为 0x25 字节。02 表示序列中的第一项是整数。10 告诉您第一个整数的长度为 0x10 字节。以下0x10 (16) 个字节是 ECDSA 签名的“r”值。第一个整数后面是字节 02。这告诉您序列的第二个整数即将开始。11 告诉您,接下来的 0x11 (17) 个字节组成第 2 个整数,即 ECDSA 签名的“s”值。它是 11 个字节,因为整数的第一个字节是 00。每当整数的第一个字节为

所以在这之后,真正的签名值是:

r: 4E 32 32 90 CA D9 BD D2 5F 8B BE 3B F2 BF E9 7F
s: A7 83 A6 68 AD 74 7E 1A 0E 8F 73 BD DF 7A E8 B5

“额外”字节用于ASN。1格式。

 类似资料:
  • 我想创建一个签名并使用openssl验证它。我想有我的签名的十六进制输出。 这是我的密码 我得到这个错误: 如果我在创建签名的过程中删除了-hex,它就可以工作了。

  • 我正在尝试使用加密来验证open-ssl签名,这是open-ssl部分: 现在在我的C代码中: 但是我总是收到验证失败的消息

  • 我正在尝试使用公钥验证散列的ECDSA签名。我写了一个小的围棋程序,成功地做到了这一点,但是我不能把它移植到C语言中。 这是我的输入数据: < li >公钥:< code > mfkwewyhkozizj 0 caqyikozij0 dackcdqgaedd 9 vxm phjv 4 vofo 0 zofplr r5 iczxquxsr 9 eka ouo 9 b 7 wl 1 daggi 0 e

  • 我正在编写一些代码,试图对一些数据进行签名。在将openssl生成的私钥转换为Java密钥库之后,我将Java签名类与SHA256withRSA一起使用。我试图确认openssl中Java类返回的签名,但由于某些原因,我无法让openssl进行验证。我最终需要在iOS Swift 3中实现这个签名验证,但在找到库之前,我想尝试根据openssl标准检查Java签名。 例如,我从我们的登录服务器得到

  • 下面是Java代码: 然后使用C代码来验证签名 我在想我需要将我的签名编码为hexa,但它并没有解决我的问题。我已经使用crypto编写了一个c版本的符号方法,并且已经验证过了。所以为什么当我使用java代码时,签名没有得到验证。谢谢

  • 我应该如何更改A方法?任何想法都是好的。提前谢谢。