JsonEncrypt.java
/*
* GovWay - A customizable API Gateway
* https://govway.org
*
* Copyright (c) 2005-2024 Link.it srl (https://link.it).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3, as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openspcoop2.utils.security;
import java.util.Iterator;
import java.util.Properties;
import org.apache.cxf.rs.security.jose.common.JoseConstants;
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.jwe.JweEncryptionProvider;
import org.apache.cxf.rs.security.jose.jwe.JweHeaders;
import org.apache.cxf.rs.security.jose.jwe.JweJsonProducer;
import org.apache.cxf.rs.security.jose.jwe.JweUtils;
import org.apache.cxf.rs.security.jose.jwk.JsonWebKey;
import org.apache.cxf.rs.security.jose.jwk.JsonWebKeys;
import org.apache.cxf.rs.security.jose.jwk.JwkUtils;
import org.openspcoop2.utils.UtilsException;
import org.openspcoop2.utils.certificate.KeyStore;
/**
* Encrypt
*
* @author Poli Andrea (apoli@link.it)
* @author $Author$
* @version $Rev$, $Date$
*/
public class JsonEncrypt {
private JweEncryptionProvider provider;
private ContentAlgorithm contentAlgorithm;
private KeyAlgorithm keyAlgorithm;
private JWEOptions options;
private JweHeaders headers;
private JwtHeaders jwtHeaders;
public JsonEncrypt(Properties props, JWEOptions options) throws UtilsException{
this(props, null, options);
}
public JsonEncrypt(Properties props, JwtHeaders jwtHeaders, JWEOptions options) throws UtilsException{
try {
this.headers = new JweHeaders();
this.options=options;
String tmp = props.getProperty(JoseConstants.RSSEC_ENCRYPTION_ZIP_ALGORITHM);
if(tmp!=null && JoseConstants.JWE_DEFLATE_ZIP_ALGORITHM.equalsIgnoreCase(tmp.trim())) {
this.options.setDeflate(true); // overwrite options
}
this.provider = JsonUtils.getJweEncryptionProvider(props);
if(this.provider==null) {
KeyAlgorithm keyAlgorithmP = JweUtils.getKeyEncryptionAlgorithm(props, null);
if (KeyAlgorithm.DIRECT.equals(keyAlgorithmP)) {
this.provider = JsonUtils.getJweEncryptionProviderFromJWKSymmetric(props, this.headers);
}
else {
this.provider = JweUtils.loadEncryptionProvider(props, JsonUtils.newMessage(), this.headers);
}
}
this.contentAlgorithm = JweUtils.getContentEncryptionAlgorithm(props, ContentAlgorithm.A256GCM);
this.keyAlgorithm = JweUtils.getKeyEncryptionAlgorithm(props, null);
/** if(this.keyAlgorithm==null) {
// throw new Exception("KeyAlgorithm undefined");
// }*/
this.jwtHeaders = jwtHeaders;
}catch(Exception t) {
throw JsonUtils.convert(options.getSerialization(), JsonUtils.ENCRYPT,JsonUtils.SENDER,t);
}
}
public JsonEncrypt(java.security.KeyStore keystore, String alias, String keyAlgorithm, String contentAlgorithm,
JWEOptions options) throws UtilsException{
initTrustStore(new KeyStore(keystore), alias, keyAlgorithm, contentAlgorithm, null, options);
}
public JsonEncrypt(KeyStore keystore, String alias, String keyAlgorithm, String contentAlgorithm,
JWEOptions options) throws UtilsException{
initTrustStore(keystore, alias, keyAlgorithm, contentAlgorithm, null, options);
}
public JsonEncrypt(java.security.KeyStore keystore, String alias, String keyAlgorithm, String contentAlgorithm,
JwtHeaders jwtHeaders, JWEOptions options) throws UtilsException{
initTrustStore(new KeyStore(keystore), alias, keyAlgorithm, contentAlgorithm, jwtHeaders, options);
}
public JsonEncrypt(KeyStore keystore, String alias, String keyAlgorithm, String contentAlgorithm,
JwtHeaders jwtHeaders, JWEOptions options) throws UtilsException{
initTrustStore(keystore, alias, keyAlgorithm, contentAlgorithm, jwtHeaders, options);
}
private void initTrustStore(KeyStore keystore, String alias, String keyAlgorithm, String contentAlgorithm,
JwtHeaders jwtHeaders, JWEOptions options) throws UtilsException{
try {
this.options=options;
this.keyAlgorithm = org.apache.cxf.rs.security.jose.jwa.KeyAlgorithm.getAlgorithm(keyAlgorithm);
this.contentAlgorithm = org.apache.cxf.rs.security.jose.jwa.ContentAlgorithm.getAlgorithm(contentAlgorithm);
String compression = null;
if(this.options.isDeflate()) {
compression = JoseConstants.JWE_DEFLATE_ZIP_ALGORITHM;
}
this.provider = JweUtils.createJweEncryptionProvider( keystore.getPublicKey(alias), this.keyAlgorithm, this.contentAlgorithm, compression);
this.jwtHeaders = jwtHeaders;
}catch(Exception t) {
throw JsonUtils.convert(options.getSerialization(), JsonUtils.ENCRYPT,JsonUtils.SENDER,t);
}
}
public JsonEncrypt(java.security.KeyStore keystore, String alias, String passwordPrivateKey, String keyAlgorithm, String contentAlgorithm,
JWEOptions options) throws UtilsException{
initKeystore(new KeyStore(keystore), alias, passwordPrivateKey, keyAlgorithm, contentAlgorithm, null, options);
}
public JsonEncrypt(KeyStore keystore, String alias, String passwordPrivateKey, String keyAlgorithm, String contentAlgorithm,
JWEOptions options) throws UtilsException{
initKeystore(keystore, alias, passwordPrivateKey, keyAlgorithm, contentAlgorithm, null, options);
}
public JsonEncrypt(java.security.KeyStore keystore, String alias, String passwordPrivateKey, String keyAlgorithm, String contentAlgorithm,
JwtHeaders jwtHeaders, JWEOptions options) throws UtilsException{
initKeystore(new KeyStore(keystore), alias, passwordPrivateKey, keyAlgorithm, contentAlgorithm, jwtHeaders, options);
}
public JsonEncrypt(KeyStore keystore, String alias, String passwordPrivateKey, String keyAlgorithm, String contentAlgorithm,
JwtHeaders jwtHeaders, JWEOptions options) throws UtilsException{
initKeystore(keystore, alias, passwordPrivateKey, keyAlgorithm, contentAlgorithm, jwtHeaders, options);
}
private void initKeystore(KeyStore keystore, String alias, String passwordPrivateKey, String keyAlgorithm, String contentAlgorithm,
JwtHeaders jwtHeaders, JWEOptions options) throws UtilsException{
try {
this.options=options;
this.keyAlgorithm = org.apache.cxf.rs.security.jose.jwa.KeyAlgorithm.getAlgorithm(keyAlgorithm);
this.contentAlgorithm = org.apache.cxf.rs.security.jose.jwa.ContentAlgorithm.getAlgorithm(contentAlgorithm);
String compression = null;
if(this.options.isDeflate()) {
compression = JoseConstants.JWE_DEFLATE_ZIP_ALGORITHM;
}
if (KeyAlgorithm.DIRECT.equals(this.keyAlgorithm)) {
this.provider = JweUtils.getDirectKeyJweEncryption(keystore.getSecretKey(alias, passwordPrivateKey), this.contentAlgorithm);
}
else {
this.provider = JweUtils.createJweEncryptionProvider(keystore.getSecretKey(alias, passwordPrivateKey), this.keyAlgorithm, this.contentAlgorithm, compression);
}
this.jwtHeaders = jwtHeaders;
}catch(Exception t) {
throw JsonUtils.convert(options.getSerialization(), JsonUtils.ENCRYPT,JsonUtils.SENDER,t);
}
}
public JsonEncrypt(JsonWebKeys jsonWebKeys, boolean secretKey, String alias, String keyAlgorithm, String contentAlgorithm,
JWEOptions options) throws UtilsException{
initJsonWebKey(JsonUtils.readKey(jsonWebKeys, alias),secretKey, keyAlgorithm, contentAlgorithm, null, options);
}
public JsonEncrypt(JsonWebKeys jsonWebKeys, boolean secretKey, String alias, String keyAlgorithm, String contentAlgorithm,
JwtHeaders jwtHeaders, JWEOptions options) throws UtilsException{
initJsonWebKey(JsonUtils.readKey(jsonWebKeys, alias),secretKey, keyAlgorithm, contentAlgorithm, jwtHeaders, options);
}
public JsonEncrypt(JsonWebKey jsonWebKey, boolean secretKey, String keyAlgorithm, String contentAlgorithm,
JWEOptions options) throws UtilsException{
initJsonWebKey(jsonWebKey,secretKey, keyAlgorithm, contentAlgorithm, null, options);
}
public JsonEncrypt(JsonWebKey jsonWebKey, boolean secretKey, String keyAlgorithm, String contentAlgorithm,
JwtHeaders jwtHeaders, JWEOptions options) throws UtilsException{
initJsonWebKey(jsonWebKey,secretKey, keyAlgorithm, contentAlgorithm, jwtHeaders, options);
}
private void initJsonWebKey(JsonWebKey jsonWebKey, boolean secretKey, String keyAlgorithm, String contentAlgorithm,
JwtHeaders jwtHeaders, JWEOptions options) throws UtilsException{
try {
this.options=options;
this.keyAlgorithm = org.apache.cxf.rs.security.jose.jwa.KeyAlgorithm.getAlgorithm(keyAlgorithm);
this.contentAlgorithm = org.apache.cxf.rs.security.jose.jwa.ContentAlgorithm.getAlgorithm(contentAlgorithm);
String compression = null;
if(this.options.isDeflate()) {
compression = JoseConstants.JWE_DEFLATE_ZIP_ALGORITHM;
}
if(secretKey) {
if(jsonWebKey.getAlgorithm()==null) {
jsonWebKey.setAlgorithm(contentAlgorithm);
}
if (KeyAlgorithm.DIRECT.equals(this.keyAlgorithm)) {
this.provider = JweUtils.getDirectKeyJweEncryption(JwkUtils.toSecretKey(jsonWebKey), this.contentAlgorithm);
}
else {
this.provider = JweUtils.createJweEncryptionProvider(JwkUtils.toSecretKey(jsonWebKey), this.keyAlgorithm, this.contentAlgorithm, compression);
}
if(this.provider==null) {
throw new UtilsException("(JsonWebKey) JwsEncryptionProvider init failed; check content algorithm ("+contentAlgorithm+")");
}
}else {
this.provider = JweUtils.createJweEncryptionProvider(JwkUtils.toRSAPublicKey(jsonWebKey), this.keyAlgorithm, this.contentAlgorithm, compression);
}
this.jwtHeaders = jwtHeaders;
}catch(Exception t) {
throw JsonUtils.convert(options.getSerialization(), JsonUtils.ENCRYPT,JsonUtils.SENDER,t);
}
}
public String encrypt(String jsonString) throws UtilsException{
try {
switch(this.options.getSerialization()) {
case JSON: return encryptJson(jsonString);
case COMPACT: return encryptCompact(jsonString);
default: throw new UtilsException("Unsupported serialization '"+this.options.getSerialization()+"'");
}
}
catch(Exception t) {
throw JsonUtils.convert(this.options.getSerialization(), JsonUtils.ENCRYPT,JsonUtils.SENDER,t);
}
}
public String encrypt(byte[] json) throws UtilsException{
try {
switch(this.options.getSerialization()) {
case JSON: return encryptJson(json);
case COMPACT: return encryptCompact(json);
default: throw new UtilsException("Unsupported serialization '"+this.options.getSerialization()+"'");
}
}
catch(Exception t) {
throw JsonUtils.convert(this.options.getSerialization(), JsonUtils.ENCRYPT,JsonUtils.SENDER,t);
}
}
private String encryptCompact(String jsonString) throws Exception {
return encryptCompact(jsonString.getBytes());
}
private String encryptCompact(byte[] json) throws Exception {
JweHeaders headersBuild = null;
if(this.keyAlgorithm!=null) {
headersBuild = new JweHeaders(this.keyAlgorithm,this.contentAlgorithm,this.options.isDeflate());
}
else {
headersBuild = new JweHeaders(this.contentAlgorithm,this.options.isDeflate());
}
fillJwtHeaders(headersBuild, this.keyAlgorithm);
return this.provider.encrypt(json, headersBuild);
}
private String encryptJson(String jsonString) throws Exception {
return encryptJson(jsonString.getBytes());
}
private String encryptJson(byte[] json) throws Exception {
JweHeaders sharedUnprotectedHeaders = null;
if(this.keyAlgorithm!=null) {
sharedUnprotectedHeaders = new JweHeaders();
sharedUnprotectedHeaders.setKeyEncryptionAlgorithm(this.keyAlgorithm);
}
JweHeaders protectedHeaders = new JweHeaders(this.contentAlgorithm, this.options.isDeflate());
fillJwtHeaders(protectedHeaders, this.keyAlgorithm);
JweJsonProducer producer = null;
if(sharedUnprotectedHeaders!=null) {
protectedHeaders.removeProperty("alg"); // e' in sharedUnprotectedHeaders
producer = new JweJsonProducer(protectedHeaders, sharedUnprotectedHeaders, json);
}
else {
producer = new JweJsonProducer(protectedHeaders, json);
}
return producer.encryptWith(this.provider);
}
private void fillJwtHeaders(JweHeaders headers, org.apache.cxf.rs.security.jose.jwa.KeyAlgorithm keyAlgo) throws Exception {
if(this.headers!=null &&
this.headers.asMap()!=null && !this.headers.asMap().isEmpty()) {
Iterator<String> itKeys = this.headers.asMap().keySet().iterator();
while (itKeys.hasNext()) {
String key = itKeys.next();
if(!headers.containsHeader(key)) {
headers.setHeader(key, this.headers.getHeader(key));
}
}
}
if(this.jwtHeaders!=null) {
this.jwtHeaders.fillJwsHeaders(headers, false, keyAlgo!=null ? keyAlgo.getJwaName() : null);
}
}
}