VYPR
Critical severity9.1NVD Advisory· Published Mar 28, 2017· Updated May 13, 2026

CVE-2016-9121

CVE-2016-9121

Description

go-jose before 1.0.4 suffers from an invalid curve attack for the ECDH-ES algorithm. When deriving a shared key using ECDH-ES for an encrypted message, go-jose neglected to check that the received public key on a message is on the same curve as the static private key of the receiver, thus making it vulnerable to an invalid curve attack.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
gopkg.in/square/go-jose.v1Go
< 1.0.41.0.4
github.com/square/go-joseGo
< 1.0.41.0.4

Affected products

1

Patches

1
c7581939a365

Merge branch 'cs/164590'

https://github.com/square/go-joseCedric StaubAug 31, 2016via ghsa
5 files changed · +66 3
  • asymmetric.go+4 0 modified
    @@ -370,6 +370,10 @@ func (ctx ecDecrypterSigner) decryptKey(headers rawHeader, recipient *recipientI
     		return nil, errors.New("square/go-jose: invalid epk header")
     	}
     
    +	if !ctx.privateKey.Curve.IsOnCurve(publicKey.X, publicKey.Y) {
    +		return nil, errors.New("square/go-jose: invalid public key in epk header")
    +	}
    +
     	apuData := headers.Apu.bytes()
     	apvData := headers.Apv.bytes()
     
    
  • asymmetric_test.go+30 0 modified
    @@ -18,6 +18,8 @@ package jose
     
     import (
     	"bytes"
    +	"crypto/ecdsa"
    +	"crypto/elliptic"
     	"crypto/rand"
     	"crypto/rsa"
     	"errors"
    @@ -429,3 +431,31 @@ func TestInvalidEllipticCurve(t *testing.T) {
     		t.Error("should not generate ES384 signature with P-521 key")
     	}
     }
    +
    +func TestInvalidECPublicKey(t *testing.T) {
    +	// Invalid key
    +	invalid := &ecdsa.PrivateKey{
    +		PublicKey: ecdsa.PublicKey{
    +			Curve: elliptic.P256(),
    +			X:     fromBase64Int("MTEx"),
    +			Y:     fromBase64Int("MTEx"),
    +		},
    +		D: fromBase64Int("0_NxaRPUMQoAJt50Gz8YiTr8gRTwyEaCumd-MToTmIo="),
    +	}
    +
    +	headers := rawHeader{
    +		Alg: string(ECDH_ES),
    +		Epk: &JsonWebKey{
    +			Key: &invalid.PublicKey,
    +		},
    +	}
    +
    +	dec := ecDecrypterSigner{
    +		privateKey: ecTestKey256,
    +	}
    +
    +	_, err := dec.decryptKey(headers, nil, randomKeyGenerator{size: 16})
    +	if err == nil {
    +		t.Fatal("decrypter accepted JWS with invalid ECDH public key")
    +	}
    +}
    
  • cipher/ecdh_es.go+4 0 modified
    @@ -33,6 +33,10 @@ func DeriveECDHES(alg string, apuData, apvData []byte, priv *ecdsa.PrivateKey, p
     	supPubInfo := make([]byte, 4)
     	binary.BigEndian.PutUint32(supPubInfo, uint32(size)*8)
     
    +	if !priv.PublicKey.Curve.IsOnCurve(pub.X, pub.Y) {
    +		panic("public key not on same curve as private key")
    +	}
    +
     	z, _ := priv.PublicKey.Curve.ScalarMult(pub.X, pub.Y, priv.D.Bytes())
     	reader := NewConcatKDF(crypto.SHA256, z.Bytes(), algID, ptyUInfo, ptyVInfo, supPubInfo, []byte{})
     
    
  • cipher/ecdh_es_test.go+17 0 modified
    @@ -67,6 +67,23 @@ func TestVectorECDHES(t *testing.T) {
     	}
     }
     
    +func TestInvalidECPublicKey(t *testing.T) {
    +	defer func() { recover() }()
    +
    +	// Invalid key
    +	invalid := &ecdsa.PrivateKey{
    +		PublicKey: ecdsa.PublicKey{
    +			Curve: elliptic.P256(),
    +			X:     fromBase64Int("MTEx"),
    +			Y:     fromBase64Int("MTEx"),
    +		},
    +		D: fromBase64Int("0_NxaRPUMQoAJt50Gz8YiTr8gRTwyEaCumd-MToTmIo="),
    +	}
    +
    +	DeriveECDHES("A128GCM", []byte{}, []byte{}, bobKey, &invalid.PublicKey, 16)
    +	t.Fatal("should panic if public key was invalid")
    +}
    +
     func BenchmarkECDHES_128(b *testing.B) {
     	apuData := []byte("APU")
     	apvData := []byte("APV")
    
  • jwk.go+11 3 modified
    @@ -23,6 +23,7 @@ import (
     	"crypto/rsa"
     	"crypto/x509"
     	"encoding/base64"
    +	"errors"
     	"fmt"
     	"math/big"
     	"reflect"
    @@ -277,13 +278,20 @@ func (key rawJsonWebKey) ecPublicKey() (*ecdsa.PublicKey, error) {
     	}
     
     	if key.X == nil || key.Y == nil {
    -		return nil, fmt.Errorf("square/go-jose: invalid EC key, missing x/y values")
    +		return nil, errors.New("square/go-jose: invalid EC key, missing x/y values")
    +	}
    +
    +	x := key.X.bigInt()
    +	y := key.Y.bigInt()
    +
    +	if !curve.IsOnCurve(x, y) {
    +		return nil, errors.New("square/go-jose: invalid EC key, X/Y are not on declared curve")
     	}
     
     	return &ecdsa.PublicKey{
     		Curve: curve,
    -		X:     key.X.bigInt(),
    -		Y:     key.Y.bigInt(),
    +		X:     x,
    +		Y:     y,
     	}, nil
     }
     
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

7

News mentions

0

No linked articles in our index yet.