/
pem.go
89 lines (82 loc) · 2.15 KB
/
pem.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
package wraputil
import (
"bytes"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"errors"
"fmt"
)
func LoadSinglePEMBlock(data []byte, expected_types []string) ([]byte, error) {
if !bytes.HasPrefix(data, []byte("-----BEGIN ")) {
return nil, errors.New("Missing expected PEM header")
}
pemBlock, remain := pem.Decode(data)
if pemBlock == nil {
return nil, errors.New("Could not parse PEM data")
}
found := false
for _, expected_type := range expected_types {
if pemBlock.Type == expected_type {
found = true
break
}
}
if !found {
return nil, fmt.Errorf("Found PEM block of type \"%s\" instead of types %s", pemBlock.Type, expected_types)
}
if remain != nil && len(remain) > 0 {
return nil, errors.New("Trailing data found after PEM data")
}
return pemBlock.Bytes, nil
}
func IsPEMBlock(data []byte) bool {
if bytes.HasPrefix(data, []byte("-----BEGIN ")) {
pemBlock, remain := pem.Decode(data)
return pemBlock != nil && len(remain) == 0
} else {
return false
}
}
func LoadX509CertFromPEM(certdata []byte) (*x509.Certificate, error) {
certblock, err := LoadSinglePEMBlock(certdata, []string{"CERTIFICATE"})
if err != nil {
return nil, err
}
cert, err := x509.ParseCertificate(certblock)
if err != nil {
return nil, err
}
return cert, nil
}
func LoadX509CSRFromPEM(certdata []byte) (*x509.CertificateRequest, error) {
pemBlock, err := LoadSinglePEMBlock(certdata, []string{"CERTIFICATE REQUEST"})
if err != nil {
return nil, err
}
csr, err := x509.ParseCertificateRequest(pemBlock)
if err != nil {
return nil, err
}
return csr, nil
}
func LoadRSAKeyFromPEM(keydata []byte) (*rsa.PrivateKey, error) {
keyblock, err := LoadSinglePEMBlock(keydata, []string{"RSA PRIVATE KEY", "PRIVATE KEY"})
if err != nil {
return nil, err
}
privkey, err := x509.ParsePKCS1PrivateKey(keyblock)
if err == nil {
return privkey, nil
}
tmpkey, err := x509.ParsePKCS8PrivateKey(keyblock)
if err == nil {
privkey, ok := tmpkey.(*rsa.PrivateKey)
if ok {
return privkey, nil
} else {
return nil, errors.New("non-RSA private key found in PKCS#8 block")
}
}
return nil, errors.New("could not load PEM private key as PKCS#1 or PKCS#8")
}