无法将类型为“RSACng”的对象转换为类型“System.Security.Cryptography.RSACryptoServiceProvider”

4
我收到了这个异常:

无法将类型为“RSACng”的对象强制转换为类型“System.Security.Cryptography.RSACryptoServiceProvider”

调用此方法:
GoogleCredential cred = GoogleCredential.FromFile(path);

完整的异常信息:

Unable to cast object of type 'RSACng' to type 'System.Security.Cryptography.RSACryptoServiceProvider'
   at Google.Apis.Auth.OAuth2.ServiceAccountCredential.Initializer.FromPrivateKey(String privateKey) in C:\Apiary\2019-09-11.10-11-15\Src\Support\Google.Apis.Auth\OAuth2\ServiceAccountCredential.cs:line 110
   at Google.Apis.Auth.OAuth2.DefaultCredentialProvider.CreateServiceAccountCredentialFromParameters(JsonCredentialParameters credentialParameters) in C:\Apiary\2019-09-11.10-11-15\Src\Support\Google.Apis.Auth\OAuth2\DefaultCredentialProvider.cs:line 243
   at Google.Apis.Auth.OAuth2.DefaultCredentialProvider.CreateDefaultCredentialFromParameters(JsonCredentialParameters credentialParameters) in C:\Apiary\2019-09-11.10-11-15\Src\Support\Google.Apis.Auth\OAuth2\DefaultCredentialProvider.cs:line 197
   at Google.Apis.Auth.OAuth2.GoogleCredential.FromFile(String path) in C:\Apiary\2019-09-11.10-11-15\Src\Support\Google.Apis.Auth\OAuth2\GoogleCredential.cs:line 114
   at ServerUtil.GCloudReporter..ctor(String version, String deployEnv)  

使用 .NET Framework 4.5.1

Google APIs libs 版本为 1.41.1


查看 https://github.com/googleapis/google-api-dotnet-client/blob/master/Src/Support/Google.Apis.Auth/OAuth2/ServiceAccountCredential.cs 这段代码尝试将 RSA.Create() 方法的结果转换为 RSACryptoServiceProvider。RSA 类的工厂方法可以被 machine.config 重写,而且默认值可能因 .NET 运行时的不同而异,详情请参见 https://dusted.codes/how-to-use-rsa-in-dotnet-rsacryptoserviceprovider-vs-rsacng-and-good-practise-patterns。也许没有人深入测试过这个问题 :-) - vitalygolub
5个回答

4

我遇到了完全相同的异常。

在我的情况下,我使用的是Sustainsys.Saml2.AspNetCore2版本(2.8.0)的nuget包。

我已经升级到2.9.0并删除了所有与身份验证相关的Cookie。

这解决了我的问题。


这并没有真正回答问题。如果您有不同的问题,可以通过点击提问来提出。如果您想在此问题获得新的答案时得到通知,您可以关注此问题。一旦您拥有足够的声望,您还可以添加悬赏以吸引更多关注。- 来自审核 - MD. RAKIB HASAN

2
问题在于该应用程序运行在.NET Core环境中,但是这个特定的代码是在为.NET Framework设置的项目中。将代码移动到具有.NET Core设置的项目中可以解决问题。

5
@Yuri 你说问题在于该应用程序是在.NET Core中运行,然后你将代码移动到了一个.NET Core项目中。这让人感到困惑,因为它本来就在那里。但最终你解决了问题,请与社区分享。 - Matthew

2
在我的案例中,当我想要将我的通知服务从服务层使用到我的.NetCore项目时,出现了这个错误。

无法将类型为“RSACng”的对象强制转换为类型“System.Security.Cryptography.RSACryptoServiceProvider”

我只是通过包管理器向我的.NetCore项目添加了“FirebaseAdmin”包。
对我来说很困惑,因为我在不需要此包的我的.Net Framework项目上没有遇到此错误。
这是一个相当愚蠢的错误,但我希望这可以为其他人节省宝贵的时间。

0

这个例子使用变量来指定本地计算机存储中的特定证书以及应该使用密码学 API:下一代(CNG)加密/解密的字符串。

using System;
using System.Security.Cryptography.X509Certificates;
using System.Text;

namespace X509CertEncrypt
{
    class Program
    {
        // Variables 
        public static string certificateName = "localhost";
        public static string sSecret = "TextToEncrypt";

        static void Main(string[] args)
        {
            Program p = new Program();

            // Get the certificate 
            p.getCertificate(certificateName);

            // Encryption 
            string sEncryptedSecret = string.Empty;
            sEncryptedSecret = p.EncryptRsa(sSecret);

            // Decryption 
            string sDecryptedSecret = string.Empty;
            sDecryptedSecret = p.decryptRsa(sEncryptedSecret);

            ////Display the original data and the decrypted data.
            Console.WriteLine("Original:   {0}", sSecret);
            Console.WriteLine("Encypted Value:   {0}", sEncryptedSecret);
            Console.WriteLine("Round Trip: {0}", sDecryptedSecret);
            Console.WriteLine("Press the Enter key to exit.");
        }

