0

インストールされた証明書でxml文書に署名する際に問題があります。私は、証明書ファイル(.pfx)を使用してX509Certificate2のLocalMachine、CurrentUser、およびInitializeインスタンスにインストールされた証明書で試しました。それぞれには独自の問題があります。私の好みは、LocalMachineストアにインストールされている証明書を使用することです。私は三つの方法とそれぞれに懸念概説している下:X.509証明書がインストールされたXML文書に署名する

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; 

StoreLocationある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; 

私は場合、私は唯一のPrivateKeyを取得することができます権限を以下のフォルダ%ALLUSERSPROFILE%¥Application Data¥Microsoft¥Crypto¥RSA¥MachineKeysに変更します。これは、署名を実装する正しい方法を見ていない。

var certificateFile = @"C:\CertificateFolder\AuthorizedCertificate.pfx"; 
var myCert = new X509Certificate2(certificateFile, password, X509KeyStorageFlags.UserKeySet); 

証明書ファイルを使用して、この方法は、私は証明書ファイルと望ましいではありません、パスワードを提供する必要があると思いますが動作します。

最初のメソッド(LocalMachine)を動作させるにはどうすればよいですか?これを行うには、推奨/ベストプラクティスの方法は何ですか?

は参考のために、以下のコードは

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)); 
} 

答えて

0

LOCALMACHINEストアバージョン

XML文書に署名するために使用される

var SigningKey = myCert.GetRSAPrivateKey(); 

var SigningKey = myCert.PrivateKey; 

を交換

(S/RSA/DSA /適宜)

PrivateKeyのプロパティのみRSACryptoServiceProviderまたはDSACryptoServiceProviderにキャストされたキーを返すことができます。 「無効なプロバイダタイプが指定されています」とは、秘密キーがCAPIではなくCNGに格納されていることを意味します。

これは、.NET 4.6.2以降がインストールされている場合にのみ有効です。これは、SignedXmlおよびそのヘルパークラス内の特定の制限(RSAC非対応のRSAに関するRSA)が修正されたためです。

(代替:OSは、この問題を解決するためにCNGブリッジにCAPIを追加のWindows 10にアップグレード)

あるCurrentUserストアのバージョン

あなたはPFXから証明書をインポートするときにインポートしているため、このバージョンでは失敗しますそれはMachineKeySetで(またはあなたがUserKeySetを指定しなかったので、それは以前にマシンキーストアからエクスポートされていました)。ユーザーストア内の証明書のコピーには、マシンストア内の秘密キーの寿命が記載されています。そして何らかの理由で、あなたはそれにアクセスできません。 (「何らかの理由で」通常はあなたがそれを追加できなかったことを示唆しているからです...PFX証明書のPrivateKeyプロパティが機能するように、(PFXesは、メタデータの多くを運ぶ)キーがCAPI CSPに格納されるべきであると言うので)

PFXバージョン

これは動作します。

+0

ありがとうございます。 myCert.GetRSAPrivateKey()は.NET Framework 4.6.1で動作しましたが、コードの別の部分(signedXml.ComputeSignature())で次のエラーが発生しました。 System.NotSupportedExceptionメソッドがサポートされていません。 System.Security.Cryptography.RSA.DecryptValue(Byte [] rgb)のByte [] DecryptValue(Byte []) at System.Security.Cryptography.Xml.SignedXml.ComputeSignature() – imran

+0

@imran 4.6.2を必要とする答えに説明されています。 – bartonjs

関連する問題