BYOKLocalEncrypt.java

  1. /*
  2.  * GovWay - A customizable API Gateway
  3.  * https://govway.org
  4.  *
  5.  * Copyright (c) 2005-2025 Link.it srl (https://link.it).
  6.  *
  7.  * This program is free software: you can redistribute it and/or modify
  8.  * it under the terms of the GNU General Public License version 3, as published by
  9.  * the Free Software Foundation.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  18.  *
  19.  */

  20. package org.openspcoop2.security.keystore;

  21. import java.security.Key;
  22. import java.security.cert.Certificate;
  23. import java.security.cert.X509Certificate;

  24. import javax.crypto.SecretKey;

  25. import org.apache.commons.lang.StringUtils;
  26. import org.apache.cxf.rs.security.jose.jwk.JsonWebKey;
  27. import org.apache.cxf.rs.security.jose.jwk.JsonWebKeys;
  28. import org.apache.cxf.rs.security.jose.jwk.JwkUtils;
  29. import org.openspcoop2.protocol.sdk.state.RequestInfo;
  30. import org.openspcoop2.security.SecurityException;
  31. import org.openspcoop2.security.keystore.cache.GestoreKeystoreCache;
  32. import org.openspcoop2.utils.UtilsException;
  33. import org.openspcoop2.utils.certificate.JWK;
  34. import org.openspcoop2.utils.certificate.JWKSet;
  35. import org.openspcoop2.utils.certificate.KeyStore;
  36. import org.openspcoop2.utils.certificate.KeyUtils;
  37. import org.openspcoop2.utils.certificate.KeystoreType;
  38. import org.openspcoop2.utils.certificate.SymmetricKeyUtils;
  39. import org.openspcoop2.utils.certificate.byok.BYOKCostanti;
  40. import org.openspcoop2.utils.certificate.byok.BYOKLocalConfig;
  41. import org.openspcoop2.utils.io.Base64Utilities;
  42. import org.openspcoop2.utils.io.HexBinaryUtilities;
  43. import org.openspcoop2.utils.security.CipherInfo;
  44. import org.openspcoop2.utils.security.Decrypt;
  45. import org.openspcoop2.utils.security.DecryptOpenSSLPass;
  46. import org.openspcoop2.utils.security.DecryptOpenSSLPassPBKDF2;
  47. import org.openspcoop2.utils.security.DecryptWrapKey;
  48. import org.openspcoop2.utils.security.Encrypt;
  49. import org.openspcoop2.utils.security.EncryptOpenSSLPass;
  50. import org.openspcoop2.utils.security.EncryptOpenSSLPassPBKDF2;
  51. import org.openspcoop2.utils.security.EncryptWrapKey;
  52. import org.openspcoop2.utils.security.JOSESerialization;
  53. import org.openspcoop2.utils.security.JWEOptions;
  54. import org.openspcoop2.utils.security.JWTOptions;
  55. import org.openspcoop2.utils.security.JsonDecrypt;
  56. import org.openspcoop2.utils.security.JsonEncrypt;
  57. import org.openspcoop2.utils.security.JsonUtils;
  58. import org.openspcoop2.utils.security.JwtHeaders;
  59. import org.openspcoop2.utils.security.OpenSSLEncryptionMode;

  60. import com.nimbusds.jose.jwk.KeyUse;

  61. /**    
  62.  * BYOKLocalEncrypt
  63.  *
  64.  * @author Poli Andrea (poli@link.it)
  65.  * @author $Author$
  66.  * @version $Rev$, $Date$
  67.  */
  68. public class BYOKLocalEncrypt {

  69.     private RequestInfo requestInfo;
  70.    
  71.     public BYOKLocalEncrypt(RequestInfo requestInfo) {
  72.         this.requestInfo = requestInfo;
  73.     }
  74.     public BYOKLocalEncrypt() {
  75.     }
  76.    
  77.     private static final String JAVA_SEPARATOR = ".";
  78.    
  79.     private String getKeystoreError(BYOKLocalConfig config) {
  80.         return "Access to keystore ["+config.getKeystoreType().getNome()+"] '"+config.getKeystorePath()+"' failed";
  81.     }
  82.     private String getKeyError(BYOKLocalConfig config) {
  83.         return "Access to key ["+config.getKeystoreType().getNome()+"] '"+config.getKeystorePath()+"' failed";
  84.     }
  85.     private static final String ENCODING_MODE_UNDEFINED = "Encoding mode undefined";
  86.     private static final String KEYSTORE_PREFIX = "Keystore [";
  87.    
  88.     public String wrap(BYOKLocalConfig config,
  89.             String value) throws UtilsException {
  90.         return wrap(config,
  91.                 value.getBytes());
  92.     }
  93.     public String wrap(BYOKLocalConfig config,
  94.             byte[] value) throws UtilsException {
  95.        
  96.         BYOKEncryptKey byokEncryptKey = new BYOKEncryptKey();

  97.         boolean initPasswordKeyDerivation = false;
  98.         try {
  99.             switch (config.getKeystoreType()) {
  100.             case JKS:
  101.             case PKCS12:
  102.             case PKCS11:
  103.             case JCEKS:
  104.                 readKeystore(byokEncryptKey, config, true);
  105.                 break;
  106.             case JWK_SET:
  107.                 readJwk(byokEncryptKey, config, true);
  108.                 break;
  109.             case PUBLIC_KEY:
  110.                 readPublicKey(byokEncryptKey, config);
  111.                 break;
  112.             case SYMMETRIC_KEY:
  113.                 readSecretKey(byokEncryptKey, config);
  114.                 break;
  115.             case PASSWORD_KEY_DERIVATION:
  116.                 readPasswordKeyDerivation(byokEncryptKey, config, true);
  117.                 initPasswordKeyDerivation = true;
  118.                 break;
  119.             default:
  120.                 throw new UtilsException(KEYSTORE_PREFIX+config.getKeystoreType().getNome()+"] unsupported");
  121.             }
  122.         }catch(Exception e) {
  123.             throw new UtilsException(e.getMessage(),e);
  124.         }
  125.        
  126.         /**System.out.println("CONF ["+config.getName()+"] java["+config.isJavaEngine()+"] jose["+config.isJoseEngine()+"]");*/
  127.         if(config.isJavaEngine()) {
  128.             if(config.isKeyWrap()) {
  129.                 if(initPasswordKeyDerivation) {
  130.                     throw new UtilsException(KEYSTORE_PREFIX+config.getKeystoreType().getNome()+"] unusable with key wrap java mode");
  131.                 }
  132.                 return encJavaKeyWrap(byokEncryptKey, config, value);
  133.             }
  134.             else {
  135.                 return encJava(byokEncryptKey, config, value);
  136.             }
  137.         }
  138.         else if(config.isJoseEngine()) {
  139.             if(initPasswordKeyDerivation) {
  140.                 throw new UtilsException(KEYSTORE_PREFIX+config.getKeystoreType().getNome()+"] unusable with jose mode");
  141.             }
  142.             return encJose(byokEncryptKey, config, value);
  143.         }
  144.         else if(config.isOpenSSLEngine()) {
  145.             return encOpenSSL(byokEncryptKey, config, value);
  146.         }
  147.         else {
  148.             throw new UtilsException("Encrypt mode undefined");
  149.         }
  150.        
  151.     }
  152.    
  153.     public byte[] unwrap(BYOKLocalConfig config,
  154.             byte[] value) throws UtilsException {
  155.         return unwrap(config, new String(value));
  156.     }
  157.     public byte[] unwrap(BYOKLocalConfig config,
  158.             String value) throws UtilsException {
  159.        
  160.         BYOKEncryptKey byokEncryptKey = new BYOKEncryptKey();

  161.         boolean initPasswordKeyDerivation = false;
  162.         try {
  163.             switch (config.getKeystoreType()) {
  164.             case JKS:
  165.             case PKCS12:
  166.             case PKCS11:
  167.             case JCEKS:
  168.                 readKeystore(byokEncryptKey, config, false);
  169.                 break;
  170.             case JWK_SET:
  171.                 readJwk(byokEncryptKey, config, false);
  172.                 break;
  173.             case KEY_PAIR:
  174.                 readKeyPair(byokEncryptKey, config);
  175.                 break;
  176.             case SYMMETRIC_KEY:
  177.                 readSecretKey(byokEncryptKey, config);
  178.                 break;
  179.             case PASSWORD_KEY_DERIVATION:
  180.                 readPasswordKeyDerivation(byokEncryptKey, config, false);
  181.                 initPasswordKeyDerivation = true;
  182.                 break;
  183.             default:
  184.                 throw new UtilsException(KEYSTORE_PREFIX+config.getKeystoreType().getNome()+"] unsupported");
  185.             }
  186.         }catch(Exception e) {
  187.             throw new UtilsException(e.getMessage(),e);
  188.         }
  189.        
  190.         /**System.out.println("CONF ["+config.getName()+"] java["+config.isJavaEngine()+"] jose["+config.isJoseEngine()+"]");*/
  191.         if(config.isJavaEngine()) {
  192.             return unwrapJava(initPasswordKeyDerivation, config, value, byokEncryptKey);
  193.         }
  194.         else if(config.isJoseEngine()) {
  195.             if(initPasswordKeyDerivation) {
  196.                 throw new UtilsException(KEYSTORE_PREFIX+config.getKeystoreType().getNome()+"] unusable with jose mode");
  197.             }
  198.             return decryptJose(byokEncryptKey, config, value);
  199.         }
  200.         else if(config.isOpenSSLEngine()) {
  201.             return decryptOpenSSL(byokEncryptKey, config, value);
  202.         }
  203.         else {
  204.             throw new UtilsException("Encrypt mode undefined");
  205.         }
  206.        
  207.     }
  208.     private byte[] unwrapJava(boolean initPasswordKeyDerivation, BYOKLocalConfig config, String value, BYOKEncryptKey byokEncryptKey) throws UtilsException {
  209.         if(initPasswordKeyDerivation) {
  210.             if(config.isKeyWrap()) {
  211.                 throw new UtilsException(KEYSTORE_PREFIX+config.getKeystoreType().getNome()+"] unusable with key wrap java mode");
  212.             }
  213.             else {
  214.                 readJavaPasswordKeyDerivationForUnwrap(byokEncryptKey, config, value);
  215.             }
  216.         }
  217.         if(config.isKeyWrap()) {
  218.             return decryptJavaKeyWrap(byokEncryptKey, config, value);
  219.         }
  220.         else {
  221.             return decryptJava(byokEncryptKey, config, value);
  222.         }
  223.     }
  224.    
  225.    
  226.     private void readKeystore(BYOKEncryptKey byokEncryptKey, BYOKLocalConfig config, boolean wrap) throws UtilsException, SecurityException {
  227.         String type = KeystoreType.PKCS11.equals(config.getKeystoreType()) ? config.getKeystoreHsmType() : config.getKeystoreType().getNome();
  228.         MerlinKeystore merlinKs = GestoreKeystoreCache.getMerlinKeystore(this.requestInfo,
  229.                 config.getKeystorePath(), type,
  230.                 config.getKeystorePassword());
  231.         if(merlinKs==null || merlinKs.getKeyStore()==null) {
  232.             throw new UtilsException(getKeystoreError(config));
  233.         }
  234.         byokEncryptKey.ks = merlinKs.getKeyStore();
  235.         // bisogna sapere se e' secret o meno
  236.         if(KeystoreType.JCEKS.equals(config.getKeystoreType())) {
  237.             byokEncryptKey.key = byokEncryptKey.ks.getSecretKey(config.getKeyAlias(), config.getKeyPassword());
  238.             byokEncryptKey.secret = true;
  239.         }
  240.         else if(wrap) {
  241.             byokEncryptKey.key = merlinKs.getKeyStore().getPublicKey(config.getKeyAlias());
  242.         }
  243.         else {
  244.             byokEncryptKey.key = merlinKs.getKeyStore().getPrivateKey(config.getKeyAlias(), config.getKeyPassword());
  245.         }
  246.     }
  247.     private void readJwk(BYOKEncryptKey byokEncryptKey, BYOKLocalConfig config, boolean wrap) throws UtilsException, SecurityException {
  248.         JWKSetStore jwtStore = GestoreKeystoreCache.getJwkSetStore(this.requestInfo, config.getKeystorePath());
  249.         if(jwtStore==null || jwtStore.getJwkSet()==null) {
  250.             throw new UtilsException(getKeystoreError(config));
  251.         }
  252.         byokEncryptKey.jsonWebKeys = jwtStore.getJwkSet().getJsonWebKeys();
  253.         /**if(config.isJavaEngine()) {*/
  254.         // bisogna sapere se e' secret o meno
  255.         JsonWebKey jwk = JsonUtils.readKey(byokEncryptKey.jsonWebKeys, config.getKeyAlias());
  256.         if(jwk==null) {
  257.             throw new UtilsException("Access to keystore ["+config.getKeystoreType().getNome()+"] '"+config.getKeystorePath()+"' failed for alias '"+config.getKeyAlias()+"'");
  258.         }
  259.         if(jwk.getAlgorithm()==null) {
  260.             jwk.setAlgorithm(config.isJavaEngine() ? "A256GCM" : config.getContentAlgorithm());
  261.         }
  262.         if(config.getKeyAlgorithm().contains(KeyUtils.ALGO_RSA)) {
  263.             if(wrap) {
  264.                 byokEncryptKey.key = JwkUtils.toRSAPublicKey(jwk);
  265.             }
  266.             else {
  267.                 byokEncryptKey.key = JwkUtils.toRSAPrivateKey(jwk);
  268.             }
  269.         }
  270.         else if(config.getKeyAlgorithm().contains(KeyUtils.ALGO_EC)) {
  271.             if(wrap) {
  272.                 byokEncryptKey.key = JwkUtils.toECPublicKey(jwk);
  273.             }
  274.             else {
  275.                 byokEncryptKey.key = JwkUtils.toECPrivateKey(jwk);
  276.             }
  277.         }
  278.         else {
  279.             byokEncryptKey.key = JwkUtils.toSecretKey(jwk);
  280.             byokEncryptKey.secret = true;
  281.         }
  282.         /**}*/
  283.     }
  284.    
  285.     private String readKeyAlgo(BYOKLocalConfig config) {
  286.         String algo = config.getKeyAlgorithm();
  287.         if(config.isJoseEngine() || config.isKeyWrap()) {
  288.             if(config.getKeyAlgorithm().contains(KeyUtils.ALGO_RSA)) {
  289.                 algo = KeyUtils.ALGO_RSA;
  290.             }
  291.             else if(config.getKeyAlgorithm().contains(KeyUtils.ALGO_DSA)) {
  292.                 algo = KeyUtils.ALGO_DSA;
  293.             }
  294.             else if(config.getKeyAlgorithm().contains(KeyUtils.ALGO_DH)) {
  295.                 algo = KeyUtils.ALGO_DH;
  296.             }
  297.             else if(config.getKeyAlgorithm().contains(KeyUtils.ALGO_EC)) {
  298.                 algo = KeyUtils.ALGO_EC;
  299.             }
  300.             else {
  301.                 algo = KeyUtils.ALGO_RSA;
  302.             }
  303.         }
  304.         return algo;
  305.     }
  306.    
  307.     private byte[] readKeyInline(BYOKLocalConfig config) throws SecurityException {
  308.         String keyInLine = config.getKeyInline();
  309.         byte [] key = null;
  310.         if(config.isKeyBase64Encoding()) {
  311.             key = Base64Utilities.decode(keyInLine.getBytes());
  312.         }
  313.         else if(config.isKeyHexEncoding()) {
  314.             try {
  315.                 key = HexBinaryUtilities.decode(keyInLine);
  316.             }catch(Exception e) {
  317.                 throw new SecurityException(e.getMessage());
  318.             }
  319.         }
  320.         else {
  321.             key = keyInLine.getBytes();
  322.         }
  323.         return key;
  324.     }
  325.     private byte[] readEncodedKeyFromPath(BYOKLocalConfig config) throws SecurityException {
  326.         byte [] encodedKey = GestoreKeystoreCache.getExternalResource(this.requestInfo, config.getKeyPath(), null).getResource();
  327.         byte [] key = null;
  328.         if(config.isKeyBase64Encoding()) {
  329.             key = Base64Utilities.decode(encodedKey);
  330.         }
  331.         else {
  332.             try {
  333.                 key = HexBinaryUtilities.decode(new String(encodedKey));
  334.             }catch(Exception e) {
  335.                 throw new SecurityException(e.getMessage());
  336.             }
  337.         }
  338.         return key;
  339.     }
  340.    
  341.     private byte[] readPublicKeyInline(BYOKLocalConfig config) throws SecurityException {
  342.         String publicKeyInLine = config.getPublicKeyInline();
  343.         byte [] key = null;
  344.         if(config.isPublicKeyBase64Encoding()) {
  345.             key = Base64Utilities.decode(publicKeyInLine.getBytes());
  346.         }
  347.         else if(config.isPublicKeyHexEncoding()) {
  348.             try {
  349.                 key = HexBinaryUtilities.decode(publicKeyInLine);
  350.             }catch(Exception e) {
  351.                 throw new SecurityException(e.getMessage());
  352.             }
  353.         }
  354.         else {
  355.             key = publicKeyInLine.getBytes();
  356.         }
  357.         return key;
  358.     }
  359.     private byte[] readEncodedPublicKeyFromPath(BYOKLocalConfig config) throws SecurityException {
  360.         byte [] encodedKey = GestoreKeystoreCache.getExternalResource(this.requestInfo, config.getPublicKeyPath(), null).getResource();
  361.         byte [] key = null;
  362.         if(config.isPublicKeyBase64Encoding()) {
  363.             key = Base64Utilities.decode(encodedKey);
  364.         }
  365.         else {
  366.             try {
  367.                 key = HexBinaryUtilities.decode(new String(encodedKey));
  368.             }catch(Exception e) {
  369.                 throw new SecurityException(e.getMessage());
  370.             }
  371.         }
  372.         return key;
  373.     }
  374.    
  375.     private void readPublicKey(BYOKEncryptKey byokEncryptKey, BYOKLocalConfig config) throws UtilsException, SecurityException {
  376.        
  377.         String algo = readKeyAlgo(config);
  378.        
  379.         PublicKeyStore publicKeyStore = null;
  380.         if(config.getKeyInline()!=null && StringUtils.isNotEmpty(config.getKeyInline())) {
  381.             byte [] key = readKeyInline(config);
  382.             publicKeyStore = GestoreKeystoreCache.getPublicKeyStore(this.requestInfo, key, algo);
  383.         }
  384.         else {
  385.             if(config.isKeyBase64Encoding() || config.isKeyHexEncoding()) {
  386.                 byte [] key = readEncodedKeyFromPath(config);
  387.                 publicKeyStore = GestoreKeystoreCache.getPublicKeyStore(this.requestInfo, key, algo);
  388.             }
  389.             else {
  390.                 publicKeyStore = GestoreKeystoreCache.getPublicKeyStore(this.requestInfo, config.getKeyPath(), algo);
  391.             }
  392.         }
  393.         if(publicKeyStore==null) {
  394.             throw new UtilsException(getKeyError(config));
  395.         }
  396.         byokEncryptKey.key = publicKeyStore.getPublicKey();
  397.         if(config.isJoseEngine()) {
  398.             if(config.getKeyId()!=null && StringUtils.isNotEmpty(config.getKeyId())) {
  399.                 config.setKeyAlias(config.getKeyId());
  400.             }
  401.             else {
  402.                 config.generateKeyAlias();
  403.             }
  404.             JWK jwk = new JWK(publicKeyStore.getPublicKey(), config.getKeyAlias());
  405.             JWKSet jwkSet = new JWKSet();
  406.             jwkSet.addJwk(jwk);
  407.             jwkSet.getJson(); // rebuild
  408.             byokEncryptKey.jsonWebKeys = jwkSet.getJsonWebKeys();
  409.         }
  410.     }
  411.     private void readKeyPair(BYOKEncryptKey byokEncryptKey, BYOKLocalConfig config) throws UtilsException, SecurityException {
  412.        
  413.         String algo = readKeyAlgo(config);
  414.        
  415.         KeyPairStore keyPairStore = getKeyPairStore(algo, config);
  416.         if(keyPairStore==null) {
  417.             throw new UtilsException(getKeyError(config));
  418.         }
  419.         byokEncryptKey.key = keyPairStore.getPrivateKey();
  420.         if(config.isJoseEngine()) {
  421.             if(config.getKeyId()!=null && StringUtils.isNotEmpty(config.getKeyId())) {
  422.                 config.setKeyAlias(config.getKeyId());
  423.             }
  424.             else {
  425.                 config.generateKeyAlias();
  426.             }
  427.             JWK jwk = new JWK(keyPairStore.getPublicKey(), keyPairStore.getPrivateKey(), config.getKeyAlias(), KeyUse.ENCRYPTION);
  428.             JWKSet jwkSet = new JWKSet();
  429.             jwkSet.addJwk(jwk);
  430.             jwkSet.getJson(); // rebuild
  431.             byokEncryptKey.jsonWebKeys = jwkSet.getJsonWebKeys();
  432.         }
  433.     }
  434.     private KeyPairStore getKeyPairStore(String algo, BYOKLocalConfig config) throws SecurityException {
  435.         KeyPairStore keyPairStore = null;
  436.         if(config.getKeyInline()!=null && StringUtils.isNotEmpty(config.getKeyInline())) {
  437.            
  438.             byte [] key = readKeyInline(config);
  439.            
  440.             if(config.getPublicKeyInline()!=null && StringUtils.isNotEmpty(config.getPublicKeyInline())) {
  441.                 byte [] publicKey = readPublicKeyInline(config);
  442.                 keyPairStore = GestoreKeystoreCache.getKeyPairStore(this.requestInfo, key, publicKey, config.getKeyPassword(), algo);
  443.             }
  444.             else {
  445.                 if(config.isPublicKeyBase64Encoding() || config.isPublicKeyHexEncoding()) {
  446.                     byte [] publicKey = readEncodedPublicKeyFromPath(config);
  447.                     keyPairStore = GestoreKeystoreCache.getKeyPairStore(this.requestInfo, key, publicKey, config.getKeyPassword(), algo);
  448.                 }
  449.                 else {
  450.                     keyPairStore = GestoreKeystoreCache.getKeyPairStore(this.requestInfo, key, config.getPublicKeyPath(), config.getKeyPassword(), algo);
  451.                 }
  452.             }
  453.         }
  454.         else {
  455.             keyPairStore = getKeyPairStoreFromPath(algo, config);
  456.         }
  457.         return keyPairStore;
  458.     }
  459.     private KeyPairStore getKeyPairStoreFromPath(String algo, BYOKLocalConfig config) throws SecurityException {
  460.         KeyPairStore keyPairStore = null;
  461.         if(config.isKeyBase64Encoding() || config.isKeyHexEncoding()) {
  462.             keyPairStore = getEncodedKeyPairStoreFromPath(algo, config);
  463.         }
  464.         else {
  465.        
  466.             if(config.getPublicKeyInline()!=null && StringUtils.isNotEmpty(config.getPublicKeyInline())) {
  467.                 byte [] publicKey = readPublicKeyInline(config);
  468.                 keyPairStore = GestoreKeystoreCache.getKeyPairStore(this.requestInfo, config.getKeyPath(), publicKey, config.getKeyPassword(), algo);
  469.             }
  470.             else {
  471.                 if(config.isPublicKeyBase64Encoding() || config.isPublicKeyHexEncoding()) {
  472.                     byte [] publicKey = readEncodedPublicKeyFromPath(config);
  473.                     keyPairStore = GestoreKeystoreCache.getKeyPairStore(this.requestInfo, config.getKeyPath(), publicKey, config.getKeyPassword(), algo);
  474.                 }
  475.                 else {
  476.                     keyPairStore = GestoreKeystoreCache.getKeyPairStore(this.requestInfo, config.getKeyPath(), config.getPublicKeyPath(), config.getKeyPassword(), algo);
  477.                 }
  478.             }
  479.            
  480.         }
  481.         return keyPairStore;
  482.     }
  483.     private KeyPairStore getEncodedKeyPairStoreFromPath(String algo, BYOKLocalConfig config) throws SecurityException {
  484.         byte [] key = readEncodedKeyFromPath(config);
  485.        
  486.         if(config.getPublicKeyInline()!=null && StringUtils.isNotEmpty(config.getPublicKeyInline())) {
  487.             byte [] publicKey = readPublicKeyInline(config);
  488.             return GestoreKeystoreCache.getKeyPairStore(this.requestInfo, key, publicKey, config.getKeyPassword(), algo);
  489.         }
  490.         else {
  491.             if(config.isPublicKeyBase64Encoding() || config.isPublicKeyHexEncoding()) {
  492.                 byte [] publicKey = readEncodedPublicKeyFromPath(config);
  493.                 return GestoreKeystoreCache.getKeyPairStore(this.requestInfo, key, publicKey, config.getKeyPassword(), algo);
  494.             }
  495.             else {
  496.                 return GestoreKeystoreCache.getKeyPairStore(this.requestInfo, key, config.getPublicKeyPath(), config.getKeyPassword(), algo);
  497.             }
  498.         }
  499.     }
  500.     private void readSecretKey(BYOKEncryptKey byokEncryptKey, BYOKLocalConfig config) throws UtilsException, SecurityException {
  501.         String algo = config.isJoseEngine() ? SymmetricKeyUtils.ALGO_AES : config.getKeyAlgorithm();
  502.         SecretKeyStore secretKeyStore = null;
  503.         if(config.getKeyInline()!=null && StringUtils.isNotEmpty(config.getKeyInline())) {
  504.             byte [] key = readKeyInline(config);
  505.             secretKeyStore = GestoreKeystoreCache.getSecretKeyStore(this.requestInfo, key, algo);
  506.         }
  507.         else {
  508.             if(config.isKeyBase64Encoding() || config.isKeyHexEncoding()) {
  509.                 byte [] key = readEncodedKeyFromPath(config);
  510.                 secretKeyStore = GestoreKeystoreCache.getSecretKeyStore(this.requestInfo, key, algo);
  511.             }
  512.             else {
  513.                 secretKeyStore = GestoreKeystoreCache.getSecretKeyStore(this.requestInfo, config.getKeyPath(), algo);
  514.             }
  515.         }
  516.         initSecretKey(secretKeyStore, byokEncryptKey, config);
  517.     }
  518.     private void readPasswordKeyDerivation(BYOKEncryptKey byokEncryptKey, BYOKLocalConfig config, boolean wrap) throws UtilsException, SecurityException {
  519.         byokEncryptKey.pwdKeyDerivationConfig = new SecretPasswordKeyDerivationConfig(config.getPassword(), config.getPasswordType(), config.getPasswordIteration());
  520.         if(!config.isOpenSSLEngine() && wrap ) {
  521.             SecretKeyStore secretKeyStore = GestoreKeystoreCache.getSecretKeyStore(this.requestInfo, byokEncryptKey.pwdKeyDerivationConfig);
  522.             initSecretKey(secretKeyStore, byokEncryptKey, config);
  523.         }
  524.     }
  525.     private void readJavaPasswordKeyDerivationForUnwrap(BYOKEncryptKey byokEncryptKey, BYOKLocalConfig config, String wrapValue) throws UtilsException {
  526.        
  527.         String [] tmp = wrapValue.split("\\.");
  528.         if(tmp==null || tmp.length!=2) {
  529.             throw new UtilsException("Wrong format");
  530.         }
  531.         byte[]iv = null;
  532.         byte[]dataEncrypted = null;
  533.         if(config.isBase64Encoding()) {
  534.             iv = Base64Utilities.decode(tmp[0]);
  535.             dataEncrypted = Base64Utilities.decode(tmp[1]);
  536.         }
  537.         else if(config.isHexEncoding()) {
  538.             iv = HexBinaryUtilities.decode(tmp[0]);
  539.             dataEncrypted = HexBinaryUtilities.decode(tmp[1]);
  540.         }
  541.         else {
  542.             throw new UtilsException(ENCODING_MODE_UNDEFINED);
  543.         }
  544.        
  545.         CipherInfo cipherInfo = null;
  546.         if(BYOKCostanti.isOpenSSLPBKDF2PasswordDerivationKeyMode(byokEncryptKey.pwdKeyDerivationConfig.getPasswordEncryptionMode())) {
  547.             cipherInfo = DecryptOpenSSLPassPBKDF2.buildCipherInfo(dataEncrypted,
  548.                     byokEncryptKey.pwdKeyDerivationConfig.getPassword(),
  549.                     byokEncryptKey.pwdKeyDerivationConfig.getPasswordIterator(),
  550.                     OpenSSLEncryptionMode.toMode(byokEncryptKey.pwdKeyDerivationConfig.getPasswordEncryptionMode()));
  551.         }
  552.         else {
  553.             cipherInfo = DecryptOpenSSLPass.buildCipherInfo(dataEncrypted,
  554.                     byokEncryptKey.pwdKeyDerivationConfig.getPassword(),
  555.                     null,
  556.                     OpenSSLEncryptionMode.toMode(byokEncryptKey.pwdKeyDerivationConfig.getPasswordEncryptionMode()));
  557.         }
  558.         try {
  559.             initSecretKey((SecretKey) cipherInfo.getKey(), iv, cipherInfo.getSalt(),
  560.                     byokEncryptKey, config);
  561.         }catch(Exception e) {
  562.             throw new UtilsException(e.getMessage(),e);
  563.         }
  564.     }
  565.     private void initSecretKey(SecretKeyStore secretKeyStore, BYOKEncryptKey byokEncryptKey, BYOKLocalConfig config) throws UtilsException, SecurityException {
  566.         if(secretKeyStore==null) {
  567.             throw new UtilsException(getKeyError(config));
  568.         }
  569.         initSecretKey(secretKeyStore.getSecretKey(), secretKeyStore.getIv(), secretKeyStore.getSalt(),
  570.                 byokEncryptKey, config);
  571.     }
  572.     private void initSecretKey(SecretKey key, byte[]iv, byte[]salt,
  573.             BYOKEncryptKey byokEncryptKey, BYOKLocalConfig config) throws UtilsException {
  574.         byokEncryptKey.key = key;
  575.         byokEncryptKey.iv = iv;
  576.         byokEncryptKey.salt = salt;
  577.         byokEncryptKey.secret = true;
  578.         if(config.isJoseEngine()) {
  579.             if(config.getKeyId()!=null && StringUtils.isNotEmpty(config.getKeyId())) {
  580.                 config.setKeyAlias(config.getKeyId());
  581.             }
  582.             else {
  583.                 config.generateKeyAlias();
  584.             }
  585.             JWK jwk = new JWK(key, config.getKeyAlias(), KeyUse.ENCRYPTION);
  586.             JWKSet jwkSet = new JWKSet();
  587.             jwkSet.addJwk(jwk);
  588.             jwkSet.getJson(); // rebuild
  589.             byokEncryptKey.jsonWebKeys = jwkSet.getJsonWebKeys();
  590.         }
  591.     }
  592.    
  593.     private String encJava(BYOKEncryptKey byokEncryptKey, BYOKLocalConfig config, byte[] value) throws UtilsException {
  594.        
  595.         Encrypt encrypt = null;
  596.         if(byokEncryptKey.secret &&
  597.                 byokEncryptKey.iv!=null) {
  598.             encrypt = new Encrypt(byokEncryptKey.key, byokEncryptKey.iv);
  599.         }
  600.         else {
  601.             encrypt = new Encrypt(byokEncryptKey.key);
  602.         }
  603.        
  604.         if(byokEncryptKey.secret &&
  605.                 byokEncryptKey.iv==null) {
  606.             encrypt.initIV(config.getContentAlgorithm());
  607.         }
  608.        
  609.         byte [] encrypted = null;
  610.         try {
  611.             /**System.out.println("encrypt ["+config.getContentAlgorithm()+"]...");*/
  612.             encrypted = encrypt.encrypt(value, config.getContentAlgorithm());
  613.             /**System.out.println("encrypt ok");*/
  614.         }catch(Exception e) {
  615.             /**System.out.println("encrypt ERROR: "+e.getMessage());*/
  616.             throw new UtilsException(e.getMessage(),e);
  617.         }
  618.        
  619.         if(byokEncryptKey.secret &&
  620.                 byokEncryptKey.salt!=null){
  621.             encrypted = EncryptOpenSSLPass.formatOutput(byokEncryptKey.salt, encrypted);
  622.         }
  623.        
  624.         String en = null;
  625.         if(config.isBase64Encoding()) {
  626.             en = Base64Utilities.encodeAsString(encrypted);
  627.         }
  628.         else if(config.isHexEncoding()) {
  629.             en = HexBinaryUtilities.encodeAsString(encrypted);
  630.         }
  631.         else {
  632.             throw new UtilsException("Java algorithm undefined in keystore ["+config.getKeystoreType().getNome()+"] '"+config.getKeystorePath()+"'");
  633.         }
  634.         if(byokEncryptKey.secret) {
  635.             if(config.isBase64Encoding()) {
  636.                 return encrypt.getIVBase64AsString()+JAVA_SEPARATOR+en;
  637.             }
  638.             else {
  639.                 return encrypt.getIVHexBinaryAsString()+JAVA_SEPARATOR+en;
  640.             }
  641.         }
  642.         return en;
  643.     }
  644.    
  645.     private String encJavaKeyWrap(BYOKEncryptKey byokEncryptKey, BYOKLocalConfig config, byte[] value) throws UtilsException {
  646.        
  647.         EncryptWrapKey encrypt = null;
  648.         if(byokEncryptKey.ks!=null) {
  649.             encrypt = new EncryptWrapKey(byokEncryptKey.ks, config.getKeyAlias());
  650.         }
  651.         else {
  652.             encrypt = new EncryptWrapKey(byokEncryptKey.key);
  653.         }
  654.                
  655.         byte [] encrypted = null;
  656.         try {
  657.             /**System.out.println("encrypt ["+config.getKeyAlgorithm()+"] ["+config.getContentAlgorithm()+"]...");*/
  658.             encrypted = encrypt.encrypt(value, config.getKeyAlgorithm(), config.getContentAlgorithm());
  659.             /**System.out.println("encrypt ok");*/
  660.         }catch(Exception e) {
  661.             /**System.out.println("encrypt ERROR: "+e.getMessage());*/
  662.             throw new UtilsException(e.getMessage(),e);
  663.         }
  664.        
  665.         String en = null;
  666.         if(config.isBase64Encoding()) {
  667.             en = Base64Utilities.encodeAsString(encrypted);
  668.         }
  669.         else if(config.isHexEncoding()) {
  670.             en = HexBinaryUtilities.encodeAsString(encrypted);
  671.         }
  672.         else {
  673.             throw new UtilsException("Java algorithm undefined in keystore ["+config.getKeystoreType().getNome()+"] '"+config.getKeystorePath()+"'");
  674.         }

  675.         if(config.isBase64Encoding()) {
  676.             return encrypt.getWrappedKeyBase64()+JAVA_SEPARATOR+encrypt.getIVBase64AsString()+JAVA_SEPARATOR+en;
  677.         }
  678.         else {
  679.             return encrypt.getWrappedKeyHexBinary()+JAVA_SEPARATOR+encrypt.getIVHexBinaryAsString()+JAVA_SEPARATOR+en;
  680.         }
  681.        
  682.     }
  683.    
  684.     private String encJose(BYOKEncryptKey byokEncryptKey, BYOKLocalConfig config, byte[] value) throws UtilsException {
  685.         JsonEncrypt encrypt = null;
  686.         JwtHeaders jwtHeaders = null;
  687.         JWEOptions options = new JWEOptions(JOSESerialization.COMPACT);
  688.         if(byokEncryptKey.ks!=null) {
  689.             jwtHeaders = this.getJwtHeaders(config, byokEncryptKey.ks);
  690.             if(byokEncryptKey.secret) {
  691.                 encrypt = new JsonEncrypt(byokEncryptKey.ks, config.getKeyAlias(), config.getKeyPassword(), config.getKeyAlgorithm(), config.getContentAlgorithm(),
  692.                         jwtHeaders, options);
  693.             }
  694.             else {
  695.                 encrypt = new JsonEncrypt(byokEncryptKey.ks, config.getKeyAlias(), config.getKeyAlgorithm(), config.getContentAlgorithm(),
  696.                         jwtHeaders, options);
  697.             }
  698.         }
  699.         else {
  700.             jwtHeaders = this.getJwtHeaders(config, byokEncryptKey.jsonWebKeys);
  701.             encrypt = new JsonEncrypt(byokEncryptKey.jsonWebKeys, byokEncryptKey.secret, config.getKeyAlias(), config.getKeyAlgorithm(), config.getContentAlgorithm(),
  702.                     jwtHeaders, options);
  703.         }
  704.         return encrypt.encrypt(value);
  705.     }
  706.    
  707.     private JwtHeaders getJwtHeaders(BYOKLocalConfig config, KeyStore ks) throws UtilsException {
  708.         return getJwtHeaders(config, ks, null);
  709.     }
  710.     private JwtHeaders getJwtHeaders(BYOKLocalConfig config, JsonWebKeys jsonWebKeys) throws UtilsException {
  711.         return getJwtHeaders(config, null, jsonWebKeys);
  712.     }
  713.     private JwtHeaders getJwtHeaders(BYOKLocalConfig config, KeyStore ks, JsonWebKeys jsonWebKeys) throws UtilsException {
  714.         JwtHeaders jwtHeaders = new JwtHeaders();
  715.         if(config.isJoseIncludeKeyId()) {
  716.             jwtHeaders.setKid(config.getKeyAlias());
  717.         }

  718.         if(config.isJoseIncludeCert()) {
  719.             jwtHeaders.setAddX5C(true);
  720.         }
  721.         if(config.isJoseIncludeCertSha1()) {
  722.             jwtHeaders.setX509IncludeCertSha1(true);
  723.         }
  724.         if(config.isJoseIncludeCertSha256()) {
  725.             jwtHeaders.setX509IncludeCertSha256(true);
  726.         }
  727.         if(ks!=null && (config.isJoseIncludeCert() || config.isJoseIncludeCertSha1 ()|| config.isJoseIncludeCertSha256())) {
  728.             Certificate cert = ks.getCertificate(config.getKeyAlias());
  729.             if(cert instanceof X509Certificate) {
  730.                 jwtHeaders.addX509cert((X509Certificate)cert);
  731.             }
  732.         }
  733.        
  734.         if(jsonWebKeys!=null && config.isJoseIncludePublicKey()) {
  735.             jwtHeaders.setJwKey(jsonWebKeys, config.getKeyAlias());
  736.         }
  737.        
  738.         return jwtHeaders;
  739.     }
  740.    
  741.     private String encOpenSSL(BYOKEncryptKey byokEncryptKey, BYOKLocalConfig config, byte[] value) throws UtilsException {
  742.         if(BYOKCostanti.isOpenSSLPBKDF2PasswordDerivationKeyMode(byokEncryptKey.pwdKeyDerivationConfig.getPasswordEncryptionMode())) {
  743.             return encOpenSSLPBKDF2(byokEncryptKey, config, value);
  744.         }
  745.         else {
  746.             return encOpenSSLStandard(byokEncryptKey, config, value);
  747.         }
  748.     }
  749.     private String encOpenSSLStandard(BYOKEncryptKey byokEncryptKey, BYOKLocalConfig config, byte[] value) throws UtilsException {
  750.        
  751.         SecretPasswordKeyDerivationConfig passwordKeyDerivationConfig = byokEncryptKey.pwdKeyDerivationConfig;
  752.        
  753.         EncryptOpenSSLPass encrypt = new EncryptOpenSSLPass(passwordKeyDerivationConfig.getPassword(),
  754.                 OpenSSLEncryptionMode.toMode(passwordKeyDerivationConfig.getPasswordEncryptionMode()));
  755.        
  756.         if(config.isBase64Encoding()) {
  757.             return encrypt.encryptBase64AsString(value);
  758.         }
  759.         else if(config.isHexEncoding()) {
  760.             return encrypt.encryptHexBinaryAsString(value);
  761.         }
  762.         else {
  763.             throw new UtilsException(ENCODING_MODE_UNDEFINED);
  764.         }
  765.     }
  766.     private String encOpenSSLPBKDF2(BYOKEncryptKey byokEncryptKey, BYOKLocalConfig config, byte[] value) throws UtilsException {
  767.        
  768.         SecretPasswordKeyDerivationConfig passwordKeyDerivationConfig = byokEncryptKey.pwdKeyDerivationConfig;
  769.        
  770.         EncryptOpenSSLPassPBKDF2 encrypt = new EncryptOpenSSLPassPBKDF2(passwordKeyDerivationConfig.getPassword(),
  771.                 passwordKeyDerivationConfig.getPasswordIterator(),
  772.                 OpenSSLEncryptionMode.toMode(passwordKeyDerivationConfig.getPasswordEncryptionMode()));
  773.        
  774.         if(config.isBase64Encoding()) {
  775.             return encrypt.encryptBase64AsString(value);
  776.         }
  777.         else if(config.isHexEncoding()) {
  778.             return encrypt.encryptHexBinaryAsString(value);
  779.         }
  780.         else {
  781.             throw new UtilsException(ENCODING_MODE_UNDEFINED);
  782.         }
  783.     }
  784.    
  785.    
  786.    
  787.    
  788.     private byte[] decryptJava(BYOKEncryptKey byokEncryptKey, BYOKLocalConfig config, String value) throws UtilsException {
  789.        
  790.         Decrypt d = null;
  791.         byte[]dataEncrypted = null;
  792.         if(byokEncryptKey.secret) {
  793.             String [] tmp = value.split("\\.");
  794.             if(tmp==null || tmp.length!=2) {
  795.                 throw new UtilsException("Atteso formato iv.secret (enc)");
  796.             }
  797.             byte[]iv = null;
  798.             if(config.isBase64Encoding()) {
  799.                 iv = Base64Utilities.decode(tmp[0]);
  800.                 dataEncrypted = Base64Utilities.decode(tmp[1]);
  801.             }
  802.             else if(config.isHexEncoding()) {
  803.                 iv = HexBinaryUtilities.decode(tmp[0]);
  804.                 dataEncrypted = HexBinaryUtilities.decode(tmp[1]);
  805.             }
  806.             else {
  807.                 iv = tmp[0].getBytes();
  808.                 dataEncrypted = tmp[1].getBytes();
  809.             }
  810.             if(KeystoreType.PASSWORD_KEY_DERIVATION.equals(config.getKeystoreType())) {
  811.                 dataEncrypted = DecryptOpenSSLPass.extractCipherBytes(dataEncrypted);
  812.             }
  813.             d = new Decrypt(byokEncryptKey.key, iv);
  814.         }
  815.         else {
  816.             if(config.isBase64Encoding()) {
  817.                 dataEncrypted = Base64Utilities.decode(value);
  818.             }
  819.             else if(config.isHexEncoding()) {
  820.                 dataEncrypted = HexBinaryUtilities.decode(value);
  821.             }
  822.             else {
  823.                 dataEncrypted = value.getBytes();
  824.             }
  825.             d = new Decrypt(byokEncryptKey.key);
  826.         }
  827.        
  828.         return d.decrypt(dataEncrypted, config.getContentAlgorithm());
  829.     }
  830.    
  831.     private byte[] decryptJavaKeyWrap(BYOKEncryptKey byokEncryptKey, BYOKLocalConfig config, String value) throws UtilsException {
  832.         String [] tmp = value.split("\\.");
  833.         if(tmp==null || tmp.length!=3) {
  834.             throw new UtilsException("Atteso formato wrappedKey.iv.secret ("+config.getEncoding()+")");
  835.         }
  836.         byte[]wrappedKey = null;
  837.         byte[]iv = null;
  838.         byte[]dataEncrypted = null;
  839.         if(config.isBase64Encoding()) {
  840.             wrappedKey = Base64Utilities.decode(tmp[0]);
  841.             iv = Base64Utilities.decode(tmp[1]);
  842.             dataEncrypted = Base64Utilities.decode(tmp[2]);
  843.         }
  844.         else if(config.isHexEncoding()) {
  845.             wrappedKey = HexBinaryUtilities.decode(tmp[0]);
  846.             iv = HexBinaryUtilities.decode(tmp[1]);
  847.             dataEncrypted = HexBinaryUtilities.decode(tmp[2]);
  848.         }
  849.         else {
  850.             wrappedKey = tmp[0].getBytes();
  851.             iv = tmp[1].getBytes();
  852.             dataEncrypted = tmp[2].getBytes();
  853.         }
  854.        
  855.         DecryptWrapKey d = new DecryptWrapKey(byokEncryptKey.key);
  856.         return d.decrypt(dataEncrypted, wrappedKey, iv, config.getKeyAlgorithm(), config.getContentAlgorithm());
  857.     }
  858.    
  859.     private byte[] decryptJose(BYOKEncryptKey byokEncryptKey, BYOKLocalConfig config, String value) throws UtilsException {
  860.         JsonDecrypt decrypt = null;
  861.         JWTOptions options = new JWTOptions(JOSESerialization.COMPACT);
  862.         if(byokEncryptKey.ks!=null) {
  863.             decrypt = new JsonDecrypt(byokEncryptKey.ks, byokEncryptKey.secret, config.getKeyAlias(), config.getKeyPassword(), config.getKeyAlgorithm(), config.getContentAlgorithm(),
  864.                         options);
  865.         }
  866.         else {
  867.             decrypt = new JsonDecrypt(byokEncryptKey.jsonWebKeys, byokEncryptKey.secret, config.getKeyAlias(), config.getKeyAlgorithm(), config.getContentAlgorithm(),
  868.                     options);
  869.         }
  870.         decrypt.decrypt(value);
  871.         return decrypt.getDecodedPayloadAsByte();
  872.     }
  873.    
  874.     private byte[] decryptOpenSSL(BYOKEncryptKey byokEncryptKey, BYOKLocalConfig config, String value) throws UtilsException {
  875.         if(BYOKCostanti.isOpenSSLPBKDF2PasswordDerivationKeyMode(byokEncryptKey.pwdKeyDerivationConfig.getPasswordEncryptionMode())) {
  876.             return decryptOpenSSLPBKDF2(byokEncryptKey, config, value);
  877.         }
  878.         else {
  879.             return decryptOpenSSLStandard(byokEncryptKey, config, value);
  880.         }
  881.     }
  882.     private byte[] decryptOpenSSLStandard(BYOKEncryptKey byokEncryptKey, BYOKLocalConfig config, String value) throws UtilsException {
  883.        
  884.         SecretPasswordKeyDerivationConfig passwordKeyDerivationConfig = byokEncryptKey.pwdKeyDerivationConfig;
  885.        
  886.         DecryptOpenSSLPass decrypt = new DecryptOpenSSLPass(passwordKeyDerivationConfig.getPassword(),
  887.                 OpenSSLEncryptionMode.toMode(passwordKeyDerivationConfig.getPasswordEncryptionMode()));
  888.        
  889.         if(config.isBase64Encoding()) {
  890.             return decrypt.decryptBase64(value);
  891.         }
  892.         else if(config.isHexEncoding()) {
  893.             return decrypt.decryptHexBinary(value);
  894.         }
  895.         else {
  896.             throw new UtilsException(ENCODING_MODE_UNDEFINED);
  897.         }
  898.     }
  899.     private byte[] decryptOpenSSLPBKDF2(BYOKEncryptKey byokEncryptKey, BYOKLocalConfig config, String value) throws UtilsException {
  900.        
  901.         SecretPasswordKeyDerivationConfig passwordKeyDerivationConfig = byokEncryptKey.pwdKeyDerivationConfig;
  902.        
  903.         DecryptOpenSSLPassPBKDF2 decrypt = new DecryptOpenSSLPassPBKDF2(passwordKeyDerivationConfig.getPassword(),
  904.                 passwordKeyDerivationConfig.getPasswordIterator(),
  905.                 OpenSSLEncryptionMode.toMode(passwordKeyDerivationConfig.getPasswordEncryptionMode()));
  906.        
  907.         if(config.isBase64Encoding()) {
  908.             return decrypt.decryptBase64(value);
  909.         }
  910.         else if(config.isHexEncoding()) {
  911.             return decrypt.decryptHexBinary(value);
  912.         }
  913.         else {
  914.             throw new UtilsException(ENCODING_MODE_UNDEFINED);
  915.         }
  916.     }
  917. }

  918. class BYOKEncryptKey{
  919.     Key key = null;
  920.     byte[]iv = null;
  921.     byte[]salt = null;
  922.     boolean secret = false;
  923.     KeyStore ks = null;
  924.     JsonWebKeys jsonWebKeys = null;
  925.     SecretPasswordKeyDerivationConfig pwdKeyDerivationConfig = null;
  926. }