CodecCrypt.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.crypt;

  21. import org.openspcoop2.utils.UtilsException;
  22. import org.openspcoop2.utils.random.RandomGenerator;
  23. import org.slf4j.Logger;

  24. /**
  25.  * CodecCrypt
  26.  *
  27.  * @author Poli Andrea (apoli@link.it)
  28.  * @author $Author$
  29.  * @version $Rev$, $Date$
  30.  */
  31. public class CodecCrypt implements ICrypt {

  32.     private static final String ITERATOR = "rounds=";
  33.    
  34.     private Logger log;
  35.     private CodecType type;
  36.     private CryptConfig config;
  37.     private RandomGenerator randomGenerator;

  38.     public CodecCrypt(CodecType type){
  39.         this.type = type;
  40.         if(this.type == null) {
  41.             this.type = CodecType.SHA2_BASED_UNIX_CRYPT_SHA256;
  42.         }
  43.     }
  44.    
  45.     @Override
  46.     public void init(Logger log, CryptConfig config) {
  47.         this.log = log;
  48.        
  49.         this.config = config;
  50.         if(this.config == null) {
  51.             this.config = new CryptConfig();
  52.         }
  53.        
  54.         this.randomGenerator = new RandomGenerator(this.config.isUseSecureRandom(), this.config.getAlgorithmSecureRandom());
  55.     }
  56.    
  57.     @Override
  58.     public String crypt(String password) throws UtilsException {
  59.        
  60.         Integer saltLength = this.config.getSaltLength();
  61.         if(saltLength==null) {
  62.             switch (this.type) {
  63.             case LIBC_CRYPT_MD5:
  64.             case LIBC_CRYPT_MD5_APACHE:
  65.                 saltLength = 8;
  66.                 break;
  67.             case SHA2_BASED_UNIX_CRYPT_SHA256:
  68.             case SHA2_BASED_UNIX_CRYPT_SHA512:
  69.                 saltLength = 16;
  70.                 break;
  71.             case DES_UNIX_CRYPT:
  72.                 saltLength = 2;
  73.                 break;
  74.             }
  75.         }
  76.        
  77.         if(this.randomGenerator==null) {
  78.             throw new UtilsException("RandomGenerator undefined");
  79.         }
  80.         String salt = this.randomGenerator.nextRandom(saltLength);
  81.                
  82.         if(!CodecType.DES_UNIX_CRYPT.equals(this.type)) {
  83.            
  84.             //   a) the salt salt_prefix, $5$ or $6$ respectively
  85.             //   b) the rounds=<N> specification, if one was present in the input salt string. A trailing '$' is added in this case to separate the rounds specification from the following text.
  86.             //   c) the salt string truncated to 16 characters (solo per SHA2)
  87.             //   d) a '$' character
  88.            
  89.             StringBuilder sb = new StringBuilder();
  90.             String prefix = this.type.getPrefix();
  91.             if(salt.startsWith(prefix) && salt.length()>prefix.length()) {
  92.                 salt = salt.substring(prefix.length());
  93.             }
  94.             sb.append(prefix);
  95.            
  96.             if(this.config.getIteration()!=null && this.config.getIteration().intValue()>0 &&
  97.                     (CodecType.SHA2_BASED_UNIX_CRYPT_SHA256.equals(this.type) || CodecType.SHA2_BASED_UNIX_CRYPT_SHA512.equals(this.type)) &&
  98.                     !salt.startsWith(ITERATOR)) {
  99.                 sb.append(ITERATOR).append(this.config.getIteration().intValue()).append("$");
  100.                 sb.append(salt);
  101.             }
  102.             else {
  103.                 sb.append(salt);
  104.             }
  105.            
  106.             if(!salt.endsWith("$")) {
  107.                 sb.append("$");
  108.             }
  109.            
  110.             salt = sb.toString();
  111.         }
  112.         return this._crypt(password, salt);
  113.     }

  114.     @Override
  115.     public boolean check(String password, String pwcrypt) {
  116.         try{
  117.             boolean checkPwS = false;
  118.             String newPw = this._crypt(password, pwcrypt);
  119.             if (newPw.equals(pwcrypt)) {
  120.                 checkPwS = true;
  121.             }
  122.             return checkPwS;
  123.         }catch(Throwable e){
  124.             if(this.log!=null) {
  125.                 this.log.error("Verifica password '"+pwcrypt+"' fallita: "+e.getMessage(),e);
  126.             }
  127.             return false;
  128.         }
  129.     }

  130.     private String _crypt(String password, String salt) throws UtilsException {
  131.        
  132.         byte [] keyBytes = null;
  133.         try {
  134.             keyBytes = password.getBytes(this.config.getCharsetName());
  135.         }catch(Throwable e){
  136.             throw new UtilsException(e.getMessage(), e);
  137.         }
  138.         switch (this.type) {
  139.             case LIBC_CRYPT_MD5:
  140.                 if(salt!=null) {
  141.                     return org.apache.commons.codec.digest.Md5Crypt.md5Crypt(keyBytes, salt);
  142.                 }
  143.                 else {
  144.                     return org.apache.commons.codec.digest.Md5Crypt.md5Crypt(keyBytes);
  145.                 }
  146.             case LIBC_CRYPT_MD5_APACHE:
  147.                 if(salt!=null) {
  148.                     return org.apache.commons.codec.digest.Md5Crypt.apr1Crypt(keyBytes, salt);
  149.                 }
  150.                 else {
  151.                     return org.apache.commons.codec.digest.Md5Crypt.apr1Crypt(keyBytes);
  152.                 }
  153.             case SHA2_BASED_UNIX_CRYPT_SHA256:
  154.                 if(salt!=null) {
  155.                     return org.apache.commons.codec.digest.Sha2Crypt.sha256Crypt(keyBytes, salt);
  156.                 }
  157.                 else {
  158.                     return org.apache.commons.codec.digest.Sha2Crypt.sha256Crypt(keyBytes);
  159.                 }
  160.             case SHA2_BASED_UNIX_CRYPT_SHA512:
  161.                 if(salt!=null) {
  162.                     return org.apache.commons.codec.digest.Sha2Crypt.sha512Crypt(keyBytes, salt);
  163.                 }
  164.                 else {
  165.                     return org.apache.commons.codec.digest.Sha2Crypt.sha512Crypt(keyBytes);
  166.                 }
  167.             case DES_UNIX_CRYPT:
  168.                 if(salt!=null) {
  169.                     return org.apache.commons.codec.digest.UnixCrypt.crypt(keyBytes, salt);
  170.                 }
  171.                 else {
  172.                     return org.apache.commons.codec.digest.UnixCrypt.crypt(keyBytes);
  173.                 }
  174.         }
  175.        
  176.         throw new UtilsException("Unsupported type '"+this.type+"'");
  177.     }

  178. }