8236765e9c
This change generates the certificate subject key identifier using the recommended method in the RFC 5280 section 4.2.1.2.
76 lines
2.3 KiB
Go
76 lines
2.3 KiB
Go
package x509util
|
|
|
|
import (
|
|
"crypto"
|
|
"crypto/rand"
|
|
"crypto/sha1"
|
|
"crypto/x509"
|
|
"crypto/x509/pkix"
|
|
"encoding/asn1"
|
|
"math/big"
|
|
"net"
|
|
"net/url"
|
|
|
|
"github.com/pkg/errors"
|
|
"github.com/smallstep/cli/crypto/x509util"
|
|
)
|
|
|
|
// SplitSANs splits a slice of Subject Alternative Names into slices of
|
|
// IP Addresses and DNS Names. If an element is not an IP address, then it
|
|
// is bucketed as a DNS Name.
|
|
func SplitSANs(sans []string) (dnsNames []string, ips []net.IP, emails []string, uris []*url.URL) {
|
|
return x509util.SplitSANs(sans)
|
|
}
|
|
|
|
func CreateSANs(sans []string) []SubjectAlternativeName {
|
|
dnsNames, ips, emails, uris := SplitSANs(sans)
|
|
sanTypes := make([]SubjectAlternativeName, 0, len(sans))
|
|
for _, v := range dnsNames {
|
|
sanTypes = append(sanTypes, SubjectAlternativeName{Type: "dns", Value: v})
|
|
}
|
|
for _, v := range ips {
|
|
sanTypes = append(sanTypes, SubjectAlternativeName{Type: "ip", Value: v.String()})
|
|
}
|
|
for _, v := range emails {
|
|
sanTypes = append(sanTypes, SubjectAlternativeName{Type: "email", Value: v})
|
|
}
|
|
for _, v := range uris {
|
|
sanTypes = append(sanTypes, SubjectAlternativeName{Type: "uri", Value: v.String()})
|
|
}
|
|
return sanTypes
|
|
}
|
|
|
|
// generateSerialNumber returns a random serial number.
|
|
func generateSerialNumber() (*big.Int, error) {
|
|
limit := new(big.Int).Lsh(big.NewInt(1), 128)
|
|
sn, err := rand.Int(rand.Reader, limit)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "error generating serial number")
|
|
}
|
|
return sn, nil
|
|
}
|
|
|
|
// subjectPublicKeyInfo is a PKIX public key structure defined in RFC 5280.
|
|
type subjectPublicKeyInfo struct {
|
|
Algorithm pkix.AlgorithmIdentifier
|
|
SubjectPublicKey asn1.BitString
|
|
}
|
|
|
|
// generateSubjectKeyID generates the key identifier according the the RFC 5280
|
|
// section 4.2.1.2.
|
|
//
|
|
// The keyIdentifier is composed of the 160-bit SHA-1 hash of the value of the
|
|
// BIT STRING subjectPublicKey (excluding the tag, length, and number of unused
|
|
// bits).
|
|
func generateSubjectKeyID(pub crypto.PublicKey) ([]byte, error) {
|
|
b, err := x509.MarshalPKIXPublicKey(pub)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "error marshaling public key")
|
|
}
|
|
var info subjectPublicKeyInfo
|
|
if _, err = asn1.Unmarshal(b, &info); err != nil {
|
|
return nil, errors.Wrap(err, "error unmarshaling public key")
|
|
}
|
|
hash := sha1.Sum(info.SubjectPublicKey.Bytes)
|
|
return hash[:], nil
|
|
}
|