-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcertificate.go
75 lines (66 loc) · 2.12 KB
/
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
// Adapted from https://golang.org/src/crypto/tls/generate_cert.go?m=text,
// which has the following copyright notice:
//
// Copyright 2009 The Go Authors. All rights reserved. Use of this source code
// is governed by a BSD-style license that can be found in the LICENSE file.
package main
import (
"crypto/ecdsa"
"crypto/elliptic"
crand "crypto/rand"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"math/big"
"net"
"time"
)
func pemBlockForKey(key *ecdsa.PrivateKey) (*pem.Block, error) {
bytes, e := x509.MarshalECPrivateKey(key)
if e != nil {
return nil, e
}
return &pem.Block{Type: "EC PRIVATE KEY", Bytes: bytes}, nil
}
func pemBlockForCertificate(der []byte) *pem.Block {
return &pem.Block{Type: "CERTIFICATE", Bytes: der}
}
// Generates a self-signed end-entity X.509 certificate valid for the given
// `hosts` (DNS names and/or IP addresses), the given organizationalUnit `ou`,
// for the validity period `notBefore` through `notAfter`.
//
// Returns a new ECDSA key and a DER-encoded X.509 certificate, or an error.
func generateCertificate(hosts []string, ou string, notBefore, notAfter time.Time) (*ecdsa.PrivateKey, []byte, error) {
key, e := ecdsa.GenerateKey(elliptic.P256(), crand.Reader)
if e != nil {
return nil, nil, e
}
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, e := crand.Int(crand.Reader, serialNumberLimit)
if e != nil {
return nil, nil, e
}
template := x509.Certificate{
SerialNumber: serialNumber,
Subject: pkix.Name{
Organization: []string{ou},
},
NotBefore: notBefore,
NotAfter: notAfter,
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
BasicConstraintsValid: true,
}
for _, h := range hosts {
if ip := net.ParseIP(h); ip != nil {
template.IPAddresses = append(template.IPAddresses, ip)
} else {
template.DNSNames = append(template.DNSNames, h)
}
}
der, e := x509.CreateCertificate(crand.Reader, &template, &template, &key.PublicKey, key)
if e != nil {
return nil, nil, e
}
return key, der, nil
}