ECDSA 签名 - 是否可以得出所用密钥的结论?

ECDSA signature - Is a conclusion to the used key possible?

我注意到,如果我使用 ECDsa.SignData 方法,我总是会得到不同的 ECDSA 签名。

所以我想知道是否可以从ECDSA签名推断出使用的密钥?

如果 Alice 向 Bob1 和 Bob2 发送消息,Eve 可以在没有来自 Alice 的 public 的情况下确定签名来自同一发送者吗?

public static byte[] SignData(KeyPair privateKeyPair, byte[] data)
{
    var ecDsa = ECDsa.Create(ECCurve.NamedCurves.brainpoolP320r1);
    ecDsa.ImportParameters(privateKeyPair.CreateECParameters());
    return ecDsa.SignData(data, HashAlgorithmName.SHA512);
}

public static bool VerifyData(KeyPair signedKeyPair, byte[] data, byte[] signature)
{
    var ecDsa = ECDsa.Create(ECCurve.NamedCurves.brainpoolP320r1);
    ecDsa.ImportParameters(signedKeyPair.CreateECParameters());
    return ecDsa.VerifyData(data,signature, HashAlgorithmName.SHA512);
}

var plainMsg = Encoding.UTF8.GetBytes("Hello World");
var keyPair = BrainpoolKeyGenerator.CreateKeyPair(true);

var signature1 = SignData(keyPair, plainMsg);
var signature2 = SignData(keyPair, plainMsg);

Assert.That(signature1,Is.Not.EquivalentTo(signature2), "Signature #1 and #2 are NOT equal");

Assert.That(VerifyData(keyPair.ExportPublicKey(), plainMsg, signature1), "Signature of #1 is valid");
Assert.That(VerifyData(keyPair.ExportPublicKey(), plainMsg, signature2), "Signature of #2 is valid");

不,对同一数据有两个 ECDSA 签名并不能表明它是由同一方签名两次还是由两个不同的方签名。

为了讨论 ECDSA 的工作原理,我们需要一些快速(松散定义)的术语:

  • G,生成器,是曲线上的一个点。
    • 与曲线的私钥 (d) 关联的 public 密钥是 d * G,使用曲线数学我们不会在这里讨论。
    • 对于 brainpoolP320r1,G 值在 RFC5639, section 3.5 中分解为 xy
  • n,曲线顺序,是给定 Gd 的最大合法值。
    • RFC5639 将此值称为 q,但大多数其他内容都将其称为 n

Wikipedia 上有 ECDSA 细分,但公式的要点是:

  • 创建一个随机数 k 使得 0 < k < n
  • r是一个整数,等于EC点的X坐标k * G
  • z 为解释为数字的消息摘要(带有一些 trimming/extension)
  • kInvkn 的倒数(另见 Extended Euclidean Algorithm)。
  • skInv * (z + (r * d)) mod n
  • 签名为(r,s)。
    • 在.NET中,(r, s)值以IEEE P1363格式表示,即前半部分为r,后半部分为s,它们的长度由曲线.

所以,签名的前半部分实际上是一个随机数。椭圆曲线密码学基于这样一个事实,即很难计算 Q / G(其中 Q 是 public 密钥,也就是曲线上的一个点),因此从 [=22= 恢复 k ]很难。

签名的后半部分 (s) 是唯一涉及签名者密钥的部分,但它被 k 打败了很多。

签名验证算法然后检查是否 Qz'z 的验证者版本),结合 rs 进行配方平衡。如果不是,则没有迹象表明是因为 hash/digest 错误还是 public 键错误。