#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証明書なので IsCA と BasicConstraintsValid は true に設定
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. コード