/
certs.go
151 lines (116 loc) · 4.28 KB
/
certs.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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
package connectivity_adapter
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/base64"
"encoding/pem"
"strings"
"testing"
"github.com/stretchr/testify/require"
)
const (
rsaKeySize = 2048
)
// Create Key generates rsa.PrivateKey
func CreateKey(t *testing.T) *rsa.PrivateKey {
key, err := rsa.GenerateKey(rand.Reader, rsaKeySize)
require.NoError(t, err)
return key
}
// CreateCsr creates CSR request
func CreateCsr(t *testing.T, strSubject string, keys *rsa.PrivateKey) []byte {
subject := parseSubject(strSubject)
var csrTemplate = x509.CertificateRequest{
Subject: subject,
}
// step: generate the csr request
csrCertificate, err := x509.CreateCertificateRequest(rand.Reader, &csrTemplate, keys)
require.NoError(t, err)
csr := pem.EncodeToMemory(&pem.Block{
Type: "CERTIFICATE REQUEST", Bytes: csrCertificate,
})
return csr
}
// encodedCertChainToPemBytes decodes certificates chain and return pemBlock's bytes for client cert and ca cert
func encodedCertChainToPemBytes(t *testing.T, encodedChain string) []byte {
crtBytes := decodeBase64Cert(encodedChain, t)
clientCrtPem, rest := pem.Decode(crtBytes)
require.NotNil(t, clientCrtPem)
require.NotEmpty(t, rest)
caCrtPem, _ := pem.Decode(rest)
require.NotNil(t, caCrtPem)
certChainBytes := append(clientCrtPem.Bytes, caCrtPem.Bytes...)
return certChainBytes
}
// encodedCertToPemBytes decodes certificate and return pemBlock's bytes for it
func encodedCertToPemBytes(t *testing.T, encodedCert string) []byte {
crtBytes := decodeBase64Cert(encodedCert, t)
certificate, _ := pem.Decode(crtBytes)
require.NotNil(t, certificate)
return certificate.Bytes
}
// DecodeAndParseCerts decodes base64 encoded certificates chain and parses it
func DecodeAndParseCerts(t *testing.T, crtResponse *CrtResponse) DecodedCrtResponse {
certChainBytes := encodedCertChainToPemBytes(t, crtResponse.CRTChain)
certificateChain, err := x509.ParseCertificates(certChainBytes)
require.NoError(t, err)
clientCertBytes := encodedCertToPemBytes(t, crtResponse.ClientCRT)
clientCertificate, err := x509.ParseCertificate(clientCertBytes)
require.NoError(t, err)
caCertificateBytes := encodedCertToPemBytes(t, crtResponse.CaCRT)
caCertificate, err := x509.ParseCertificate(caCertificateBytes)
require.NoError(t, err)
return DecodedCrtResponse{
CRTChain: certificateChain,
ClientCRT: clientCertificate,
CaCRT: caCertificate,
}
}
// CheckIfSubjectEquals verifies that specified subject is equal to this in certificate
func CheckIfSubjectEquals(t *testing.T, expectedSubject string, certificate *x509.Certificate) {
subjectInfo := extractSubject(expectedSubject)
actualSubject := certificate.Subject
require.Equal(t, subjectInfo["CN"], actualSubject.CommonName)
require.Equal(t, []string{subjectInfo["C"]}, actualSubject.Country)
require.Equal(t, []string{subjectInfo["O"]}, actualSubject.Organization)
require.Equal(t, []string{subjectInfo["OU"]}, actualSubject.OrganizationalUnit)
require.Equal(t, []string{subjectInfo["L"]}, actualSubject.Locality)
require.Equal(t, []string{subjectInfo["ST"]}, actualSubject.Province)
}
// CheckIfCertIsSigned verifies that client certificate is signed by server certificate
func CheckIfCertIsSigned(t *testing.T, certificates []*x509.Certificate) {
clientCrt := certificates[0]
serverCrt := certificates[1]
err := clientCrt.CheckSignatureFrom(serverCrt)
require.NoError(t, err)
}
func EncodeBase64(src []byte) string {
return base64.StdEncoding.EncodeToString(src)
}
func parseSubject(subject string) pkix.Name {
subjectInfo := extractSubject(subject)
return pkix.Name{
CommonName: subjectInfo["CN"],
Country: []string{subjectInfo["C"]},
Organization: []string{subjectInfo["O"]},
OrganizationalUnit: []string{subjectInfo["OU"]},
Locality: []string{subjectInfo["L"]},
Province: []string{subjectInfo["ST"]},
}
}
func decodeBase64Cert(certificate string, t *testing.T) []byte {
crtBytes, err := base64.StdEncoding.DecodeString(certificate)
require.NoError(t, err)
return crtBytes
}
func extractSubject(subject string) map[string]string {
result := map[string]string{}
segments := strings.Split(subject, ",")
for _, segment := range segments {
parts := strings.Split(segment, "=")
result[parts[0]] = parts[1]
}
return result
}