【问题标题】:SignedData giving Invalid algorithm specified.exceptionSignedData 给出了无效的算法指定。异常
【发布时间】:2020-01-12 08:16:59
【问题描述】:

我尝试使用 myCert.pfx 文件的私钥和公钥对我的签名数据进行签名和验证。但是在签署数据时,我得到“指定的算法无效”。异常

我们使用的.Net框架是4.5,代码如下

public static void CallMainMethod()
{
    string str = "Sign and verify the data";
    X509Certificate2 certificate = LoadPrivateKey();

    byte[] hashBytes = GetDataHash(str);
    byte[] signature = GetDigitalSignature(hashBytes);
} 

 private static X509Certificate2 LoadPrivateKey()
{
    return new X509Certificate2(@"d:\Keys\myCert.pfx", "Pass#@123");
}

 private static byte[]  GetDataHash(string sampleData)
{
    //choose any hash algorithm
    SHA256Managed managedHash = new SHA256Managed();
    return managedHash.ComputeHash(Encoding.Unicode.GetBytes(sampleData));
}

private static byte[] GetDigitalSignature(byte[] data)
{
    X509Certificate2 certificate = LoadPrivateKey();
    RSACryptoServiceProvider provider = (RSACryptoServiceProvider)certificate.PrivateKey;   
    return provider.SignHash(data, "SHA256");
}

【问题讨论】:

    标签: c# x509certificate sha256 x509certificate2 pfx


    【解决方案1】:

    我相信旧版 RSACryptoServiceProvider 不支持 SHA2 算法。将最后一个方法改写如下:

    private static byte[] GetDigitalSignature(byte[] data)
    {
        X509Certificate2 certificate = LoadPrivateKey();
        RSA provider = certificate.GetRSAPrivateKey();   
        return provider.SignHash(data, "SHA256", RSASignaturePadding.Pkcs1);
    }
    

    这种风格在 .NET Framework 4.6 及更高版本中是首选(@bartonjs,如果我对 .NET 版本有误,请纠正我)。

    【讨论】:

    • 我们当前的 .NET 框架是 4.5,是否有任何替代方案可以使其在 Framework 4.5 中工作。
    • 仅通过 CryptoAPI 互操作。不直接通过 .NET API。
    • 是的,.NET Framework 4.6。 (docs.microsoft.com/en-us/dotnet/api/…)
    【解决方案2】:

    虽然@Crypt32 给出了最佳答案(升级到 .NET Framework 4.6 或更高版本并使用GetRSAPrivateKey()SignData 的更好版本——此时它已经发布了 4 年多),如果你真的需要留在 net45 上,您最简单的答案是使用 X509KeyStorageFlags.Exportable 打开 PFX 并将密钥复制到更好的提供程序中。

    return new X509Certificate2(@"d:\Keys\myCert.pfx", "Pass#@123", X509KeyStorageFlags.Exportable);
    

    ...

    RSA legacyProv = (RSA)certificate.PrivateKey;
    RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
    provider.ImportParameters(legacyProv.ExportParameters(true));
    return provider.SignHash(data, "SHA256");
    

    【讨论】:

    • 你不是说RSACng class 而不是RSACryptoServiceProvider吗?
    • @Crypt32 RSACryptoServiceProvider 可以执行 SHA-2-256 签名...只要它使用正确的提供程序类型 (24) 和提供程序(Microsoft 增强 RSA 和 AES 加密提供程序)。 PFX 导入往往是较旧的提供商名称之一,这就是它失败的原因。那,并且 net45 中不存在 RSACng :)。 (net46 中的新功能)。
    • 好的,感谢您的澄清。在旧版本中,我使用互操作并且不知道这种方式。但这不适用于安装在具有不可导出密钥的证书存储中的证书,我认为。
    • @Crypt32 正确。可以使用 prov 24 重新打开密钥,但人们经常将其编写得太脆弱,无法可靠地处理 3rd 方/HSM 提供程序。由于这里有 PFX 负载,我采用了更简单的解决方法。
    猜你喜欢
    • 2011-11-17
    • 1970-01-01
    • 2012-06-21
    • 1970-01-01
    • 1970-01-01
    • 2017-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多