1

我正在编写一个简单的示例代码来演示如何使用 X509 证书进行加密和解密。

public static byte[] Encrypt(byte[] content, X509Certificate2Collection encryptingCertificates)
    {
        if (content == null)
        {
            throw new ApplicationException("NullContent");
        }
        if (encryptingCertificates == null || encryptingCertificates.Count == 0)
        {
            throw new ApplicationException("NoCertificates");
        }

        CmsRecipientCollection recipients = new CmsRecipientCollection(SubjectIdentifierType.IssuerAndSerialNumber, encryptingCertificates);
        EnvelopedCms dataEnvelope = new EnvelopedCms(new ContentInfo(new Oid("1.2.840.113549.1.7.1"), content), new AlgorithmIdentifier(new Oid("2.16.840.1.101.3.4.1.2")));
        dataEnvelope.Encrypt(recipients);

        return dataEnvelope.Encode();
    }

public static byte[] Decrypt(byte[] encryptedContent, X509Certificate2Collection decryptingCertificates)
    {
        if (decryptingCertificates == null || decryptingCertificates.Count == 0)
        {
            throw new ApplicationException("NoCertificates");
        }

        EnvelopedCms dataEnvelope = new EnvelopedCms();

        dataEnvelope.Decode(encryptedContent);
        dataEnvelope.Decrypt(decryptingCertificates);

        ContentInfo contentInfo = dataEnvelope.ContentInfo;

        return contentInfo.Content;
    }

我遇到了一个问题 - 必须解密的代码(dataEnvelope.Decrypt(decryptingCertificates))抛出 CryptographicException:访问被拒绝。

CryptographicException: Access denied.
   at System.Security.Cryptography.Pkcs.EnvelopedCms.DecryptContent(RecipientInfoCollection recipientInfos, X509Certificate2Collection extraStore)
   at CertificateTestingTool.CertificateResolver.Decrypt(Byte[] encryptedContent, X509Certificate2Collection decryptingCerti
ficates)
   at CertificateTestingTool.Program.Main(String[] args)

它发生在 windows server 2012 和 windows 8 上。我已经在 win server 2008 和 win 7 上检查了此代码,它工作正常。

附加信息:我不使用 PKI,我从文件夹 (X509Certificate2Collection.Import(...)) 中使用私钥导入 *.pfx 文件,并且它已成功导入。

public static X509Certificate2Collection GetCertificates(string certPath, string password)
    {
        X509Certificate2Collection certs = null;
        var logger = Log.Logger;
        certs = new X509Certificate2Collection();
        var flags = X509KeyStorageFlags.DefaultKeySet;
        certs.Import(certPath, password, flags);

        return certs;
    }

有人可以帮我吗?据我了解,在新的操作系统版本中引入了一些权限规则。

4

1 回答 1

1

此问题是由于调用 API CryptMsgControl 时发生异常引起的。

为什么win7能用,win8不能用?

这是因为代码导入的证书使用的是 KeySpec AT_SIGNATURE。这不是加密/解密的正确规范。它是用来签名的。AT_KEYEXCHANGE 适合此目的。

在 Win7 中,由于解析遗留 CAPI 密钥的特定实现没有严格执行来自 KeySpec 的密钥用法,因此不正确的规范起作用。因此,AT_SIGNATURE 允许加密/解密使用。

为了解决这个问题,我们需要使用 certutil 命令工具导入证书,命令如下:

certutil -user –p -importpfx 我的 AT_KEYEXCHANGE

我们只需要确保 pfx 文件的 KeySpec 设置为 1 (AT_KEYEXCHANGE)。要检查这一点,我们可以使用命令 certutil.exe -dump -v xyz.pfx

当我们使用指定了 KeySpec AT_KEYEXCHANGE 的 certutil 导入 pfx 时,我们正在修改 pfx 文件的 KeySpec 属性。之后,我们可以再次将其导出为 pfx 文件,然后我们可以使用上面提到的命令再次检查 KeySpec,我们会看到 KeySpec 更改为 AT_KEYEXCHANGE。

您可以在此处找到更多详细信息

于 2013-12-11T14:21:40.257 回答