langでPKI入門 - 4
1. この記事の対象の人
- Golang で、証明書失効リスト( CRL )を作りたい人
2. 概要
この記事では、
1. Go で秘密鍵と証明書を生成
2. Go で失効させる証明書のリストを生成
3. Go で Issuing Distribution Point のExtensionを作成
4. Go で証明書失効リスト( CRL )を作成
5. OpenSSL で証明書失効リスト( CRL )の中身を確認
します。
3. Golang で自己署名 CA 証明書と秘密鍵を作成
証明書失効リストを発行する自己署名 CA の「証明書」と「秘密鍵」を作成します。
詳細な説明は、GolangでPKI入門 - 2 を参照ください。
証明書失効リスト作成時に引数で必要になるので、秘密鍵はDER形式にしておきます。
//PrivateKey of Self Sign CA Certificate
privateCaKey, err := rsa.GenerateKey(rand.Reader, 2048)
publicCaKey := privateCaKey.Public()
//[RFC5280]
subjectCa := pkix.Name{
CommonName: "ca01",
OrganizationalUnit: []string{"Example Org Unit"},
Organization: []string{"Example Org"},
Country: []string{"JP"},
}
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,
}
//Self Sign CA Certificate
caCertificate, err := x509.CreateCertificate(rand.Reader, caTpl, caTpl, publicCaKey, privateCaKey)
//Convert to ASN.1 DER encoded form
derCaCert, err = x509.ParseCertificate(caCertificate)
if err != nil {
log.Fatalf("ERROR:%v\n", err)
}
4. Golang で証明書失効リストを作成
失効させる証明書のリストを作成
var rcs []pkix.RevokedCertificate
rc := pkix.RevokedCertificate{
SerialNumber: big.NewInt(100),
RevocationTime: time.Now(),
}
rcs = append(rcs, rc)
rc = pkix.RevokedCertificate{
SerialNumber: big.NewInt(108),
RevocationTime: time.Now(),
}
rcs = append(rcs, rc)
var rcs []pkix.RevokedCertificate
rc := pkix.RevokedCertificate{
SerialNumber: big.NewInt(100),
RevocationTime: time.Now(),
}
rcs = append(rcs, rc)
rc = pkix.RevokedCertificate{
SerialNumber: big.NewInt(108),
RevocationTime: time.Now(),
}
rcs = append(rcs, rc)
ここでは、シリアルが100と108の証明書を失効させます。
証明書失効リストの crlExtensions に Issuing Distribution Point を追加
Go で証明書失効リストを作成するときに利用する x509.RevocationList には、直接 Issuing Distribution Point を追加するFieldはありません。
別途 Issuing Distribution Point 用の構造体を作成して、Extensionに追加してやる必要があります。
RFC5280 では、Issuing Distribution Pointは以下のように定義されています。
id-ce-issuingDistributionPoint OBJECT IDENTIFIER ::= { id-ce 28 }
IssuingDistributionPoint ::= SEQUENCE {
distributionPoint [0] DistributionPointName OPTIONAL,
onlyContainsUserCerts [1] BOOLEAN DEFAULT FALSE,
onlyContainsCACerts [2] BOOLEAN DEFAULT FALSE,
onlySomeReasons [3] ReasonFlags OPTIONAL,
indirectCRL [4] BOOLEAN DEFAULT FALSE,
onlyContainsAttributeCerts [5] BOOLEAN DEFAULT FALSE }
DistributionPointName ::= CHOICE {
fullName [0] GeneralNames,
nameRelativeToCRLIssuer [1] RelativeDistinguishedName }
GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
GeneralName ::= CHOICE {
otherName [0] OtherName,
rfc822Name [1] IA5String,
dNSName [2] IA5String,
x400Address [3] ORAddress,
directoryName [4] Name,
ediPartyName [5] EDIPartyName,
uniformResourceIdentifier [6] IA5String,
iPAddress [7] OCTET STRING,
registeredID [8] OBJECT IDENTIFIER }
上記に従い、issuingDistributionPoint と distributionPointName を 以下の Go の構造体として定義しました。
// RFC5280, 5.2.5
type issuingDistributionPoint struct {
DistributionPoint distributionPointName `asn1:"optional,tag:0"`
OnlyContainsUserCerts bool `asn1:"optional,tag:1"`
OnlyContainsCACerts bool `asn1:"optional,tag:2"`
OnlySomeReasons asn1.BitString `asn1:"optional,tag:3"`
IndirectCRL bool `asn1:"optional,tag:4"`
OnlyContainsAttributeCerts bool `asn1:"optional,tag:5"`
}
type distributionPointName struct {
FullName []asn1.RawValue `asn1:"optional,tag:0"`
RelativeName pkix.RDNSequence `asn1:"optional,tag:1"`
}
distributionPointName の FullName フィールドの型は GeneralNames です。
GeneralName の uniformResourceIdentifier で証明書失効リストの取得先を指定したいので、
asn1.RawValue 型で以下のように設定
Class: 2
Context-specific ( asn1.RawValue の定義による)
Tag: 6
GeneralName の6番目つまり uniformResourceIdentifier
Bytes: []byte("http://www.example.com/example.crl")
uniformResourceIdentifier の エンコーディングは IA5String です。ただ、crl への URI で使われている範囲の文字列は IA5String と UTF8 で同じbyteになるので直接 byte 配列として渡しています。
dp := distributionPointName{
FullName: []asn1.RawValue{
{Tag: 6, Class: 2, Bytes: []byte("http://www.example.com/example.crl")},
},
}
Extension に作成した IssuingDistributionPoint を設定します。
var oidExtensionIssuingDistributionPoint = []int{2, 5, 29, 28}
idp := issuingDistributionPoint{
DistributionPoint: dp,
}
v, err := asn1.Marshal(idp)
cdpExt := pkix.Extension{
Id: oidExtensionIssuingDistributionPoint,
Critical: true,
Value: v,
}
x509.RevocationList 構造体の設定
x509.RevocationList 構造体に設定したい値を入れていきます。
crlTpl := &x509.RevocationList{
SignatureAlgorithm: x509.SHA256WithRSA,
RevokedCertificates: rcs,
Number: big.NewInt(2),
ThisUpdate: time.Now(),
NextUpdate: time.Now().Add(24 * time.Hour),
ExtraExtensions: []pkix.Extension{cdpExt},
}
証明書失効リストを作成
証明書失効リストを発行します
var derCrl []byte
derCrl, err = x509.CreateRevocationList(rand.Reader, crlTpl, derCaCert, privateCaKey)
if err != nil {
log.Fatalf("ERROR:%v\n", err)
}
f, err = os.Create("ca01.crl")
if err != nil {
log.Fatalf("ERROR:%v\n", err)
}
err = pem.Encode(f, &pem.Block{Type: "X509 CRL", Bytes: derCrl})
if err != nil {
log.Fatalf("ERROR:%v\n", err)
}
err = f.Close()
5. 証明書失効リストを確認する
発行した証明書失効リストを Openssl で確認します。設定した要素がすべて入っていますね。
$ openssl crl -inform pem -in example.crl -text
Certificate Revocation List (CRL):
Version 2 (0x1)
Signature Algorithm: sha256WithRSAEncryption
Issuer: C = JP, O = Example Org, OU = Example Org Unit, CN = ca01
Last Update: Oct 24 04:16:04 2020 GMT
Next Update: Oct 25 04:16:04 2020 GMT
CRL extensions:
X509v3 Authority Key Identifier:
keyid:0A:42:8D:9B:23:A9:77:11:FF:FD:0F:CC:58:F4:36:F4:98:06:7F:28
X509v3 CRL Number:
2
X509v3 Issuing Distribution Point: critical
Full Name:
URI:http://www.example.com/example.crl
Revoked Certificates:
Serial Number: 64
Revocation Date: Oct 24 04:16:04 2020 GMT
Serial Number: 6C
Revocation Date: Oct 24 04:16:04 2020 GMT
Signature Algorithm: sha256WithRSAEncryption
6c:0d:23:e8:50:bf:84:ae:10:85:3e:43:28:0f:43:fd:58:cb:
83:8c:7c:a8:5c:7d:78:71:f1:0c:03:97:43:88:8c:32:02:5c:
a6:6c:e2:a4:7d:94:56:08:a8:9c:17:95:b4:be:11:bb:65:52:
43:25:de:c0:d5:d0:df:ac:0f:ca:8c:a7:23:82:19:12:e2:9d:
49:83:9e:ca:bc:2e:f3:60:79:39:47:cb:ed:17:52:25:9f:42:
26:9e:1b:67:5f:af:e1:3a:14:67:5f:4f:de:10:c5:32:03:7f:
40:a0:b6:bc:3f:05:33:73:91:0b:73:4e:f2:3c:be:b0:e4:63:
e0:d0:81:6e:91:14:d9:04:35:21:3e:22:1e:31:bd:47:40:c9:
69:f0:e5:57:bc:c3:2c:ae:b8:06:38:35:f1:59:6f:45:2c:45:
08:2e:63:49:ab:f5:54:0b:54:d2:a8:fc:62:ea:a5:46:62:28:
a9:89:76:96:cf:47:28:3d:81:c3:e9:fb:ce:54:a8:07:71:6d:
c6:d8:b7:e7:33:b0:05:df:c4:79:56:e1:99:ed:9f:33:f8:15:
b9:32:4e:82:4c:0c:a7:a5:23:d4:f7:e1:94:26:2b:e0:55:1a:
38:f6:72:21:a9:e0:29:06:80:9a:05:e3:43:c2:4a:dd:74:c6:
d6:79:ec:9d
-----BEGIN X509 CRL-----
MIICKDCCARACAQEwDQYJKoZIhvcNAQELBQAwTTELMAkGA1UEBhMCSlAxFDASBgNV
BAoTC0V4YW1wbGUgT3JnMRkwFwYDVQQLExBFeGFtcGxlIE9yZyBVbml0MQ0wCwYD
VQQDEwRjYTAxFw0yMDEwMjQwNDE2MDRaFw0yMDEwMjUwNDE2MDRaMCgwEgIBZBcN
MjAxMDI0MDQxNjA0WjASAgFsFw0yMDEwMjQwNDE2MDRaoGUwYzAfBgNVHSMEGDAW
gBQKQo2bI6l3Ef/9D8xY9Db0mAZ/KDAKBgNVHRQEAwIBAjA0BgNVHRwBAf8EKjAo
oCagJIYiaHR0cDovL3d3dy5leGFtcGxlLmNvbS9leGFtcGxlLmNybDANBgkqhkiG
9w0BAQsFAAOCAQEAbA0j6FC/hK4QhT5DKA9D/VjLg4x8qFx9eHHxDAOXQ4iMMgJc
pmzipH2UVgionBeVtL4Ru2VSQyXewNXQ36wPyoynI4IZEuKdSYOeyrwu82B5OUfL
7RdSJZ9CJp4bZ1+v4ToUZ19P3hDFMgN/QKC2vD8FM3ORC3NO8jy+sORj4NCBbpEU
2QQ1IT4iHjG9R0DJafDlV7zDLK64Bjg18VlvRSxFCC5jSav1VAtU0qj8YuqlRmIo
qYl2ls9HKD2Bw+n7zlSoB3Ftxti35zOwBd/EeVbhme2fM/gVuTJOgkwMp6Uj1Pfh
lCYr4FUaOPZyIangKQaAmgXjQ8JK3XTG1nnsnQ==
-----END X509 CRL-----
6. コード
Author And Source
この問題について(langでPKI入門 - 4), 我々は、より多くの情報をここで見つけました https://qiita.com/tardevnull/items/2e12e6a0d8b096334a31著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .