.Net,XmlDSigEx:使用X509Certificate2中的公钥的CngKey.import

时间:2011-12-21 12:26:10

标签: .net x509certificate cng

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

1 个答案:

答案 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);