/****************************************************************************** * Product: Adempiere ERP & CRM Smart Business Solution * * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * * under the terms version 2 of the GNU General Public License 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, write to the Free Software Foundation, Inc., * * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * * For the text or an alternative of this public license, you may reach us * * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * * or via info@compiere.org or http://www.compiere.org/license.html * *****************************************************************************/ package org.compiere.util; import java.io.UnsupportedEncodingException; import java.math.BigDecimal; import java.security.AlgorithmParameters; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.sql.Timestamp; import java.util.logging.Level; import javax.crypto.Cipher; import org.adempiere.base.Core; import org.adempiere.base.IKeyStore; /** * Default implementation of {@link SecureInterface} for encryption and decryption. *

* Change log: *

* * @author Jorg Janke * @version $Id: Secure.java,v 1.2 2006/07/30 00:52:23 jjanke Exp $ */ public class Secure implements SecureInterface { /** * Hash checksum number * @param key key * @return checksum number */ public static int hash (String key) { long tableSize = 2147483647; // one less than max int long hashValue = 0; for (int i = 0; i < key.length(); i++) hashValue = (37 * hashValue) + (key.charAt(i) -31); hashValue %= tableSize; if (hashValue < 0) hashValue += tableSize; int retValue = (int)hashValue; return retValue; } // hash /** * Convert Byte Array to Hex String * @param bytes bytes * @return HexString */ public static String convertToHexString (byte[] bytes) { // see also Util.toHex int size = bytes.length; StringBuilder buffer = new StringBuilder(size*2); for(int i=0; i " + encString); return encString; } catch (Exception ex) { // log.log(Level.INFO, value, ex); if (log.isLoggable(Level.INFO))log.log(Level.INFO, "Problem encrypting string", ex); } // Fallback return CLEARVALUE_START + value + CLEARVALUE_END; } // encrypt /** * Decryption. * The methods must recognize clear text values * @param value encrypted value * @param AD_Client_ID * @return decrypted String */ public String decrypt (String value,int AD_Client_ID) { if (value == null || value.length() == 0) return value; boolean isEncrypted = value.startsWith(ENCRYPTEDVALUE_START) && value.endsWith(ENCRYPTEDVALUE_END); if (isEncrypted) value = value.substring(ENCRYPTEDVALUE_START.length(), value.length()-ENCRYPTEDVALUE_END.length()); // Needs to be hex String byte[] data = convertHexString(value); if (data == null) // cannot decrypt { if (isEncrypted) { // log.info("Failed: " + value); log.info("Failed"); return null; } // assume not encrypted return value; } // Init if (m_keyStore == null) initCipher(); // Encrypt if (value != null && value.length() > 0) { try { Cipher cipher = Cipher.getInstance(m_keyStore.getAlgorithm()); AlgorithmParameters ap = cipher.getParameters(); cipher.init(Cipher.DECRYPT_MODE, m_keyStore.getKey(AD_Client_ID), ap); byte[] out = cipher.doFinal(data); String retValue = new String(out, "UTF8"); // globalqss - [ 1577737 ] Security Breach - show database password // log.log (Level.ALL, value + " => " + retValue); return retValue; } catch (Exception ex) { // log.info("Failed: " + value + " - " + ex.toString()); if (log.isLoggable(Level.INFO)) log.info("Failed decrypting " + ex.toString()); } } return null; } // decrypt /** * Not implemented, just return value as it is * @param value clear value * @param ad_client_id * @return integer value */ public Integer encrypt (Integer value,int ad_client_id) { return value; } // encrypt /** * Not implemented, just return value as it is * @param value encrypted value * @return integer value */ public Integer decrypt (Integer value,int ad_client_id) { return value; } // decrypt /** * Not implemented, just return value as it is * @param value clear value * @param ad_client_id * @return BigDecimal value */ public BigDecimal encrypt (BigDecimal value,int ad_client_id) { return value; } // encrypt /** * Not implemented, just return value as it is * @param value encrypted value * @return Big decimal value */ public BigDecimal decrypt (BigDecimal value,int ad_client_id) { return value; } // decrypt /** * Not implemented, just return value as it is * @param value clear value * @param ad_client_id * @return Timestamp value */ public Timestamp encrypt (Timestamp value,int ad_client_id) { return value; } // encrypt /** * Not implemented, just return value as it is * @param value encrypted value * @return Timestamp value */ public Timestamp decrypt (Timestamp value,int ad_client_id) { return value; } // decrypt /** * Perform MD5 Digest of value * JavaScript version see - http://pajhome.org.uk/crypt/md5/index.html * * @param value text to digest * @return HexString of digested message (length = 32 characters) */ public String getDigest (String value) { if (m_md == null) { try { m_md = MessageDigest.getInstance("MD5"); } catch (NoSuchAlgorithmException nsae) { nsae.printStackTrace(); } } // Convert String to array of bytes byte[] input = value.getBytes(); byte[] output = null; // Reset MessageDigest object if (m_md != null) { m_md.reset(); // feed this array of bytes to the MessageDigest object m_md.update(input); // Get the resulting bytes after the encryption process output = m_md.digest(); m_md.reset(); // } return convertToHexString(output); } // getDigest /** * Checks, if value is a valid digest * @param value digest string * @return true if valid digest */ public boolean isDigest (String value) { if (value == null || value.length() != 32) return false; // needs to be a hex string, so try to convert it return (convertHexString(value) != null); } // isDigest /** * Convert String and salt to SHA-512 hash with iterations * https://www.owasp.org/index.php/Hashing_Java * * @param value message * @return HexString of message (length = 128 characters) * @throws NoSuchAlgorithmException * @throws UnsupportedEncodingException */ public String getSHA512Hash (int iterations, String value, byte[] salt) throws NoSuchAlgorithmException, UnsupportedEncodingException { MessageDigest digest = MessageDigest.getInstance("SHA-512"); digest.reset(); digest.update(salt); byte[] input = digest.digest(value.getBytes("UTF-8")); for (int i = 0; i < iterations; i++) { digest.reset(); input = digest.digest(input); } digest.reset(); // return convertToHexString(input); } // getSHA512Hash /** * String Representation * @return info */ @Override public String toString () { StringBuilder sb = new StringBuilder ("Secure["); sb.append(m_keyStore.getAlgorithm()) .append ("]"); return sb.toString (); } // toString /** * @return keystore */ public IKeyStore getKeyStore(){ IKeyStore keyStore = Core.getKeyStore(); if(keyStore==null) keyStore = new DefaultKeyStore(); return keyStore; } } // Secure