X509Certificate2変数があり、変数の秘密キーをRSACryptoServiceProviderにキャストしようとしています
RSACryptoServiceProvider pkey = (RSACryptoServiceProvider)cert.PrivateKey;
ただし、この例外が発生します。
System.InvalidCastException: 'タイプ' System.Security.Cryptography.RSACng 'のオブジェクトをタイプ' System.Security.Cryptography.RSACryptoServiceProvider 'にキャストできません。'
SOの他の回答が私のものと同じ手順を提案したので例外が発生するので、これが起こるのは奇妙です。これに対する解決策はありますか?
私の場合、以下のようにローカルストア証明書を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();
}
エクスポートポリシーが既に正しい証明書を作成するだけで、エクスポートポリシーを設定しているコードを完全に回避できます。 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));