Skip to content

Commit

Permalink
Make built-in types implement the new DigestSigner and DigestVerify i…
Browse files Browse the repository at this point in the history
…nterface

Signed-off-by: qmuntal <[email protected]>
  • Loading branch information
qmuntal committed May 12, 2023
1 parent 77e3f9f commit 4277f81
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 6 deletions.
22 changes: 22 additions & 0 deletions ecdsa.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,13 @@ func (es *ecdsaKeySigner) Sign(rand io.Reader, content []byte) ([]byte, error) {
if err != nil {
return nil, err
}
return es.SignDigest(rand, digest)
}

// SignDigest signs message digest with the private key, possibly using
// entropy from rand.
// The resulting signature should follow RFC 8152 section 8.
func (es *ecdsaKeySigner) SignDigest(rand io.Reader, digest []byte) ([]byte, error) {
r, s, err := ecdsa.Sign(rand, es.key, digest)
if err != nil {
return nil, err
Expand Down Expand Up @@ -86,6 +93,13 @@ func (es *ecdsaCryptoSigner) Sign(rand io.Reader, content []byte) ([]byte, error
if err != nil {
return nil, err
}
return es.SignDigest(rand, digest)
}

// SignDigest signs message digest with the private key, possibly using
// entropy from rand.
// The resulting signature should follow RFC 8152 section 8.
func (es *ecdsaCryptoSigner) SignDigest(rand io.Reader, digest []byte) ([]byte, error) {
sigASN1, err := es.signer.Sign(rand, digest, nil)
if err != nil {
return nil, err
Expand Down Expand Up @@ -153,7 +167,15 @@ func (ev *ecdsaVerifier) Verify(content []byte, signature []byte) error {
if err != nil {
return err
}
return ev.VerifyDigest(digest, signature)
}

// VerifyDigest verifies message digest with the public key, returning nil
// for success.
// Otherwise, it returns ErrVerification.
//
// Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-8.1
func (ev *ecdsaVerifier) VerifyDigest(digest, signature []byte) error {
// verify signature
r, s, err := decodeECDSASignature(ev.key.Curve, signature)
if err != nil {
Expand Down
26 changes: 20 additions & 6 deletions rsa.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,20 @@ func (rs *rsaSigner) Algorithm() Algorithm {
//
// Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-8
func (rs *rsaSigner) Sign(rand io.Reader, content []byte) ([]byte, error) {
hash := rs.alg.hashFunc()
digest, err := computeHash(hash, content)
digest, err := rs.alg.computeHash(content)
if err != nil {
return nil, err
}
return rs.SignDigest(rand, digest)
}

// SignDigest signs message digest with the private key, possibly using
// entropy from rand.
// The resulting signature should follow RFC 8152 section 8.
func (rs *rsaSigner) SignDigest(rand io.Reader, digest []byte) ([]byte, error) {
return rs.key.Sign(rand, digest, &rsa.PSSOptions{
SaltLength: rsa.PSSSaltLengthEqualsHash, // defined in RFC 8230 sec 2
Hash: hash,
Hash: rs.alg.hashFunc(),
})
}

Expand All @@ -54,12 +60,20 @@ func (rv *rsaVerifier) Algorithm() Algorithm {
//
// Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-8
func (rv *rsaVerifier) Verify(content []byte, signature []byte) error {
hash := rv.alg.hashFunc()
digest, err := computeHash(hash, content)
digest, err := rv.alg.computeHash(content)
if err != nil {
return err
}
if err := rsa.VerifyPSS(rv.key, hash, digest, signature, &rsa.PSSOptions{
return rv.VerifyDigest(digest, signature)
}

// VerifyDigest verifies message digest with the public key, returning nil
// for success.
// Otherwise, it returns ErrVerification.
//
// Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-8.1
func (rv *rsaVerifier) VerifyDigest(digest, signature []byte) error {
if err := rsa.VerifyPSS(rv.key, rv.alg.hashFunc(), digest, signature, &rsa.PSSOptions{
SaltLength: rsa.PSSSaltLengthEqualsHash, // defined in RFC 8230 sec 2
}); err != nil {
return ErrVerification
Expand Down
12 changes: 12 additions & 0 deletions signer.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@ type Signer interface {
Sign(rand io.Reader, content []byte) ([]byte, error)
}

// DigestSigner is an interface for private keys to sign digested COSE signatures.
type DigestSigner interface {
Signer

// SignDigest signs message digest with the private key, possibly using
// entropy from rand.
// The resulting signature should follow RFC 8152 section 8.
SignDigest(rand io.Reader, digest []byte) ([]byte, error)
}

// NewSigner returns a signer with a given signing key.
// The signing key can be a golang built-in crypto private key, a key in HSM, or
// a remote KMS.
Expand All @@ -34,6 +44,8 @@ type Signer interface {
// public key of type `*rsa.PublicKey`, `*ecdsa.PublicKey`, or
// `ed25519.PublicKey` are accepted.
//
// The returned signer for rsa and ecdsa keys also implements `cose.DigestSigner`.
//
// Note: `*rsa.PrivateKey`, `*ecdsa.PrivateKey`, and `ed25519.PrivateKey`
// implement `crypto.Signer`.
func NewSigner(alg Algorithm, key crypto.Signer) (Signer, error) {
Expand Down
12 changes: 12 additions & 0 deletions verifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,21 @@ type Verifier interface {
Verify(content, signature []byte) error
}

// DigestVerifier is an interface for public keys to verify digested COSE signatures.
type DigestVerifier interface {
Verifier

// VerifyDigest verifies message digest with the public key, returning nil
// for success.
// Otherwise, it returns ErrVerification.
VerifyDigest(digest, signature []byte) error
}

// NewVerifier returns a verifier with a given public key.
// Only golang built-in crypto public keys of type `*rsa.PublicKey`,
// `*ecdsa.PublicKey`, and `ed25519.PublicKey` are accepted.
//
// The returned signer for rsa and ecdsa keys also implements `cose.DigestSigner`.
func NewVerifier(alg Algorithm, key crypto.PublicKey) (Verifier, error) {
switch alg {
case AlgorithmPS256, AlgorithmPS384, AlgorithmPS512:
Expand Down

0 comments on commit 4277f81

Please sign in to comment.