密钥不存在 - 使用自签名 ECDSA 证书
Key does not exist - using self signed ECDSA certificate
我对 XML 邮件进行数字签名时遇到问题。要求规定 ECDSA 证书要与特定曲线一起使用。这意味着如果不创建 SignatureDescription
、AsymmetricSignatureFormatter
和 AsymmetricSignatureDeformatter
.[=21 的自定义实现,SignedXml.ComputeSignature(...)
方法提供的 RSA 和 DSA 功能将无法工作=]
也就是说,在没有发布大量代码的情况下,我创建了一个简单的函数,它应该获取证书并使用其 public 密钥使用 ECDsaCng
class 对数据进行签名这就是我用来创建上述自定义实现的方法。
发生的情况是,即使使用我的自定义实现,我也会抛出异常“System.Security.Cryptography.CryptographicException: Key does not exist.
”。但是,如果我只是创建一个 CngKey
而不是导入它,它就可以工作。据我所见,这个异常被抛出了调用 internal static extern ErrorCode NCryptSignHash(...)
方法的代码,它位于 ncrypt.dll
所以我的问题是为什么抛出异常“System.Security.Cryptography.CryptographicException: Key does not exist.
”以及如何解决它。
[TestMethod]
public void CreateSignatureTest()
{
var request = "Some xml goes here...";
var store = new X509Store(StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
var certificates = store.Certificates;
var applicableCertificate = certificates.Cast<X509Certificate2>()
.FirstOrDefault(certificate => certificate.Subject.Contains("ECDSA_CERT_NAME"));
var encryptingKey = (ECDsaCng)applicableCertificate.GetECDsaPublicKey();
var exported = encryptingKey.Key.Export(CngKeyBlobFormat.EccPublicBlob);
var creationParameters = new CngKeyCreationParameters
{
ExportPolicy = CngExportPolicies.AllowPlaintextExport
};
using (CngKey objCngKey = CngKey.Import(exported, CngKeyBlobFormat.EccPublicBlob)) // This will throw a Key Does Not Exist Exception
//using (CngKey objCngKey = CngKey.Create(CngAlgorithm.ECDsaP256, null, creationParameters)) // This works...
{
//'Convert String to be signed to a byte array
var data = Encoding.Default.GetBytes(request);
//'Create a ECDsaCng Object
var ecdsa = new ECDsaCng(objCngKey);
//'Sign the string
var bSignature = ecdsa.SignData(data);
//'Convert Signature to Base64 string for better reading
var sSignature = Convert.ToBase64String(bSignature);
}
}
您获取了 public 密钥。然后将其导入到一个新容器中并调用 Sign。由于签名需要私钥,因此抛出一个异常,指出私钥字段不存在。
你为什么要克隆这个对象?只需调用 cert.GetECDsaPrivateKey()
并使用该对象即可。
我对 XML 邮件进行数字签名时遇到问题。要求规定 ECDSA 证书要与特定曲线一起使用。这意味着如果不创建 SignatureDescription
、AsymmetricSignatureFormatter
和 AsymmetricSignatureDeformatter
.[=21 的自定义实现,SignedXml.ComputeSignature(...)
方法提供的 RSA 和 DSA 功能将无法工作=]
也就是说,在没有发布大量代码的情况下,我创建了一个简单的函数,它应该获取证书并使用其 public 密钥使用 ECDsaCng
class 对数据进行签名这就是我用来创建上述自定义实现的方法。
发生的情况是,即使使用我的自定义实现,我也会抛出异常“System.Security.Cryptography.CryptographicException: Key does not exist.
”。但是,如果我只是创建一个 CngKey
而不是导入它,它就可以工作。据我所见,这个异常被抛出了调用 internal static extern ErrorCode NCryptSignHash(...)
方法的代码,它位于 ncrypt.dll
所以我的问题是为什么抛出异常“System.Security.Cryptography.CryptographicException: Key does not exist.
”以及如何解决它。
[TestMethod]
public void CreateSignatureTest()
{
var request = "Some xml goes here...";
var store = new X509Store(StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
var certificates = store.Certificates;
var applicableCertificate = certificates.Cast<X509Certificate2>()
.FirstOrDefault(certificate => certificate.Subject.Contains("ECDSA_CERT_NAME"));
var encryptingKey = (ECDsaCng)applicableCertificate.GetECDsaPublicKey();
var exported = encryptingKey.Key.Export(CngKeyBlobFormat.EccPublicBlob);
var creationParameters = new CngKeyCreationParameters
{
ExportPolicy = CngExportPolicies.AllowPlaintextExport
};
using (CngKey objCngKey = CngKey.Import(exported, CngKeyBlobFormat.EccPublicBlob)) // This will throw a Key Does Not Exist Exception
//using (CngKey objCngKey = CngKey.Create(CngAlgorithm.ECDsaP256, null, creationParameters)) // This works...
{
//'Convert String to be signed to a byte array
var data = Encoding.Default.GetBytes(request);
//'Create a ECDsaCng Object
var ecdsa = new ECDsaCng(objCngKey);
//'Sign the string
var bSignature = ecdsa.SignData(data);
//'Convert Signature to Base64 string for better reading
var sSignature = Convert.ToBase64String(bSignature);
}
}
您获取了 public 密钥。然后将其导入到一个新容器中并调用 Sign。由于签名需要私钥,因此抛出一个异常,指出私钥字段不存在。
你为什么要克隆这个对象?只需调用 cert.GetECDsaPrivateKey()
并使用该对象即可。