From b72d8164e60aa5aeba374b4ef299df73978e1c73 Mon Sep 17 00:00:00 2001 From: Yaron Sheffer Date: Fri, 26 Aug 2022 23:17:40 -0700 Subject: [PATCH] P384-sha384 --- crypto.go | 40 ++++++++++++++++++++++----- ecdsa.go | 3 +++ signatures_test.go | 67 +++++++++++++++++++++++++--------------------- 3 files changed, 73 insertions(+), 37 deletions(-) diff --git a/crypto.go b/crypto.go index 3ab0133..542d141 100644 --- a/crypto.go +++ b/crypto.go @@ -86,11 +86,21 @@ func NewRSAPSSSigner(keyID string, key rsa.PrivateKey, config *SignConfig, field // NewP256Signer returns a new Signer structure. Key is an elliptic curve P-256 private key. // Config may be nil for a default configuration. func NewP256Signer(keyID string, key ecdsa.PrivateKey, config *SignConfig, fields Fields) (*Signer, error) { + return newECCSigner(keyID, key, config, fields, elliptic.P256(), "P-256", "ecdsa-p256-sha256") +} + +// NewP384Signer returns a new Signer structure. Key is an elliptic curve P-384 private key. +// Config may be nil for a default configuration. +func NewP384Signer(keyID string, key ecdsa.PrivateKey, config *SignConfig, fields Fields) (*Signer, error) { + return newECCSigner(keyID, key, config, fields, elliptic.P384(), "P-384", "ecdsa-p384-sha384") +} + +func newECCSigner(keyID string, key ecdsa.PrivateKey, config *SignConfig, fields Fields, curve elliptic.Curve, curveName, alg string) (*Signer, error) { if keyID == "" { return nil, fmt.Errorf("keyID must not be empty") } - if key.Curve != elliptic.P256() { - return nil, fmt.Errorf("key curve must be P-256") + if key.Curve != curve { + return nil, fmt.Errorf("key curve must be %s", curveName) } if config == nil { config = NewSignConfig() @@ -98,7 +108,7 @@ func NewP256Signer(keyID string, key ecdsa.PrivateKey, config *SignConfig, field return &Signer{ keyID: keyID, key: key, - alg: "ecdsa-p256-sha256", + alg: alg, config: config, fields: fields, }, nil @@ -196,6 +206,10 @@ func (s Signer) sign(buff []byte) ([]byte, error) { hashed := sha256.Sum256(buff) key := s.key.(ecdsa.PrivateKey) return ecdsaSignRaw(rand.Reader, &key, hashed[:]) + case "ecdsa-p384-sha384": + hashed := sha512.Sum384(buff) + key := s.key.(ecdsa.PrivateKey) + return ecdsaSignRaw(rand.Reader, &key, hashed[:]) case "ed25519": key := s.key.(ed25519.PrivateKey) return ed25519.Sign(key, buff), nil @@ -277,19 +291,29 @@ func NewRSAPSSVerifier(keyID string, key rsa.PublicKey, config *VerifyConfig, fi // NewP256Verifier generates a new Verifier for ECDSA (P-256) signatures. Set config to nil for a default configuration. // Fields is the list of required headers and fields, which may be empty (but this is typically insecure). func NewP256Verifier(keyID string, key ecdsa.PublicKey, config *VerifyConfig, fields Fields) (*Verifier, error) { + return newECCVerifier(keyID, key, config, fields, elliptic.P256(), "P-256", "ecdsa-p256-sha256") +} + +// NewP384Verifier generates a new Verifier for ECDSA (P-384) signatures. Set config to nil for a default configuration. +// Fields is the list of required headers and fields, which may be empty (but this is typically insecure). +func NewP384Verifier(keyID string, key ecdsa.PublicKey, config *VerifyConfig, fields Fields) (*Verifier, error) { + return newECCVerifier(keyID, key, config, fields, elliptic.P384(), "P-384", "ecdsa-p384-sha384") +} + +func newECCVerifier(keyID string, key ecdsa.PublicKey, config *VerifyConfig, fields Fields, curve elliptic.Curve, curveName, alg string) (*Verifier, error) { if config == nil { config = NewVerifyConfig() } if config.verifyKeyID && keyID == "" { return nil, fmt.Errorf("keyID should not be empty") } - if key.Curve != elliptic.P256() { - return nil, fmt.Errorf("key curve must be P-256") + if key.Curve != curve { + return nil, fmt.Errorf("key curve must be %s", curveName) } return &Verifier{ keyID: keyID, key: key, - alg: "ecdsa-p256-sha256", + alg: alg, config: config, fields: fields, }, nil @@ -385,6 +409,10 @@ func (v Verifier) verify(buff []byte, sig []byte) (bool, error) { hashed := sha256.Sum256(buff) key := v.key.(ecdsa.PublicKey) return ecdsaVerifyRaw(&key, hashed[:], sig) + case "ecdsa-p384-sha384": + hashed := sha512.Sum384(buff) + key := v.key.(ecdsa.PublicKey) + return ecdsaVerifyRaw(&key, hashed[:], sig) case "ed25519": key := v.key.(ed25519.PublicKey) verified := ed25519.Verify(key, buff, sig) diff --git a/ecdsa.go b/ecdsa.go index 527abef..b592186 100644 --- a/ecdsa.go +++ b/ecdsa.go @@ -58,6 +58,9 @@ func sigComponentLen(curve string) (int, int, error) { case "P-256": lr = 32 ls = 32 + case "P-384": + lr = 48 + ls = 48 default: return 0, 0, fmt.Errorf("unknown curve \"%s\"", curve) } diff --git a/signatures_test.go b/signatures_test.go index 21f8164..61e2df2 100644 --- a/signatures_test.go +++ b/signatures_test.go @@ -269,19 +269,6 @@ rOjr9w349JooGXhOxbu8nOxX -----END RSA PRIVATE KEY----- ` -var p256PubKey = `-----BEGIN PUBLIC KEY----- -MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEWAO+Y/BP3c7Aw7dSWYGkuckwl/e6 -H54D/P9uzXDjby0Frysdpcny/NL807iRVfVDDg+ctHhuRTzBwP+lwVdN2g== ------END PUBLIC KEY----- -` - -var p256PrvKey = `-----BEGIN EC PRIVATE KEY----- -MHcCAQEEIMLnTZwmWikcBCrKlXZVUjaq9jwsv22sy/P7yIIonkVwoAoGCCqGSM49 -AwEHoUQDQgAEWAO+Y/BP3c7Aw7dSWYGkuckwl/e6H54D/P9uzXDjby0Frysdpcny -/NL807iRVfVDDg+ctHhuRTzBwP+lwVdN2g== ------END EC PRIVATE KEY----- -` - // Note: the private key from the draft is never used var p256PubKey2 = `-----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEqIVYZVLCrPZHGHjP17CTW0/+D9Lf @@ -351,18 +338,6 @@ func parseRsaPublicKeyFromPemStr(pemString string) (*rsa.PublicKey, error) { return k.(*rsa.PublicKey), nil } -func parseECPrivateKeyFromPemStr(pemString string) (*ecdsa.PrivateKey, error) { - block, _ := pem.Decode([]byte(pemString)) - if block == nil { - return nil, fmt.Errorf("cannot decode PEM") - } - k, err := x509.ParseECPrivateKey(block.Bytes) - if err != nil { - return nil, err - } - return k, nil -} - func parseECPublicKeyFromPemStr(pemString string) (*ecdsa.PublicKey, error) { block, _ := pem.Decode([]byte(pemString)) if block == nil { @@ -804,9 +779,9 @@ func TestSignAndVerifyRSA(t *testing.T) { func TestSignAndVerifyP256(t *testing.T) { config := NewSignConfig().setFakeCreated(1618884475) signatureName := "sig1" - prvKey, err := parseECPrivateKeyFromPemStr(p256PrvKey) + prvKey, pubKey, err := genP256KeyPair() if err != nil { - t.Errorf("cannot read private key") + t.Errorf("cannot generate P-256 keypair") } fields := *NewFields().AddHeader("@method").AddHeader("Date").AddHeader("Content-Type").AddQueryParam("pet") signer, _ := NewP256Signer("test-key-p256", *prvKey, config, fields) @@ -817,11 +792,33 @@ func TestSignAndVerifyP256(t *testing.T) { } req.Header.Add("Signature", sig) req.Header.Add("Signature-Input", sigInput) - pubKey, err := parseECPublicKeyFromPemStr(p256PubKey) + verifier, err := NewP256Verifier("test-key-p256", *pubKey, NewVerifyConfig().SetVerifyCreated(false), fields) if err != nil { - t.Errorf("cannot read public key: %v", err) + t.Errorf("could not generate Verifier: %s", err) } - verifier, err := NewP256Verifier("test-key-p256", *pubKey, NewVerifyConfig().SetVerifyCreated(false), fields) + err = VerifyRequest(signatureName, *verifier, req) + if err != nil { + t.Errorf("verification error: %s", err) + } +} + +func TestSignAndVerifyP384(t *testing.T) { + config := NewSignConfig().setFakeCreated(1618884475) + signatureName := "sig1" + prvKey, pubKey, err := genP384KeyPair() + if err != nil { + t.Errorf("cannot generate P-384 keypair") + } + fields := *NewFields().AddHeader("@method").AddHeader("Date").AddHeader("Content-Type").AddQueryParam("pet") + signer, _ := NewP384Signer("test-key-p384", *prvKey, config, fields) + req := readRequest(httpreq2) + sigInput, sig, err := SignRequest(signatureName, *signer, req) + if err != nil { + t.Errorf("signature failed: %v", err) + } + req.Header.Add("Signature", sig) + req.Header.Add("Signature-Input", sigInput) + verifier, err := NewP384Verifier("test-key-p384", *pubKey, NewVerifyConfig().SetVerifyCreated(false), fields) if err != nil { t.Errorf("could not generate Verifier: %s", err) } @@ -1190,7 +1187,15 @@ func TestResponseDetails(t *testing.T) { } func genP256KeyPair() (priv *ecdsa.PrivateKey, pub *ecdsa.PublicKey, err error) { - priv, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + return genECCKeypair(elliptic.P256()) +} + +func genP384KeyPair() (priv *ecdsa.PrivateKey, pub *ecdsa.PublicKey, err error) { + return genECCKeypair(elliptic.P384()) +} + +func genECCKeypair(curve elliptic.Curve) (priv *ecdsa.PrivateKey, pub *ecdsa.PublicKey, err error) { + priv, err = ecdsa.GenerateKey(curve, rand.Reader) if err != nil { return nil, nil, err }