예제 #1
0
// 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
}
예제 #2
0
// 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
}
예제 #3
0
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
}