備忘録

備忘録

C#でPublic Key Pinningする

Ⅰ. はじめに

Public Key Pinningとは、SSL証明書のチェックを行うことです。
チェックを行うことで、不正な証明書を検知することができます。

例えばクラッカーはMITMを利用して傍受を試みます。
MITMを利用するとSSL証明書が書き換わる為、
不正な証明書であれば通信を行わないようにすることが出来ます。

Ⅱ. プログラム

Program.cs
ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(OnRemoteCertificateValidationCallback);
CertificateValidation.cs
public static bool OnRemoteCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
  var hashs = new Dictionary<string, string>()
  {
    { "aaa.jp", "6c276e0c4e2fa19d1656df1298d8ff6497d0cc49" },
    { "aab.jp", "7dfc0fd1abf2af11dd2f9503448009f090d529eb" },
    { "aac.jp", "bb1d931851cc679a476021494550573eb1e1148d" }
  };

  if (hashs.ContainsValue(certificate.GetCertHashString().ToLower()))
  {
    // 通信を許可する
    return true;
  }
  else
  {
    // 通信を許可しない
    return false;
  }
}

SSL証明書ハッシュ値は、SSL証明書の「拇印」の値を使います
f:id:kagasu:20170310145511p:plain

「拇印」のコピーについて

「拇印」をそのままコピーするとデータ先頭に謎のデータが付加されています。
テキストエディタやVisualStudioのエディタで見ても見た目は正しい文字列ですが、バイナリで見ると間違っていることが解ります。
面倒ですがコピーしない方が良いです。
f:id:kagasu:20170915111229p:plain

注意

証明書の有効期限を予め確認する必要があります。
上記のサンプルコードの場合、証明書を更新した後にクライアント側を修正しようとしても通信が一切できない状態になります。
アップデートチェックとしてWeb APIを利用しているケースでは致命的になる場合があります。