【问题标题】:Encrypt data with X509 certificate's private key in UWP在 UWP 中使用 X509 证书的私钥加密数据
【发布时间】:2017-11-18 02:31:45
【问题描述】:

我正在向用户显示他个人商店中的所有可用证书,使用以下方法获取:

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[] 输入, AsymmetricPaddingMode paddingMode, Void* paddingInfo, EncryptOrDecryptAction encryptOrDecrypt)

在 System.Security.Cryptography.RSACng.EncryptOrDecrypt(Byte[] 数据, RSAEncryptionPadding 填充,EncryptOrDecryptAction encryptOrDecrypt)

在 System.Security.Cryptography.RSACng.Encrypt(Byte[] 数据, RSAEncryptionPadding 填充)

我的方法

  • 当我使用 USB 密钥中的证书时:

Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException:

不支持请求的操作

在 Security.Cryptography.RSACng.EncryptOrDecrypt(SafeNCryptKeyHandle key, Byte[] 输入, AsymmetricPaddingMode paddingMode, Void* paddingInfo, EncryptOrDecryptAction encryptOrDecrypt)

在 System.Security.Cryptography.RSACng.EncryptOrDecrypt(Byte[] 数据,RSAEncryptionPadding 填充,EncryptOrDecryptAction 加密或解密)

在 System.Security.Cryptography.RSACng.Encrypt(Byte[] data, RSAEncryptionPadding padding)

我的方法

我也尝试过私钥的 SignData 方法,导致同样的异常:

encryptedFile = privateKey.SignData(hashToSign, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);

我错过了什么吗?

请注意,由于我正在使用 UWP 应用程序,因此我只能访问 some of the System.Security namespace

【问题讨论】:

  • 您是否尝试过使用 OaepSha1 而不是 OaepSha256?试图缩小问题的可能范围。
  • 不幸的是,我使用 OaepSha1 和 Pkcs1 得到了相同的结果。
  • @ThomasFerro 您应该使用 PublicKey 加密某些东西,并使用 PrivateKey 解密。
  • @pepi 我要在这里对数据进行数字签名,所以重点不是让这些数据不可读。相反,目标是能够证明给定用户使用他的公钥解密数据来签署文档。

标签: c# encryption uwp x509certificate2


【解决方案1】:

我找到了解决问题的方法,这是由于这两个错误:

首先,这里使用的加密方法不是Encrypt,而是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 获取证书时不会抛出任何异常并且确实对数据进行了签名文件而不是来自商店。

【讨论】:

  • 可能是商店中的密钥应用了一些权限/限制,这些权限/限制要么没有导出到 PFX,要么 PFX 来自在权限设置之前。
猜你喜欢
  • 1970-01-01
  • 2018-07-19
  • 2017-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-06
  • 2023-04-02
相关资源
最近更新 更多