...
1 package x509
2
3 import (
4 "crypto"
5 "crypto/rand"
6 "crypto/rsa"
7 "crypto/x509"
8 "crypto/x509/pkix"
9 "math"
10 "math/big"
11 "net"
12 "time"
13
14 "k8s.io/client-go/util/keyutil"
15
16 pem "edge-infra.dev/pkg/lib/crypto/certs/pem"
17 )
18
19 type CertInfo struct {
20 Name string
21 CommonName string
22 Organization []string
23 DNSNames []string
24 IPs []net.IP
25 Usages []x509.ExtKeyUsage
26 }
27
28 type EncodedKeyPair struct {
29 Key []byte
30 Cert []byte
31 }
32
33
34 func GenerateCertAndKey(certInfo CertInfo, caCert *x509.Certificate, caKeySigner crypto.Signer) (encodedKeyPair EncodedKeyPair, err error) {
35 key, err := GenPrivateKey()
36 if err != nil {
37 return
38 }
39 x509CertBytes, err := GenPublicCert(certInfo, key, caCert, caKeySigner)
40 if err != nil {
41 return
42 }
43
44 encodedKey, _ := keyutil.MarshalPrivateKeyToPEM(key)
45 encodedCert := pem.Encodex509CertAsPem(x509CertBytes)
46
47 encodedKeyPair = EncodedKeyPair{
48 Key: encodedKey,
49 Cert: encodedCert,
50 }
51
52 return
53 }
54
55
56 func GenPrivateKey() (crypto.Signer, error) {
57 return rsa.GenerateKey(rand.Reader, 2048)
58 }
59
60
61
62 func GenPublicCert(ci CertInfo, key crypto.Signer, caCert *x509.Certificate, caKey crypto.Signer) ([]byte, error) {
63 serial, err := rand.Int(rand.Reader, new(big.Int).SetInt64(math.MaxInt64))
64 if err != nil {
65 return nil, err
66 }
67
68 notAfter := time.Now().Add(time.Hour * 24 * 365).UTC()
69 certTmpl := x509.Certificate{
70 Subject: pkix.Name{
71 CommonName: ci.CommonName,
72 Organization: ci.Organization,
73 },
74 DNSNames: ci.DNSNames,
75 IPAddresses: ci.IPs,
76 SerialNumber: serial,
77 NotBefore: caCert.NotBefore,
78 NotAfter: notAfter,
79 KeyUsage: 3,
80 ExtKeyUsage: ci.Usages,
81 BasicConstraintsValid: true,
82 IsCA: false,
83 }
84
85 certDERBytes, err := x509.CreateCertificate(rand.Reader, &certTmpl, caCert, key.Public(), caKey)
86 if err != nil {
87 return nil, err
88 }
89 return certDERBytes, nil
90 }
91
View as plain text