001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2016 ForgeRock AS.
015 */
016
017package org.forgerock.json.jose.jwe;
018
019import java.security.Key;
020
021import org.forgerock.json.jose.common.JwtReconstruction;
022import org.forgerock.json.jose.exceptions.JweDecryptionException;
023import org.forgerock.json.jose.exceptions.JwsVerifyingException;
024import org.forgerock.json.jose.jws.SignedJwt;
025import org.forgerock.json.jose.jws.handlers.SigningHandler;
026import org.forgerock.json.jose.jwt.JwtClaimsSet;
027import org.forgerock.json.jose.jwt.Payload;
028
029/**
030 * A nested signed-then-encrypted JWT.
031 */
032public class SignedThenEncryptedJwt extends EncryptedJwt {
033    private static final JwtReconstruction JWT_RECONSTRUCTION = new JwtReconstruction();
034
035    /**
036     * Constructs a fresh signed-then-encrypted JWT with the given signed JWT payload, JWE headers and encryption key.
037     *
038     * @param header the JWE headers.
039     * @param payload the signed JWT payload.
040     * @param publicKey the encryption key.
041     */
042    public SignedThenEncryptedJwt(final JweHeader header, final SignedJwt payload, final Key publicKey) {
043        super(header, payload, publicKey);
044    }
045
046    /**
047     * Reconstructs a signed-then-encrypted JWT from components parts of the encrypted JWT string.
048     *
049     * @param header the decoded headers.
050     * @param encodedHeader the encoded headers.
051     * @param encryptedContentEncryptionKey the encrypted content encryption key (CEK), or null if not used.
052     * @param initialisationVector the initialisation vector (IV).
053     * @param ciphertext the encrypted ciphertext payload.
054     * @param authenticationTag the authentication MAC tag.
055     */
056    public SignedThenEncryptedJwt(final JweHeader header, final String encodedHeader,
057            final byte[] encryptedContentEncryptionKey,
058            final byte[] initialisationVector, final byte[] ciphertext, final byte[] authenticationTag) {
059        super(header, encodedHeader, encryptedContentEncryptionKey, initialisationVector, ciphertext,
060                authenticationTag);
061    }
062
063    /**
064     * Verifies that the signature is valid on the nested signed JWT.
065     * @param signingHandler the handler to use for verifying the signature.
066     * @return {@literal true} if the signature is valid, otherwise {@literal false}.
067     * @throws JwsVerifyingException if the outer JWT has not already been decrypted.
068     */
069    public boolean verify(SigningHandler signingHandler) {
070        if (getPayload() == null) {
071            throw new JwsVerifyingException("JWT must be decrypted before the nested signature can be verified");
072        }
073        return ((SignedJwt) getPayload()).verify(signingHandler);
074    }
075
076    /**
077     * Decrypts the outer JWT and then verifies the signature on the inner JWT.
078     *
079     * @param decryptionKey the decryption key for the outer JWE.
080     * @param signingHandler the signing handler for verifying the nested JWS.
081     * @return {@literal true} if the nested signature is valid, otherwise {@literal false}.
082     * @throws JweDecryptionException if the JWE cannot be decrypted.
083     */
084    public boolean decryptAndVerify(Key decryptionKey, SigningHandler signingHandler) {
085        decrypt(decryptionKey);
086        return verify(signingHandler);
087    }
088
089    @Override
090    public JwtClaimsSet getClaimsSet() {
091        return ((SignedJwt) getPayload()).getClaimsSet();
092    }
093
094
095    @Override
096    Payload decodePayload(String decryptedPayload) {
097        return JWT_RECONSTRUCTION.reconstructJwt(decryptedPayload, SignedJwt.class);
098    }
099}