@ -14,6 +14,10 @@ import (
import "github.com/namecoin/ncdns/x509"
// A DehydratedCertificate represents the (nearly) minimal set of data required
// to deterministically construct a valid x509 certificate when combined with a
// domain name. See the Dehydrated TLS Certificates specification at:
// https://github.com/namecoin/proposals/blob/master/ifa-0003.md
// TODO: add a version field
type DehydratedCertificate struct {
PubkeyB64 string
@ -23,6 +27,8 @@ type DehydratedCertificate struct {
SignatureB64 string
}
// SerialNumber calculates the certificate serial number according to the
// Dehydrated TLS Certificates specification.
func ( dehydrated DehydratedCertificate ) SerialNumber ( name string ) ( [ ] byte , error ) {
nameHash := sha256 . Sum256 ( [ ] byte ( name ) )
@ -63,6 +69,8 @@ func (dehydrated DehydratedCertificate) String() string {
return string ( binOutput )
}
// ParseDehydratedCert parses a dehydrated certificate from an interface as
// would be returned by a JSON Unmarshaler.
func ParseDehydratedCert ( data interface { } ) ( * DehydratedCertificate , error ) {
dehydrated , ok := data . ( [ ] interface { } )
if ! ok {
@ -122,6 +130,9 @@ func ParseDehydratedCert(data interface{}) (*DehydratedCertificate, error) {
return & result , nil
}
// DehydrateCert dehydrates a certificate. If the input certificate is not
// compatible with the Dehydrated TLS Certificates specification, the resulting
// dehydrated certificate will not rehydrate into a valid x509 certificate.
func DehydrateCert ( cert * x509 . Certificate ) ( * DehydratedCertificate , error ) {
pubkeyBytes , err := x509 . MarshalPKIXPublicKey ( cert . PublicKey )
@ -154,10 +165,10 @@ func DehydrateCert(cert *x509.Certificate) (*DehydratedCertificate, error) {
return & result , nil
}
// Accepts as input the bare minimum data needed to produce a valid cert.
// The input is untrusted.
// The output is safe.
// The timestamps are in 5-minute increments.
// RehydrateCert converts a dehydrated certificate into a standard x509
// certificate, but does not fill in the domain name or any fields that depend
// on it. The resulting certificate is intended to be used as input to
// FillRehydratedCertTemplate.
func RehydrateCert ( dehydrated * DehydratedCertificate ) ( * x509 . Certificate , error ) {
pubkeyBin , err := base64 . StdEncoding . DecodeString ( dehydrated . PubkeyB64 )
@ -205,6 +216,9 @@ func RehydrateCert(dehydrated *DehydratedCertificate) (*x509.Certificate, error)
return & template , nil
}
// FillRehydratedCertTemplate fills in the domain name (and all dependent
// fields) to an x509 certificate that was returned by RehydrateCert, and
// returns a []byte suitable for inserting into a TLS trust store.
func FillRehydratedCertTemplate ( template x509 . Certificate , name string ) ( [ ] byte , error ) {
template . Subject = pkix . Name {