1

次のコードがあります

var factory = new ChannelFactory<INewsClient>();
factory.Credentials.ClientCertificate.Certificate = GetCertificate();
factory.Endpoint.Address = new EndpointAddress("https://blabla.com/myservice/");
var binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
factory.Endpoint.Binding = binding;
var channel = factory.CreateChannel();
channel.GetNews();

.NET 3.5 では動作しますが、.NET4.0 では動作しません。ビザールか?私が使用している証明書は、ローカル マシン (チェーンなし) で検証されません。3.5 では、クライアント証明書の有効性は SSL の確立には関係ありませんが、4.0 に移行すると、証明書は SSL に使用される前に検証されます。(CAPI2 イベント ログにエラーが表示されます)。醜い SecurityNegotiationException が発生します...

スタックトレース:

System.ServiceModel.Security.SecurityNegotiationException: 権限 'pep.uat.dialectpayments.com' で SSL/TLS の安全なチャネルを確立できませんでした。---> System.Net.WebException: 要求が中止されました: SSL/TLS セキュア チャネルを作成できませんでした。
   System.Net.HttpWebRequest.GetResponse() で
   System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply (TimeSpan タイムアウト) で
   --- 内部例外スタック トレースの終了 ---

サーバー スタック トレース:
   System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException (WebException webException、HttpWebRequest 要求、HttpAbortReason abortReason) で
   System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply (TimeSpan タイムアウト) で
   System.ServiceModel.Channels.RequestChannel.Request (メッセージ メッセージ、TimeSpan タイムアウト) で
   System.ServiceModel.Dispatcher.RequestChannelBinder.Request (メッセージ メッセージ、TimeSpan タイムアウト) で
   System.ServiceModel.Channels.ServiceChannel.Call (文字列アクション、Boolean oneway、ProxyOperationRuntime 操作、Object[] ins、Object[] outs、TimeSpan タイムアウト) で
   System.ServiceModel.Channels.ServiceChannelProxy.InvokeService (IMethodCallMessage methodCall、ProxyOperationRuntime 操作) で
   System.ServiceModel.Channels.ServiceChannelProxy.Invoke (IMessage メッセージ) で

[0] で例外が再スローされました:
   System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage (IMessage reqMsg、IMessage retMsg) で
   System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke (MessageData& msgData、Int32 型) で
   ConsoleApplication2.Program.INewsClient.Get() で
   d:\dev\ConsoleApplication2\Program.cs:line 44 の ConsoleApplication2.Program.Main(String[] args) で

私たちのセキュリティ アーキテクチャでは、証明書はサーバー上の LDAP ディレクトリに対して検証されるため、クライアントが完全なチェーンを知る必要はありません。

質問は、この新しい動作を無効にするにはどうすればよいですか?

4

1 に答える 1

1

わかりました、ここで私自身の答えを提供します...

一言で言えば、X509 の .NET 4 では非永続 CSP を使用できないようです。つまり、CSP が機能するには KeyContainerName が必要です。

私の GetCertificate() メソッドは次のことを行っていました: (つまり、非永続的)

var certificate = new X509Certificate2(@"C:\public.cer");
var rsa = RSA.Create();
rsa.FromXmlString("<RSAKeyValue>......</RSAKeyValue>");
certificate.PrivateKey = rsa;
return certificate;

これに変更すると、私のサンプルは 3.5 と 4.0 で動作します: (KeyContainerName を設定すると、暗号化フォルダーに物理的なエントリが作成されます)

var certificate = new X509Certificate2(@"C:\public.cer");
CspParameters parameters = new CspParameters { KeyContainerName = "KeyContainer" };
var rsa = new RSACryptoServiceProvider(parameters);
rsa.FromXmlString("<RSAKeyValue>......</RSAKeyValue>");
certificate.PrivateKey = rsa;
return certificate;

簡単にするために、秘密鍵を .pfx ファイルにエクスポートしようとしましたが、.NET 4.0 では最初の方法を使用できませんでしたが、.NET 3.5 では使用できました。どうも、.NET 4.0 では秘密鍵をエクスポートできません。このリンクは私がそれを修正するのに役立ちました。

それでも、ここで 3.5 と 4.0 の間で何が変わったのかを知っておくとよいでしょう。

于 2011-09-04T22:59:06.440 に答える