2016-11-03 21 views
2

自己署名付き証明書を使用してtls.Config.GetCertificateにフィードする機能を実装する方法を理解しようとしています。自己署名入り証明書を使ってtls.Config.GetCertificateを実装する

私は生成する必要があると思う。また残念ながら、これまでのところイムこのエラー 2016/11/03 23:18:20 http2: server: error reading preface from client 127.0.0.1:34346: remote error: tls: unknown certificate authority

で立ち往生 https://ericchiang.github.io/tls/go/https/2015/06/21/go-tls.html

、これを読んで、ベースとしてhttps://golang.org/src/crypto/tls/generate_cert.go

をこのビンのソースを使用CA証明書を発行し、その鍵で署名しますが、進める方法はわかりません(....)。

ここに私のコードは、誰かがそれを助けることができますか?

package gssc 

import (
    "crypto/rand" 
    "crypto/rsa" 
    "crypto/tls" 
    "crypto/x509" 
    "crypto/x509/pkix" 
    "github.com/pkg/errors" 
    "math/big" 
    "net" 
    "strings" 
    "time" 
) 

func GetCertificate(arg interface{}) func(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) { 
    var opts Certopts 
    var err error 
    if host, ok := arg.(string); ok { 
     opts = Certopts{ 
      RsaBits: 2048, 
      Host:  host, 
      ValidFrom: time.Now(), 
     } 
    } else if o, ok := arg.(Certopts); ok { 
     opts = o 
    } else { 
     err = errors.New("Invalid arg type, must be string(hostname) or Certopt{...}") 
    } 
    return func(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) { 
     if err != nil { 
      return nil, err 
     } 
     return generate(opts) 
    } 
} 

type Certopts struct { 
    RsaBits int 
    Host  string 
    IsCA  bool 
    ValidFrom time.Time 
    ValidFor time.Duration 
} 

func generate(opts Certopts) (*tls.Certificate, error) { 

    priv, err := rsa.GenerateKey(rand.Reader, opts.RsaBits) 
    if err != nil { 
     return nil, errors.Wrap(err, "failed to generate private key") 
    } 

    notAfter := opts.ValidFrom.Add(opts.ValidFor) 

    serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) 
    serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) 
    if err != nil { 
     return nil, errors.Wrap(err, "Failed to generate serial number\n") 
    } 

    template := x509.Certificate{ 
     SerialNumber: serialNumber, 
     Subject: pkix.Name{ 
      Organization: []string{"Acme Co"}, 
     }, 
     NotBefore: opts.ValidFrom, 
     NotAfter: notAfter, 

     KeyUsage:    x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, 
     ExtKeyUsage:   []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, 
     BasicConstraintsValid: true, 
    } 

    hosts := strings.Split(opts.Host, ",") 
    for _, h := range hosts { 
     if ip := net.ParseIP(h); ip != nil { 
      template.IPAddresses = append(template.IPAddresses, ip) 
     } else { 
      template.DNSNames = append(template.DNSNames, h) 
     } 
    } 

    if opts.IsCA { 
     template.IsCA = true 
     template.KeyUsage |= x509.KeyUsageCertSign 
    } 

    derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv) 
    if err != nil { 
     return nil, errors.Wrap(err, "Failed to create certificate") 
    } 

    return &tls.Certificate{ 
     Certificate: [][]byte{derBytes}, 
     PrivateKey: priv, 
    }, nil 
} 

これは私が

package main 

import (
    "crypto/tls" 
    "github.com/mh-cbon/gssc" 
    "net/http" 
) 

type ww struct{} 

func (s *ww) ServeHTTP(w http.ResponseWriter, req *http.Request) { 
    w.Header().Set("Content-Type", "text/plain") 
    w.Write([]byte("This is an example server.\n")) 
} 

func main() { 
    s := &http.Server{ 
     Handler: &ww{}, 
     Addr: ":8080", 
     TLSConfig: &tls.Config{ 
      InsecureSkipVerify: true, 
      GetCertificate:  gssc.GetCertificate("example.org"), 
     }, 
    } 
    s.ListenAndServeTLS("", "") 

} 

おかげでたくさん使うテストコードです!

+0

あなたがfmt'行く '使用しない理由はありますか? –

答えて

2

tls.Config.GetCertificateの実装で問題が発生しています。

tls.Config.GetCertificateが呼び出されるたびに証明書を生成しています。証明書を一度生成してから匿名関数に戻す必要があります。 gssc.GetCertificate

cert, err := generate(opts) 

return func(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) { 
     if err != nil { 
      return nil, err 
     } 
     return cert, err 
    } 
+0

フィードバックをいただきありがとうございます。残念ながら、以前は[バイナリ](https://github.com/mh-cbon/sscg)ツールを作成するためにこのコードを使用していたため、残念ながら実際には役に立ちませんでした。プレーンファイルなので、うまくいきました。私はこのGetCertメソッドを[this](https://godoc.org/golang.org/x/crypto/acme/autocert)と同じ方法で実装しようと考えています。多分私は私の元の投稿でprecuredしている必要があります。 –

+1

が更新されました。私はこれが問題だと思っています。 –

+0

うん!私は問題が今、私は毎回新しい証明書を生成していたので、その後のリクエストが来たときにブラウザが混乱していたことがわかります。私はまだエラーがあります。 '2016/11/09 11:18:36 http2:server:クライアントからの序文を読み込む際にエラーが発生しました。127.0.0.1:41748:リモートエラー:tls:不明な認証局ですが、これは別の質問i推測。ありがとう! –

関連する問題