Skip to content

Commit

Permalink
Add TBSCertificate.SignWithPredicate to abstract out sources-of-signa…
Browse files Browse the repository at this point in the history
…tures
  • Loading branch information
JackDoanRivian committed Oct 3, 2024
1 parent fd4d68a commit 5194e59
Showing 1 changed file with 43 additions and 34 deletions.
77 changes: 43 additions & 34 deletions cert/sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,22 +42,58 @@ type beingSignedCertificate interface {
setSignature([]byte) error
}

type SignerPredicate func(certBytes []byte) ([]byte, error)

// Sign will create a sealed certificate using details provided by the TBSCertificate as long as those
// details do not violate constraints of the signing certificate.
// If the TBSCertificate is a CA then signer must be nil.
func (t *TBSCertificate) Sign(signer Certificate, curve Curve, key []byte) (Certificate, error) {
return t.sign(signer, curve, key, nil)
func (t *TBSCertificate) Sign(signWith Certificate, curve Curve, key []byte) (Certificate, error) {
switch t.Curve {
case Curve_CURVE25519:
signer := ed25519.PrivateKey(key)
sp := func(certBytes []byte) ([]byte, error) {
sig := ed25519.Sign(signer, certBytes)
return sig, nil
}
return t.SignWithPredicate(signWith, curve, sp)
case Curve_P256:
signer := &ecdsa.PrivateKey{
PublicKey: ecdsa.PublicKey{
Curve: elliptic.P256(),
},
// ref: https://github.com/golang/go/blob/go1.19/src/crypto/x509/sec1.go#L95
D: new(big.Int).SetBytes(key),
}
// ref: https://github.com/golang/go/blob/go1.19/src/crypto/x509/sec1.go#L119
signer.X, signer.Y = signer.Curve.ScalarBaseMult(key)
sp := func(certBytes []byte) ([]byte, error) {
// We need to hash first for ECDSA
// - https://pkg.go.dev/crypto/ecdsa#SignASN1
hashed := sha256.Sum256(certBytes)
return ecdsa.SignASN1(rand.Reader, signer, hashed[:])
}
return t.SignWithPredicate(signWith, curve, sp)
default:
return nil, fmt.Errorf("invalid curve: %s", t.Curve)
}
}

func (t *TBSCertificate) SignPkcs11(signer Certificate, curve Curve, client *pkclient.PKClient) (Certificate, error) {
if curve != Curve_P256 {
if client == nil {
return nil, fmt.Errorf("pkclient must be non-nil")
}
switch t.Curve {
case Curve_CURVE25519:
return nil, fmt.Errorf("only P256 is supported by PKCS#11")
case Curve_P256:
//todo: verify that pkcs11 hashes for you
return t.SignWithPredicate(signer, curve, client.SignASN1)
default:
return nil, fmt.Errorf("invalid curve: %s", t.Curve)
}

return t.sign(signer, curve, nil, client)
}

func (t *TBSCertificate) sign(signer Certificate, curve Curve, key []byte, client *pkclient.PKClient) (Certificate, error) {
func (t *TBSCertificate) SignWithPredicate(signer Certificate, curve Curve, sp SignerPredicate) (Certificate, error) {
if curve != t.Curve {
return nil, fmt.Errorf("curve in cert and private key supplied don't match")
}
Expand Down Expand Up @@ -112,34 +148,7 @@ func (t *TBSCertificate) sign(signer Certificate, curve Curve, key []byte, clien
return nil, err
}

var sig []byte
switch t.Curve {
case Curve_CURVE25519:
signer := ed25519.PrivateKey(key)
sig = ed25519.Sign(signer, certBytes)
case Curve_P256:
if client != nil {
sig, err = client.SignASN1(certBytes)
} else {
signer := &ecdsa.PrivateKey{
PublicKey: ecdsa.PublicKey{
Curve: elliptic.P256(),
},
// ref: https://github.com/golang/go/blob/go1.19/src/crypto/x509/sec1.go#L95
D: new(big.Int).SetBytes(key),
}
// ref: https://github.com/golang/go/blob/go1.19/src/crypto/x509/sec1.go#L119
signer.X, signer.Y = signer.Curve.ScalarBaseMult(key)

// We need to hash first for ECDSA
// - https://pkg.go.dev/crypto/ecdsa#SignASN1
hashed := sha256.Sum256(certBytes)
sig, err = ecdsa.SignASN1(rand.Reader, signer, hashed[:])
}
default:
return nil, fmt.Errorf("invalid curve: %s", t.Curve)
}

sig, err := sp(certBytes)
if err != nil {
return nil, err
}
Expand Down

0 comments on commit 5194e59

Please sign in to comment.