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
19// OpaqueSigner is an interface that supports signing payloads with opaque
20// private key(s). Private key operations preformed by implementors may, for
21// example, occur in a hardware module. An OpaqueSigner may rotate signing keys
22// transparently to the user of this interface.
23type OpaqueSigner interface {
24	// Public returns the public key of the current signing key.
25	Public() *JSONWebKey
26	// Algs returns a list of supported signing algorithms.
27	Algs() []SignatureAlgorithm
28	// SignPayload signs a payload with the current signing key using the given
29	// algorithm.
30	SignPayload(payload []byte, alg SignatureAlgorithm) ([]byte, error)
31}
32
33type opaqueSigner struct {
34	signer OpaqueSigner
35}
36
37func newOpaqueSigner(alg SignatureAlgorithm, signer OpaqueSigner) (recipientSigInfo, error) {
38	var algSupported bool
39	for _, salg := range signer.Algs() {
40		if alg == salg {
41			algSupported = true
42			break
43		}
44	}
45	if !algSupported {
46		return recipientSigInfo{}, ErrUnsupportedAlgorithm
47	}
48
49	return recipientSigInfo{
50		sigAlg:    alg,
51		publicKey: signer.Public,
52		signer: &opaqueSigner{
53			signer: signer,
54		},
55	}, nil
56}
57
58func (o *opaqueSigner) signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) {
59	out, err := o.signer.SignPayload(payload, alg)
60	if err != nil {
61		return Signature{}, err
62	}
63
64	return Signature{
65		Signature: out,
66		protected: &rawHeader{},
67	}, nil
68}
69
70// OpaqueVerifier is an interface that supports verifying payloads with opaque
71// public key(s). An OpaqueSigner may rotate signing keys transparently to the
72// user of this interface.
73type OpaqueVerifier interface {
74	VerifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error
75}
76
77type opaqueVerifier struct {
78	verifier OpaqueVerifier
79}
80
81func (o *opaqueVerifier) verifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error {
82	return o.verifier.VerifyPayload(payload, signature, alg)
83}
84
85// OpaqueKeyEncrypter is an interface that supports encrypting keys with an opaque key.
86type OpaqueKeyEncrypter interface {
87	// KeyID returns the kid
88	KeyID() string
89	// Algs returns a list of supported key encryption algorithms.
90	Algs() []KeyAlgorithm
91	// encryptKey encrypts the CEK using the given algorithm.
92	encryptKey(cek []byte, alg KeyAlgorithm) (recipientInfo, error)
93}
94
95type opaqueKeyEncrypter struct {
96	encrypter OpaqueKeyEncrypter
97}
98
99func newOpaqueKeyEncrypter(alg KeyAlgorithm, encrypter OpaqueKeyEncrypter) (recipientKeyInfo, error) {
100	var algSupported bool
101	for _, salg := range encrypter.Algs() {
102		if alg == salg {
103			algSupported = true
104			break
105		}
106	}
107	if !algSupported {
108		return recipientKeyInfo{}, ErrUnsupportedAlgorithm
109	}
110
111	return recipientKeyInfo{
112		keyID:  encrypter.KeyID(),
113		keyAlg: alg,
114		keyEncrypter: &opaqueKeyEncrypter{
115			encrypter: encrypter,
116		},
117	}, nil
118}
119
120func (oke *opaqueKeyEncrypter) encryptKey(cek []byte, alg KeyAlgorithm) (recipientInfo, error) {
121	return oke.encrypter.encryptKey(cek, alg)
122}
123
124//OpaqueKeyDecrypter is an interface that supports decrypting keys with an opaque key.
125type OpaqueKeyDecrypter interface {
126	DecryptKey(encryptedKey []byte, header Header) ([]byte, error)
127}
128
129type opaqueKeyDecrypter struct {
130	decrypter OpaqueKeyDecrypter
131}
132
133func (okd *opaqueKeyDecrypter) decryptKey(headers rawHeader, recipient *recipientInfo, generator keyGenerator) ([]byte, error) {
134	mergedHeaders := rawHeader{}
135	mergedHeaders.merge(&headers)
136	mergedHeaders.merge(recipient.header)
137
138	header, err := mergedHeaders.sanitized()
139	if err != nil {
140		return nil, err
141	}
142
143	return okd.decrypter.DecryptKey(recipient.encryptedKey, header)
144}
145