DigestConfig.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.utils.digest;

  21. import java.io.File;
  22. import java.io.FileInputStream;
  23. import java.io.FileNotFoundException;
  24. import java.io.InputStream;
  25. import java.io.Serializable;
  26. import java.util.ArrayList;
  27. import java.util.List;
  28. import java.util.Properties;
  29. import java.util.regex.Matcher;
  30. import java.util.regex.Pattern;

  31. import org.apache.commons.lang.StringUtils;
  32. import org.openspcoop2.utils.UtilsException;

  33. /**
  34.  * IDigest
  35.  *
  36.  * @author Tommaso Burlon (tommaso.burlon@link.it)
  37.  * @author $Author$
  38.  * @version $Rev$, $Date$
  39.  */
  40. public class DigestConfig implements Serializable {
  41.     /**
  42.      *
  43.      */
  44.     private static final long serialVersionUID = 1L;

  45.     private static final String DIGEST_TYPE = "digest.type";
  46.     private static final String DIGEST_SALT_LENGTH = "digest.salt.length";
  47.     private static final String DIGEST_SALT_SECURE_RANDOM_ALGORITHM = "digest.salt.secureRandomAlgorithm";
  48.     private static final String DIGEST_BASE64_ENCODE = "digest.base64Encode";
  49.     private static final String DIGEST_HASH_COMPOSITION = "digest.composition";
  50.    
  51.     private DigestType digestType = null;
  52.     private Integer saltLength = null;
  53.     private String algorithmSecureRandom = "SHA1PRNG";
  54.     private String hashComposition = "${message}${salt}";
  55.     private boolean base64Encode = false;
  56.    
  57.     public DigestConfig() {}
  58.    
  59.     public DigestConfig(String resource) throws UtilsException{
  60.        
  61.         try (InputStream is = getInputStream(resource)){
  62.            
  63.             if(is!=null) {
  64.                 Properties p = new Properties();
  65.                 p.load(is);
  66.                 this.initEngine(p);
  67.             } else {
  68.                 throw new UtilsException("Resource ["+resource+"] not found");
  69.             }
  70.         } catch(Exception e) {
  71.             throw new UtilsException(e.getMessage(),e);
  72.         }
  73.     }
  74.     private InputStream getInputStream(String resource) throws FileNotFoundException {
  75.         File f = new File(resource);
  76.         InputStream is = null;
  77.         if(f.exists()) {
  78.             is = new FileInputStream(f);
  79.         } else {
  80.             is = DigestConfig.class.getResourceAsStream(resource);
  81.         }
  82.         if(is==null) {
  83.             is = DigestConfig.class.getResourceAsStream("/org/openspcoop2/utils/crypt/digest.properties");
  84.         }
  85.         return is;
  86.     }
  87.     public DigestConfig(InputStream is) throws UtilsException{
  88.         try{
  89.             Properties p = new Properties();
  90.             p.load(is);
  91.             this.initEngine(p);
  92.         }catch(Exception e){
  93.             throw new UtilsException(e.getMessage(),e);
  94.         }
  95.     }
  96.     public DigestConfig(Properties p) throws UtilsException {
  97.         this.initEngine(p);
  98.     }
  99.    
  100.     private void initEngine(Properties p) throws UtilsException {
  101.         final String NOT_CORRECT_PROPERTY = "Property: '%s' value: '%s' not correct: %s";

  102.         String tipo = DigestConfig.getProperty(p, DigestConfig.DIGEST_TYPE, true);
  103.         if(StringUtils.isNotEmpty(tipo)) {
  104.             DigestType digestTypeProp = null;
  105.             try {
  106.                 digestTypeProp = DigestType.valueOf(tipo);
  107.             }catch(IllegalArgumentException | NullPointerException e) {
  108.                 throw new UtilsException(String.format(NOT_CORRECT_PROPERTY, DigestConfig.DIGEST_TYPE, tipo, e.getMessage()), e);
  109.             }
  110.             this.digestType = digestTypeProp;
  111.         }
  112.        
  113.         String saltLengthProp = getProperty(p, DIGEST_SALT_LENGTH, false);
  114.         if(StringUtils.isNotEmpty(saltLengthProp)) {
  115.             try {
  116.                 this.saltLength = Integer.valueOf(saltLengthProp);
  117.             }catch(NumberFormatException e) {
  118.                 throw new UtilsException(String.format(NOT_CORRECT_PROPERTY, DigestConfig.DIGEST_SALT_LENGTH, saltLengthProp, e.getMessage()), e);
  119.             }
  120.         }
  121.        
  122.         String secureRandomAlgo = getProperty(p, DIGEST_SALT_SECURE_RANDOM_ALGORITHM, false);
  123.         if(StringUtils.isNotEmpty(secureRandomAlgo)) {
  124.             this.algorithmSecureRandom = secureRandomAlgo;
  125.         }
  126.        
  127.         String digestBase64Encode = getProperty(p, DIGEST_BASE64_ENCODE, false);
  128.         if(StringUtils.isNotEmpty(digestBase64Encode)) {
  129.             this.base64Encode = Boolean.valueOf(digestBase64Encode);
  130.         }
  131.        
  132.         String digestHashComposition = getProperty(p, DIGEST_HASH_COMPOSITION, false);
  133.         if(StringUtils.isNotEmpty(digestHashComposition)) {
  134.             this.hashComposition = digestHashComposition;
  135.         }
  136.     }
  137.    
  138.     protected static String getProperty(Properties p, String name, boolean  required) throws UtilsException {
  139.         String pValue = p.getProperty(name);
  140.         if(pValue == null) {
  141.             if(required) {
  142.                 throw new UtilsException("Property '" + name + "' not found");
  143.             }
  144.             return null;
  145.         }
  146.         else {
  147.             return pValue.trim();
  148.         }
  149.     }
  150.    
  151.    
  152.     private static final Pattern COMPOSITION_VAR_PATTERN = Pattern.compile("\\$\\{([^\\}]*)\\}");
  153.     private static final String SALT_LABEL = "salt";
  154.     private static final String MESSAGE_LABEL = "message";
  155.     public byte[] composeMessage(byte[] input, byte[] salt) {
  156.         String scheme = this.getHashComposition();
  157.         Pattern pattern = DigestConfig.COMPOSITION_VAR_PATTERN;
  158.        
  159.         List<byte[]> bytes = new ArrayList<>();
  160.         Matcher matcher = pattern.matcher(scheme);
  161.         int lastIndex = 0;
  162.         int size = 0;
  163.        
  164.         while (matcher.find(lastIndex)) {
  165.             if (lastIndex < matcher.start()) {
  166.                 bytes.add(scheme.substring(lastIndex, matcher.start()).getBytes());
  167.                 size += (matcher.start() - lastIndex);
  168.             }
  169.            
  170.             lastIndex = matcher.end();
  171.            
  172.             byte[] sub = null;
  173.             if (matcher.group(1).equals(MESSAGE_LABEL))
  174.                 sub = input;
  175.             if (matcher.group(1).equals(SALT_LABEL))
  176.                 sub = salt;
  177.            
  178.             if (sub != null) {
  179.                 size += sub.length;
  180.                 bytes.add(sub);
  181.             }
  182.         }
  183.        
  184.         if (lastIndex < scheme.length()) {
  185.             bytes.add(scheme.substring(lastIndex).getBytes());
  186.             size += scheme.length() - lastIndex;
  187.         }
  188.        
  189.         byte[] buf = new byte[size];
  190.         lastIndex = 0;
  191.         for (byte[] src : bytes) {
  192.             System.arraycopy(src, 0, buf, lastIndex, src.length);
  193.             lastIndex += src.length;
  194.         }
  195.        
  196.         return buf;
  197.     }
  198.    
  199.     public DigestType getDigestType() {
  200.         return this.digestType;
  201.     }

  202.     public void setDigestType(DigestType digestType) {
  203.         this.digestType = digestType;
  204.     }
  205.    
  206.     public Integer getSaltLength() {
  207.         return this.saltLength;
  208.     }

  209.     public void setSaltLength(Integer saltLength) {
  210.         this.saltLength = saltLength;
  211.     }

  212.     public String getAlgorithmSecureRandom() {
  213.         return this.algorithmSecureRandom;
  214.     }

  215.     public void setAlgorithmSecureRandom(String algorithmSecureRandom) {
  216.         this.algorithmSecureRandom = algorithmSecureRandom;
  217.     }

  218.     public boolean isBase64Encode() {
  219.         return this.base64Encode;
  220.     }

  221.     public void setBase64Encode(boolean base64Encode) {
  222.         this.base64Encode = base64Encode;
  223.     }
  224.    
  225.     public String getHashComposition() {
  226.         return this.hashComposition;
  227.     }

  228.     public void setHashComposition(String hashComposition) {
  229.         this.hashComposition = hashComposition;
  230.     }
  231. }