/**
* 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.nio.charset.StandardCharsets;
import java.util.logging.Logger;
import org.apache.cxf.common.logging.LogUtils;
import org.apache.cxf.common.util.Base64Exception;
import org.apache.cxf.common.util.Base64UrlUtility;
import org.apache.cxf.jaxrs.json.basic.JsonMapObject;
import org.apache.cxf.jaxrs.json.basic.JsonMapObjectReaderWriter;
import org.apache.cxf.rs.security.jose.common.JoseUtils;
public class JweCompactConsumer {
protected static final Logger LOG = LogUtils.getL7dLogger(JweCompactConsumer.class);
private JweDecryptionInput jweDecryptionInput;
public JweCompactConsumer(String jweContent) {
String[] parts = JoseUtils.getCompactParts(jweContent);
if (parts.length != 5) {
LOG.warning("5 JWE parts are expected");
throw new JweException(JweException.Error.INVALID_COMPACT_JWE);
}
try {
String headersJson = new String(Base64UrlUtility.decode(parts[0]));
byte[] encryptedCEK = Base64UrlUtility.decode(parts[1]);
byte[] initVector = Base64UrlUtility.decode(parts[2]);
byte[] encryptedContent = Base64UrlUtility.decode(parts[3]);
byte[] authTag = Base64UrlUtility.decode(parts[4]);
JsonMapObjectReaderWriter reader = new JsonMapObjectReaderWriter();
JsonMapObject joseHeaders = reader.fromJsonToJsonObject(headersJson);
if (joseHeaders.getUpdateCount() != null) {
LOG.warning("Duplicate headers have been detected");
throw new JweException(JweException.Error.INVALID_COMPACT_JWE);
}
JweHeaders jweHeaders = new JweHeaders(joseHeaders.asMap());
jweDecryptionInput = new JweDecryptionInput(encryptedCEK,
initVector,
encryptedContent,
authTag,
null,
headersJson,
jweHeaders);
} catch (Base64Exception ex) {
LOG.warning("Incorrect Base64 URL encoding");
throw new JweException(JweException.Error.INVALID_COMPACT_JWE);
}
}
public String getDecodedJsonHeaders() {
return jweDecryptionInput.getDecodedJsonHeaders();
}
public JweHeaders getJweHeaders() {
return jweDecryptionInput.getJweHeaders();
}
public byte[] getEncryptedContentEncryptionKey() {
return jweDecryptionInput.getEncryptedCEK();
}
public byte[] getContentDecryptionCipherInitVector() {
return jweDecryptionInput.getInitVector();
}
public byte[] getContentEncryptionCipherAAD() {
return JweHeaders.toCipherAdditionalAuthData(jweDecryptionInput.getDecodedJsonHeaders());
}
public byte[] getEncryptionAuthenticationTag() {
return jweDecryptionInput.getAuthTag();
}
public byte[] getEncryptedContent() {
return jweDecryptionInput.getEncryptedContent();
}
public byte[] getEncryptedContentWithAuthTag() {
return getCipherWithAuthTag(getEncryptedContent(), getEncryptionAuthenticationTag());
}
public JweDecryptionInput getJweDecryptionInput() {
return jweDecryptionInput;
}
public static byte[] getCipherWithAuthTag(byte[] cipher, byte[] authTag) {
byte[] encryptedContentWithTag = new byte[cipher.length + authTag.length];
System.arraycopy(cipher, 0, encryptedContentWithTag, 0, cipher.length);
System.arraycopy(authTag, 0, encryptedContentWithTag, cipher.length, authTag.length);
return encryptedContentWithTag;
}
public byte[] getDecryptedContent(JweDecryptionProvider decryption) {
// temp workaround
return decryption.decrypt(jweDecryptionInput);
}
public String getDecryptedContentText(JweDecryptionProvider decryption) {
return new String(getDecryptedContent(decryption), StandardCharsets.UTF_8);
}
public boolean validateCriticalHeaders() {
return JweUtils.validateCriticalHeaders(getJweHeaders());
}
}