我正在尝试验证已使用ECDsa算法签名的XML签名。我的工作基于XmlDSigEx库,我必须稍微修改以满足我的需求。 我目前的问题与从证书中获取公钥并将其用作CngKey有关。我用过:
// var cert = X509Certificate2 ...
var key = CngKey.Import(cert.GetPublicKey(), CngKeyBlobFormat.EccPublicBlob);
抛出“参数不正确”。我找不到任何预期将公钥格式作为密钥传递的信息。因此,我请求帮助解决此问题:如何将存储在X509Certificate中的公钥传递给CngKey?
TIA, 阿洛伊斯
PS:我考虑过使用BouncyCastle来提取公钥。我试过BC的
X509Certificate.CertificateStructure.SubjectPublicKeyInfo.GetEncoded()
以及
X509Certificate.CertificateStructure.SubjectPublicKeyInfo.PublicKeyData.GetBytes()
将密钥传递给CngKey;但是会出现同样的错误。
答案 0 :(得分:0)
我一直在与同一类型的问题作斗争,但是使用BouncyCastle进行C#并尝试将密钥导入CngKey。 ECDsaCng支持RFC4050 XML格式进行公钥导入。我已经设法使用下面的代码导入使用BouncyCastle生成的密钥,并验证使用BouncyCastle生成的ECDsaCng的哈希值。
//Specify which curve we are using
string theCurveName = "prime256v1";
X509Certificate2 x509cert = null; //get your x509 certificate here...
//BouncyCastle publickey creation from certificate publickey
var namedCurve = X962NamedCurves.GetByName(theCurveName);
ECPublicKeyParameters publickey = new ECPublicKeyParameters("ECDSA",
namedCurve.Curve.DecodePoint(x509cert.GetPublicKey()), // Q
X962NamedCurves.GetOid(theCurveName));
//now we have the public key in bouncy castle
//we can create the xml to import to CngKey
//Prime256v1 = 1.2.840.10045.3.1.7
var xmlImport = @"<ECDSAKeyValue xmlns='http://www.w3.org/2001/04/xmldsig-more#'>
<DomainParameters>
<NamedCurve URN='urn:oid:" + X962NamedCurves.GetOid(theCurveName).Id + @"' />
</DomainParameters>
<PublicKey>
<X Value='" + publickey.Q.X.ToBigInteger().ToString() + @"' xsi:type='PrimeFieldElemType' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' />
<Y Value='" + publickey.Q.Y.ToBigInteger().ToString() + @"' xsi:type='PrimeFieldElemType' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' />
</PublicKey>
</ECDSAKeyValue>";
var eccImporter = new ECDsaCng();
eccImporter.FromXmlString(xmlImport, ECKeyXmlFormat.Rfc4050);
//prep bouncy castle signature to single array
var sig0 = sig[0].ToByteArrayUnsigned();
var sig1 = sig[1].ToByteArrayUnsigned();
byte[] newSig = new byte[sig0.Length + sig1.Length];
sig0.CopyTo(newSig, 0);
sig1.CopyTo(newSig, sig0.Length);
var isok = eccImporter.VerifyHash(manualhash, newSig);