From 6f29ac7726bf31ea9c149ed300f84f03768b9979 Mon Sep 17 00:00:00 2001 From: telecoda Date: Mon, 18 Oct 2021 11:49:15 +0100 Subject: [PATCH 1/3] Support curve size of 31 and 32 bytes --- keys/ecc/ecc.go | 78 ++++++++++++++++++++++++++----------------------- 1 file changed, 41 insertions(+), 37 deletions(-) diff --git a/keys/ecc/ecc.go b/keys/ecc/ecc.go index b1debe4..486d816 100644 --- a/keys/ecc/ecc.go +++ b/keys/ecc/ecc.go @@ -2,44 +2,44 @@ package ecc import ( - "math/big" "crypto/ecdsa" - "crypto/elliptic" - "crypto/x509" - "encoding/pem" + "crypto/elliptic" + "crypto/x509" + "encoding/pem" "errors" + "math/big" ) // ReadPublic loads ecdsa.PublicKey from given PKCS1 X509 or PKIX blobs -func ReadPublic(raw []byte) (key *ecdsa.PublicKey,err error) { +func ReadPublic(raw []byte) (key *ecdsa.PublicKey, err error) { var encoded *pem.Block - + if encoded, _ = pem.Decode(raw); encoded == nil { return nil, errors.New("Ecc.ReadPublic(): Key must be PEM encoded PKCS1 X509 certificate or PKIX EC public key") } - + var parsedKey interface{} var cert *x509.Certificate - + if parsedKey, err = x509.ParsePKIXPublicKey(encoded.Bytes); err != nil { - if cert,err = x509.ParseCertificate(encoded.Bytes);err!=nil { + if cert, err = x509.ParseCertificate(encoded.Bytes); err != nil { return nil, err } - - parsedKey=cert.PublicKey + + parsedKey = cert.PublicKey } - + var ok bool - + if key, ok = parsedKey.(*ecdsa.PublicKey); !ok { return nil, errors.New("Ecc.ReadPublic(): Key is not a valid *ecdsa.PublicKey") } - + return key, nil } // ReadPrivate loads ecdsa.PrivateKey from given PKCS1 or PKCS8 blobs -func ReadPrivate(raw []byte) (key *ecdsa.PrivateKey,err error) { +func ReadPrivate(raw []byte) (key *ecdsa.PrivateKey, err error) { var encoded *pem.Block if encoded, _ = pem.Decode(raw); encoded == nil { @@ -48,41 +48,45 @@ func ReadPrivate(raw []byte) (key *ecdsa.PrivateKey,err error) { var parsedKey interface{} - if parsedKey,err=x509.ParseECPrivateKey(encoded.Bytes);err!=nil { - if parsedKey, err = x509.ParsePKCS8PrivateKey(encoded.Bytes);err!=nil { - return nil,err + if parsedKey, err = x509.ParseECPrivateKey(encoded.Bytes); err != nil { + if parsedKey, err = x509.ParsePKCS8PrivateKey(encoded.Bytes); err != nil { + return nil, err } } var ok bool - - if key,ok=parsedKey.(*ecdsa.PrivateKey);!ok { + + if key, ok = parsedKey.(*ecdsa.PrivateKey); !ok { return nil, errors.New("Ecc.ReadPrivate(): Key is not valid *ecdsa.PrivateKey") } - - return key,nil + + return key, nil } // NewPublic constructs ecdsa.PublicKey from given (X,Y) -func NewPublic(x,y []byte) (*ecdsa.PublicKey) { - return &ecdsa.PublicKey{ Curve: curve(len(x)), - X:new(big.Int).SetBytes(x), - Y:new(big.Int).SetBytes(y) } +func NewPublic(x, y []byte) *ecdsa.PublicKey { + return &ecdsa.PublicKey{Curve: curve(len(x)), + X: new(big.Int).SetBytes(x), + Y: new(big.Int).SetBytes(y)} } // NewPrivate constructs ecdsa.PrivateKey from given (X,Y) and D -func NewPrivate(x,y,d []byte) (*ecdsa.PrivateKey) { - return &ecdsa.PrivateKey {D:new(big.Int).SetBytes(d), - PublicKey: ecdsa.PublicKey{ Curve:curve(len(x)), - X:new(big.Int).SetBytes(x), - Y:new(big.Int).SetBytes(y)}} +func NewPrivate(x, y, d []byte) *ecdsa.PrivateKey { + return &ecdsa.PrivateKey{D: new(big.Int).SetBytes(d), + PublicKey: ecdsa.PublicKey{Curve: curve(len(x)), + X: new(big.Int).SetBytes(x), + Y: new(big.Int).SetBytes(y)}} } -func curve(size int) (elliptic.Curve) { +func curve(size int) elliptic.Curve { switch size { - case 32: return elliptic.P256() - case 48: return elliptic.P384() - case 65,66: return elliptic.P521() //adjust for P-521 curve, which can be 65 or 66 bytes - default: return nil //unsupported curve + case 31, 32: + return elliptic.P256() + case 48: + return elliptic.P384() + case 65, 66: + return elliptic.P521() //adjust for P-521 curve, which can be 65 or 66 bytes + default: + return nil //unsupported curve } -} \ No newline at end of file +} From 81c3a93a988f1420d86fddbef906905c4d522502 Mon Sep 17 00:00:00 2001 From: telecoda Date: Mon, 18 Oct 2021 11:49:55 +0100 Subject: [PATCH 2/3] Add temporary test to reproduce panic using rand.Reader --- jose_test.go | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/jose_test.go b/jose_test.go index 42b2054..5aabd74 100644 --- a/jose_test.go +++ b/jose_test.go @@ -1786,6 +1786,41 @@ func (s *TestSuite) TestDecrypt_ECDH_ES_A128GCM(c *C) { c.Assert(test, Equals, `{"exp":1392553211,"sub":"alice","nbf":1392552611,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"586dd129-a29f-49c8-9de7-454af1155e27","iat":1392552611}`) } +func (s *TestSuite) TestEncrypt_ECDH_ES_A128CBC_HS256_Panic(c *C) { + + // this test recreates the panic - sometimes a 31 byte curve is created on an ephemeral key + // + // if d, x, y, err = elliptic.GenerateKey(pubKey.Curve, rand.Reader); err != nil { + // return nil, nil, err + // } + + //given + payload := `{"hello": "world"}` + + //when + for i := 0; i < 1000; i++ { + test, err := Encrypt(payload, ECDH_ES, A128CBC_HS256, Ecc256Public()) + + fmt.Printf("\nECDH-ES A128CBC_HS256= %v\n", test) + + //then + c.Assert(err, IsNil) + + parts := strings.Split(test, ".") + + c.Assert(len(parts), Equals, 5) + c.Assert(len(parts[0]), Equals, 230) + c.Assert(len(parts[1]), Equals, 0) + c.Assert(len(parts[2]), Equals, 22) + c.Assert(len(parts[3]), Equals, 43) + c.Assert(len(parts[4]), Equals, 22) + + //make sure we consistent with ourselfs + t, _, _ := Decode(test, Ecc256Private()) + c.Assert(t, Equals, payload) + } +} + func (s *TestSuite) TestEncrypt_ECDH_ES_A128CBC_HS256(c *C) { //given payload := `{"hello": "world"}` From ffc75f26fefb706dc13b3ed425f950d079e8663f Mon Sep 17 00:00:00 2001 From: telecoda Date: Tue, 2 Nov 2021 17:04:18 +0000 Subject: [PATCH 3/3] Remove unnecessary test --- jose_test.go | 35 ----------------------------------- 1 file changed, 35 deletions(-) diff --git a/jose_test.go b/jose_test.go index 5aabd74..42b2054 100644 --- a/jose_test.go +++ b/jose_test.go @@ -1786,41 +1786,6 @@ func (s *TestSuite) TestDecrypt_ECDH_ES_A128GCM(c *C) { c.Assert(test, Equals, `{"exp":1392553211,"sub":"alice","nbf":1392552611,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"586dd129-a29f-49c8-9de7-454af1155e27","iat":1392552611}`) } -func (s *TestSuite) TestEncrypt_ECDH_ES_A128CBC_HS256_Panic(c *C) { - - // this test recreates the panic - sometimes a 31 byte curve is created on an ephemeral key - // - // if d, x, y, err = elliptic.GenerateKey(pubKey.Curve, rand.Reader); err != nil { - // return nil, nil, err - // } - - //given - payload := `{"hello": "world"}` - - //when - for i := 0; i < 1000; i++ { - test, err := Encrypt(payload, ECDH_ES, A128CBC_HS256, Ecc256Public()) - - fmt.Printf("\nECDH-ES A128CBC_HS256= %v\n", test) - - //then - c.Assert(err, IsNil) - - parts := strings.Split(test, ".") - - c.Assert(len(parts), Equals, 5) - c.Assert(len(parts[0]), Equals, 230) - c.Assert(len(parts[1]), Equals, 0) - c.Assert(len(parts[2]), Equals, 22) - c.Assert(len(parts[3]), Equals, 43) - c.Assert(len(parts[4]), Equals, 22) - - //make sure we consistent with ourselfs - t, _, _ := Decode(test, Ecc256Private()) - c.Assert(t, Equals, payload) - } -} - func (s *TestSuite) TestEncrypt_ECDH_ES_A128CBC_HS256(c *C) { //given payload := `{"hello": "world"}`