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.handlers.encryption;
018
019import java.security.GeneralSecurityException;
020import java.security.Key;
021
022import javax.crypto.Cipher;
023
024import org.forgerock.json.jose.exceptions.JweDecryptionException;
025import org.forgerock.json.jose.exceptions.JweEncryptionException;
026import org.forgerock.json.jose.jwe.EncryptionMethod;
027import org.forgerock.json.jose.jwe.JweEncryption;
028
029/**
030 * Provides JWE key encapsulation using the AES KeyWrap algorithm.
031 */
032public final class AESKeyWrapEncryptionHandler implements EncryptionHandler {
033    private final ContentEncryptionHandler contentEncryptionHandler;
034    private final EncryptionMethod encryptionMethod;
035
036    /**
037     * Constructs an AES KeyWrap encryption handler for the given underlying content encryption method.
038     *
039     * @param method the content encryption method.
040     */
041    public AESKeyWrapEncryptionHandler(final EncryptionMethod method) {
042        this.contentEncryptionHandler = ContentEncryptionHandler.getInstance(method);
043        this.encryptionMethod = method;
044    }
045
046    @Override
047    public Key getContentEncryptionKey() {
048        return contentEncryptionHandler.generateEncryptionKey();
049    }
050
051    @Override
052    public byte[] generateJWEEncryptedKey(final Key key, final Key contentEncryptionKey) {
053        try {
054            final Cipher cipher = Cipher.getInstance("AESWrap");
055            cipher.init(Cipher.WRAP_MODE, key);
056            return cipher.wrap(contentEncryptionKey);
057        } catch (GeneralSecurityException e) {
058            throw new JweEncryptionException(e);
059        }
060    }
061
062    @Override
063    public byte[] generateInitialisationVector() {
064        return contentEncryptionHandler.generateInitialisationVector();
065    }
066
067    @Override
068    public JweEncryption encryptPlaintext(final Key contentEncryptionKey, final byte[] initialisationVector,
069            final byte[] plaintext,
070            final byte[] additionalAuthenticatedData) {
071        return contentEncryptionHandler.encrypt(contentEncryptionKey, initialisationVector, plaintext,
072                additionalAuthenticatedData);
073    }
074
075    @Override
076    public Key decryptContentEncryptionKey(final Key key, final byte[] encryptedContentEncryptionKey) {
077        try {
078            final Cipher cipher = Cipher.getInstance("AESWrap");
079            cipher.init(Cipher.UNWRAP_MODE, key);
080            return cipher.unwrap(encryptedContentEncryptionKey, encryptionMethod.getEncryptionAlgorithm(),
081                    Cipher.SECRET_KEY);
082        } catch (GeneralSecurityException e) {
083            throw new JweDecryptionException();
084        }
085    }
086
087    @Override
088    public byte[] decryptCiphertext(final Key contentEncryptionKey, final byte[] initialisationVector,
089            final byte[] ciphertext,
090            final byte[] authenticationTag, final byte[] additionalAuthenticatedData) {
091        return contentEncryptionHandler.decrypt(contentEncryptionKey, initialisationVector,
092                new JweEncryption(ciphertext, authenticationTag), additionalAuthenticatedData);
093    }
094}