在证书库中的客户端证书不(Using client certificate not in certi

2019-09-02 05:32发布

我想我自己反对使用我的客户端证书的WebService身份验证,但是,由于种种原因(我解释一下),我不希望从存储区加载证书,而从磁盘读取它。

下列:

// gw is teh WebService client
X509Certificate cert = new X509Certificate(PathToCertificate);
_gw.ClientCertificates.Add(ClientCertificate());
ServicePointManager.ServerCertificateValidationCallback = (a,b,c,d) => true;
_gw.DoSomeCall();

总是返回403 - 服务没有授权我。 但是,当我保存证书到的CertStore,它的工作原理。 (如在MSDN说明。)

是否有可能使用证书不是在商店?

(原因是,我得到Windows服务(客户端)有时调用Web服务(服务器),以及时间不详量后,在服务“忘记”我的证书和犯规授权对服务器,没有明显的理由)

Answer 1:

什么类型的文件是PathToCertificate? 如果它只是一个.CER文件,它将不包含证书的私钥,并尝试使用该证书的SSL / TLS将失败。

不过,如果你有一个包括证书的公钥和私钥一个PKCS7或PKCS12文件,你的代码就可以了(你可能需要使用,需要一个密码,如果私钥有一个过载)。

为了测试这个,我去http://www.mono-project.com/UsingClientCertificatesWithXSP并创建了client.p12文件遵循着这些指导。 我还创建使用HttpListener用于测试的简单HTTPS服务器。

然后,我整理了以下程序为“client.exe”并运行,如:

 client.exe https://<MYSSLSERVER>/ client.p12 password

其中client.p12是之前和“密码”产生的PKCS12文件是我的证书的私钥设置密码。

using System;
using System.IO;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Text;

public class HttpWebRequestClientCertificateTest : ICertificatePolicy {

    public bool CheckValidationResult (ServicePoint sp, X509Certificate certificate,
            WebRequest request, int error)
    {
            return true; // server certificate's CA is not known to windows.
    }

    static void Main (string[] args)
    {
            string host = "https://localhost:1234/";
            if (args.Length > 0)
                    host = args[0];

            X509Certificate2 certificate = null;
            if (args.Length > 1) {
                    string password = null;
                    if (args.Length > 2)
                            password = args [2];
                    certificate = new X509Certificate2 (args[1], password);
            }

            ServicePointManager.CertificatePolicy = new HttpWebRequestClientCertificateTest ();

            HttpWebRequest req = (HttpWebRequest) WebRequest.Create (host);
            if (certificate != null)
                    req.ClientCertificates.Add (certificate);

            WebResponse resp = req.GetResponse ();
            Stream stream = resp.GetResponseStream ();
            StreamReader sr = new StreamReader (stream, Encoding.UTF8);
            Console.WriteLine (sr.ReadToEnd ());
    }
}

让我知道如果你要我载的服务器代码,并在测试中双方使用的证书。



Answer 2:

潜在的问题可能是SSL会话(Schannel中的高速缓存)的缓存。 只有第一个请求协商SSL握手。 后续请求将使用相同的会话ID,并希望服务器接受它。 如果服务器清除会话ID,请求将失败,403错误。 要禁用本地SSL会话缓存(并迫使每个请求SSL协商),你必须打开Windows的注册表文件夹:

[HKEY_LOCAL_MACHINE] [系统] [CURRENTCONTROLSET] [控制] [SecurityProviders] [SCHANNEL]

并添加一个名为ClientCacheTime(DWORD)值为0的关键。

这个问题是这里介绍:

http://support.microsoft.com/?id=247658



Answer 3:

您有至少两个问题的潜力......

第一...

您的客户端证书文件不能包含一个私钥,除非它使用密码进行访问。 您应该使用一个PKCS#12(* .PFX)证书用的密码,这样您的客户端访问私钥。 你的客户端代码将打开证书时,因为其他人已经发布提供密码。 有几种方法来创建此,最简单的方法是使用下面的命令行,首先生成证书,然后使用MMC证书管理器导出证书私钥:

Process p = Process.Start(
    "makecert.exe",
    String.Join(" ", new string[] {
        "-r",//                     Create a self signed certificate
        "-pe",//                    Mark generated private key as exportable
        "-n", "CN=" + myHostName,// Certificate subject X500 name (eg: CN=Fred Dews)
        "-b", "01/01/2000",//       Start of the validity period; default to now.
        "-e", "01/01/2036",//       End of validity period; defaults to 2039
        "-eku",//                   Comma separated enhanced key usage OIDs
        "1.3.6.1.5.5.7.3.1," +//    Server Authentication (1.3.6.1.5.5.7.3.1)
        "1.3.6.1.5.5.7.3.2", //     Client Authentication (1.3.6.1.5.5.7.3.2)
        "-ss", "my",//              Subject's certificate store name that stores the output certificate
        "-sr", "LocalMachine",//    Subject's certificate store location.
        "-sky", "exchange",//       Subject key type <signature|exchange|<integer>>.
        "-sp",//                    Subject's CryptoAPI provider's name
        "Microsoft RSA SChannel Cryptographic Provider",
        "-sy", "12",//              Subject's CryptoAPI provider's type
        myHostName + ".cer"//       [outputCertificateFile]
    })
);

第二...

你的下一个问题将是服务器端。 服务器必须允许此证书。 你有正确的逻辑,但在电线上的错误的一边,移动这条线到Web服务器处理请求。 如果不能,则必须采取以上保存到服务器的“.CER”文件并将其添加到服务器计算机的信任列表:

ServicePointManager.ServerCertificateValidationCallback = (a,b,c,d) => true;


Answer 4:

你需要一个证书密码? 如果是这样,则在构造它的字段。

X509Certificate cert = new X509Certificate(PathToCertificate,YourPassword);


文章来源: Using client certificate not in certificate store