| package jws | 
 |  | 
 | import ( | 
 | 	"bytes" | 
 | 	"encoding/base64" | 
 | 	"encoding/json" | 
 | 	"errors" | 
 | 	"math/rand" | 
 | 	"testing" | 
 |  | 
 | 	"github.com/SermoDigital/jose/crypto" | 
 | ) | 
 |  | 
 | type easy []byte | 
 |  | 
 | func (e *easy) UnmarshalJSON(b []byte) error { | 
 | 	if len(b) > 1 && b[0] == '"' && b[len(b)-1] == '"' { | 
 | 		b = b[1 : len(b)-1] | 
 | 	} | 
 | 	// json.Marshal encodes easy as it would a []byte, so in | 
 | 	// `"base64"` format. | 
 | 	dst := make([]byte, base64.StdEncoding.DecodedLen(len(b))) | 
 | 	n, err := base64.StdEncoding.Decode(dst, b) | 
 | 	if err != nil { | 
 | 		return err | 
 | 	} | 
 | 	*e = easy(dst[:n]) | 
 | 	return nil | 
 | } | 
 |  | 
 | var _ json.Unmarshaler = (*easy)(nil) | 
 |  | 
 | var easyData = easy("easy data!") | 
 |  | 
 | func TestParseWithUnmarshaler(t *testing.T) { | 
 | 	j := New(easyData, crypto.SigningMethodRS512) | 
 | 	b, err := j.Flat(rsaPriv) | 
 | 	if err != nil { | 
 | 		t.Error(err) | 
 | 	} | 
 |  | 
 | 	var e easy | 
 | 	j2, err := Parse(b, &e) | 
 | 	if err != nil { | 
 | 		t.Error(err) | 
 | 	} | 
 |  | 
 | 	if !bytes.Equal(easyData, *j2.Payload().(*easy)) { | 
 | 		Error(t, easyData, *j2.Payload().(*easy)) | 
 | 	} | 
 | } | 
 |  | 
 | func TestParseCompact(t *testing.T) { | 
 | 	j := New(easyData, crypto.SigningMethodRS512) | 
 | 	b, err := j.Compact(rsaPriv) | 
 | 	if err != nil { | 
 | 		t.Error(err) | 
 | 	} | 
 |  | 
 | 	j2, err := ParseCompact(b) | 
 | 	if err != nil { | 
 | 		t.Error(err) | 
 | 	} | 
 |  | 
 | 	var k easy | 
 | 	if err := k.UnmarshalJSON([]byte(j2.Payload().(string))); err != nil { | 
 | 		t.Error(err) | 
 | 	} | 
 |  | 
 | 	if !bytes.Equal(k, easyData) { | 
 | 		Error(t, easyData, k) | 
 | 	} | 
 | } | 
 |  | 
 | func TestParseCompactWithUnmarshaler(t *testing.T) { | 
 | 	j := New(easyData, crypto.SigningMethodRS512) | 
 | 	b, err := j.Compact(rsaPriv) | 
 | 	if err != nil { | 
 | 		t.Error(err) | 
 | 	} | 
 | 	var e easy | 
 | 	j2, err := ParseCompact(b, &e) | 
 | 	if err != nil { | 
 | 		t.Error(err) | 
 | 	} | 
 | 	if !bytes.Equal(easyData, *j2.Payload().(*easy)) { | 
 | 		Error(t, easyData, *j2.Payload().(*easy)) | 
 | 	} | 
 | } | 
 |  | 
 | func TestParseGeneral(t *testing.T) { | 
 | 	sm := []crypto.SigningMethod{ | 
 | 		crypto.SigningMethodRS256, | 
 | 		crypto.SigningMethodPS384, | 
 | 		crypto.SigningMethodPS512, | 
 | 	} | 
 |  | 
 | 	j := New(easyData, sm...) | 
 | 	b, err := j.General(rsaPriv) | 
 | 	if err != nil { | 
 | 		t.Error(err) | 
 | 	} | 
 |  | 
 | 	j2, err := ParseGeneral(b) | 
 | 	if err != nil { | 
 | 		t.Error(err) | 
 | 	} | 
 |  | 
 | 	for i, v := range j2.(*jws).sb { | 
 | 		k := v.protected.Get("alg").(string) | 
 | 		if k != sm[i].Alg() { | 
 | 			Error(t, sm[i].Alg(), k) | 
 | 		} | 
 | 	} | 
 | } | 
 |  | 
 | func TestVerifyMulti(t *testing.T) { | 
 | 	sm := []crypto.SigningMethod{ | 
 | 		crypto.SigningMethodRS256, | 
 | 		crypto.SigningMethodPS384, | 
 | 		crypto.SigningMethodPS512, | 
 | 	} | 
 |  | 
 | 	j := New(easyData, sm...) | 
 | 	b, err := j.General(rsaPriv) | 
 | 	if err != nil { | 
 | 		t.Error(err) | 
 | 	} | 
 |  | 
 | 	j2, err := ParseGeneral(b) | 
 | 	if err != nil { | 
 | 		t.Error(err) | 
 | 	} | 
 |  | 
 | 	keys := []interface{}{rsaPub, rsaPub, rsaPub} | 
 | 	if err := j2.VerifyMulti(keys, sm, nil); err != nil { | 
 | 		t.Error(err) | 
 | 	} | 
 | } | 
 |  | 
 | func TestVerifyMultiOneKey(t *testing.T) { | 
 | 	sm := []crypto.SigningMethod{ | 
 | 		crypto.SigningMethodRS256, | 
 | 		crypto.SigningMethodPS384, | 
 | 		crypto.SigningMethodPS512, | 
 | 	} | 
 |  | 
 | 	j := New(easyData, sm...) | 
 | 	b, err := j.General(rsaPriv) | 
 | 	if err != nil { | 
 | 		t.Error(err) | 
 | 	} | 
 |  | 
 | 	j2, err := ParseGeneral(b) | 
 | 	if err != nil { | 
 | 		t.Error(err) | 
 | 	} | 
 |  | 
 | 	keys := []interface{}{rsaPub} | 
 | 	if err := j2.VerifyMulti(keys, sm, nil); err != nil { | 
 | 		t.Error(err) | 
 | 	} | 
 | } | 
 |  | 
 | func TestVerifyMultiMismatchedAlgs(t *testing.T) { | 
 | 	sm := []crypto.SigningMethod{ | 
 | 		crypto.SigningMethodRS256, | 
 | 		crypto.SigningMethodPS384, | 
 | 		crypto.SigningMethodPS512, | 
 | 	} | 
 |  | 
 | 	j := New(easyData, sm...) | 
 | 	b, err := j.General(rsaPriv) | 
 | 	if err != nil { | 
 | 		t.Error(err) | 
 | 	} | 
 |  | 
 | 	j2, err := ParseGeneral(b) | 
 | 	if err != nil { | 
 | 		t.Error(err) | 
 | 	} | 
 |  | 
 | 	shuffle := func(a []crypto.SigningMethod) { | 
 | 		N := len(a) | 
 | 		for i := 0; i < N; i++ { | 
 | 			r := i + rand.Intn(N-i) | 
 | 			a[r], a[i] = a[i], a[r] | 
 | 		} | 
 | 	} | 
 |  | 
 | 	shuffle(sm) | 
 |  | 
 | 	keys := []interface{}{rsaPub, rsaPub, rsaPub} | 
 | 	if err := j2.VerifyMulti(keys, sm, nil); err == nil { | 
 | 		t.Error("Should NOT be nil") | 
 | 	} | 
 | } | 
 |  | 
 | func TestVerifyMultiNotEnoughMethods(t *testing.T) { | 
 | 	sm := []crypto.SigningMethod{ | 
 | 		crypto.SigningMethodRS256, | 
 | 		crypto.SigningMethodPS384, | 
 | 		crypto.SigningMethodPS512, | 
 | 	} | 
 |  | 
 | 	j := New(easyData, sm...) | 
 | 	b, err := j.General(rsaPriv) | 
 | 	if err != nil { | 
 | 		t.Error(err) | 
 | 	} | 
 |  | 
 | 	j2, err := ParseGeneral(b) | 
 | 	if err != nil { | 
 | 		t.Error(err) | 
 | 	} | 
 |  | 
 | 	sm = sm[0 : len(sm)-1] | 
 |  | 
 | 	keys := []interface{}{rsaPub, rsaPub, rsaPub} | 
 | 	if err := j2.VerifyMulti(keys, sm, nil); err == nil { | 
 | 		t.Error("Should NOT be nil") | 
 | 	} | 
 | } | 
 |  | 
 | func TestVerifyMultiNotEnoughKeys(t *testing.T) { | 
 | 	sm := []crypto.SigningMethod{ | 
 | 		crypto.SigningMethodRS256, | 
 | 		crypto.SigningMethodPS384, | 
 | 		crypto.SigningMethodPS512, | 
 | 	} | 
 |  | 
 | 	j := New(easyData, sm...) | 
 | 	b, err := j.General(rsaPriv) | 
 | 	if err != nil { | 
 | 		t.Error(err) | 
 | 	} | 
 |  | 
 | 	j2, err := ParseGeneral(b) | 
 | 	if err != nil { | 
 | 		t.Error(err) | 
 | 	} | 
 |  | 
 | 	keys := []interface{}{rsaPub, rsaPub} | 
 | 	if err := j2.VerifyMulti(keys, sm, nil); err == nil { | 
 | 		t.Error("Should NOT be nil") | 
 | 	} | 
 | } | 
 |  | 
 | func TestVerifyMultiSigningOpts(t *testing.T) { | 
 | 	sm := []crypto.SigningMethod{ | 
 | 		crypto.SigningMethodRS256, | 
 | 		crypto.SigningMethodPS384, | 
 | 		crypto.SigningMethodPS512, | 
 | 	} | 
 |  | 
 | 	j := New(easyData, sm...) | 
 | 	b, err := j.General(rsaPriv) | 
 | 	if err != nil { | 
 | 		t.Error(err) | 
 | 	} | 
 |  | 
 | 	j2, err := ParseGeneral(b) | 
 | 	if err != nil { | 
 | 		t.Error(err) | 
 | 	} | 
 |  | 
 | 	o := SigningOpts{ | 
 | 		Number:  3, | 
 | 		Indices: []int{0, 1, 2}, | 
 | 	} | 
 |  | 
 | 	keys := []interface{}{rsaPub, rsaPub, rsaPub} | 
 | 	if err := j2.VerifyMulti(keys, sm, &o); err != nil { | 
 | 		t.Error(err) | 
 | 	} | 
 | } | 
 |  | 
 | func TestVerifyMultiSigningOptsErr(t *testing.T) { | 
 | 	sm := []crypto.SigningMethod{ | 
 | 		crypto.SigningMethodRS256, | 
 | 		crypto.SigningMethodPS384, | 
 | 		crypto.SigningMethodPS512, | 
 | 	} | 
 |  | 
 | 	j := New(easyData, sm...) | 
 | 	b, err := j.General(rsaPriv) | 
 | 	if err != nil { | 
 | 		t.Error(err) | 
 | 	} | 
 |  | 
 | 	j2, err := ParseGeneral(b) | 
 | 	if err != nil { | 
 | 		t.Error(err) | 
 | 	} | 
 |  | 
 | 	o := SigningOpts{ | 
 | 		Number:  4, | 
 | 		Indices: []int{0, 1, 2, 3}, | 
 | 	} | 
 |  | 
 | 	keys := []interface{}{rsaPub, rsaPub, rsaPub} | 
 | 	if err := j2.VerifyMulti(keys, sm, &o); err == nil { | 
 | 		t.Error("Should not be nil!") | 
 | 	} | 
 | } | 
 |  | 
 | func TestVerify(t *testing.T) { | 
 | 	j := New(easyData, crypto.SigningMethodPS512) | 
 | 	b, err := j.Flat(rsaPriv) | 
 | 	if err != nil { | 
 | 		t.Error(err) | 
 | 	} | 
 |  | 
 | 	j2, err := ParseFlat(b) | 
 | 	if err != nil { | 
 | 		t.Error(err) | 
 | 	} | 
 |  | 
 | 	if err := j2.Verify(rsaPub, crypto.SigningMethodPS512); err != nil { | 
 | 		t.Error(err) | 
 | 	} | 
 | } | 
 |  | 
 | func TestVerifyCallback(t *testing.T) { | 
 | 	j := New(easyData, crypto.SigningMethodPS512) | 
 | 	b, err := j.Flat(rsaPriv) | 
 | 	if err != nil { | 
 | 		t.Error(err) | 
 | 	} | 
 |  | 
 | 	j2, err := ParseFlat(b) | 
 | 	if err != nil { | 
 | 		t.Error(err) | 
 | 	} | 
 |  | 
 | 	cb := func(j JWS) ([]interface{}, error) { | 
 | 		return []interface{}{rsaPub}, nil | 
 | 	} | 
 |  | 
 | 	if err := j2.VerifyCallback(cb, []crypto.SigningMethod{crypto.SigningMethodPS512}, nil); err != nil { | 
 | 		t.Error(err) | 
 | 	} | 
 | } | 
 |  | 
 | func TestVerifyCallbackErr(t *testing.T) { | 
 | 	j := New(easyData, crypto.SigningMethodPS512) | 
 | 	b, err := j.Flat(rsaPriv) | 
 | 	if err != nil { | 
 | 		t.Error(err) | 
 | 	} | 
 |  | 
 | 	j2, err := ParseFlat(b) | 
 | 	if err != nil { | 
 | 		t.Error(err) | 
 | 	} | 
 |  | 
 | 	cb := func(j JWS) ([]interface{}, error) { | 
 | 		return nil, errors.New("k") | 
 | 	} | 
 |  | 
 | 	if err := j2.VerifyCallback(cb, []crypto.SigningMethod{crypto.SigningMethodPS512}, nil); err == nil { | 
 | 		t.Error("Should not be nil!") | 
 | 	} | 
 | } | 
 |  | 
 | func TestVerifyNoSBs(t *testing.T) { | 
 | 	j := New(easyData, crypto.SigningMethodPS512) | 
 | 	b, err := j.Flat(rsaPriv) | 
 | 	if err != nil { | 
 | 		t.Error(err) | 
 | 	} | 
 |  | 
 | 	j2, err := ParseFlat(b) | 
 | 	if err != nil { | 
 | 		t.Error(err) | 
 | 	} | 
 | 	j2.(*jws).sb = nil | 
 | 	if err := j2.Verify(rsaPub, crypto.SigningMethodPS512); err != ErrCannotValidate { | 
 | 		Error(t, ErrCannotValidate, err) | 
 | 	} | 
 | } |