GolangでPKI入門 - 1

#1. この記事の対象のひと
- GolangでRSA秘密鍵・公開鍵(PEM・DER形式)を作りたい人
- GolangでSubjectPublicKeyInfo(PEM・DER形式)を作りたい人
- GolangでPrivateKeyInfo(PEM・DER形式)を作りたい人


#2. GolangでRSA秘密鍵作成
以下エラー処理は省略しますので悪しからず
###2048bitのRSA秘密鍵作成

```go
	//PKCS#1 format RSA PrivateKey [RFC8017]
	rsaPrivateKey, err := rsa.GenerateKey(rand.Reader, 2048)
```

###DER形式で保存する

```go
	derRsaPrivateKey := x509.MarshalPKCS1PrivateKey(rsaPrivateKey)
	f, err := os.Create("derFormatRsaPrivate.key")
	_, err = f.Write(derRsaPrivateKey)
	err = f.Close()
```

###保存したDER形式のRSA秘密鍵をOpenSSLコマンドで確認する
```
openssl rsa -text -inform der -in derFormatRsaPrivate.key
```

###PEM形式で保存する

```go
	f, err = os.Create("pemFormatRsaPrivate.key")
	err = pem.Encode(f, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: derRsaPrivateKey})
	err = f.Close()
```

###保存したPEM形式のRSA秘密鍵をOpenSSLコマンドで確認する
```
openssl rsa -text -in pemFormatRsaPrivate.key
```

#3. GolangでRSA公開鍵作成
###2048bitのRSA公開鍵の作成
```go
	//PKCS#1 format RSA PublicKey [RFC8017]
	var rsaPublicKey crypto.PublicKey
	rsaPublicKey = rsaPrivateKey.Public()
```
###DER形式で保存する

```go
	var derRsaPublicKey []byte
	if rsaPublicKeyPointer, ok := rsaPublicKey.(*rsa.PublicKey); ok {
		derRsaPublicKey = x509.MarshalPKCS1PublicKey(rsaPublicKeyPointer)
	}
	f, err = os.Create("derFormatRsaPublic.key")
	_, err = f.Write(derRsaPublicKey)
	err = f.Close()
```
###保存したDER形式のRSA公開鍵をOpenSSLコマンドで確認する
```
openssl rsa -text -RSAPublicKey_in -inform der -in derFormatRsaPublic.key
```
###PEM形式で保存する

```go
	f, err = os.Create("pemFormatRsaPublic.key")
	err = pem.Encode(f, &pem.Block{Type: "RSA PUBLIC KEY", Bytes: derRsaPublicKey})
	err = f.Close()
```
###保存したPEM形式のRSA公開鍵をOpenSSLコマンドで確認する
```
openssl rsa -text -RSAPublicKey_in -in pemFormatRsaPublic.key
```

#4. GolangでSubjectPublicKeyInfo作成
あんまり需要はないきがしますが...
### SubjectPublicKeyInfo作成
```go
	//[RFC5280]
	publicKeyInfo, err := x509.MarshalPKIXPublicKey(rsaPublicKey)
```
###DER形式で保存する
```go
	//拡張子は適当
	f, err = os.Create("subjectPublicKeyInfo.der")
	_, err = f.Write(publicKeyInfo)
	err = f.Close()
```
###PEM形式で保存する
```go
	//拡張子は適当
	f, err = os.Create("subjectPublicKeyInfo.pem")
	err = pem.Encode(f, &pem.Block{Type: "PUBLIC KEY", Bytes: publicKeyInfo})
	err = f.Close()
```
###保存したPEM形式のSubjectPublicKeyInfoをOpenSSLコマンドで確認する
RFC 5280に定義されたSubjectPublicKeyInfoの構造

```
   SubjectPublicKeyInfo  ::=  SEQUENCE  {
        algorithm            AlgorithmIdentifier,
        subjectPublicKey     BIT STRING  }

   AlgorithmIdentifier  ::=  SEQUENCE  {
        algorithm               OBJECT IDENTIFIER,
        parameters              ANY DEFINED BY algorithm OPTIONAL  }
```

OpenSSLのasn1parseで中身を表示

```
openssl asn1parse -in subjectPublicKeyInfo.pem
    0:d=0  hl=4 l= 290 cons: SEQUENCE
    4:d=1  hl=2 l=  13 cons: SEQUENCE
    6:d=2  hl=2 l=   9 prim: OBJECT            :rsaEncryption
   17:d=2  hl=2 l=   0 prim: NULL
   19:d=1  hl=4 l= 271 prim: BIT STRING
```

#5. GolangでPrivateKeyInfo作成
### PrivateKeyInfo作成
```go
	//PKCS#8 format RSA PrivateKey [RFC5208]
	privateKeyInfo, err := x509.MarshalPKCS8PrivateKey(rsaPrivateKey)
```
###DER形式で保存する
```go
	//拡張子は適当
	f, err = os.Create("privateKeyInfo.der")
	_, err = f.Write(privateKeyInfo)
	err = f.Close()
```
###PEM形式で保存する
```go
	//拡張子は適当
	f, err = os.Create("privateKeyInfo.pem")
	err = pem.Encode(f, &pem.Block{Type: "PRIVATE KEY", Bytes: privateKeyInfo})
	err = f.Close()
```
###保存したPEM形式のPrivateKeyInfoをOpenSSLコマンドで確認する
RFC 5208に定義されたPrivateKeyInfoの構造

```
   PrivateKeyInfo ::= SEQUENCE {
        version                   Version,
        privateKeyAlgorithm       PrivateKeyAlgorithmIdentifier,
        privateKey                PrivateKey,
        attributes           [0]  IMPLICIT Attributes OPTIONAL }
   Version ::= INTEGER
   PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
   PrivateKey ::= OCTET STRING
   Attributes ::= SET OF Attribute
```

OpenSSLのasn1parseで中身を表示

```
$ openssl asn1parse -in privateKeyInfo.pem
    0:d=0  hl=4 l=1212 cons: SEQUENCE
    4:d=1  hl=2 l=   1 prim: INTEGER           :00
    7:d=1  hl=2 l=  13 cons: SEQUENCE
    9:d=2  hl=2 l=   9 prim: OBJECT            :rsaEncryption
   20:d=2  hl=2 l=   0 prim: NULL
   22:d=1  hl=4 l=1190 prim: OCTET STRING      [HEX DUMP]:308204A202 ~以下略~
```

#6. コード
コードはこちら
https://github.com/tardevnull/gopkicookbook1