CodecCrypt.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.crypt;
import org.openspcoop2.utils.UtilsException;
import org.openspcoop2.utils.random.RandomGenerator;
import org.slf4j.Logger;
/**
* CodecCrypt
*
* @author Poli Andrea (apoli@link.it)
* @author $Author$
* @version $Rev$, $Date$
*/
public class CodecCrypt implements ICrypt {
private static final String ITERATOR = "rounds=";
private Logger log;
private CodecType type;
private CryptConfig config;
private RandomGenerator randomGenerator;
public CodecCrypt(CodecType type){
this.type = type;
if(this.type == null) {
this.type = CodecType.SHA2_BASED_UNIX_CRYPT_SHA256;
}
}
@Override
public void init(Logger log, CryptConfig config) {
this.log = log;
this.config = config;
if(this.config == null) {
this.config = new CryptConfig();
}
this.randomGenerator = new RandomGenerator(this.config.isUseSecureRandom(), this.config.getAlgorithmSecureRandom());
}
@Override
public String crypt(String password) throws UtilsException {
Integer saltLength = this.config.getSaltLength();
if(saltLength==null) {
switch (this.type) {
case LIBC_CRYPT_MD5:
case LIBC_CRYPT_MD5_APACHE:
saltLength = 8;
break;
case SHA2_BASED_UNIX_CRYPT_SHA256:
case SHA2_BASED_UNIX_CRYPT_SHA512:
saltLength = 16;
break;
case DES_UNIX_CRYPT:
saltLength = 2;
break;
}
}
if(this.randomGenerator==null) {
throw new UtilsException("RandomGenerator undefined");
}
String salt = this.randomGenerator.nextRandom(saltLength);
if(!CodecType.DES_UNIX_CRYPT.equals(this.type)) {
// a) the salt salt_prefix, $5$ or $6$ respectively
// 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.
// c) the salt string truncated to 16 characters (solo per SHA2)
// d) a '$' character
StringBuilder sb = new StringBuilder();
String prefix = this.type.getPrefix();
if(salt.startsWith(prefix) && salt.length()>prefix.length()) {
salt = salt.substring(prefix.length());
}
sb.append(prefix);
if(this.config.getIteration()!=null && this.config.getIteration().intValue()>0 &&
(CodecType.SHA2_BASED_UNIX_CRYPT_SHA256.equals(this.type) || CodecType.SHA2_BASED_UNIX_CRYPT_SHA512.equals(this.type)) &&
!salt.startsWith(ITERATOR)) {
sb.append(ITERATOR).append(this.config.getIteration().intValue()).append("$");
sb.append(salt);
}
else {
sb.append(salt);
}
if(!salt.endsWith("$")) {
sb.append("$");
}
salt = sb.toString();
}
return this._crypt(password, salt);
}
@Override
public boolean check(String password, String pwcrypt) {
try{
boolean checkPwS = false;
String newPw = this._crypt(password, pwcrypt);
if (newPw.equals(pwcrypt)) {
checkPwS = true;
}
return checkPwS;
}catch(Throwable e){
if(this.log!=null) {
this.log.error("Verifica password '"+pwcrypt+"' fallita: "+e.getMessage(),e);
}
return false;
}
}
private String _crypt(String password, String salt) throws UtilsException {
byte [] keyBytes = null;
try {
keyBytes = password.getBytes(this.config.getCharsetName());
}catch(Throwable e){
throw new UtilsException(e.getMessage(), e);
}
switch (this.type) {
case LIBC_CRYPT_MD5:
if(salt!=null) {
return org.apache.commons.codec.digest.Md5Crypt.md5Crypt(keyBytes, salt);
}
else {
return org.apache.commons.codec.digest.Md5Crypt.md5Crypt(keyBytes);
}
case LIBC_CRYPT_MD5_APACHE:
if(salt!=null) {
return org.apache.commons.codec.digest.Md5Crypt.apr1Crypt(keyBytes, salt);
}
else {
return org.apache.commons.codec.digest.Md5Crypt.apr1Crypt(keyBytes);
}
case SHA2_BASED_UNIX_CRYPT_SHA256:
if(salt!=null) {
return org.apache.commons.codec.digest.Sha2Crypt.sha256Crypt(keyBytes, salt);
}
else {
return org.apache.commons.codec.digest.Sha2Crypt.sha256Crypt(keyBytes);
}
case SHA2_BASED_UNIX_CRYPT_SHA512:
if(salt!=null) {
return org.apache.commons.codec.digest.Sha2Crypt.sha512Crypt(keyBytes, salt);
}
else {
return org.apache.commons.codec.digest.Sha2Crypt.sha512Crypt(keyBytes);
}
case DES_UNIX_CRYPT:
if(salt!=null) {
return org.apache.commons.codec.digest.UnixCrypt.crypt(keyBytes, salt);
}
else {
return org.apache.commons.codec.digest.UnixCrypt.crypt(keyBytes);
}
}
throw new UtilsException("Unsupported type '"+this.type+"'");
}
}