Openssl ECDSA 按原样签署输入 - 没有摘要

Openssl ECDSA sign input as-is - without digest

我正在尝试使用 openssl 对现有摘要进行签名。

假设我已经有了摘要 'mydigest'。话虽如此,我不想使用:

echo -n "mydigest" | openssl dgst -sha256 -sign key.pem | openssl enc -A -base64

我有 ECDSA 而不是 rsa,所以我认为我不应该使用 rsautl,它按原样使用输入。

所以我的假设是我需要一些按原样接受输入(mydigest)并用我的 ECDSA 私钥签名的东西。

我尝试了以下以查看使用不同哈希算法创建的哈希大小是否对签名结果有任何影响:

echo -n "mydigest" | openssl pkeyutl -sign -inkey key.pem | openssl enc -A -base64

echo -n "my-very-very-very-long-digest" | openssl pkeyutl -sign -inkey key.pem | openssl enc -A -base64

但是就输出长度而言,两个命令的输出大小相同。我假设对于大的 my-very..-long-digest 它应该 return 更大的输出(因为它应该按原样接受输入而不缩短(散列)。

========================================

编辑。

也许下面的例子有助于理解我的问题。这是 bouncycastle 的一个例子。

 // sign something
String messageToSign = "something_to_sign";
ECDomainParameters domain = new ECDomainParameters(spec.getCurve(), spec.getG(), spec.getN());
ECDSASigner signer = new ECDSASigner();
signer.init(true, new ECPrivateKeyParameters(privateKey, domain));
MessageDigest digest = MessageDigest.getInstance("Keccak-256");
byte[] hash = digest.digest(messageToSign.getBytes(StandardCharsets.UTF_8));
BigInteger[] signature = signer.generateSignature(hash);

假设我有以下内容:

  1. 散列。
  2. 键。

现在我想用 openssl 创建签名,它应该将 hashkeys 作为输入而不创建散列。基本上我想替换

BigInteger[] signature = signer.generateSignature(hash);

在使用 openssl 的示例中。

openssl * ????? *

我假设结果的大小应该表明我用于哈希的哈希算法(具有不同的摘要大小)是否对结果有任何影响。

openssl pkeyutl -sign -inkey ecprivkey.pem完全正确。

I would assume for the large my-very..-long-digest it should return larger output (because it should take the input as-is without shortening (hashing).

你假设错了。 ECDSA 签名在数学上由两个整数 (r,s) 组成,范围从 1 到曲线子群的阶数;它完全不受用作(或用于)输入的哈希大小的影响。 推荐 使用大小与子组匹配的散列——例如SHA256(或您的 Keccak256)与 P-256 又名 secp256r1 - 因为否则如果哈希值太大,它会被截断,或者如果太小,它会被填充并降低安全性。

对于 DSA 也是如此,对于 RSA 也是如此——对于 RSA,签名始终是 RSA 密钥的大小,并且填充小于 RSA 密钥的编码和填充散列,但也-大的被拒绝为错误。 (这种情况非常罕见,因为 2048 位以下的 RSA 密钥不再被认为是可以接受的安全使用,而且没有人使用那么大的哈希值。)

ECDSA 签名的大小表示——或编码——可能会有所不同,并且有多种不同的标准。 OpenSSL 始终使用 rfc3279 2.2.3. So do the standard SunEC and BouncyCastle providers in Java by default. The length of the ASN.1 encoding depends, usually only slightly, on the values of the two integers which as you correctly note are controlled by a random value (k) and thus effectively pseudo-random numbers themselves. See (ADDED) and (cross) https://crypto.stackexchange.com/questions/33095/shouldnt-a-signature-using-ecdsa-be-exactly-96-bytes-not-102-or-103 and https://crypto.stackexchange.com/questions/44988/length-of-ecdsa-signature

中所示的 ASN.1 整数序列

Bouncy 提供程序还支持“{hash}with{PLAIN-,CVC-}ECDSA”算法,这些算法执行相同的数学签名,但使用 P1363 定义的更简单的表示,只是两个固定大小的(无符号双字节序)整数(等于子组订单大小)串联。编辑:自 Java 9 以来,SunEC 提供商使用不同的名称“{hash}withECDSAinP1363format”(不知何故我在第一次写作时错过了这个)。 JWS 也使用这种表示。最后,您展示的 Bouncy LWAPI returns 或采用 BigInteger[] -- 数学值 -- 并将编码和解码留给您。