/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.cxf.rs.security.jose.jwe;
import java.security.Key;
import java.security.spec.AlgorithmParameterSpec;
import java.util.logging.Logger;
import org.apache.cxf.common.logging.LogUtils;
import org.apache.cxf.rs.security.jose.common.JoseConstants;
import org.apache.cxf.rs.security.jose.jwa.AlgorithmUtils;
import org.apache.cxf.rs.security.jose.jwa.ContentAlgorithm;
import org.apache.cxf.rs.security.jose.jwa.KeyAlgorithm;
import org.apache.cxf.rs.security.jose.jws.JwsUtils;
import org.apache.cxf.rt.security.crypto.CryptoUtils;
import org.apache.cxf.rt.security.crypto.KeyProperties;
public abstract class AbstractJweDecryption implements JweDecryptionProvider {
protected static final Logger LOG = LogUtils.getL7dLogger(JwsUtils.class);
private KeyDecryptionProvider keyDecryptionAlgo;
private ContentDecryptionProvider contentDecryptionAlgo;
protected AbstractJweDecryption(KeyDecryptionProvider keyDecryptionAlgo,
ContentDecryptionProvider contentDecryptionAlgo) {
this.keyDecryptionAlgo = keyDecryptionAlgo;
this.contentDecryptionAlgo = contentDecryptionAlgo;
}
protected byte[] getContentEncryptionKey(JweDecryptionInput jweDecryptionInput) {
return keyDecryptionAlgo.getDecryptedContentEncryptionKey(jweDecryptionInput);
}
public JweDecryptionOutput decrypt(String content) {
JweCompactConsumer consumer = new JweCompactConsumer(content);
byte[] cek = getContentEncryptionKey(consumer.getJweDecryptionInput());
return doDecrypt(consumer.getJweDecryptionInput(), cek);
}
public byte[] decrypt(JweDecryptionInput jweDecryptionInput) {
byte[] cek = getContentEncryptionKey(jweDecryptionInput);
return doDecrypt(jweDecryptionInput, cek).getContent();
}
protected JweDecryptionOutput doDecrypt(JweDecryptionInput jweDecryptionInput, byte[] cek) {
KeyProperties keyProperties = new KeyProperties(getContentEncryptionAlgorithm(jweDecryptionInput));
keyProperties.setAdditionalData(getContentEncryptionCipherAAD(jweDecryptionInput));
AlgorithmParameterSpec spec = getContentEncryptionCipherSpec(jweDecryptionInput);
keyProperties.setAlgoSpec(spec);
boolean compressionSupported =
JoseConstants.JWE_DEFLATE_ZIP_ALGORITHM.equals(jweDecryptionInput.getJweHeaders().getZipAlgorithm());
keyProperties.setCompressionSupported(compressionSupported);
byte[] actualCek = getActualCek(cek,
jweDecryptionInput.getJweHeaders().getContentEncryptionAlgorithm().getJwaName());
Key secretKey = CryptoUtils.createSecretKeySpec(actualCek, keyProperties.getKeyAlgo());
byte[] bytes =
CryptoUtils.decryptBytes(getEncryptedContentWithAuthTag(jweDecryptionInput), secretKey, keyProperties);
return new JweDecryptionOutput(jweDecryptionInput.getJweHeaders(), bytes);
}
protected byte[] getEncryptedContentEncryptionKey(JweCompactConsumer consumer) {
return consumer.getEncryptedContentEncryptionKey();
}
protected AlgorithmParameterSpec getContentEncryptionCipherSpec(JweDecryptionInput jweDecryptionInput) {
return contentDecryptionAlgo.getAlgorithmParameterSpec(
getContentEncryptionCipherInitVector(jweDecryptionInput));
}
protected String getContentEncryptionAlgorithm(JweDecryptionInput jweDecryptionInput) {
return AlgorithmUtils.toJavaName(jweDecryptionInput.getJweHeaders()
.getContentEncryptionAlgorithm().getJwaName());
}
protected byte[] getContentEncryptionCipherAAD(JweDecryptionInput jweDecryptionInput) {
return contentDecryptionAlgo.getAdditionalAuthenticationData(
jweDecryptionInput.getDecodedJsonHeaders(), jweDecryptionInput.getAad());
}
protected byte[] getEncryptedContentWithAuthTag(JweDecryptionInput jweDecryptionInput) {
return contentDecryptionAlgo.getEncryptedSequence(jweDecryptionInput.getJweHeaders(),
jweDecryptionInput.getEncryptedContent(),
getEncryptionAuthenticationTag(jweDecryptionInput));
}
protected byte[] getContentEncryptionCipherInitVector(JweDecryptionInput jweDecryptionInput) {
return jweDecryptionInput.getInitVector();
}
protected byte[] getEncryptionAuthenticationTag(JweDecryptionInput jweDecryptionInput) {
return jweDecryptionInput.getAuthTag();
}
protected int getEncryptionAuthenticationTagLenBits(JweDecryptionInput jweDecryptionInput) {
return getEncryptionAuthenticationTag(jweDecryptionInput).length * 8;
}
protected byte[] getActualCek(byte[] theCek, String algoJwt) {
return theCek;
}
@Override
public KeyAlgorithm getKeyAlgorithm() {
return keyDecryptionAlgo.getAlgorithm();
}
@Override
public ContentAlgorithm getContentAlgorithm() {
return contentDecryptionAlgo.getAlgorithm();
}
}