Skip to content

Commit

Permalink
P384-sha384
Browse files Browse the repository at this point in the history
  • Loading branch information
yaronf committed Aug 27, 2022
1 parent a7dc215 commit b72d816
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 37 deletions.
40 changes: 34 additions & 6 deletions crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,19 +86,29 @@ 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()
}
return &Signer{
keyID: keyID,
key: key,
alg: "ecdsa-p256-sha256",
alg: alg,
config: config,
fields: fields,
}, nil
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down
3 changes: 3 additions & 0 deletions ecdsa.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
67 changes: 36 additions & 31 deletions signatures_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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)
Expand All @@ -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)
}
Expand Down Expand Up @@ -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
}
Expand Down

0 comments on commit b72d816

Please sign in to comment.