// CreateSelfSignedCertificate creates a new certificate based on // a template. The following members of template are used: SerialNumber, // Subject, NotBefore, NotAfter, KeyUsage, BasicConstraintsValid, IsCA, // MaxPathLen, SubjectKeyId, DNSNames. // // The certificate is signed by parent. If parent is equal to template then the // certificate is self-signed. // // The returned slice is the certificate in DER encoding. func CreateCertificate(rand io.Reader, template, parent *Certificate, priv *rsa.PrivateKey) (cert []byte, err os.Error) { asn1PublicKey, err := asn1.MarshalToMemory(rsaPublicKey{ N: asn1.RawValue{Tag: 2, Bytes: priv.PublicKey.N.Bytes()}, E: priv.PublicKey.E, }) if err != nil { return } if len(template.SubjectKeyId) > 0 && len(parent.SubjectKeyId) > 0 { template.AuthorityKeyId = parent.SubjectKeyId } extensions, err := buildExtensions(template) if err != nil { return } encodedPublicKey := asn1.BitString{BitLength: len(asn1PublicKey) * 8, Bytes: asn1PublicKey} c := tbsCertificate{ Version: 3, SerialNumber: asn1.RawValue{Bytes: template.SerialNumber, Tag: 2}, SignatureAlgorithm: algorithmIdentifier{oidSHA1WithRSA}, Issuer: parent.Subject.toRDNSequence(), Validity: validity{template.NotBefore, template.NotAfter}, Subject: template.Subject.toRDNSequence(), PublicKey: publicKeyInfo{algorithmIdentifier{oidRSA}, encodedPublicKey}, Extensions: extensions, } tbsCertContents, err := asn1.MarshalToMemory(c) if err != nil { return } c.Raw = tbsCertContents h := sha1.New() h.Write(tbsCertContents) digest := h.Sum() signature, err := rsa.SignPKCS1v15(rand, priv, rsa.HashSHA1, digest) if err != nil { return } cert, err = asn1.MarshalToMemory(certificate{ c, algorithmIdentifier{oidSHA1WithRSA}, asn1.BitString{Bytes: signature, BitLength: len(signature) * 8}, }) return }
// MarshalPKCS1PrivateKey converts a private key to ASN.1 DER encoded form. func MarshalPKCS1PrivateKey(key *rsa.PrivateKey) []byte { priv := pkcs1PrivateKey{ Version: 1, N: asn1.RawValue{Tag: 2, Bytes: key.PublicKey.N.Bytes()}, E: key.PublicKey.E, D: asn1.RawValue{Tag: 2, Bytes: key.D.Bytes()}, P: asn1.RawValue{Tag: 2, Bytes: key.P.Bytes()}, Q: asn1.RawValue{Tag: 2, Bytes: key.Q.Bytes()}, } b, _ := asn1.MarshalToMemory(priv) return b }
func buildExtensions(template *Certificate) (ret []extension, err os.Error) { ret = make([]extension, 5 /* maximum number of elements. */) n := 0 if template.KeyUsage != 0 { ret[n].Id = oidExtensionKeyUsage ret[n].Critical = true var a [2]byte a[0] = reverseBitsInAByte(byte(template.KeyUsage)) a[1] = reverseBitsInAByte(byte(template.KeyUsage >> 8)) l := 1 if a[1] != 0 { l = 2 } ret[n].Value, err = asn1.MarshalToMemory(asn1.BitString{Bytes: a[0:l], BitLength: l * 8}) if err != nil { return } n++ } if template.BasicConstraintsValid { ret[n].Id = oidExtensionBasicConstraints ret[n].Value, err = asn1.MarshalToMemory(basicConstraints{template.IsCA, template.MaxPathLen}) ret[n].Critical = true if err != nil { return } n++ } if len(template.SubjectKeyId) > 0 { ret[n].Id = oidExtensionSubjectKeyId ret[n].Value, err = asn1.MarshalToMemory(template.SubjectKeyId) if err != nil { return } n++ } if len(template.AuthorityKeyId) > 0 { ret[n].Id = oidExtensionAuthorityKeyId ret[n].Value, err = asn1.MarshalToMemory(authKeyId{template.AuthorityKeyId}) if err != nil { return } n++ } if len(template.DNSNames) > 0 { ret[n].Id = oidExtensionSubjectAltName rawValues := make([]asn1.RawValue, len(template.DNSNames)) for i, name := range template.DNSNames { rawValues[i] = asn1.RawValue{Tag: 2, Class: 2, Bytes: []byte(name)} } ret[n].Value, err = asn1.MarshalToMemory(rawValues) if err != nil { return } n++ } // Adding another extension here? Remember to update the maximum number // of elements in the make() at the top of the function. return ret[0:n], nil }