| /*- |
| * 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 |
| |
| // OpaqueSigner is an interface that supports signing payloads with opaque |
| // private key(s). Private key operations performed by implementers may, for |
| // example, occur in a hardware module. An OpaqueSigner may rotate signing keys |
| // transparently to the user of this interface. |
| type OpaqueSigner interface { |
| // Public returns the public key of the current signing key. |
| Public() *JSONWebKey |
| // Algs returns a list of supported signing algorithms. |
| Algs() []SignatureAlgorithm |
| // SignPayload signs a payload with the current signing key using the given |
| // algorithm. |
| SignPayload(payload []byte, alg SignatureAlgorithm) ([]byte, error) |
| } |
| |
| type opaqueSigner struct { |
| signer OpaqueSigner |
| } |
| |
| func newOpaqueSigner(alg SignatureAlgorithm, signer OpaqueSigner) (recipientSigInfo, error) { |
| var algSupported bool |
| for _, salg := range signer.Algs() { |
| if alg == salg { |
| algSupported = true |
| break |
| } |
| } |
| if !algSupported { |
| return recipientSigInfo{}, ErrUnsupportedAlgorithm |
| } |
| |
| return recipientSigInfo{ |
| sigAlg: alg, |
| publicKey: signer.Public, |
| signer: &opaqueSigner{ |
| signer: signer, |
| }, |
| }, nil |
| } |
| |
| func (o *opaqueSigner) signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) { |
| out, err := o.signer.SignPayload(payload, alg) |
| if err != nil { |
| return Signature{}, err |
| } |
| |
| return Signature{ |
| Signature: out, |
| protected: &rawHeader{}, |
| }, nil |
| } |
| |
| // OpaqueVerifier is an interface that supports verifying payloads with opaque |
| // public key(s). An OpaqueSigner may rotate signing keys transparently to the |
| // user of this interface. |
| type OpaqueVerifier interface { |
| VerifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error |
| } |
| |
| type opaqueVerifier struct { |
| verifier OpaqueVerifier |
| } |
| |
| func (o *opaqueVerifier) verifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error { |
| return o.verifier.VerifyPayload(payload, signature, alg) |
| } |
| |
| // OpaqueKeyEncrypter is an interface that supports encrypting keys with an opaque key. |
| type OpaqueKeyEncrypter interface { |
| // KeyID returns the kid |
| KeyID() string |
| // Algs returns a list of supported key encryption algorithms. |
| Algs() []KeyAlgorithm |
| // encryptKey encrypts the CEK using the given algorithm. |
| encryptKey(cek []byte, alg KeyAlgorithm) (recipientInfo, error) |
| } |
| |
| type opaqueKeyEncrypter struct { |
| encrypter OpaqueKeyEncrypter |
| } |
| |
| func newOpaqueKeyEncrypter(alg KeyAlgorithm, encrypter OpaqueKeyEncrypter) (recipientKeyInfo, error) { |
| var algSupported bool |
| for _, salg := range encrypter.Algs() { |
| if alg == salg { |
| algSupported = true |
| break |
| } |
| } |
| if !algSupported { |
| return recipientKeyInfo{}, ErrUnsupportedAlgorithm |
| } |
| |
| return recipientKeyInfo{ |
| keyID: encrypter.KeyID(), |
| keyAlg: alg, |
| keyEncrypter: &opaqueKeyEncrypter{ |
| encrypter: encrypter, |
| }, |
| }, nil |
| } |
| |
| func (oke *opaqueKeyEncrypter) encryptKey(cek []byte, alg KeyAlgorithm) (recipientInfo, error) { |
| return oke.encrypter.encryptKey(cek, alg) |
| } |
| |
| //OpaqueKeyDecrypter is an interface that supports decrypting keys with an opaque key. |
| type OpaqueKeyDecrypter interface { |
| DecryptKey(encryptedKey []byte, header Header) ([]byte, error) |
| } |
| |
| type opaqueKeyDecrypter struct { |
| decrypter OpaqueKeyDecrypter |
| } |
| |
| func (okd *opaqueKeyDecrypter) decryptKey(headers rawHeader, recipient *recipientInfo, generator keyGenerator) ([]byte, error) { |
| mergedHeaders := rawHeader{} |
| mergedHeaders.merge(&headers) |
| mergedHeaders.merge(recipient.header) |
| |
| header, err := mergedHeaders.sanitized() |
| if err != nil { |
| return nil, err |
| } |
| |
| return okd.decrypter.DecryptKey(recipient.encryptedKey, header) |
| } |