aboutsummaryrefslogtreecommitdiff
path: root/certificate.go
diff options
context:
space:
mode:
Diffstat (limited to 'certificate.go')
-rw-r--r--certificate.go212
1 files changed, 112 insertions, 100 deletions
diff --git a/certificate.go b/certificate.go
index d065ab2..ac66fbc 100644
--- a/certificate.go
+++ b/certificate.go
@@ -1,83 +1,87 @@
package pki
import (
- "crypto/rand"
- "crypto/x509"
- "crypto/x509/pkix"
- "encoding/pem"
- "fmt"
- "math/big"
- "net"
- "time"
+ "crypto/rand"
+ "crypto/x509"
+ "crypto/x509/pkix"
+ "encoding/pem"
+ "fmt"
+ "math/big"
+ "net"
+ "time"
)
// labels used in the pem file format to mark certificate sign requests and certificates
const (
- PemLabelCertificateRequest = "CERTIFICATE REQUEST"
- PemLabelCertificate = "CERTIFICATE"
+ PemLabelCertificateRequest = "CERTIFICATE REQUEST"
+ PemLabelCertificate = "CERTIFICATE"
)
type (
- // Use CertificateData to fill in the minimum data you need to create a certificate
- // sign request.
- CertificateData struct {
- Subject pkix.Name
-
- DNSNames []string
- EmailAddresses []string
- IPAddresses []net.IP
- }
-
- // Certificate is an alias on the x509.Certificate to add some methods.
- Certificate x509.Certificate
- // CertificateRequest is an alias on the x509.CertificateRequest to add some methods.
- CertificateRequest x509.CertificateRequest
-
- // CertificateOptions is used to provide the necessary information to create
- // a certificate from a certificate sign request.
- CertificateOptions struct {
- SerialNumber *big.Int
- NotBefore time.Time
- NotAfter time.Time // Validity bounds.
- IsCA bool
- // how many sub ca are allowed between this ca and the end/final certificate
- // if it is -1, then no limit will be set
- CALength int
- KeyUsage x509.KeyUsage
- }
+ // Use CertificateData to fill in the minimum data you need to create a certificate
+ // sign request.
+ CertificateData struct {
+ Subject pkix.Name
+
+ DNSNames []string
+ EmailAddresses []string
+ IPAddresses []net.IP
+ }
+
+ // Certificate is an alias on the x509.Certificate to add some methods.
+ Certificate x509.Certificate
+ // CertificateRequest is an alias on the x509.CertificateRequest to add some methods.
+ CertificateRequest x509.CertificateRequest
+
+ // CertificateOptions is used to provide the necessary information to create
+ // a certificate from a certificate sign request.
+ CertificateOptions struct {
+ SerialNumber *big.Int
+ NotBefore time.Time
+ NotAfter time.Time // Validity bounds.
+ IsCA bool
+ // how many sub ca are allowed between this ca and the end/final certificate
+ // if it is -1, then no limit will be set
+ CALength int
+ KeyUsage x509.KeyUsage
+ }
)
// Create a new set of certificate data.
func NewCertificateData() *CertificateData {
- return &CertificateData{Subject: pkix.Name{}}
+ return &CertificateData{Subject: pkix.Name{}}
}
// Create a certificate sign request from the input data and the private key of
// the request creator.
func (c *CertificateData) ToCertificateRequest(private_key PrivateKey) (*CertificateRequest, error) {
- csr := &x509.CertificateRequest{}
-
- csr.Subject = c.Subject
- csr.DNSNames = c.DNSNames
- csr.IPAddresses = c.IPAddresses
- csr.EmailAddresses = c.EmailAddresses
-
- csr_asn1, err := x509.CreateCertificateRequest(rand.Reader, csr, private_key.PrivateKey())
- if err != nil { return nil, err }
- return LoadCertificateSignRequest(csr_asn1)
+ csr := &x509.CertificateRequest{}
+
+ csr.Subject = c.Subject
+ csr.DNSNames = c.DNSNames
+ csr.IPAddresses = c.IPAddresses
+ csr.EmailAddresses = c.EmailAddresses
+
+ csr_asn1, err := x509.CreateCertificateRequest(rand.Reader, csr, private_key.PrivateKey())
+ if err != nil {
+ return nil, err
+ }
+ return LoadCertificateSignRequest(csr_asn1)
}
// Load a certificate sign request from its asn1 representation.
func LoadCertificateSignRequest(raw []byte) (*CertificateRequest, error) {
- csr, err := x509.ParseCertificateRequest(raw)
- if err != nil { return nil, err }
- return (*CertificateRequest)(csr), nil
+ csr, err := x509.ParseCertificateRequest(raw)
+ if err != nil {
+ return nil, err
+ }
+ return (*CertificateRequest)(csr), nil
}
// Return the certificate sign request as a pem block.
func (c *CertificateRequest) MarshalPem() (marshalledPemBlock, error) {
- block := &pem.Block{Type: PemLabelCertificateRequest, Bytes: c.Raw}
- return pem.EncodeToMemory(block), nil
+ block := &pem.Block{Type: PemLabelCertificateRequest, Bytes: c.Raw}
+ return pem.EncodeToMemory(block), nil
}
// Convert the certificate sign request to a certificate using the private key
@@ -86,63 +90,71 @@ func (c *CertificateRequest) MarshalPem() (marshalledPemBlock, error) {
// Please also see the certificate options struct for information on mandatory fields.
// For more information, please read http://golang.org/pkg/crypto/x509/#CreateCertificate
func (c *CertificateRequest) ToCertificate(private_key PrivateKey,
- cert_opts CertificateOptions, ca *Certificate) (*Certificate, error) {
-
- if err := cert_opts.Valid(); err != nil { return nil, err }
-
- template := &x509.Certificate{}
- template.Subject = c.Subject
- template.DNSNames = c.DNSNames
- template.IPAddresses = c.IPAddresses
- template.EmailAddresses = c.EmailAddresses
-
- // if no ca is given, we have to set IsCA to self sign
- if ca == nil {
- template.IsCA = true
- }
-
- template.NotBefore = cert_opts.NotBefore
- template.NotAfter = cert_opts.NotAfter
- template.KeyUsage = cert_opts.KeyUsage
- template.IsCA = cert_opts.IsCA
- if cert_opts.IsCA {
- template.BasicConstraintsValid = true
- }
- if cert_opts.CALength >= 0 {
- template.MaxPathLen = cert_opts.CALength
- template.MaxPathLenZero = true
- template.BasicConstraintsValid = true
- }
- template.SerialNumber = cert_opts.SerialNumber
-
- var cert_asn1 []byte
- var err error
- // if we have no ca which can sign the cert, a self signed cert is wanted
- // (or isn't it? Maybe we should split creation of the template? But that would be ugly)
- if ca == nil {
- cert_asn1, err = x509.CreateCertificate(rand.Reader, template, template, c.PublicKey, private_key.PrivateKey())
- } else {
- cert_asn1, err = x509.CreateCertificate(rand.Reader, template, (*x509.Certificate)(ca), c.PublicKey, private_key.PrivateKey())
- }
- if err != nil { return nil, err }
- return LoadCertificate(cert_asn1)
+ cert_opts CertificateOptions, ca *Certificate) (*Certificate, error) {
+
+ if err := cert_opts.Valid(); err != nil {
+ return nil, err
+ }
+
+ template := &x509.Certificate{}
+ template.Subject = c.Subject
+ template.DNSNames = c.DNSNames
+ template.IPAddresses = c.IPAddresses
+ template.EmailAddresses = c.EmailAddresses
+
+ // if no ca is given, we have to set IsCA to self sign
+ if ca == nil {
+ template.IsCA = true
+ }
+
+ template.NotBefore = cert_opts.NotBefore
+ template.NotAfter = cert_opts.NotAfter
+ template.KeyUsage = cert_opts.KeyUsage
+ template.IsCA = cert_opts.IsCA
+ if cert_opts.IsCA {
+ template.BasicConstraintsValid = true
+ }
+ if cert_opts.CALength >= 0 {
+ template.MaxPathLen = cert_opts.CALength
+ template.MaxPathLenZero = true
+ template.BasicConstraintsValid = true
+ }
+ template.SerialNumber = cert_opts.SerialNumber
+
+ var cert_asn1 []byte
+ var err error
+ // if we have no ca which can sign the cert, a self signed cert is wanted
+ // (or isn't it? Maybe we should split creation of the template? But that would be ugly)
+ if ca == nil {
+ cert_asn1, err = x509.CreateCertificate(rand.Reader, template, template, c.PublicKey, private_key.PrivateKey())
+ } else {
+ cert_asn1, err = x509.CreateCertificate(rand.Reader, template, (*x509.Certificate)(ca), c.PublicKey, private_key.PrivateKey())
+ }
+ if err != nil {
+ return nil, err
+ }
+ return LoadCertificate(cert_asn1)
}
// Load a certificate from its asn1 representation.
func LoadCertificate(raw []byte) (*Certificate, error) {
- cert, err := x509.ParseCertificate(raw)
- if err != nil { return nil, err }
- return (*Certificate)(cert), nil
+ cert, err := x509.ParseCertificate(raw)
+ if err != nil {
+ return nil, err
+ }
+ return (*Certificate)(cert), nil
}
// marshal the certificate to a pem block
func (c *Certificate) MarshalPem() (marshalledPemBlock, error) {
- block := &pem.Block{Type: PemLabelCertificate, Bytes: c.Raw}
- return pem.EncodeToMemory(block), nil
+ block := &pem.Block{Type: PemLabelCertificate, Bytes: c.Raw}
+ return pem.EncodeToMemory(block), nil
}
// Check if the certificate options have the required fields set.
func (co *CertificateOptions) Valid() error {
- if co.SerialNumber == nil { return fmt.Errorf("No serial number set!") }
- return nil
+ if co.SerialNumber == nil {
+ return fmt.Errorf("No serial number set!")
+ }
+ return nil
}