我在使用已安装的证书签署 xml 文档时遇到问题。我已经尝试使用证书文件 (.pfx) 将证书安装在 X509Certificate2 的 LocalMachine、CurrentUser 和 Initialize 实例中。每个都有自己的问题;我的偏好是使用安装在 LocalMachine 商店中的证书。下面我概述了三种方法以及每种方法的关注点:
StoreLocation LocalMachine - 首选方法
var certStore = new X509Store(StoreLocation.LocalMachine);
certStore.Open(OpenFlags.ReadOnly);
var certCollection = certStore.Certificates.Find(X509FindType.FindByThumbprint, certificateThumbPrint, true);
var myCert = certCollection[0];
// I can get the correct certificate but the following line throws "Invalid provider type specified." error
var SigningKey = myCert.PrivateKey;
存储位置 CurrentUser
var certStore = new X509Store(StoreLocation.CurrentUser);
certStore.Open(OpenFlags.ReadOnly);
var certCollection = certStore.Certificates.Find(X509FindType.FindByThumbprint, certificateThumbPrint, true);
var myCert = certCollection[0];
// I can get the correct certificate but the following line throws "Keyset does not exist" error
var SigningKey = myCert.PrivateKey;
如果我将权限更改为以下文件夹 %ALLUSERSPROFILE%\Application Data\Microsoft\Crypto\RSA\MachineKeys,我只能获取 PrivateKey。这看起来不是实现签名的正确方法。
使用证书文件
var certificateFile = @"C:\CertificateFolder\AuthorizedCertificate.pfx";
var myCert = new X509Certificate2(certificateFile, password, X509KeyStorageFlags.UserKeySet);
此方法有效,但是我必须提供不需要的证书文件和密码。
我怎样才能让第一种方法(LocalMachine)起作用?推荐/最佳实践方法是什么?
作为参考,以下代码用于签署 xml 文档
private void SignXml(XmlDocument xmlDoc, X509Certificate2 cert)
{
// Create a SignedXml object.
SignedXml signedXml = new SignedXml(xmlDoc);
// Add the key to the SignedXml document.
signedXml.SigningKey = cert.PrivateKey;
// Create a reference to be signed.
Reference reference = new Reference();
reference.Uri = "";
// Add an enveloped transformation to the reference.
var env = new XmlDsigEnvelopedSignatureTransform();
reference.AddTransform(env);
// Include the public key of the certificate in the assertion.
signedXml.KeyInfo = new KeyInfo();
signedXml.KeyInfo.AddClause(new KeyInfoX509Data(cert, X509IncludeOption.WholeChain));
// Add the reference to the SignedXml object.
signedXml.AddReference(reference);
// Compute the signature.
signedXml.ComputeSignature();
// Get the XML representation of the signature and save
// it to an XmlElement object.
XmlElement xmlDigitalSignature = signedXml.GetXml();
// Append the element to the XML document.
xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, true));
}