blob: afc6201b1c347fd73dc74b1439fb3ca2ae3e1df3 [file] [log] [blame]
/*
* 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.oltu.jose.jwe;
import org.apache.oltu.commons.encodedtoken.TokenDecoder;
import org.apache.oltu.commons.json.CustomizableBuilder;
import org.apache.oltu.jose.jwe.encryption.ContentEncryptMethod;
import org.apache.oltu.jose.jwe.encryption.DecryptingKey;
import org.apache.oltu.jose.jwe.encryption.EncryptingKey;
import org.apache.oltu.jose.jwe.encryption.KeyEncryptMethod;
import org.apache.oltu.jose.jwe.io.JWEHeaderWriter;
public class JWE {
/**
* The JWE Header.
*/
private final Header header;
/**
* The JWE encryptedKey.
*/
private final String encryptedKey;
//TODO remove??
/**
* The JWE Payload.
*/
private final String payload;
/**
* The JWE Content Encryption.
*/
private final String contentEncryption;
JWE(Header header, String encryptedKey, String payload ,String contentEncryption) {
this.header = header;
this.encryptedKey = encryptedKey;
this.payload = payload;
this.contentEncryption = contentEncryption;
}
public Header getHeader() {
return header;
}
public String getEncryptedKey() {
return encryptedKey;
}
public String getPayload() {
return payload;
}
public String getContentEncryption() {
return contentEncryption;
}
public <EK extends EncryptingKey, DK extends DecryptingKey> boolean acceptAlgorithm(KeyEncryptMethod<EK, DK> keyEncryptMethod, ContentEncryptMethod<EK, DK> contentEncryptMethod) {
if (keyEncryptMethod == null) {
throw new IllegalArgumentException("An encrypt method is required in order to decrypt the content encryption key.");
}
if (contentEncryptMethod == null) {
throw new IllegalArgumentException("An encrypt method is required in order to decrypt the payload.");
}
if (header == null || header.getAlgorithm() == null || header.getEncryptionAlgorithm() == null) {
throw new IllegalStateException("JWE token must have a valid JSON header with specified algorithm.");
}
return header.getAlgorithm().equalsIgnoreCase(keyEncryptMethod.getAlgorithm()) && header.getEncryptionAlgorithm().equalsIgnoreCase(contentEncryptMethod.getAlgorithm());
}
public <EK extends EncryptingKey, DK extends DecryptingKey> String decrypt(KeyEncryptMethod<EK, DK> keyEncryptMethod,
DK decryptingKey, ContentEncryptMethod<EK, DK> contentEncryptMethod) {
if (!acceptAlgorithm(keyEncryptMethod, contentEncryptMethod)) {
throw new IllegalArgumentException("Impossible to decrypt current JWE");
}
if (decryptingKey == null) {
throw new IllegalArgumentException("A decrypting key is required in order to decrypt the JWE");
}
if (encryptedKey == null) {
throw new IllegalStateException("JWE token must have an encrypted key.");
}
if (contentEncryption == null) {
throw new IllegalStateException("JWE token must have a content encryption");
}
return contentEncryptMethod.decrypt(new JWEHeaderWriter().write(header), contentEncryption, keyEncryptMethod.decrypt(encryptedKey, decryptingKey));
}
public static final class Builder extends CustomizableBuilder<JWE> {
/**
* The {@code alg} JWE Header parameter.
*/
private String algorithm;
/**
* The {@code enc} JWE Header parameter.
*/
private String encryptionAlgorithm;
/**
* The {@code zip} JWE Header key.
*/
private String compressionAlgorithm;
/**
* The {@code jku} JWE Header parameter.
*/
private String jwkSetUrl;
/**
* The {@code jwk} JWE Header parameter.
*/
private String jsonWebKey;
/**
* The {@code x5u} JWE Header parameter.
*/
private String x509url;
/**
* The {@code x5t} JWE Header parameter.
*/
private String x509CertificateThumbprint;
/**
* The {@code x5c} JWE Header parameter.
*/
private String x509CertificateChain;
/**
* The {@code kid} JWE Header parameter.
*/
private String keyId;
/**
* The {@code typ} JWE Header parameter.
*/
private String type;
/**
* The {@code cty} JWE Header parameter.
*/
private String contentType;
/**
* The {@code crit} JWE Header parameter.
*/
private String[] critical;
/**
* The JWE encryptedKey.
*/
private String encryptedKey;
/**
* The JWE Payload.
*/
private String payload;
/**
* The JWE Content Encryption.
*/
private String contentEncryption;
public Builder setAlgorithm(String algorithm) {
this.algorithm = algorithm;
return this;
}
public Builder setEncryptionAlgorithm(String encryptionAlgorithm) {
this.encryptionAlgorithm = encryptionAlgorithm;
return this;
}
public Builder setCompressionAlgorithm(String compressionAlgorithm) {
this.compressionAlgorithm = compressionAlgorithm;
return this;
}
public Builder setJwkSetUrl(String jwkSetUrl) {
this.jwkSetUrl = jwkSetUrl;
return this;
}
public Builder setJsonWebKey(String jsonWebKey) {
this.jsonWebKey = jsonWebKey;
return this;
}
public Builder setX509url(String x509url) {
this.x509url = x509url;
return this;
}
public Builder setX509CertificateThumbprint(String x509CertificateThumbprint) {
this.x509CertificateThumbprint = x509CertificateThumbprint;
return this;
}
public Builder setX509CertificateChain(String x509CertificateChain) {
this.x509CertificateChain = x509CertificateChain;
return this;
}
public Builder setKeyId(String keyId) {
this.keyId = keyId;
return this;
}
public Builder setType(String type) {
this.type = type;
return this;
}
public Builder setContentType(String contentType) {
this.contentType = contentType;
return this;
}
public Builder setEncryptedKey(String encryptedKey) {
this.encryptedKey = encryptedKey;
return this;
}
public Builder setCritical(String[] critical) {
this.critical = critical;
return this;
}
public Builder setPayload(String payload) {
this.payload = payload;
return this;
}
public Builder setContentEncryption(String contentEncryption) {
this.contentEncryption = contentEncryption;
return this;
}
public <EK extends EncryptingKey, DK extends DecryptingKey> Builder encrypt(KeyEncryptMethod<EK, DK> keyEncryptMethod,
EK encryptingKey, ContentEncryptMethod<EK, DK> contentEncryptMethod) {
if (keyEncryptMethod == null) {
throw new IllegalArgumentException("A key encryption method is required in order to encrypt the content encryption key.");
}
if (encryptingKey == null) {
throw new IllegalArgumentException("An encryption key is required in order to encrypt the content encryption key.");
}
if (payload == null) {
throw new IllegalStateException("Payload needs to be set in order to encrypt it.");
}
if (contentEncryptMethod == null) {
throw new IllegalArgumentException("A key encryption method is required in order to encrypt the payload.");
}
setAlgorithm(keyEncryptMethod.getAlgorithm());
setEncryptionAlgorithm(contentEncryptMethod.getAlgorithm());
String header = new JWEHeaderWriter().write(new Header(algorithm,
encryptionAlgorithm,
compressionAlgorithm,
jwkSetUrl,
jsonWebKey,
x509url,
x509CertificateThumbprint,
x509CertificateChain,
keyId, type,
contentType,
critical,
getCustomFields()));
ContentEncryptionKey cek = keyEncryptMethod.encrypt(encryptingKey);
setEncryptedKey(cek.getEncryptedKey());
return setContentEncryption(contentEncryptMethod.encrypt(TokenDecoder.base64Encode(header), payload, cek.getContentEncryptionKey()));
}
@Override
public JWE build() {
return new JWE(new Header(algorithm,
encryptionAlgorithm,
compressionAlgorithm,
jwkSetUrl,
jsonWebKey,
x509url,
x509CertificateThumbprint,
x509CertificateChain,
keyId, type,
contentType,
critical,
getCustomFields()),
encryptedKey,
payload,
contentEncryption);
}
}
}