.net-3.5 - RSACryptoServiceProvider.ImportParameters 抛出 System.Security.Cryptography.CryptographicException : Bad Data

标签 .net-3.5 cryptography rsa

将 Windows 窗体应用程序从 .NET 1.1 框架升级到 .NET 3.5 框架时,我遇到了 RSACryptoServiceProvider 问题。在数据库中,我存储了包含加密签名(SHA1 哈希)的二进制文件,并且将公钥作为包含十六进制字符串的文本文档存储在文件系统中。我从文件系统读取文件并获取证书中编码的公钥没有任何问题。

从公钥中,我获取模块和指数字段作为公钥的一部分。我将这些值分配给 RSAParameters 对象的新实例。接下来,我创建 RSACryptoServiceProvider 类的新实例并调用 ImportParameters。在该调用中,3.5 代码抛出异常。请注意,1.1 代码完全没有问题。

有谁知道赋予 RSAParameters 属性的字节数组是否需要转换,以便我也可以在 3.5 代码中使用它们?我已经尝试过反转数组或将字节数组转换为 BigInteger,但这并不能解决我的问题。

作为引用,完整的堆栈跟踪:

System.Security.Cryptography.CryptographicException: Bad Data.

   at System.Security.Cryptography.CryptographicException.ThrowCryptogaphicException(Int32 hr)
   at System.Security.Cryptography.Utils._ImportKey(SafeProvHandle hCSP, Int32 keyNumber, CspProviderFlags flags, Object cspObject, SafeKeyHandle& hKey)
   at System.Security.Cryptography.RSACryptoServiceProvider.ImportParameters(RSAParameters parameters)

出现错误之前的源代码: //------------------------------------------------ ------------------* //验证证书。 * //------------------------------------------------ ------------------*

            // verify the CA certificate (output = public key van CA)
            byte[] lv_PkCA = VerifyCertificate(byte[], in_PkEUR);

            // verify the VU certificate (output = public key van VU)
            byte[] lv_PkVU = VerifyCertificate(byte[], lv_PkCA);


            //------------------------------------------------------------------
            // Verify the signatures
            //------------------------------------------------------------------

            // calculate hash with the SHA1 algorithm
            SHA1 lv_HashAlgoritm = new SHA1CryptoServiceProvider();

            byte[] lv_Modulus  = new byte[128];
            byte[] lv_Exponent = new byte[8];
            Buffer.BlockCopy(lv_PkVU, lv_PkVU.Length - 128 - 8, lv_Modulus , 0, lv_Modulus.Length);
            Buffer.BlockCopy(lv_PkVU, lv_PkVU.Length - 8      , lv_Exponent, 0, lv_Exponent.Length);

            // init RSA parameters
            RSAParameters lv_RSAKeyInfo = new RSAParameters();
            lv_RSAKeyInfo.Modulus  = lv_Modulus;
            lv_RSAKeyInfo.Exponent = lv_Exponent;

            // init RSA algoritme
            RSACryptoServiceProvider lv_RSA = new RSACryptoServiceProvider();
            lv_RSA.ImportParameters(lv_RSAKeyInfo);

更多引用,请参阅VerifyCertificate方法的内容。

