2016-08-17 91 views
0

我在数字签名XML消息时遇到问题。要求规定ECDSA证书将与特定曲线一起使用。这意味着由该SignedXml.ComputeSignature(...)方法提供的RSA和DSA功能将没有创造的SignatureDescriptionAsymmetricSignatureFormatterAsymmetricSignatureDeformatter定制的实施工作。密钥不存在 - 使用自签名ECDSA证书

这就是说,并没有过多的代码我已经创建了一个简单的函数,应该拿一个证书,并使用其公钥签名数据使用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); 
    } 
} 

回答

2

您提取了公钥。然后将其导入到一个新容器中并称为Sign。由于需要私钥才能进行签名,因此引发了一个例外情况,指出私钥字段不存在。

你为什么要克隆的对象反正?只需拨打cert.GetECDsaPrivateKey()并使用该对象即可。

+0

我试过这个 var encryptingKey =(ECDsaCng)applicableCertificate.GetECDsaPrivateKey(); VAR导出=((ECDsaCng)encryptingKey).Key.Export(CngKeyBlobFormat.EccPrivateBlob);现在得到一个不同的异常“请求的操作不被支持。”我的印象是,我会加密与公众和接收器将验证对私钥? – Geek

+1

这就是加密的工作原理,是的;但签署是相反的。签名者使用私钥(只有他们拥有),验证者使用公共。但我仍然不明白你为什么要克隆这个对象(这对于一张智能卡来说不起作用)。 'cert.GetECDsaPrivateKey()。SignData(...)'(虽然using语句都不错) – bartonjs

+0

的最后注释是一个很好的指针,我拿出克隆,现在我可以签回一个签名。我现在剩下的唯一问题是如何将它应用于自定义的SignatureDescription,AsymmetricSignatureFormatter和AsymmetricSignatureDeformatter实现,然后创建Signature XML节点。 – Geek