-
Notifications
You must be signed in to change notification settings - Fork 18
/
x509_certificate.go
96 lines (81 loc) · 2.97 KB
/
x509_certificate.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
90
91
92
93
94
95
96
package signing
import (
"bytes"
"crypto/x509"
"encoding/pem"
"errors"
"fmt"
"github.com/open-component-model/ocm/pkg/utils"
)
// CreateAndVerifyX509CertificateFromFiles creates and verifies a x509 certificate from certificate files.
// The certificates must be in PEM format.
func CreateAndVerifyX509CertificateFromFiles(certPath, intermediateCAsCertsPath, rootCACertPath string) (*x509.Certificate, error) {
var err error
var rootCACert []byte
if rootCACertPath != "" {
rootCACert, err = utils.ReadFile(rootCACertPath)
if err != nil {
return nil, fmt.Errorf("unable to read root CA certificate file: %w", err)
}
}
var intermediateCAsCerts []byte
if intermediateCAsCertsPath != "" {
intermediateCAsCerts, err = utils.ReadFile(intermediateCAsCertsPath)
if err != nil {
return nil, fmt.Errorf("unable to read intermediate CAs certificates file: %w", err)
}
}
cert, err := utils.ReadFile(certPath)
if err != nil {
return nil, fmt.Errorf("unable to read certificate file: %w", err)
}
return CreateAndVerifyX509Certificate(cert, intermediateCAsCerts, rootCACert)
}
// CreateAndVerifyX509Certificate creates and verifies a x509 certificate from in-memory raw certificates.
// The certificates must be in PEM format.
func CreateAndVerifyX509Certificate(cert, intermediateCAsCerts, rootCACert []byte) (*x509.Certificate, error) {
// First, create the set of root certificates. For this example we only
// have one. It's also possible to omit this in order to use the
// default root set of the current operating system.
var roots *x509.CertPool
if rootCACert != nil {
roots = x509.NewCertPool()
block, _ := pem.Decode(rootCACert)
if block == nil {
return nil, errors.New("unable to decode root CA certificate")
}
parsedCert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
return nil, fmt.Errorf("unable to parse root CA certificate: %w", err)
}
if !bytes.Equal(parsedCert.RawIssuer, parsedCert.RawSubject) || !parsedCert.IsCA {
return nil, errors.New("the given root CA certificate doesn't fulfil the requirements for a root CA certificate (Issuer == Subject && CA == true) ")
}
if ok := roots.AppendCertsFromPEM(rootCACert); !ok {
return nil, errors.New("unable to parse root ca certificate")
}
}
var intermediates *x509.CertPool
if intermediateCAsCerts != nil {
intermediates = x509.NewCertPool()
if ok := intermediates.AppendCertsFromPEM(intermediateCAsCerts); !ok {
return nil, errors.New("unable to parse intermediate cas certificates")
}
}
block, _ := pem.Decode(cert)
if block == nil {
return nil, errors.New("unable to decode certificate")
}
parsedCert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
return nil, fmt.Errorf("unable to parse certificate: %w", err)
}
opts := x509.VerifyOptions{
Roots: roots,
Intermediates: intermediates,
}
if _, err := parsedCert.Verify(opts); err != nil {
return nil, fmt.Errorf("unable to verify certificate: %w", err)
}
return parsedCert, nil
}