1/*-
2 * Copyright 2018 Square Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package jose
18
19import (
20	"fmt"
21	"testing"
22)
23
24type signWrapper struct {
25	pk      *JSONWebKey
26	wrapped payloadSigner
27	algs    []SignatureAlgorithm
28}
29
30var _ = OpaqueSigner(&signWrapper{})
31
32func (sw *signWrapper) Algs() []SignatureAlgorithm {
33	return sw.algs
34}
35
36func (sw *signWrapper) Public() *JSONWebKey {
37	return sw.pk
38}
39
40func (sw *signWrapper) SignPayload(payload []byte, alg SignatureAlgorithm) ([]byte, error) {
41	sig, err := sw.wrapped.signPayload(payload, alg)
42	if err != nil {
43		return nil, err
44	}
45	return sig.Signature, nil
46}
47
48type verifyWrapper struct {
49	wrapped []payloadVerifier
50}
51
52var _ = OpaqueVerifier(&verifyWrapper{})
53
54func (vw *verifyWrapper) VerifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error {
55	if len(vw.wrapped) == 0 {
56		return fmt.Errorf("error: verifier had no keys")
57	}
58	var err error
59	for _, v := range vw.wrapped {
60		err = v.verifyPayload(payload, signature, alg)
61		if err == nil {
62			return nil
63		}
64	}
65	return err
66}
67
68func TestRoundtripsJWSOpaque(t *testing.T) {
69	sigAlgs := []SignatureAlgorithm{RS256, RS384, RS512, PS256, PS384, PS512, ES256, ES384, ES512, EdDSA}
70
71	serializers := []func(*JSONWebSignature) (string, error){
72		func(obj *JSONWebSignature) (string, error) { return obj.CompactSerialize() },
73		func(obj *JSONWebSignature) (string, error) { return obj.FullSerialize(), nil },
74	}
75
76	corrupter := func(obj *JSONWebSignature) {}
77
78	for _, alg := range sigAlgs {
79		signingKey, verificationKey := GenerateSigningTestKey(alg)
80
81		for i, serializer := range serializers {
82			sw := makeOpaqueSigner(t, signingKey, alg)
83			vw := makeOpaqueVerifier(t, []interface{}{verificationKey}, alg)
84
85			err := RoundtripJWS(alg, serializer, corrupter, sw, verificationKey, "test_nonce")
86			if err != nil {
87				t.Error(err, alg, i)
88			}
89
90			err = RoundtripJWS(alg, serializer, corrupter, signingKey, vw, "test_nonce")
91			if err != nil {
92				t.Error(err, alg, i)
93			}
94
95			err = RoundtripJWS(alg, serializer, corrupter, sw, vw, "test_nonce")
96			if err != nil {
97				t.Error(err, alg, i)
98			}
99		}
100	}
101}
102
103func makeOpaqueSigner(t *testing.T, signingKey interface{}, alg SignatureAlgorithm) *signWrapper {
104	ri, err := makeJWSRecipient(alg, signingKey)
105	if err != nil {
106		t.Fatal(err)
107	}
108	return &signWrapper{
109		wrapped: ri.signer,
110		algs:    []SignatureAlgorithm{alg},
111		pk:      &JSONWebKey{Key: ri.publicKey()},
112	}
113}
114
115func makeOpaqueVerifier(t *testing.T, verificationKey []interface{}, alg SignatureAlgorithm) *verifyWrapper {
116	var verifiers []payloadVerifier
117	for _, vk := range verificationKey {
118		verifier, err := newVerifier(vk)
119		if err != nil {
120			t.Fatal(err)
121		}
122		verifiers = append(verifiers, verifier)
123	}
124	return &verifyWrapper{wrapped: verifiers}
125}
126
127func TestOpaqueSignerKeyRotation(t *testing.T) {
128
129	sigAlgs := []SignatureAlgorithm{RS256, RS384, RS512, PS256, PS384, PS512, ES256, ES384, ES512, EdDSA}
130
131	serializers := []func(*JSONWebSignature) (string, error){
132		func(obj *JSONWebSignature) (string, error) { return obj.CompactSerialize() },
133		func(obj *JSONWebSignature) (string, error) { return obj.FullSerialize(), nil },
134	}
135
136	for _, alg := range sigAlgs {
137		for i, serializer := range serializers {
138			sk1, pk1 := GenerateSigningTestKey(alg)
139			sk2, pk2 := GenerateSigningTestKey(alg)
140
141			sw := makeOpaqueSigner(t, sk1, alg)
142			sw.pk.KeyID = "first"
143			vw := makeOpaqueVerifier(t, []interface{}{pk1, pk2}, alg)
144
145			signer, err := NewSigner(
146				SigningKey{Algorithm: alg, Key: sw},
147				&SignerOptions{NonceSource: staticNonceSource("test_nonce")},
148			)
149			if err != nil {
150				t.Fatal(err, alg, i)
151			}
152
153			jws1, err := signer.Sign([]byte("foo bar baz"))
154			if err != nil {
155				t.Fatal(err, alg, i)
156			}
157			jws1 = rtSerialize(t, serializer, jws1, vw)
158			if kid := jws1.Signatures[0].Protected.KeyID; kid != "first" {
159				t.Errorf("expected kid %q but got %q", "first", kid)
160			}
161
162			swNext := makeOpaqueSigner(t, sk2, alg)
163			swNext.pk.KeyID = "next"
164			sw.wrapped = swNext.wrapped
165			sw.pk = swNext.pk
166
167			jws2, err := signer.Sign([]byte("foo bar baz next"))
168			if err != nil {
169				t.Error(err, alg, i)
170			}
171			jws2 = rtSerialize(t, serializer, jws2, vw)
172			if kid := jws2.Signatures[0].Protected.KeyID; kid != "next" {
173				t.Errorf("expected kid %q but got %q", "next", kid)
174			}
175		}
176	}
177}
178
179func rtSerialize(t *testing.T, serializer func(*JSONWebSignature) (string, error), sig *JSONWebSignature, vk interface{}) *JSONWebSignature {
180	b, err := serializer(sig)
181	if err != nil {
182		t.Fatal(err)
183	}
184	sig, err = ParseSigned(b)
185	if err != nil {
186		t.Fatal(err)
187	}
188	if _, err := sig.Verify(vk); err != nil {
189		t.Fatal(err)
190	}
191	return sig
192}
193