web-dev-qa-db-ja.com

HttpWebRequestにクライアント証明書を送信させる

私はp12証明書を持っています。これを次のようにロードします。

_X509Certificate2 certificate = new X509Certificate2(certName, password,
        X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet |
        X509KeyStorageFlags.Exportable);
_

それは正しくロードされます。実際、私がcertificate.PrivateKey.ToXmlString(true);を実行すると、エラーなしで完全なxmlが返されます。しかし、私がするなら:

_try
{
    X509Chain chain = new X509Chain();
    var chainBuilt = chain.Build(certificate);
    Console.WriteLine("Chain building status: "+ chainBuilt);

    if (chainBuilt == false)
        foreach (X509ChainStatus chainStatus in chain.ChainStatus)
            Console.WriteLine("Chain error: "+ chainStatus.Status);
}
catch (Exception ex)
{
    Console.WriteLine(ex);
}
_

それは書きます:

_Chain building status: False
Chain error: RevocationStatusUnknown 
Chain error: OfflineRevocation 
_

だから私がするとき:

_        ServicePointManager.CheckCertificateRevocationList = false;
    ServicePointManager.ServerCertificateValidationCallback = (a, b, c, d) => true;
    ServicePointManager.Expect100Continue = true;
    Console.WriteLine("connessione a:" + Host);
    HttpWebRequest req = (HttpWebRequest)WebRequest.Create(Host);
    req.PreAuthenticate = true;
    req.AllowAutoRedirect = true;
    req.ClientCertificates.Add(certificate);
    req.Method = "POST";
    req.ContentType = "application/x-www-form-urlencoded";
    string postData = "login-form-type=cert";
    byte[] postBytes = Encoding.UTF8.GetBytes(postData);
    req.ContentLength = postBytes.Length;
    Stream postStream = req.GetRequestStream();
    postStream.Write(postBytes, 0, postBytes.Length);
    postStream.Flush();
    postStream.Close();

    WebResponse resp = req.GetResponse();
_

サーバーは、証明書が送信されていない/有効でないと言っています。

私の質問は:

  • チェーンビルドがfalseでも証明書を送信するにはどうすればよいですか?
  • 送信する前に証明書の検証をチェックしない証明書を投稿する別のクラスがありますか?

どうもありがとう。アントニーノ

7
Perry

問題を解決しました。ポイントは、P12ファイル(PFXとして)に複数の証明書が含まれているため、次のようにロードする必要があることです。

X509Certificate2Collection certificates = new X509Certificate2Collection();
certificates.Import(certName, password, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);

次のようにHttpWebRequestに追加されます:request.ClientCertificates = certificates;

応援してくれてありがとう。

完全なサンプルコード

string Host = @"https://localhost/";
string certName = @"C:\temp\cert.pfx";
string password = @"password";

try
{
    X509Certificate2Collection certificates = new X509Certificate2Collection();
    certificates.Import(certName, password, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);

    ServicePointManager.ServerCertificateValidationCallback = (a, b, c, d) => true;
    HttpWebRequest req = (HttpWebRequest)WebRequest.Create(Host);
    req.AllowAutoRedirect = true;
    req.ClientCertificates = certificates;
    req.Method = "POST";
    req.ContentType = "application/x-www-form-urlencoded";
    string postData = "login-form-type=cert";
    byte[] postBytes = Encoding.UTF8.GetBytes(postData);
    req.ContentLength = postBytes.Length;

    Stream postStream = req.GetRequestStream();
    postStream.Write(postBytes, 0, postBytes.Length);
    postStream.Flush();
    postStream.Close();
    WebResponse resp = req.GetResponse();

    Stream stream = resp.GetResponseStream();
    using (StreamReader reader = new StreamReader(stream))
    {
        string line = reader.ReadLine();
        while (line != null)
        {
            Console.WriteLine(line);
            line = reader.ReadLine();
        }
    }

    stream.Close();
}
catch(Exception e)
{
    Console.WriteLine(e);
}
13
Perry

問題は、ローカルシステムアカウントで実行されていない、または明示的な秘密キーのアクセス許可を持たないプロセスのクライアント認証に通常は使用できない秘密キーをマシンストアにインストールすることです。現在のユーザーストアにキーをインストールする必要があります。

X509Certificate2 certificate = new X509Certificate2(certName, password,
        X509KeyStorageFlags.UserKeySet | X509KeyStorageFlags.PersistKeySet |
        X509KeyStorageFlags.Exportable);
1
Crypt32

IEからエクスポートされた秘密キーを含むpfx証明書を使用して、コードの修正バージョンを使用してコマンドラインプログラムを作成しました。安全なWebサイトに認証して保護されたページを取得できます。

string Host = @"https://localhost/";
string certName = @"C:\temp\cert.pfx";
string password = @"password";

try
{
    X509Certificate2 certificate = new X509Certificate2(certName, password);

    ServicePointManager.CheckCertificateRevocationList = false;
    ServicePointManager.ServerCertificateValidationCallback = (a, b, c, d) => true;
    ServicePointManager.Expect100Continue = true;
    HttpWebRequest req = (HttpWebRequest)WebRequest.Create(Host);
    req.PreAuthenticate = true;
    req.AllowAutoRedirect = true;
    req.ClientCertificates.Add(certificate);
    req.Method = "POST";
    req.ContentType = "application/x-www-form-urlencoded";
    string postData = "login-form-type=cert";
    byte[] postBytes = Encoding.UTF8.GetBytes(postData);
    req.ContentLength = postBytes.Length;

    Stream postStream = req.GetRequestStream();
    postStream.Write(postBytes, 0, postBytes.Length);
    postStream.Flush();
    postStream.Close();
    WebResponse resp = req.GetResponse();

    Stream stream = resp.GetResponseStream();
    using (StreamReader reader = new StreamReader(stream))
    {
        string line = reader.ReadLine();
        while (line != null)
        {
            Console.WriteLine(line);
            line = reader.ReadLine();
        }
    }

    stream.Close();
}
catch(Exception e)
{
    Console.WriteLine(e);
}
1
sly