private byte[] VerifyCertificate(
    byte[] in_Certificate,
    byte[] in_PublicKey)
{
    byte[] lv_CHR      = new byte[8];
    byte[] lv_Modulus  = new byte[128];
    byte[] lv_Exponent = new byte[8];
    Buffer.BlockCopy(in_PublicKey, in_PublicKey.Length - 128 - 8 - 8, lv_CHR     , 0, lv_CHR.Length);
    Buffer.BlockCopy(in_PublicKey, in_PublicKey.Length - 128 - 8    , lv_Modulus , 0, lv_Modulus.Length);
    Buffer.BlockCopy(in_PublicKey, in_PublicKey.Length - 8          , lv_Exponent, 0, lv_Exponent.Length);

    byte[] lv_Signature = new byte[128];
    byte[] lv_Cn        = new byte[58];
    byte[] lv_CAR       = new byte[8];
    Buffer.BlockCopy(in_Certificate,   0, lv_Signature, 0, lv_Signature.Length);
    Buffer.BlockCopy(in_Certificate, 128, lv_Cn       , 0, lv_Cn.Length);
    Buffer.BlockCopy(in_Certificate, 186, lv_CAR      , 0, lv_CAR.Length);

    for (int lv_Index = 0; lv_Index < lv_CAR.Length; lv_Index++)
    {
        if (lv_CAR[lv_Index] != lv_CHR[lv_Index])
            throw new Exception("Validation error: CAR not in public key.");
    }

    BigInteger lv_BiModulus   = new BigInteger(lv_Modulus);
    BigInteger lv_BiExponent  = new BigInteger(lv_Exponent);
    BigInteger lv_BiSignature = new BigInteger(lv_Signature);
    byte[] lv_Sr = lv_BiSignature.modPow(lv_BiExponent, lv_BiModulus).getBytes(lv_Signature.Length);

    if (lv_Sr.Length != 128)
        throw new Exception("The certificate coult not be validated: size of signature should be 128 bytes.");
    if ((lv_Sr[0]   != (byte)0x6A) ||
        (lv_Sr[127] != (byte)0xBC))
        throw new Exception("The certificate coult not be validated: invalid format.");

    byte[] lv_Cr = new byte[106];
    byte[] lv_H  = new byte[20];
    Buffer.BlockCopy(lv_Sr,   1, lv_Cr, 0, lv_Cr.Length);
    Buffer.BlockCopy(lv_Sr, 107, lv_H , 0, lv_H.Length);

    byte[] lv_C = new byte[164];
    Buffer.BlockCopy(lv_Cr, 0, lv_C,   0, lv_Cr.Length);
    Buffer.BlockCopy(lv_Cn, 0, lv_C, 106, lv_Cn.Length);

    // bereken de Hash van de public key
    SHA1CryptoServiceProvider lv_SHA1 = new SHA1CryptoServiceProvider();
    byte[] lv_Hash = lv_SHA1.ComputeHash(lv_C);

    // vergelijk de berekende hash met de hash in het certificaat
    if (lv_Hash.Length != lv_H.Length)
        throw new Exception("The certificate coult not be verified: hash length invalid.");
    for (int lv_Index = 0; lv_Index < lv_Hash.Length; lv_Index++)
    {
        if (lv_Hash[lv_Index] != lv_H[lv_Index])
            throw new DiantaException("The certificate coult not be verified: hash not invalid.");
    }

    return lv_C;
}

感谢您提前提供的帮助。

亲切的问候,

雷内

最佳答案

指数可以有一个前缀 0,但不能有两个或更多。

您可能使用的指数为 65537(99% 的 RSA key 对都使用该指数),因此 lv_RSAKeyInfo.Exponent{0, 0, 0, 0, 0, 1, 0, 1}.

删除多余的零,您的代码应该可以工作。

关于.net-3.5 - RSACryptoServiceProvider.ImportParameters 抛出 System.Security.Cryptography.CryptographicException : Bad Data,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5515217/

相关文章:

ios - 使用 SecKeyEncrypt 的 RSA 加密给出错误 -4 (errSecUnimplemented)

c++ - OpenSSL RSA 解密随机失败 C/C++

java - InvalidKeySpecException : algid parse error, 不是序列

.net - 如果javascript被禁用,如何在服务器上检查?

sharepoint - 使用客户端对象模型 SharePoint 2010 以编程方式获取 ListItemVersion

asp.net - 如何在 asp.net checkboxlist 中设置多个选定的值

javascript - 如何在没有 javascript 的情况下对 Web 表单中的密码进行编码?

c# - 我可以使用 Paint.NET API 将其嵌入到 Winforms 应用程序中吗?

c++ - 使用给定的指数在智能卡上生成 key

cryptography - Thales Payshield HSM RSA 私钥