2018-05-09 16:15:29 +00:00
|
|
|
package connect
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"crypto"
|
|
|
|
"crypto/rand"
|
|
|
|
"crypto/x509"
|
2018-09-14 23:08:54 +00:00
|
|
|
"crypto/x509/pkix"
|
|
|
|
"encoding/asn1"
|
2018-05-09 16:15:29 +00:00
|
|
|
"encoding/pem"
|
|
|
|
"net/url"
|
|
|
|
)
|
|
|
|
|
|
|
|
// CreateCSR returns a CSR to sign the given service along with the PEM-encoded
|
|
|
|
// private key for this certificate.
|
2019-08-27 21:45:58 +00:00
|
|
|
func CreateCSR(uri CertURI, privateKey crypto.Signer, extensions ...pkix.Extension) (string, error) {
|
2018-05-09 16:15:29 +00:00
|
|
|
template := &x509.CertificateRequest{
|
|
|
|
URIs: []*url.URL{uri.URI()},
|
|
|
|
SignatureAlgorithm: x509.ECDSAWithSHA256,
|
2018-09-14 23:08:54 +00:00
|
|
|
ExtraExtensions: extensions,
|
2018-05-09 16:15:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Create the CSR itself
|
|
|
|
var csrBuf bytes.Buffer
|
|
|
|
bs, err := x509.CreateCertificateRequest(rand.Reader, template, privateKey)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
err = pem.Encode(&csrBuf, &pem.Block{Type: "CERTIFICATE REQUEST", Bytes: bs})
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
return csrBuf.String(), nil
|
|
|
|
}
|
2018-09-14 23:08:54 +00:00
|
|
|
|
|
|
|
// CreateCSR returns a CA CSR to sign the given service along with the PEM-encoded
|
|
|
|
// private key for this certificate.
|
2019-08-27 21:45:58 +00:00
|
|
|
func CreateCACSR(uri CertURI, privateKey crypto.Signer) (string, error) {
|
2018-09-14 23:08:54 +00:00
|
|
|
ext, err := CreateCAExtension()
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
2019-08-27 21:45:58 +00:00
|
|
|
return CreateCSR(uri, privateKey, ext)
|
2018-09-14 23:08:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// CreateCAExtension creates a pkix.Extension for the x509 Basic Constraints
|
|
|
|
// IsCA field ()
|
|
|
|
func CreateCAExtension() (pkix.Extension, error) {
|
|
|
|
type basicConstraints struct {
|
|
|
|
IsCA bool `asn1:"optional"`
|
|
|
|
MaxPathLen int `asn1:"optional"`
|
|
|
|
}
|
|
|
|
basicCon := basicConstraints{IsCA: true, MaxPathLen: 0}
|
|
|
|
bitstr, err := asn1.Marshal(basicCon)
|
|
|
|
if err != nil {
|
|
|
|
return pkix.Extension{}, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return pkix.Extension{
|
|
|
|
Id: []int{2, 5, 29, 19}, // from x509 package
|
|
|
|
Critical: true,
|
|
|
|
Value: bitstr,
|
|
|
|
}, nil
|
|
|
|
}
|