

■やりたい事  
購入したサーバー証明書がサーバーとの通信時に自分のプロジェクトのサーバーから  
送られてきたものである事をチェックたいのですが、  
どのようにすれば良いかがわかりません。

■やってみた事  
手順は下記になり、下記のURLの方のページを参考にしました。  
<http://qiita.com/harmegiddo/items/b72ca4f430292251c8a6>

１．APIのURLを送信した時に、証明書のハッシュを取得しておきます。  
２．このハッシュ値をプログラム内に定数として持ちます。  
３．リクエストを投げた時に、サーバーから送られてきた証明書のハッシュと  
定数のハッシュを比較して一致すればTrueとなります。  
４．証明書が更新された場合は、ハッシュ値が異なるの定数も更新する必要があります。

SSL Policy Error:のログには **RemoteCertificateChainErrors** と表示されていました。

■定数

[code]

    private string FingerPrint = "ハッシュ値";
    
[/code]

■呼び出し元

[code]

    ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(ValidateServerCertificate); 
    
[/code]

■デリゲート

[code]

    public bool ValidateServerCertificate
                (
                  object sender,
                  System.Security.Cryptography.X509Certificates.X509Certificate certificate,
                  X509Chain chain,
                  System.Net.Security.SslPolicyErrors sslPolicyErrors)
    {
    
        UnityEngine.Debug.Log("SSL Policy Error: " + sslPolicyErrors.ToString());
        UnityEngine.Debug.Log("Cert. Hash: " + certificate.GetCertHashString());
    
        if (certificate.GetCertHashString() == FingerPrint)
        {
            UnityEngine.Debug.Log("Correct!");
            return true;
        }
        return false;
    }
    
[/code]

■質問１  
プログラム上で自分たちのプロジェクトのサーバーから送られてきたものであることを  
どのようにチェックすれば良いでしょうか？

■質問２  
下記URLから購入したサーバー証明書と通信に使用している証明書のハッシュ値は  
一致したのですが、このページは誰でもみれるので誰でもなりすませるのではないかと  
思っています。  
ユニークである事はどのように判断しているのでしょうか？  
<https://www.geotrust.co.jp/resources/repository/intermediate.html>

■質問３  
**RemoteCertificateChainErrors** はサーバーとの認証に失敗しているという事だと  
思うのですが、X509Chain .ChainPolicy.ExtraStoreに  
サーバー証明書もしくは付随する中間証明書を追加すれば良いでしょうか？


CC BY-SA 3.0
2016-02-17T12:43:00.507
22214
2016-02-20T11:23:43.940
2016-02-20T11:23:43.940
5261
5261
question
c# unity3d ssl
自分のプロジェクトのサーバー証明書のみを正としてサーバー証明書の検証を行う方法が知りたいです。


「オレオレ証明書を回避せず」という表現がちょっと良く分かりませんが、正しいか評価しないという設定はしたくないと言う意味ですよね。

<http://qiita.com/harmegiddo/items/b72ca4f430292251c8a6>  
上記と同じことをしているわけですよね。  
おっしゃる通り、のことをすれば良いと思いますので、指定されているコードに問題があるというよりは、試験環境の問題があるのではないでしょうか。  
証明書が本当に正しくルートから辿れ、認証されていて、有効期限ないのものか  
比較しているハッシュ値は正しいものか  
確認している端末に適切なCA証明書が入っているか  
などは確認済みでしょうか？

ちなみに、オレオレ証明書を正しいとして処理するのは大変で、オレオレ証明書の公開情報を書く端末に配布するとかルート証明書で署名して、ルート証明書公開情報を端末に配布する必要があります。それをするなら、最近のフリー証明書を使えば良いとなるかと思います。


CC BY-SA 3.0
2016-02-18T01:42:53.543
22219
2016-02-18T01:42:53.543
4956
22214
answer


まず、`RemoteCertificateChainErrors`を解決しましょう。CAが署名した証明書で検証に失敗すると言うことは何かが間違っています。たとえばWebサーバで中間証明書の配信の設定をしていないとか間違っているとか。[Apache
+ OpenSSL ジオトラスト クイックSSL プレミアム インストール手順
(新規)](https://www.geotrust.co.jp/support/ssl/install/apache_openssl_new.html)

普通はプログラム側で何かをする必要はありませんし、すべきではありません。

> ■質問１  
>  プログラム上で自分たちのプロジェクトのサーバーから送られてきたものであることをどのようにチェックすれば良いでしょうか？

[Certificate pinningとかPublic key
pinningとか呼ばれる手法になります](https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning)。

余計なことをして本来やるべき検証が漏れていたなどと言うことになるとやらない方がマシということになりますので、十分に理解した上で必要性を検討したうえで行ってください。普通はサーバ証明書の検証で十分です。

> ■質問２

中間CA証明書の正当性は上流の証明書によって検証されます。誰かが「中間証明書」なるものを配布していたとしてもそれが正当に署名されていない限り意味はありません。


CC BY-SA 3.0
2016-02-18T09:28:12.767
22232
2016-02-18T09:28:12.767
5793
22214
answer