web-dev-qa-db-ja.com

RSACryptoServiceProviderへの秘密キーのキャストが機能しない

X509Certificate2変数があり、変数の秘密キーをRSACryptoServiceProviderにキャストしようとしています

RSACryptoServiceProvider pkey = (RSACryptoServiceProvider)cert.PrivateKey;

ただし、この例外が発生します。

System.InvalidCastException: 'タイプ' System.Security.Cryptography.RSACng 'のオブジェクトをタイプ' System.Security.Cryptography.RSACryptoServiceProvider 'にキャストできません。'

SOの他の回答が私のものと同じ手順を提案したので例外が発生するので、これが起こるのは奇妙です。これに対する解決策はありますか?

4
Vins

私の場合、以下のようにローカルストア証明書RSACryptoServiceProviderに変換しようとしたときに同じ問題が発生していました。

RSACryptoServiceProvider encryptProvider = 
                         certificate.PrivateKey as RSACryptoServiceProvider;

RSAの代わりにRSACryptoServiceProviderを使用することで問題が修正されました。


誰かがそれを行う方法に興味がある場合に備えて、ここに指示を入れます))。

証明書をマシンに保存するには、Visual Studio Developer Commandを開き、次のように入力します。

makecert -n "CN=JohnDoe" -sr currentuser -ss someCertStore

...ここでは、「JohnDoe」と「demoCertStore」の代わりに値を指定できます。

これで、以下のコードを使用してローカル証明書ストアから証明書にアクセスできます。

public class Program
{
    static void DumpBytes(string title, byte[] bytes)
    {
        Console.Write(title);
        foreach (byte b in bytes)
        {
            Console.Write("{0:X} ", b);
        }

        Console.WriteLine();
    }

    static void Main(string[] args)
    {
        // This will convert our input string into bytes and back
        var converter = new ASCIIEncoding();

        // Get a crypto provider out of the certificate store
        // should be wrapped in using for production code
        var store = new X509Store("someCertStore", StoreLocation.CurrentUser);

        store.Open(OpenFlags.ReadOnly);

        // should be wrapped in using for production code
        X509Certificate2 certificate = store.Certificates[0];

        RSA rsa = (RSA)certificate.PrivateKey;
        (certificate.PrivateKey as RSACng)?.Key.SetProperty(
                                                new CngProperty(
                                                    "Export Policy",
                                                    BitConverter.GetBytes((int)CngExportPolicies.AllowPlaintextExport),
                                                    CngPropertyOptions.Persist));

        string messageToSign = "This is the message I want to sign";
        Console.WriteLine("Message: {0}", messageToSign);
        byte[] messageToSignBytes = converter.GetBytes(messageToSign);

        // need to calculate a hash for this message - this will go into the
        // signature and be used to verify the message
        // Create an implementation of the hashing algorithm we are going to us
        // should be wrapped in using for production code
        DumpBytes("Message to sign in bytes: ", messageToSignBytes);
        HashAlgorithm hasher = new SHA1Managed();

        // Use the hasher to hash the message
        byte[] hash = hasher.ComputeHash(messageToSignBytes);
        DumpBytes("Hash for message: ", hash);

        // Now sign the hash to create a signature
        byte[] signature = rsa.SignHash(hash, HashAlgorithmName.SHA1, RSASignaturePadding.Pss);
        DumpBytes("Signature: ", messageToSignBytes);

        // Now use the signature to perform a successful validation of the mess
        bool validSignature = rsa.VerifyHash(hash: hash,
                                             signature: signature,
                                             hashAlgorithm: HashAlgorithmName.SHA1,
                                             padding: RSASignaturePadding.Pss);
        Console.WriteLine("Correct signature validated OK: {0}", validSignature);

        // Change one byte of the signature
        signature[0] = 99;

        // Now try the using the incorrect signature to validate the message
        bool invalidSignature = rsa.VerifyHash(hash: hash,
                                               signature: signature,
                                               hashAlgorithm: HashAlgorithmName.SHA1,
                                               padding: RSASignaturePadding.Pss);

        Console.WriteLine("Incorrect signature validated OK: {0}", invalidSignature);
        Console.ReadKey();
}
0

エクスポートポリシーが既に正しい証明書を作成するだけで、エクスポートポリシーを設定しているコードを完全に回避できます。 New-SelfSignedCertificate PowerShellユーティリティを使用して、最初からエクスポート可能な証明書を作成しました。
PS C:> New-SelfSignedCertificate -CertStoreLocation "Cert:\ CurrentUser \" -Subject "CN = JUSTIN" -KeyExportPolicy Exportable

これにより、以下の必要がなくなります。

(certificate.PrivateKey as RSACng)?.Key.SetProperty(new CngProperty("Export Policy", BitConverter.GetBytes((int)CngExportPolicies.AllowPlaintextExport),CngPropertyOptions.Persist));
0
Justin Fisher