smolcert

package module
v0.2.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 18, 2021 License: MIT Imports: 8 Imported by: 1

README

smolcert CircleCI codecov GoDoc

smolcert is an implementation of CBOR based certificates inspired by CBOR Profile of X.509 Certificates.

The goal is to have a more compact and easier to parse (especially on embedded systems) certificate format than X.509. The certificate format is specified as CDDL in the file spec.cddl. Generated binary encoded certificates can be verified against this specification.

Currently exist implementations in go and Rust, where the go implementation is the more complete, with support for easy certificate creation, signing and validation. The Rust implementation currently only supports serialization and deserialization of certificates, but no signing, verification etc.

Example

// Create a self signed certificate (i.e. as root certificate)
cert, privateKey, err := SelfSignedCertificate("root",
		time.Now().Add(time.Minute*-1),
		time.Now().Add(time.Minute),
		[]Extension{})
require.NoError(t, err)
err = validateCertificate(cert, cert.PubKey)
assert.NoError(t, err)

Running tests

go test will only run tests which only depend on go. To test more you need specify tags for the test command. If you want to verify that the serilization implementation generates valid data you need to specify the cddltest tag (go test -tags cddltest). Of course tags can be combined (go test -tags rust,cddltest).

If you want to validate that the implementations generate valid CBOR you need to install the cddl tool. This called during tests behind the cddltest flag.

Documentation

Overview

