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