DigestConfig.java
/*
* GovWay - A customizable API Gateway
* https://govway.org
*
* Copyright (c) 2005-2025 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.digest;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
import org.openspcoop2.utils.UtilsException;
/**
* IDigest
*
* @author Tommaso Burlon (tommaso.burlon@link.it)
* @author $Author$
* @version $Rev$, $Date$
*/
public class DigestConfig implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private static final String DIGEST_TYPE = "digest.type";
private static final String DIGEST_SALT_LENGTH = "digest.salt.length";
private static final String DIGEST_SALT_SECURE_RANDOM_ALGORITHM = "digest.salt.secureRandomAlgorithm";
private static final String DIGEST_BASE64_ENCODE = "digest.base64Encode";
private static final String DIGEST_HASH_COMPOSITION = "digest.composition";
private DigestType digestType = null;
private Integer saltLength = null;
private String algorithmSecureRandom = "SHA1PRNG";
private String hashComposition = "${message}${salt}";
private boolean base64Encode = false;
public DigestConfig() {}
public DigestConfig(String resource) throws UtilsException{
try (InputStream is = getInputStream(resource)){
if(is!=null) {
Properties p = new Properties();
p.load(is);
this.initEngine(p);
} else {
throw new UtilsException("Resource ["+resource+"] not found");
}
} catch(Exception e) {
throw new UtilsException(e.getMessage(),e);
}
}
private InputStream getInputStream(String resource) throws FileNotFoundException {
File f = new File(resource);
InputStream is = null;
if(f.exists()) {
is = new FileInputStream(f);
} else {
is = DigestConfig.class.getResourceAsStream(resource);
}
if(is==null) {
is = DigestConfig.class.getResourceAsStream("/org/openspcoop2/utils/crypt/digest.properties");
}
return is;
}
public DigestConfig(InputStream is) throws UtilsException{
try{
Properties p = new Properties();
p.load(is);
this.initEngine(p);
}catch(Exception e){
throw new UtilsException(e.getMessage(),e);
}
}
public DigestConfig(Properties p) throws UtilsException {
this.initEngine(p);
}
private void initEngine(Properties p) throws UtilsException {
final String NOT_CORRECT_PROPERTY = "Property: '%s' value: '%s' not correct: %s";
String tipo = DigestConfig.getProperty(p, DigestConfig.DIGEST_TYPE, true);
if(StringUtils.isNotEmpty(tipo)) {
DigestType digestTypeProp = null;
try {
digestTypeProp = DigestType.valueOf(tipo);
}catch(IllegalArgumentException | NullPointerException e) {
throw new UtilsException(String.format(NOT_CORRECT_PROPERTY, DigestConfig.DIGEST_TYPE, tipo, e.getMessage()), e);
}
this.digestType = digestTypeProp;
}
String saltLengthProp = getProperty(p, DIGEST_SALT_LENGTH, false);
if(StringUtils.isNotEmpty(saltLengthProp)) {
try {
this.saltLength = Integer.valueOf(saltLengthProp);
}catch(NumberFormatException e) {
throw new UtilsException(String.format(NOT_CORRECT_PROPERTY, DigestConfig.DIGEST_SALT_LENGTH, saltLengthProp, e.getMessage()), e);
}
}
String secureRandomAlgo = getProperty(p, DIGEST_SALT_SECURE_RANDOM_ALGORITHM, false);
if(StringUtils.isNotEmpty(secureRandomAlgo)) {
this.algorithmSecureRandom = secureRandomAlgo;
}
String digestBase64Encode = getProperty(p, DIGEST_BASE64_ENCODE, false);
if(StringUtils.isNotEmpty(digestBase64Encode)) {
this.base64Encode = Boolean.valueOf(digestBase64Encode);
}
String digestHashComposition = getProperty(p, DIGEST_HASH_COMPOSITION, false);
if(StringUtils.isNotEmpty(digestHashComposition)) {
this.hashComposition = digestHashComposition;
}
}
protected static String getProperty(Properties p, String name, boolean required) throws UtilsException {
String pValue = p.getProperty(name);
if(pValue == null) {
if(required) {
throw new UtilsException("Property '" + name + "' not found");
}
return null;
}
else {
return pValue.trim();
}
}
private static final Pattern COMPOSITION_VAR_PATTERN = Pattern.compile("\\$\\{([^\\}]*)\\}");
private static final String SALT_LABEL = "salt";
private static final String MESSAGE_LABEL = "message";
public byte[] composeMessage(byte[] input, byte[] salt) {
String scheme = this.getHashComposition();
Pattern pattern = DigestConfig.COMPOSITION_VAR_PATTERN;
List<byte[]> bytes = new ArrayList<>();
Matcher matcher = pattern.matcher(scheme);
int lastIndex = 0;
int size = 0;
while (matcher.find(lastIndex)) {
if (lastIndex < matcher.start()) {
bytes.add(scheme.substring(lastIndex, matcher.start()).getBytes());
size += (matcher.start() - lastIndex);
}
lastIndex = matcher.end();
byte[] sub = null;
if (matcher.group(1).equals(MESSAGE_LABEL))
sub = input;
if (matcher.group(1).equals(SALT_LABEL))
sub = salt;
if (sub != null) {
size += sub.length;
bytes.add(sub);
}
}
if (lastIndex < scheme.length()) {
bytes.add(scheme.substring(lastIndex).getBytes());
size += scheme.length() - lastIndex;
}
byte[] buf = new byte[size];
lastIndex = 0;
for (byte[] src : bytes) {
System.arraycopy(src, 0, buf, lastIndex, src.length);
lastIndex += src.length;
}
return buf;
}
public DigestType getDigestType() {
return this.digestType;
}
public void setDigestType(DigestType digestType) {
this.digestType = digestType;
}
public Integer getSaltLength() {
return this.saltLength;
}
public void setSaltLength(Integer saltLength) {
this.saltLength = saltLength;
}
public String getAlgorithmSecureRandom() {
return this.algorithmSecureRandom;
}
public void setAlgorithmSecureRandom(String algorithmSecureRandom) {
this.algorithmSecureRandom = algorithmSecureRandom;
}
public boolean isBase64Encode() {
return this.base64Encode;
}
public void setBase64Encode(boolean base64Encode) {
this.base64Encode = base64Encode;
}
public String getHashComposition() {
return this.hashComposition;
}
public void setHashComposition(String hashComposition) {
this.hashComposition = hashComposition;
}
}