[英]Encrypt data with X509 certificate's private key in UWP
I'm displaying to the user every available certificates in his personal store, fetched with the following method : 我正在向用户显示其个人商店中的所有可用证书,并通过以下方法获取:
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;
}
When the user select one of those certificates, a sample file is loaded and given to the following method : 当用户选择这些证书之一时,将加载示例文件并提供给以下方法:
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;
}
This method is supposed to encrypt the data with the RSA private key using the SHA256 algorithm, but it keeps falling into the catch statement. 该方法应该使用SHA256算法使用RSA私钥对数据进行加密,但是它一直属于catch语句。
The error that I get depends on the certificate that I use : 我得到的错误取决于我使用的证书:
Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: Internal.Cryptography.CryptoThrowHelper + WindowsCryptographicException:
Invalid parameter 无效的参数
at System.Security.Cryptography.RSACng.EncryptOrDecrypt(SafeNCryptKeyHandle key, Byte[] input, AsymmetricPaddingMode paddingMode, Void* paddingInfo, EncryptOrDecryptAction encryptOrDecrypt) 在System.Security.Cryptography.RSACng.EncryptOrDecrypt(SafeNCryptKeyHandle密钥,Byte []输入,AsymmetricPaddingMode paddingMode,Void * paddingInfo,EncryptOrDecryptAction cryptoOrDecrypt)
at System.Security.Cryptography.RSACng.EncryptOrDecrypt(Byte[] data, RSAEncryptionPadding padding, EncryptOrDecryptAction encryptOrDecrypt) 在System.Security.Cryptography.RSACng.EncryptOrDecrypt(Byte []数据,RSAEncryptionPadding填充,EncryptOrDecryptAction加密或解密)
at System.Security.Cryptography.RSACng.Encrypt(Byte[] data, RSAEncryptionPadding padding) 在System.Security.Cryptography.RSACng.Encrypt(Byte [] data,RSAEncryptionPadding padding)
at My method 以我的方式
Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: Internal.Cryptography.CryptoThrowHelper + WindowsCryptographicException:
The requested operation is not supported 请求的操作不受支持
at Security.Cryptography.RSACng.EncryptOrDecrypt(SafeNCryptKeyHandle key, Byte[] input, AsymmetricPaddingMode paddingMode, Void* paddingInfo, EncryptOrDecryptAction encryptOrDecrypt) 在Security.Cryptography.RSACng.EncryptOrDecrypt(SafeNCryptKeyHandle密钥,Byte []输入,AsymmetricPaddingMode paddingMode,Void * paddingInfo,EncryptOrDecryptAction cryptoOrDecrypt)
at System.Security.Cryptography.RSACng.EncryptOrDecrypt(Byte[] data, RSAEncryptionPadding padding, EncryptOrDecryptAction encryptOrDecrypt) 在System.Security.Cryptography.RSACng.EncryptOrDecrypt(Byte []数据,RSAEncryptionPadding填充,EncryptOrDecryptAction加密或解密)
at System.Security.Cryptography.RSACng.Encrypt(Byte[] data, RSAEncryptionPadding padding) 在System.Security.Cryptography.RSACng.Encrypt(Byte [] data,RSAEncryptionPadding padding)
at My method 以我的方式
I've also tried the private key's SignData method, resulting in the same exceptions : 我还尝试了私钥的SignData方法,导致了相同的异常:
encryptedFile = privateKey.SignData(hashToSign, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
Am I missing something ? 我想念什么吗?
Please note that, as I'm working in an UWP application, I can only access some of the System.Security namespace . 请注意,当我在UWP应用程序中工作时,我只能访问一些System.Security名称空间 。
I found a solution to my issues, it was due to these two mistakes : 我找到了解决问题的方法,这是由于以下两个错误:
First, the encryption method to use here isn't Encrypt but SignData , since I want to electronically sign the data. 首先,这里使用的加密方法不是Encrypt而是SignData ,因为我想对数据进行电子签名。
Second, in order to make a valid signature, the certificate needs to contain the Non-Repudation extension. 其次,为了进行有效签名,证书需要包含“ 不可否认”扩展名。 To check that, I've added this method : 为了确认这一点,我添加了以下方法:
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;
}
I now fetch the certificates using the following : 我现在使用以下方法获取证书:
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;
}
One thing that I still don't understand is why the SignData method doesn't throw any exception and did sign the data when the certificate is fetched from a pfx file and not from the store. 我仍然不明白的一件事是,当从pfx文件而不是从存储中获取证书时,为什么SignData方法不会引发任何异常并对数据进行签名。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.