rsa/pkg/ca/ca.go

73 lines
1.5 KiB
Go

/*
Package ca implements a disk file-backed certificate authority with a built-in
CRL signer. The certificate authority can issue new certificates (including the
creation of intermediate CAs) and revoke existing certificates, resulting in a
fresh CRL.
*/
package ca
import (
"crypto/rsa"
"crypto/sha1"
"crypto/x509"
"encoding/asn1"
"fmt"
"path/filepath"
"src.lwithers.me.uk/go/rsa/pkg/pemfile"
)
type CA struct {
dir string
key *rsa.PrivateKey
root *x509.Certificate
crl *x509.RevocationList
crlKey *rsa.PrivateKey
crlCert *x509.Certificate
}
const (
rootKeyFilename = "root-key.pem"
rootCertFilename = "root-cert.pem"
)
// Open an existing certificate authority in the given directory.
func Open(dir string) (*CA, error) {
ca := &CA{
dir: dir,
}
var err error
ca.key, err = pemfile.ReadKey(filepath.Join(dir, rootKeyFilename))
if err != nil {
return nil, fmt.Errorf("while opening CA (root key): %w", err)
}
ca.root, err = pemfile.ReadCert(filepath.Join(dir, rootCertFilename))
if err != nil {
return nil, fmt.Errorf("while opening CA (root cert): %w", err)
}
if err = ca.loadCRLState(); err != nil {
return nil, fmt.Errorf("while opening CA (CRL state): %w", err)
}
return ca, nil
}
func (ca *CA) GetRoot() *x509.Certificate {
return ca.root
}
func (ca *CA) GetCRLSigner() *x509.Certificate {
return ca.crlCert
}
func (ca *CA) GetCRL() *x509.RevocationList {
return ca.crl
}
func ComputeSubjectKeyId(key *rsa.PublicKey) []byte {
der, _ := asn1.Marshal(key)
h := sha1.Sum(der)
return h[:]
}