如何使用使用 sha1ecdsa 的公钥验证数据是不是符合签名?

Posted

技术标签:

【中文标题】如何使用使用 sha1ecdsa 的公钥验证数据是不是符合签名?【英文标题】:How to verify data against signature with public key that uses sha1ecdsa?如何使用使用 sha1ecdsa 的公钥验证数据是否符合签名? 【发布时间】:2015-05-07 11:08:19 【问题描述】:

对密码学知之甚少,我对看似简单的任务有很大的问题。

我有 .pem 证书、数据字节和该数据的签名。 我想通过将数据与签名进行匹配来检查是否有人更改了数据。

我的尝试:

private bool VerifySignature(byte[] data, byte[] signature)

  try
  
    X509Certificate certificate = new X509Certificate("cert_filename.pem");
    if (certificate == null)
      return false;

    DSACryptoServiceProvider dsa = (DSACryptoServiceProvider)certificate.PublicKey.Key;

    return dsa.VerifyData(data, signatureData);
  
  catch
  
    return false;
  

但它给了我一个错误

'不支持证书密钥算法' (System.NotSupportedException)。

查看加载的证书,它说签名算法是“sha1ecdsa”。

我只尝试根据签名验证数据。我在这里想念什么? 我想在没有任何外部解决方案的情况下完成它,因为它似乎真的是微不足道的任务。

更新:我正在尝试实现与以下 Java 代码相同的功能:

private boolean verify(byte[] data, byte[] signature)

  boolean isLicenseCorrect = false;

  Signature sig = Signature.getInstance("SHA1WithECDSA");
  sig.initVerify(certificate.getPublicKey());
  sig.update(data);

  return sig.verify(signature);

【问题讨论】:

根据您的更新,如果您想将 java 代码转换为 C# link 这可能有助于查看 【参考方案1】:

虽然 DSA 和 ECDSA 相关,但它们并不相同。为什么不试试ECDsaCryptoServiceProvider?请注意,ECDSA 对椭圆曲线的支持仅包括 NIST 命名曲线。

【讨论】:

不幸的是,我无法在我的 Windows 窗体代码中访问此类。我只有 ECDsa 和 ECDsaCng,我都无法使用。 好的,那么为什么你不能使用这些类?他们应该提供一个更好的目标,因为DSACryptoServiceProvider 永远不会起作用。请注意,我没有您的设置(我自己没有使用 Windows 窗体,我只知道有关加密的事情以及我在 SO 上看到的内容)。 正如我之前提到的,我对加密技术知之甚少,并且无法自己弄清楚如何解决我的任务。网上有很多使用 RSACryptoServiceProvider 或 DSACryptoServiceProvider 的文章,但我无法使用它们。 我添加了 Java 代码,我想移植到 C# 作为参考。【参考方案2】:

.NET 4.6.1 添加了对 ECDSA 的改进支持。虽然我不喜欢你的 catch-everything-and-return-false,但我将把它放在这里进行比较:

private bool VerifySignature(byte[] data, byte[] signature)

    try
    
        // new cannot return null, so no point in a null check. It would have thrown.

        using (X509Certificate certificate = new X509Certificate("cert_filename.pem"))
        using (ECDsa ecdsa = certificate.GetECDsaPublicKey())
        using (RSA rsa = certificate.GetRSAPublicKey())
        // Improved DSA is 4.6.2
        
            // You said the cert was ECDSA-SHA1, but that doesn't mean the original data was.
            // I assumed it was.
            if (ecdsa != null)
                return ecdsa.VerifyData(data, signature, HashAlgorithmName.SHA1);

            if (rsa != null)
                return rsa.VerifyData(data, signature, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);

            return false;
        
    
    catch
    
        return false;
    

请注意,在 .NET 4.6 中,RSA 基类定义了 Sign/Verify 方法,而在 4.6.1 中,ECDsa 基类得到了类似的处理。除非加载预先存在的命名密钥,否则新代码不应谈论 *CryptoServiceProvider 类型。

还值得注意的是,当公钥不是该算法类型时,Get[Algorithm]PublicKey 方法返回 null,因此需要进行空检查。

【讨论】:

以上是关于如何使用使用 sha1ecdsa 的公钥验证数据是不是符合签名?的主要内容,如果未能解决你的问题,请参考以下文章

如何将公钥从字符串类型转换为 PEM

如何使用公钥在本地验证 keycloak 访问令牌

如何使用公钥验证 ECDSA?

如何使用 jwt 公钥在 Spring Boot 中验证承载访问令牌

如何在 Java 中使用令牌和公钥验证 JWT 签名

如何搭建CA