FM牛鍵屋本舗

プログラマ(弱)の日々精進系ブログ

Go言語のTLSのHTTP実装:オレオレ証明書をコード中で登録する

Real World HTTPで GO言語でTLSの簡易HTTPサーバ、クライアントを実装しよう、というトピックがありました。

説明の通り、OpenSSLコマンドでルートCA、サーバ、クライアントの鍵と証明書を作りました。(コマンドの意味は理解できておらず…この辺りも学んでおかないと…)

本来、無条件に信頼するルートCAはOSに登録されていたり、ツールや言語によってはn内部に含まれていたりするそうです。今回のオレオレ証明書curlで叩くならコマンドラインで渡すなどの方法もとれるそうですが、、GO言語のデフォルトではOSのを参照してしまうそう。

それも面倒なので、プログラムコード内で登録します。 サーバ認証の場合、検証するのはクライアント側になるので、クライアントコードにルートCA追加処理を記述します。これは上記書籍にサンプルソースがありました。 *tls.ConfigRootCAsを使うそうです。

抜粋ですが。

   cert, err := ioutil.ReadFile("ca.crt")
    if err != nil {
        log.Println(err)
    }
    certPool := x509.NewCertPool()
    certPool.AppendCertsFromPEM(cert)

    tlsConfig := &tls.Config{
        ClientAuth: tls.RequireAndVerifyClientCert,
        MinVersion: tls.VersionTLS12,
        ClientCAs:  certPool,
    }
    tlsConfig.BuildNameToCertificate()

    server := &http.Server{
        TLSConfig: tlsConfig,
        Addr:      ":18443",
    }

じゃあクライアント認証も…ってことで、写経してみましたが動かない。

018/01/27 14:57:59 http: TLS handshake error from [::1]:57397: tls: failed to verify client's certificate: x509: certificate signed by unknown authority

むむ、CAが信頼できない、と。 じゃあどうやるんだろうってことで、crypto/tlsのドキュメントを読んだところ解決。ClientCAsを使用します。

   cert, err := ioutil.ReadFile("ca.crt")
    if err != nil {
        log.Println(err)
    }
    certPool := x509.NewCertPool()
    certPool.AppendCertsFromPEM(cert)

    tlsConfig := &tls.Config{
        ClientAuth: tls.RequireAndVerifyClientCert,
        MinVersion: tls.VersionTLS12,
        ClientCAs:  certPool,
    }
    tlsConfig.BuildNameToCertificate()

    server := &http.Server{
        TLSConfig: tlsConfig,
        Addr:      ":18443",
    }