github.com/haraldrudell/parl@v0.4.176/parlca/selfsigned.go (about)

     1  /*
     2  © 2021–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/)
     3  ISC License
     4  */
     5  
     6  package parlca
     7  
     8  import (
     9  	"crypto"
    10  	"crypto/rand"
    11  	"crypto/x509"
    12  
    13  	"github.com/haraldrudell/parl"
    14  	"github.com/haraldrudell/parl/perrors"
    15  )
    16  
    17  const (
    18  	/*
    19  		NoPassword       PasswordType = "\tnoPassword"
    20  		GeneratePassword PasswordType = "\tgeneratePassword"
    21  		GenerateOnTheFly Strategy     = iota << 0
    22  		UseFileSystem
    23  		DefaultStrategy = GenerateOnTheFly
    24  	*/
    25  	DefaultCountry  = "US" // certificate country: US
    26  	notAfterYears   = 10   // certificate validity for 10 years
    27  	caSubjectSuffix = "ca" // ca appended to commonName
    28  )
    29  
    30  type SelfSigned struct {
    31  	parl.Certificate // DER() PEM()
    32  	PrivateKey       parl.PrivateKey
    33  }
    34  
    35  func NewSelfSigned(canonicalName string, algo x509.PublicKeyAlgorithm) (ca parl.CertificateAuthority, err error) {
    36  	c := SelfSigned{}
    37  
    38  	// create private key
    39  	if c.PrivateKey, err = NewPrivateKey(algo); err != nil {
    40  		return
    41  	}
    42  
    43  	// create certificate of certificate authority
    44  	var certificateDer parl.CertificateDer
    45  	cert := &x509.Certificate{}
    46  	EnsureSelfSigned(cert)
    47  	if certificateDer, err = x509.CreateCertificate(rand.Reader,
    48  		cert,                  // template
    49  		cert,                  // parent
    50  		c.PrivateKey.Public(), // pub any: *rsa.PublicKey *ecdsa.PublicKey ed25519.PublicKey
    51  		c.PrivateKey,          // priv any: crypto.Signer
    52  	); perrors.IsPF(&err, "x509.CreateCertificate %w", err) {
    53  		return
    54  	}
    55  	c.Certificate = NewCertificate(certificateDer)
    56  	ca = &c
    57  	return
    58  }
    59  
    60  func NewSelfSigned2(privateKey parl.PrivateKey, certificate parl.Certificate) (ca parl.CertificateAuthority) {
    61  	return &SelfSigned{Certificate: certificate, PrivateKey: privateKey}
    62  }
    63  
    64  func (ca *SelfSigned) Sign(template *x509.Certificate, publicKey crypto.PublicKey) (certDER parl.CertificateDer, err error) {
    65  
    66  	// get certificate authority x509.Certificate
    67  	var caCert *x509.Certificate
    68  	if caCert, err = ca.Check(); err != nil {
    69  		return
    70  	}
    71  	caSigner := ca.PrivateKey //.Private()
    72  
    73  	// sign template
    74  	if certDER, err = x509.CreateCertificate(rand.Reader, template, caCert, publicKey, caSigner); err != nil {
    75  		err = perrors.Errorf("x509.CreateCertificate: '%w'", err)
    76  		return
    77  	}
    78  	return
    79  }
    80  
    81  func (ca *SelfSigned) Check() (cert *x509.Certificate, err error) {
    82  	if err = ca.PrivateKey.Validate(); err != nil {
    83  		return
    84  	}
    85  	if cert, err = ca.ParseCertificate(); perrors.IsPF(&err, "x509.ParseCertificate: '%w'", err) {
    86  		return
    87  	}
    88  	if cert.PublicKey == nil {
    89  		err = perrors.NewPF("public key uninitialied")
    90  		return
    91  	}
    92  	return
    93  }
    94  
    95  func (ca *SelfSigned) Private() (privateKey parl.PrivateKey) {
    96  	return ca.PrivateKey
    97  }