我正在向用户显示他个人商店中的每个可用证书,使用以下方法获取:
public List<X509Certificate2> GetPersonalCertificates()
{
var certificates = new List<X509Certificate2>();
using (var store = new X509Store(StoreName.My, StoreLocation.CurrentUser))
{
store.Open(OpenFlags.MaxAllowed);
foreach (var certificate in store.Certificates)
{
if (certificate != null && certificate.HasPrivateKey)
{
certificates.Add(certificate);
}
}
}
return certificates;
}
当用户选择其中一个证书时,会加载一个示例文件并将其提供给以下方法:
public byte[] EncryptFile(X509Certificate2 certificate, byte[] fileToEncrypt)
{
if (certificate == null || hashToSign == null) return null;
byte[] encryptedFile = null;
try
{
using (var privateKey = certificate.GetRSAPrivateKey())
{
encryptedFile = privateKey.Encrypt(hashToSign, System.Security.Cryptography.RSAEncryptionPadding.OaepSHA256);
}
}
catch (Exception e)
{
// Error management
}
return encryptedFile;
}
此方法应该使用SHA256算法使用RSA私钥加密数据,但它一直落入catch语句。
我得到的错误取决于我使用的证书:
Internal.Cryptography.CryptoThrowHelper + WindowsCryptographicException:
参数无效
在System.Security.Cryptography.RSACng.EncryptOrDecrypt(SafeNCryptKeyHandle) key,Byte [] input,AsymmetricPaddingMode paddingMode,Void * paddingInfo,EncryptOrDecryptAction encryptOrDecrypt)
在System.Security.Cryptography.RSACng.EncryptOrDecrypt(Byte []数据中, RSAEncryptionPadding padding,EncryptOrDecryptAction encryptOrDecrypt)
在System.Security.Cryptography.RSACng.Encrypt(Byte []数据中, RSAEncryptionPadding padding)
我的方法
Internal.Cryptography.CryptoThrowHelper + WindowsCryptographicException:
不支持请求的操作
at Security.Cryptography.RSACng.EncryptOrDecrypt(SafeNCryptKeyHandle) key,Byte [] input,AsymmetricPaddingMode paddingMode,Void * paddingInfo,EncryptOrDecryptAction encryptOrDecrypt)
在System.Security.Cryptography.RSACng.EncryptOrDecrypt(Byte []数据,RSAEncryptionPadding padding,EncryptOrDecryptAction encryptOrDecrypt)
在System.Security.Cryptography.RSACng.Encrypt(Byte []数据,RSAEncryptionPadding padding)
我的方法
我也尝试过私钥的 SignData 方法,导致相同的例外情况:
encryptedFile = privateKey.SignData(hashToSign, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
我错过了什么吗?
请注意,由于我正在使用UWP应用程序,因此我只能访问some of the System.Security namespace。
答案 0 :(得分:0)
我找到了解决问题的方法,原因是这两个错误:
首先,此处使用的加密方法不是加密,而是 SignData ,因为我想对数据进行电子签名。
其次,为了制作有效签名,证书需要包含 Non-Repudation 扩展名。为了检查这一点,我添加了这种方法:
private bool _canUsingCertificateForSignData(X509ExtensionCollection extensions)
{
if (extensions != null)
{
foreach (var ext in extensions)
{
if (ext.GetType().Equals(typeof(X509KeyUsageExtension)))
{
if (((X509KeyUsageExtension)ext).KeyUsages.HasFlag(X509KeyUsageFlags.NonRepudiation))
{
return true;
}
}
}
}
return false;
}
我现在使用以下内容获取证书:
public List<X509Certificate2> GetPersonalCertificates()
{
var certificates = new List<X509Certificate2>();
using (var store = new X509Store(StoreName.My, StoreLocation.CurrentUser))
{
store.Open(OpenFlags.MaxAllowed);
foreach (var certificate in store.Certificates)
{
if (certificate != null && certificate.HasPrivateKey && _canUsingCertificateForSignData(certificate.Extensions))
{
certificates.Add(certificate);
}
}
}
return certificates;
}
我仍然不明白的一件事是,为什么 SignData 方法不会抛出任何异常,并且在从 pfx获取证书时对数据进行了签名文件,而非商店。