Skip to content

Commit

Permalink
Add back crypto.Signer support for ECDSA signing keys (#227)
Browse files Browse the repository at this point in the history
Currently only PubKeyAlgoRSA supports crypto.Signer. x/crypto/openpgp
originally had support for ECDSA external crypto.Signer. This change adds
that back.
  • Loading branch information
doryiii authored Sep 11, 2024
1 parent 0f7b935 commit 2add693
Showing 1 changed file with 24 additions and 2 deletions.
26 changes: 24 additions & 2 deletions openpgp/packet/signature.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
package packet

import (
"math/big"
"bytes"
"crypto"
"crypto/dsa"
"encoding/asn1"
"encoding/binary"
"hash"
"io"
Expand Down Expand Up @@ -927,8 +929,16 @@ func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err e
sig.DSASigS = new(encoding.MPI).SetBig(s)
}
case PubKeyAlgoECDSA:
sk := priv.PrivateKey.(*ecdsa.PrivateKey)
r, s, err := ecdsa.Sign(config.Random(), sk, digest)
var r, s *big.Int
if sk, ok := priv.PrivateKey.(*ecdsa.PrivateKey); ok {
r, s, err = ecdsa.Sign(config.Random(), sk, digest)
} else {
var b []byte
b, err = priv.PrivateKey.(crypto.Signer).Sign(config.Random(), digest, sig.Hash)
if err == nil {
r, s, err = unwrapECDSASig(b)
}
}

if err == nil {
sig.ECDSASigR = new(encoding.MPI).SetBig(r)
Expand Down Expand Up @@ -960,6 +970,18 @@ func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err e
return
}

// unwrapECDSASig parses the two integer components of an ASN.1-encoded ECDSA signature.
func unwrapECDSASig(b []byte) (r, s *big.Int, err error) {
var ecsdaSig struct {
R, S *big.Int
}
_, err = asn1.Unmarshal(b, &ecsdaSig)
if err != nil {
return
}
return ecsdaSig.R, ecsdaSig.S, nil
}

// SignUserId computes a signature from priv, asserting that pub is a valid
// key for the identity id. On success, the signature is stored in sig. Call
// Serialize to write it out.
Expand Down

0 comments on commit 2add693

Please sign in to comment.