LoginSignup
18
10

More than 1 year has passed since last update.

GolangでPKI入門 - 2

Last updated at Posted at 2019-10-07

1.この記事の対象の人

  • Golangで、自己署名CA証明書を作りたい人
  • Golangで、自己署名CAで署名した「サーバ証明書」を作りたい人
  • Golangで、自己署名CAで署名した「クライアント証明書」(クライアント認証用)を作りたい人

※作成した証明書と鍵はテスト用途でお使いください。
※作成した秘密鍵は適切に管理してください。

2.Golangで自己署名CA証明書作成

以下エラー処理は省略しますので悪しからず

2048bitのCA用RSA秘密鍵、公開鍵を作成

    privateCaKey, err := rsa.GenerateKey(rand.Reader, 2048)
    publicCaKey := privateCaKey.Public()

自己署名CA証明書のサブジェクト作成

CN: ca01
OU: Example Org Unit
O: Example Org
C: JP
に設定

    // https://tools.ietf.org/html/rfc5280#section-4.1.2.6
    subjectCa := pkix.Name{
        CommonName:         "ca01",
        OrganizationalUnit: []string{"Example Org Unit"},
        Organization:       []string{"Example Org"},
        Country:            []string{"JP"},
    }

自己署名CA証明書用構造体の設定

  • CA証明書なので IsCABasicConstraintsValidtrue に設定

RFC5280 - Basic Constraints

    caTpl := &x509.Certificate{
        SerialNumber:          big.NewInt(1),
        Subject:               subjectCa,
        NotAfter:              time.Date(2022, 1, 1, 0, 0, 0, 0, time.UTC),
        NotBefore:             time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC),
        IsCA:                  true,
        KeyUsage:              x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
        BasicConstraintsValid: true,
    }

自己署名CA証明書作成

    caCertificate, err := x509.CreateCertificate(rand.Reader, caTpl, caTpl, publicCaKey, privateCaKey)

自己署名CA証明書をPEM形式で保存

    var f *os.File
    f, err = os.Create("ca01.crt")
    err = pem.Encode(f, &pem.Block{Type: "CERTIFICATE", Bytes: caCertificate})
    err = f.Close()

自己署名CAの秘密鍵をPEM形式で保存

    derCaPrivateKey := x509.MarshalPKCS1PrivateKey(privateCaKey)
    err = pem.Encode(f, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: derCaPrivateKey})
    err = f.Close()

3.Golangでサーバ証明書作成

自己署名CAの秘密鍵で署名した「サーバ証明書」を作ります

2048bitのサーバ証明書用RSA秘密鍵、公開鍵を作成

    privateSslKey, err := rsa.GenerateKey(rand.Reader, 2048)
    publicSslKey := privateSslKey.Public()

サーバ証明書のサブジェクト作成

CN: svr01
OU: Example Org Unit
O: Example Org
C: JP
に設定

    // https://tools.ietf.org/html/rfc5280#section-4.1.2.6
    subjectSsl := pkix.Name{
        CommonName:         "svr01",
        OrganizationalUnit: []string{"Example Org Unit"},
        Organization:       []string{"Example Org"},
        Country:            []string{"JP"},
    }

サーバ証明書用構造体の設定

  • ブラウザでエラーが表示されないように、subjectAlternativeNameを指定します。

SubjectAlternativeNameを svr01.example.org に指定

DNSNames: []string{"svr01.example.org"}

  • サーバ証明書用途なので、拡張キー使用法をサーバ認証に指定します。

ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}

    sslTpl := &x509.Certificate{
        SerialNumber:          big.NewInt(123),
        Subject:               subjectSsl,
        NotAfter:              time.Date(2022, 1, 1, 0, 0, 0, 0, time.UTC),
        NotBefore:             time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC),
        KeyUsage:              x509.KeyUsageDigitalSignature,
        ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
        DNSNames:              []string{"svr01.example.org"},
    }

サーバ証明書作成

  • サーバ証明書に署名する秘密鍵は「自己署名CAの秘密鍵」を指定します。
    derSslCertificate, err := x509.CreateCertificate(rand.Reader, sslTpl, caTpl, publicSslKey, privateCaKey)

サーバ証明書をPEM形式で保存

    f, err = os.Create("svr01.crt")
    err = pem.Encode(f, &pem.Block{Type: "CERTIFICATE", Bytes: derSslCertificate})
    err = f.Close()

サーバ証明書の秘密鍵をPEM形式で保存

    f, err = os.Create("svr01.key")
    derPrivateSslKey := x509.MarshalPKCS1PrivateKey(privateSslKey)
    err = pem.Encode(f, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: derPrivateSslKey})
    err = f.Close()

4.Golangでクライアント証明書作成

自己署名CAの秘密鍵で署名した「クライアント証明書」を作ります

2048bitのクライアント証明書用RSA秘密鍵、公開鍵を作成

    privateClientKey, err := rsa.GenerateKey(rand.Reader, 2048)
    publicClientKey := privateClientKey.Public()

クライアント証明書のサブジェクト作成

CN: client01
OU: Example Org Unit
O: Example Org
C: JP
に設定

    // https://tools.ietf.org/html/rfc5280#section-4.1.2.6
    subjectClient := pkix.Name{
        CommonName:         "client01",
        OrganizationalUnit: []string{"Example Org Unit"},
        Organization:       []string{"Example Org"},
        Country:            []string{"JP"},
    }

クライアント証明書用構造体の設定

  • クライアント証明書用途なので、拡張キー使用法をクライアント認証に指定します。

ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}

    cliTpl := &x509.Certificate{
        SerialNumber:          big.NewInt(456),
        Subject:               subjectClient,
        NotAfter:              time.Date(2022, 1, 1, 0, 0, 0, 0, time.UTC),
        NotBefore:             time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC),
        KeyUsage:              x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment,
        ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
    }

クライアント証明書作成

  • クライアント証明書に署名する秘密鍵は「自己署名CAの秘密鍵」を指定します。
        derClientCertificate, err := x509.CreateCertificate(rand.Reader, cliTpl, caTpl, publicClientKey, privateCaKey)

PKCS#12形式でクライアント証明書と秘密鍵を保存

クライアント認証用途なので、クライアント証明書とクライアント証明書の秘密鍵両方が必要です。ここでは、PKCS#12形式をつかって、クライアント証明書とクライアント証明書の秘密鍵をまとめて保存します。

  • PKCS#12形式を作成するために "software.sslmate.com/src/go-pkcs12" packageをimport。

  • PKCS#12形式のpasswordを pincode という文字列で指定

    cert, err := x509.ParseCertificate(derClientCertificate)
    f, err = os.Create("client01.p12")
    //PKCS#12 [RFC7292] including client private keys, client certificates
    p12, err := pkcs12.Encode(rand.Reader, privateClientKey, cert, nil, "pincode")
    _, err = f.Write(p12)
    err = f.Close()

5. コード

コードはこちら
https://github.com/tardevnull/gopkicookbook2

18
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
10