在 .NET Core 中使用 CMS 和 RSACng 进行签名
Signing with CMS and RSACng in .NET Core
似乎CNG取代了.NET Core中的CSP
如前所述 here:
This method is only supported on .NET Framework. Its use on .NET Core
throws a PlatformNotSupportedException.
但是 CmsSigner 没有公开任何 API 来支持 CNG 密钥,例如,没有像 CngParameters
这样的东西来指定用于签名的 CNG 密钥。
当我在 .NET Framework 中使用 CmsSigner(CspParameters)
时,它会创建一个用于签名的虚拟证书。
我试过这个只是为了看看会发生什么:
var signer = new CmsSigner();
signer.PrivateKey = new RSACng(CngKey.Open("rsaKey"));
signer.SignedAttributes.Add(new Pkcs9SigningTime());
var signedCms = new SignedCms(new ContentInfo(new byte[] { 1, 2, 3 }), false);
signedCms.ComputeSignature(signer);
var encodeByteBlock = signedCms.Encode();
但它在 ComputeSignature
调用中抛出了这个异常:
System.InvalidOperationException: 'No signer certificate was
provided.'
在 .NET Framework 中,我可以这样做:
var cspObj = new CspParameters()
{
ProviderName = "provider",
ProviderType = 1,
KeyNumber = (int)KeyNumber.Signature,
Flags = CspProviderFlags.UseExistingKey,
KeyContainerName = "ContainerName"
};
var signer = new CmsSigner(cspObj)
{
DigestAlgorithm = new Oid(_signerHashAlgorithmOid)
};
signer.SignedAttributes.Add(new Pkcs9SigningTime());
var signedCms = new SignedCms(contentInfo, true);
signedCms.ComputeSignature(signer);
var encodeByteBlock = signedCms.Encode();
对于 .NET Core 实现,您需要提供带有绑定私钥的证书。如果证书对您的目的不重要,您可以创建自己的虚拟证书。此示例使用 RSA-SHA256,而 .NET Framework 中的 CspParameters 版本使用 RSA-SHA1,但其他方面基本相同。
using (CngKey cngKey = CngKey.Open(...))
using (RSA rsa = new RSACng(cngKey))
{
CertificateRequest req = new CertificateRequest(
"CN=CMS Signer Dummy Certificate",
rsa,
HashAlgorithmName.SHA256,
RSASignaturePadding.Pkcs1);
DateTimeOffset now = DateTimeOffset.UtcNow;
using (X509Certificate2 cert = req.CreateSelfSigned(now, now.AddYears(1)))
{
CmsSigner signer = new CmsSigner(cert);
...
}
}
似乎CNG取代了.NET Core中的CSP 如前所述 here:
This method is only supported on .NET Framework. Its use on .NET Core throws a PlatformNotSupportedException.
但是 CmsSigner 没有公开任何 API 来支持 CNG 密钥,例如,没有像 CngParameters
这样的东西来指定用于签名的 CNG 密钥。
当我在 .NET Framework 中使用 CmsSigner(CspParameters)
时,它会创建一个用于签名的虚拟证书。
我试过这个只是为了看看会发生什么:
var signer = new CmsSigner();
signer.PrivateKey = new RSACng(CngKey.Open("rsaKey"));
signer.SignedAttributes.Add(new Pkcs9SigningTime());
var signedCms = new SignedCms(new ContentInfo(new byte[] { 1, 2, 3 }), false);
signedCms.ComputeSignature(signer);
var encodeByteBlock = signedCms.Encode();
但它在 ComputeSignature
调用中抛出了这个异常:
System.InvalidOperationException: 'No signer certificate was provided.'
在 .NET Framework 中,我可以这样做:
var cspObj = new CspParameters()
{
ProviderName = "provider",
ProviderType = 1,
KeyNumber = (int)KeyNumber.Signature,
Flags = CspProviderFlags.UseExistingKey,
KeyContainerName = "ContainerName"
};
var signer = new CmsSigner(cspObj)
{
DigestAlgorithm = new Oid(_signerHashAlgorithmOid)
};
signer.SignedAttributes.Add(new Pkcs9SigningTime());
var signedCms = new SignedCms(contentInfo, true);
signedCms.ComputeSignature(signer);
var encodeByteBlock = signedCms.Encode();
对于 .NET Core 实现,您需要提供带有绑定私钥的证书。如果证书对您的目的不重要,您可以创建自己的虚拟证书。此示例使用 RSA-SHA256,而 .NET Framework 中的 CspParameters 版本使用 RSA-SHA1,但其他方面基本相同。
using (CngKey cngKey = CngKey.Open(...))
using (RSA rsa = new RSACng(cngKey))
{
CertificateRequest req = new CertificateRequest(
"CN=CMS Signer Dummy Certificate",
rsa,
HashAlgorithmName.SHA256,
RSASignaturePadding.Pkcs1);
DateTimeOffset now = DateTimeOffset.UtcNow;
using (X509Certificate2 cert = req.CreateSelfSigned(now, now.AddYears(1)))
{
CmsSigner signer = new CmsSigner(cert);
...
}
}