3

我正在尝试验证已使用 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;但是会发生相同的错误。

4

1 回答 1

0

我一直在与相同类型的问题作斗争,但使用 C# 的 BouncyCastle 并尝试将密钥导入 CngKey。ECDsaCng 支持用于公钥导入的 RFC4050 XML 格式。我已经设法使用下面的代码导入使用 BouncyCastle 生成的密钥,并使用 ECDsaCng 验证由 BouncyCastle 生成的哈希。

//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);
于 2012-02-23T13:23:53.053 回答