0

我在对 XML 消息进行数字签名时遇到问题。要求规定 ECDSA 证书将与特定曲线一起使用。这意味着该SignedXml.ComputeSignature(...)方法提供的 RSA 和 DSA 功能如果不创建SignatureDescription,AsymmetricSignatureFormatterAsymmetricSignatureDeformatter.

话虽如此,并且没有发布大量代码,我创建了一个简单的函数,该函数应该获取证书并使用其公钥使用ECDsaCng类对数据进行签名,因为这就是我用来创建上述自定义实现的方法。

发生的情况是,即使使用我的自定义实现,我也会抛出异常“ 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);
    }
}
4

1 回答 1

2

您获取了公钥。然后将其导入一个新容器并调用 Sign。由于签名需要私钥,因此会抛出异常,指出私钥字段不存在。

你为什么要克隆对象呢?只需调用cert.GetECDsaPrivateKey()并使用该对象。

于 2016-08-17T14:12:03.047 回答