        private X509Certificate2 getCertificate(string certificateName)
        {
            X509Store my = new X509Store(StoreName.My, StoreLocation.LocalMachine);
            my.Open(OpenFlags.ReadOnly);

            X509Certificate2Collection collection = my.Certificates.Find(X509FindType.FindBySubjectName, certificateName, false);
            if (collection.Count == 1)
            {
                return collection[0];
            }
            else if (collection.Count > 1)
            {
                throw new Exception(string.Format("More than one certificate with name '{0}' found in store LocalMachine/My.", certificateName));
            }
            else
            {
                throw new Exception(string.Format("Certificate '{0}' not found in store LocalMachine/My.", certificateName));
            }
        }

        private string EncryptRsa(string input)
        {
            string output = string.Empty;
            X509Certificate2 cert = getCertificate(certificateName);

            // Changed from 
            //      using (RSACryptoServiceProvider csp = (RSACryptoServiceProvider)cert.PublicKey.Key)
            // to
            //      using (System.Security.Cryptography.RSACng csp = (System.Security.Cryptography.RSACng)cert.PublicKey.Key)
            // because of 'Unable to cast object of type 'System.Security.Cryptography.RSACng' to type 'System.Security.Cryptography.RSACryptoServiceProvider'.'

            // Changed from 
            //      byte[] bytesEncrypted = csp.Encrypt(bytesData, false);
            // To            
            //      byte[] bytesEncrypted = csp.Encrypt(bytesData, System.Security.Cryptography.RSAEncryptionPadding.OaepSHA512);

            using (System.Security.Cryptography.RSACng csp = (System.Security.Cryptography.RSACng)cert.PublicKey.Key)
            {
                byte[] bytesData = Encoding.UTF8.GetBytes(input);
                //byte[] bytesEncrypted = csp.Encrypt(bytesData, false);
                byte[] bytesEncrypted = csp.Encrypt(bytesData, System.Security.Cryptography.RSAEncryptionPadding.OaepSHA512);
                output = Convert.ToBase64String(bytesEncrypted);
            }
            return output;
        }

        private string decryptRsa(string encrypted)
        {
            string text = string.Empty;
            X509Certificate2 cert = getCertificate(certificateName);
            // using (RSACryptoServiceProvider csp = (RSACryptoServiceProvider)cert.PrivateKey)
            using (System.Security.Cryptography.RSACng csp = (System.Security.Cryptography.RSACng)cert.PrivateKey)
            {
                byte[] bytesEncrypted = Convert.FromBase64String(encrypted);
                byte[] bytesDecrypted = csp.Decrypt(bytesEncrypted, System.Security.Cryptography.RSAEncryptionPadding.OaepSHA512);
                text = Encoding.UTF8.GetString(bytesDecrypted);
            }
            return text;
        }
    }
}

0

.NET Core 步骤1:从NuGet包中安装System.Security.Cryptography.Cng 步骤2:创建一个名为“X509Certificate2Signature”的类

    using iTextSharp.text.pdf.security;
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;

namespace DigiSignNETCORE
{
    public class X509Certificate2Signature : IExternalSignature
    {
        private String hashAlgorithm;
        private String encryptionAlgorithm;
        private X509Certificate2 certificate;

        public X509Certificate2Signature(X509Certificate2 certificate, String hashAlgorithm)
        {
            if (!certificate.HasPrivateKey)
                throw new ArgumentException("No private key.");
            this.certificate = certificate;
            this.hashAlgorithm = DigestAlgorithms.GetDigest(DigestAlgorithms.GetAllowedDigests(hashAlgorithm));
            if (certificate.PrivateKey is RSACryptoServiceProvider)
                encryptionAlgorithm = "RSA";
            else if (certificate.PrivateKey is DSACryptoServiceProvider)
                encryptionAlgorithm = "DSA";
            
            else if (certificate.PrivateKey is System.Security.Cryptography.RSACng)
                encryptionAlgorithm = "RSA";
        }

        public virtual byte[] Sign(byte[] message)
        {
            if (certificate.PrivateKey is RSACryptoServiceProvider)
            {
                RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)certificate.PrivateKey;
                return rsa.SignData(message, hashAlgorithm);
            }
           else if (certificate.PrivateKey is System.Security.Cryptography.RSACng)
            {
                System.Security.Cryptography.RSACng rSACng = (System.Security.Cryptography.RSACng)certificate.PrivateKey;
                return rSACng.SignData(message,HashAlgorithmName.SHA1,RSASignaturePadding.Pkcs1);
            }

            else
            {
                DSACryptoServiceProvider dsa = (DSACryptoServiceProvider)certificate.PrivateKey;
                return dsa.SignData(message);
            }
        }

        public virtual String GetHashAlgorithm()
        {
            return hashAlgorithm;
        }

        public virtual String GetEncryptionAlgorithm()
        {
            return encryptionAlgorithm;
        }
    }
}

步骤3:在这一行中,IExternalSignature externalSignature = new X509Certificate2Signature(cert, "SHA1"); 指向您最近创建的“X509Certificate2Signature”类。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接