Package smolcert implements CBOR based certificates loosely based on the CBOR profile for X.509 certificates (https://tools.ietf.org/id/draft-raza-ace-cbor-certificates-00.html)

Current ToDos: - Limit key usage, not everyone should be able to sign keys - probably more

Index

Constants

View Source
const (
	// OIDKeyUsage specifies a KeyUsage extension. The ID right is arbitrary, we need to find a system...
	OIDKeyUsage uint64 = 0x10
)

Variables

View Source
var (
	// ErrorExtensionNotFound is the expected error if a required extension can't be found
	ErrorExtensionNotFound = errors.New("Required extension not found")
)
View Source
var ZeroTime = Time(0)

ZeroTime represent a zero timestamp which might indicate that this timestamp can be ignored

Functions

func RequiresExtension

func RequiresExtension(cert *Certificate, oid uint64, validate ValidateExtension) error

RequiresExtension checks if a certificate contains an Extension with a specific OID and validates the content of this extension via the ValidateExtension function

func Serialize

func Serialize(cert *Certificate, w io.Writer) (err error)

Serialize serializes a Certificate to an io.Writer

Types

type CertPool

type CertPool map[string]*Certificate

CertPool is a pool of root certificates which can be used to validate a certificate

func NewCertPool

func NewCertPool(rootCerts ...*Certificate) *CertPool

NewCertPool creates a new CertPool from a group of root certificates

func (*CertPool) Validate

func (c *CertPool) Validate(cert *Certificate) error

Validate takes a certificate, checks if the issuer is known to the CertPool, validates the issuer certificate and then validates the given certificate against the issuer certificate

func (*CertPool) ValidateBundle

func (c *CertPool) ValidateBundle(certBundle []*Certificate) (clientCert *Certificate, err error)

ValidateBundle validates a given bundle of certificates. It tries to build a chain of certificates within the given bundle. Uses the leaf as the client certificate and tries to validate the top certificate against the CertPool.

type Certificate

type Certificate struct {
	SerialNumber uint64 `cbor:"serial_number"`
	Issuer       string `cbor:"issuer"`
	// NotBefore and NotAfter might be 0 to indicate to be ignored during validation
	Validity   *Validity         `cbor:"validity,omitempty"`
	Subject    string            `cbor:"subject"`
	PubKey     ed25519.PublicKey `cbor:"public_key"`
	Extensions []Extension       `cbor:"extensions"`
	Signature  []byte            `cbor:"signature"`
	// contains filtered or unexported fields
}

Certificate represents CBOR based certificates based on the provide spec.cddl

func ClientCertificate

func ClientCertificate(subject string, serialNumber uint64, notBefore, notAfter time.Time,
	extensions []Extension, rootKey ed25519.PrivateKey, issuer string) (*Certificate, ed25519.PrivateKey, error)

ClientCertificate is a convenience function to create a valid client certificate

func Parse

func Parse(r io.Reader) (cert *Certificate, err error)

Parse parses a Certificate from an io.Reader

func ParseBuf

func ParseBuf(buf []byte) (cert *Certificate, err error)

ParseBuf parses a certificate from an existing byte buffer

func SelfSignedCertificate

func SelfSignedCertificate(subject string,
	notBefore, notAfter time.Time,
	extensions []Extension) (*Certificate, ed25519.PrivateKey, error)

SelfSignedCertificate is a simple function to generate a self signed certificate

func ServerCertificate

func ServerCertificate(subject string, serialNumber uint64, notBefore, notAfter time.Time,
	extensions []Extension, rootKey ed25519.PrivateKey, issuer string) (*Certificate, ed25519.PrivateKey, error)

ServerCertificate is a convenience function to create a valid server certificate

func SignCertificate

func SignCertificate(cert *Certificate, priv ed25519.PrivateKey) (*Certificate, error)

SignCertificate takes a certificate, removes the signature and creates a new signature with the given key

func SignedCertificate

func SignedCertificate(subject string, serialNumber uint64, notBefore, notAfter time.Time,
	extensions []Extension, rootKey ed25519.PrivateKey, issuer string) (*Certificate, ed25519.PrivateKey, error)

SignedCertificate creates a new certificate signed with the specified rooKey and issuer.

func (*Certificate) Bytes

func (c *Certificate) Bytes() ([]byte, error)

Bytes returns the CBOR encoded form of the certificate as byte slice

func (*Certificate) Copy

func (c *Certificate) Copy() *Certificate

Copy creates a deep copy of this certificate. This can be useful for operations where we need to change parts of the certificate, but need to continue working with an unaltered original.

func (*Certificate) PublicKey

func (c *Certificate) PublicKey() []byte

PublicKey returns the public key of this certificate as byte slice. Implements the github.com/connctd/noise.Identity interface.

type Extension

type Extension struct {
	OID      uint64 `cbor:"oid"`
	Critical bool   `cbor:"critical"`
	Value    []byte `cbor:"value"`
	// contains filtered or unexported fields
}

Extension represents a Certificate Extension as specified for X.509 certificates

type KeyUsage

type KeyUsage uint8

KeyUsage limits for what the public key in a certificate can be used. Certain KeyUsages may be required for certain tasks (i.e. certificate validation, client identification etc.), but every Certificate can only specify one KeyUsage.

const (
	KeyUsageClientIdentification KeyUsage = 0x01
	KeyUsageServerIdentification KeyUsage = 0x02
	KeyUsageSignCert             KeyUsage = 0x03
)

Defined KeyUsages

func ParseKeyUsage

func ParseKeyUsage(in []byte) (KeyUsage, error)

ParseKeyUsage parses the KeyUsage from a byte slice, i.e. the Value of an Extension

func (KeyUsage) String

func (k KeyUsage) String() string

String returns a String representation for logging and debugging

func (KeyUsage) ToBytes

func (k KeyUsage) ToBytes() []byte

ToBytes returns the byte representation of a KeyUsage to be used as Value in an Extension

type Time

type Time int64

Time is a type to represent int encoded time stamps based on the elapsed seconds since epoch

func NewTime

func NewTime(now time.Time) Time

NewTime creates a new Time from a given time.Time with second precision

func (Time) IsZero

func (t Time) IsZero() bool

IsZero is true if this is a zero time

func (Time) StdTime

func (t Time) StdTime() time.Time

StdTime returns a time.Time with second precision

type ValidateExtension

type ValidateExtension func(critical bool, val []byte) error

ValidateExtension is the definition of functions which can't be used with RequiresExtension to validate the the Value and Critical flag of an Extension

func ExpectKeyUsage

func ExpectKeyUsage(expectedKeyUsage KeyUsage) ValidateExtension

ExpectKeyUsage ensures that the KeyUsage Extension specifies the expected KeyUsage

type Validity

type Validity struct {
	NotBefore Time `cbor:"notBefore"`
	NotAfter  Time `cbor:"notAfter"`
	// contains filtered or unexported fields
}

Validity represents the time constrained validity of a Certificate. NotBefore might be ZeroTime to ignore this constraint, same goes for NotAfter

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL