blob: d6f7cc37892dd29e5b095899584742d57fd462c6 [file] [log] [blame]
/*-
* Copyright 2018 Square Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jose
import (
"fmt"
"testing"
)
type signWrapper struct {
pk *JSONWebKey
wrapped payloadSigner
algs []SignatureAlgorithm
}
var _ = OpaqueSigner(&signWrapper{})
func (sw *signWrapper) Algs() []SignatureAlgorithm {
return sw.algs
}
func (sw *signWrapper) Public() *JSONWebKey {
return sw.pk
}
func (sw *signWrapper) SignPayload(payload []byte, alg SignatureAlgorithm) ([]byte, error) {
sig, err := sw.wrapped.signPayload(payload, alg)
if err != nil {
return nil, err
}
return sig.Signature, nil
}
type verifyWrapper struct {
wrapped []payloadVerifier
}
var _ = OpaqueVerifier(&verifyWrapper{})
func (vw *verifyWrapper) VerifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error {
if len(vw.wrapped) == 0 {
return fmt.Errorf("error: verifier had no keys")
}
var err error
for _, v := range vw.wrapped {
err = v.verifyPayload(payload, signature, alg)
if err == nil {
return nil
}
}
return err
}
func TestRoundtripsJWSOpaque(t *testing.T) {
sigAlgs := []SignatureAlgorithm{RS256, RS384, RS512, PS256, PS384, PS512, ES256, ES384, ES512, EdDSA}
serializers := []func(*JSONWebSignature) (string, error){
func(obj *JSONWebSignature) (string, error) { return obj.CompactSerialize() },
func(obj *JSONWebSignature) (string, error) { return obj.FullSerialize(), nil },
}
corrupter := func(obj *JSONWebSignature) {}
for _, alg := range sigAlgs {
signingKey, verificationKey := GenerateSigningTestKey(alg)
for i, serializer := range serializers {
sw := makeOpaqueSigner(t, signingKey, alg)
vw := makeOpaqueVerifier(t, []interface{}{verificationKey}, alg)
err := RoundtripJWS(alg, serializer, corrupter, sw, verificationKey, "test_nonce")
if err != nil {
t.Error(err, alg, i)
}
err = RoundtripJWS(alg, serializer, corrupter, signingKey, vw, "test_nonce")
if err != nil {
t.Error(err, alg, i)
}
err = RoundtripJWS(alg, serializer, corrupter, sw, vw, "test_nonce")
if err != nil {
t.Error(err, alg, i)
}
}
}
}
func makeOpaqueSigner(t *testing.T, signingKey interface{}, alg SignatureAlgorithm) *signWrapper {
ri, err := makeJWSRecipient(alg, signingKey)
if err != nil {
t.Fatal(err)
}
return &signWrapper{
wrapped: ri.signer,
algs: []SignatureAlgorithm{alg},
pk: &JSONWebKey{Key: ri.publicKey()},
}
}
func makeOpaqueVerifier(t *testing.T, verificationKey []interface{}, alg SignatureAlgorithm) *verifyWrapper {
var verifiers []payloadVerifier
for _, vk := range verificationKey {
verifier, err := newVerifier(vk)
if err != nil {
t.Fatal(err)
}
verifiers = append(verifiers, verifier)
}
return &verifyWrapper{wrapped: verifiers}
}
func TestOpaqueSignerKeyRotation(t *testing.T) {
sigAlgs := []SignatureAlgorithm{RS256, RS384, RS512, PS256, PS384, PS512, ES256, ES384, ES512, EdDSA}
serializers := []func(*JSONWebSignature) (string, error){
func(obj *JSONWebSignature) (string, error) { return obj.CompactSerialize() },
func(obj *JSONWebSignature) (string, error) { return obj.FullSerialize(), nil },
}
for _, alg := range sigAlgs {
for i, serializer := range serializers {
sk1, pk1 := GenerateSigningTestKey(alg)
sk2, pk2 := GenerateSigningTestKey(alg)
sw := makeOpaqueSigner(t, sk1, alg)
sw.pk.KeyID = "first"
vw := makeOpaqueVerifier(t, []interface{}{pk1, pk2}, alg)
signer, err := NewSigner(
SigningKey{Algorithm: alg, Key: sw},
&SignerOptions{NonceSource: staticNonceSource("test_nonce")},
)
if err != nil {
t.Fatal(err, alg, i)
}
jws1, err := signer.Sign([]byte("foo bar baz"))
if err != nil {
t.Fatal(err, alg, i)
}
jws1 = rtSerialize(t, serializer, jws1, vw)
if kid := jws1.Signatures[0].Protected.KeyID; kid != "first" {
t.Errorf("expected kid %q but got %q", "first", kid)
}
swNext := makeOpaqueSigner(t, sk2, alg)
swNext.pk.KeyID = "next"
sw.wrapped = swNext.wrapped
sw.pk = swNext.pk
jws2, err := signer.Sign([]byte("foo bar baz next"))
if err != nil {
t.Error(err, alg, i)
}
jws2 = rtSerialize(t, serializer, jws2, vw)
if kid := jws2.Signatures[0].Protected.KeyID; kid != "next" {
t.Errorf("expected kid %q but got %q", "next", kid)
}
}
}
}
func rtSerialize(t *testing.T, serializer func(*JSONWebSignature) (string, error), sig *JSONWebSignature, vk interface{}) *JSONWebSignature {
b, err := serializer(sig)
if err != nil {
t.Fatal(err)
}
sig, err = ParseSigned(b)
if err != nil {
t.Fatal(err)
}
if _, err := sig.Verify(vk); err != nil {
t.Fatal(err)
}
return sig
}