mirror of
https://github.com/golang/go.git
synced 2025-05-31 23:25:39 +00:00
crypto/x509: implement crypto.Signer
Signer is an interface to support opaque private keys. These keys typically result from being kept in special hardware (i.e. a TPM) although sometimes operating systems provide a similar interface using process isolation for security rather than hardware boundaries. This changes provides updates implements crypto.Signer in CreateCRL and CreateCertificate so that they can be used with opaque keys. This CL has been discussed at: http://golang.org/cl/145910043 Change-Id: Ie4a4a583fb120ff484a5ccf267ecd2a9c5a3902b Reviewed-on: https://go-review.googlesource.com/2254 Reviewed-by: Adam Langley <agl@golang.org>
This commit is contained in:
parent
8128b0116d
commit
cef15faafe
@ -12,7 +12,7 @@ import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rsa"
|
||||
"crypto/sha1"
|
||||
_ "crypto/sha1"
|
||||
_ "crypto/sha256"
|
||||
_ "crypto/sha512"
|
||||
"crypto/x509/pkix"
|
||||
@ -1389,14 +1389,14 @@ func subjectBytes(cert *Certificate) ([]byte, error) {
|
||||
return asn1.Marshal(cert.Subject.ToRDNSequence())
|
||||
}
|
||||
|
||||
// signingParamsForPrivateKey returns the parameters to use for signing with
|
||||
// signingParamsForPublicKey returns the parameters to use for signing with
|
||||
// priv. If requestedSigAlgo is not zero then it overrides the default
|
||||
// signature algorithm.
|
||||
func signingParamsForPrivateKey(priv interface{}, requestedSigAlgo SignatureAlgorithm) (hashFunc crypto.Hash, sigAlgo pkix.AlgorithmIdentifier, err error) {
|
||||
func signingParamsForPublicKey(pub interface{}, requestedSigAlgo SignatureAlgorithm) (hashFunc crypto.Hash, sigAlgo pkix.AlgorithmIdentifier, err error) {
|
||||
var pubType PublicKeyAlgorithm
|
||||
|
||||
switch priv := priv.(type) {
|
||||
case *rsa.PrivateKey:
|
||||
switch pub := pub.(type) {
|
||||
case *rsa.PublicKey:
|
||||
pubType = RSA
|
||||
hashFunc = crypto.SHA256
|
||||
sigAlgo.Algorithm = oidSignatureSHA256WithRSA
|
||||
@ -1404,10 +1404,10 @@ func signingParamsForPrivateKey(priv interface{}, requestedSigAlgo SignatureAlgo
|
||||
Tag: 5,
|
||||
}
|
||||
|
||||
case *ecdsa.PrivateKey:
|
||||
case *ecdsa.PublicKey:
|
||||
pubType = ECDSA
|
||||
|
||||
switch priv.Curve {
|
||||
switch pub.Curve {
|
||||
case elliptic.P224(), elliptic.P256():
|
||||
hashFunc = crypto.SHA256
|
||||
sigAlgo.Algorithm = oidSignatureECDSAWithSHA256
|
||||
@ -1422,7 +1422,7 @@ func signingParamsForPrivateKey(priv interface{}, requestedSigAlgo SignatureAlgo
|
||||
}
|
||||
|
||||
default:
|
||||
err = errors.New("x509: only RSA and ECDSA private keys supported")
|
||||
err = errors.New("x509: only RSA and ECDSA keys supported")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
@ -1469,10 +1469,10 @@ func signingParamsForPrivateKey(priv interface{}, requestedSigAlgo SignatureAlgo
|
||||
//
|
||||
// The returned slice is the certificate in DER encoding.
|
||||
//
|
||||
// The only supported key types are RSA and ECDSA (*rsa.PublicKey or
|
||||
// *ecdsa.PublicKey for pub, *rsa.PrivateKey or *ecdsa.PrivateKey for priv).
|
||||
func CreateCertificate(rand io.Reader, template, parent *Certificate, pub interface{}, priv interface{}) (cert []byte, err error) {
|
||||
hashFunc, signatureAlgorithm, err := signingParamsForPrivateKey(priv, template.SignatureAlgorithm)
|
||||
// All keys types that are implemented via crypto.Signer are supported (This
|
||||
// includes *rsa.PublicKey and *ecdsa.PublicKey.)
|
||||
func CreateCertificate(rand io.Reader, template, parent *Certificate, pub interface{}, priv crypto.Signer) (cert []byte, err error) {
|
||||
hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(priv.Public(), template.SignatureAlgorithm)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -1482,10 +1482,6 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub interf
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if len(parent.SubjectKeyId) > 0 {
|
||||
template.AuthorityKeyId = parent.SubjectKeyId
|
||||
}
|
||||
@ -1529,19 +1525,7 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub interf
|
||||
digest := h.Sum(nil)
|
||||
|
||||
var signature []byte
|
||||
|
||||
switch priv := priv.(type) {
|
||||
case *rsa.PrivateKey:
|
||||
signature, err = rsa.SignPKCS1v15(rand, priv, hashFunc, digest)
|
||||
case *ecdsa.PrivateKey:
|
||||
var r, s *big.Int
|
||||
if r, s, err = ecdsa.Sign(rand, priv, digest); err == nil {
|
||||
signature, err = asn1.Marshal(ecdsaSignature{r, s})
|
||||
}
|
||||
default:
|
||||
panic("internal error")
|
||||
}
|
||||
|
||||
signature, err = priv.Sign(rand, digest, hashFunc)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@ -1588,18 +1572,15 @@ func ParseDERCRL(derBytes []byte) (certList *pkix.CertificateList, err error) {
|
||||
|
||||
// CreateCRL returns a DER encoded CRL, signed by this Certificate, that
|
||||
// contains the given list of revoked certificates.
|
||||
//
|
||||
// The only supported key type is RSA (*rsa.PrivateKey for priv).
|
||||
func (c *Certificate) CreateCRL(rand io.Reader, priv interface{}, revokedCerts []pkix.RevokedCertificate, now, expiry time.Time) (crlBytes []byte, err error) {
|
||||
rsaPriv, ok := priv.(*rsa.PrivateKey)
|
||||
if !ok {
|
||||
return nil, errors.New("x509: non-RSA private keys not supported")
|
||||
func (c *Certificate) CreateCRL(rand io.Reader, priv crypto.Signer, revokedCerts []pkix.RevokedCertificate, now, expiry time.Time) (crlBytes []byte, err error) {
|
||||
hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(priv.Public(), 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tbsCertList := pkix.TBSCertificateList{
|
||||
Version: 1,
|
||||
Signature: pkix.AlgorithmIdentifier{
|
||||
Algorithm: oidSignatureSHA1WithRSA,
|
||||
},
|
||||
Version: 1,
|
||||
Signature: signatureAlgorithm,
|
||||
Issuer: c.Subject.ToRDNSequence(),
|
||||
ThisUpdate: now.UTC(),
|
||||
NextUpdate: expiry.UTC(),
|
||||
@ -1611,21 +1592,20 @@ func (c *Certificate) CreateCRL(rand io.Reader, priv interface{}, revokedCerts [
|
||||
return
|
||||
}
|
||||
|
||||
h := sha1.New()
|
||||
h := hashFunc.New()
|
||||
h.Write(tbsCertListContents)
|
||||
digest := h.Sum(nil)
|
||||
|
||||
signature, err := rsa.SignPKCS1v15(rand, rsaPriv, crypto.SHA1, digest)
|
||||
var signature []byte
|
||||
signature, err = priv.Sign(rand, digest, hashFunc)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return asn1.Marshal(pkix.CertificateList{
|
||||
TBSCertList: tbsCertList,
|
||||
SignatureAlgorithm: pkix.AlgorithmIdentifier{
|
||||
Algorithm: oidSignatureSHA1WithRSA,
|
||||
},
|
||||
SignatureValue: asn1.BitString{Bytes: signature, BitLength: len(signature) * 8},
|
||||
TBSCertList: tbsCertList,
|
||||
SignatureAlgorithm: signatureAlgorithm,
|
||||
SignatureValue: asn1.BitString{Bytes: signature, BitLength: len(signature) * 8},
|
||||
})
|
||||
}
|
||||
|
||||
@ -1699,26 +1679,19 @@ var oidExtensionRequest = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 14}
|
||||
//
|
||||
// The returned slice is the certificate request in DER encoding.
|
||||
//
|
||||
// The only supported key types are RSA (*rsa.PrivateKey) and ECDSA
|
||||
// (*ecdsa.PrivateKey).
|
||||
func CreateCertificateRequest(rand io.Reader, template *CertificateRequest, priv interface{}) (csr []byte, err error) {
|
||||
hashFunc, sigAlgo, err := signingParamsForPrivateKey(priv, template.SignatureAlgorithm)
|
||||
// All keys types that are implemented via crypto.Signer are supported (This
|
||||
// includes *rsa.PublicKey and *ecdsa.PublicKey.)
|
||||
func CreateCertificateRequest(rand io.Reader, template *CertificateRequest, priv crypto.Signer) (csr []byte, err error) {
|
||||
var hashFunc crypto.Hash
|
||||
var sigAlgo pkix.AlgorithmIdentifier
|
||||
hashFunc, sigAlgo, err = signingParamsForPublicKey(priv.Public(), template.SignatureAlgorithm)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var publicKeyBytes []byte
|
||||
var publicKeyAlgorithm pkix.AlgorithmIdentifier
|
||||
|
||||
switch priv := priv.(type) {
|
||||
case *rsa.PrivateKey:
|
||||
publicKeyBytes, publicKeyAlgorithm, err = marshalPublicKey(&priv.PublicKey)
|
||||
case *ecdsa.PrivateKey:
|
||||
publicKeyBytes, publicKeyAlgorithm, err = marshalPublicKey(&priv.PublicKey)
|
||||
default:
|
||||
panic("internal error")
|
||||
}
|
||||
|
||||
publicKeyBytes, publicKeyAlgorithm, err = marshalPublicKey(priv.Public())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -1830,18 +1803,7 @@ func CreateCertificateRequest(rand io.Reader, template *CertificateRequest, priv
|
||||
digest := h.Sum(nil)
|
||||
|
||||
var signature []byte
|
||||
switch priv := priv.(type) {
|
||||
case *rsa.PrivateKey:
|
||||
signature, err = rsa.SignPKCS1v15(rand, priv, hashFunc, digest)
|
||||
case *ecdsa.PrivateKey:
|
||||
var r, s *big.Int
|
||||
if r, s, err = ecdsa.Sign(rand, priv, digest); err == nil {
|
||||
signature, err = asn1.Marshal(ecdsaSignature{r, s})
|
||||
}
|
||||
default:
|
||||
panic("internal error")
|
||||
}
|
||||
|
||||
signature, err = priv.Sign(rand, digest, hashFunc)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ package x509
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto"
|
||||
"crypto/dsa"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
@ -304,10 +305,11 @@ func TestCreateSelfSignedCertificate(t *testing.T) {
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
pub, priv interface{}
|
||||
checkSig bool
|
||||
sigAlgo SignatureAlgorithm
|
||||
name string
|
||||
pub interface{}
|
||||
priv crypto.Signer
|
||||
checkSig bool
|
||||
sigAlgo SignatureAlgorithm
|
||||
}{
|
||||
{"RSA/RSA", &rsaPriv.PublicKey, rsaPriv, true, SHA1WithRSA},
|
||||
{"RSA/ECDSA", &rsaPriv.PublicKey, ecdsaPriv, false, ECDSAWithSHA384},
|
||||
@ -779,7 +781,7 @@ func TestCreateCertificateRequest(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
priv interface{}
|
||||
priv crypto.Signer
|
||||
sigAlgo SignatureAlgorithm
|
||||
}{
|
||||
{"RSA", rsaPriv, SHA1WithRSA},
|
||||
|
Loading…
x
Reference in New Issue
Block a user