IDEMPIERE-613 Column Encryption Enhancement.

This commit is contained in:
Heng Sin Low 2013-02-06 18:03:42 +08:00
parent 11603bc4fe
commit b6af6a3489
14 changed files with 404 additions and 205 deletions

View File

@ -117,7 +117,7 @@ public class ColumnEncryption extends SvrProcess {
if (column.isKey() || column.isParent() || column.isStandardColumn()
|| column.isVirtualColumn() || column.isIdentifier()
|| column.isTranslated() || DisplayType.isLookup(dt)
|| DisplayType.isLOB(dt)
|| DisplayType.isLOB(dt) || DisplayType.isDate(dt) || DisplayType.isNumeric(dt)
|| "DocumentNo".equalsIgnoreCase(column.getColumnName())
|| "Value".equalsIgnoreCase(column.getColumnName())
|| "Name".equalsIgnoreCase(column.getColumnName())) {
@ -126,7 +126,7 @@ public class ColumnEncryption extends SvrProcess {
column.saveEx();
}
StringBuilder msgreturn = new StringBuilder().append(columnName).append(": cannot be encrypted");
return msgreturn.toString();
throw new Exception(msgreturn.toString());
}
// Start
@ -137,10 +137,10 @@ public class ColumnEncryption extends SvrProcess {
// Test Value
if (p_TestValue != null && p_TestValue.length() > 0) {
String encString = SecureEngine.encrypt(p_TestValue);
String encString = SecureEngine.encrypt(p_TestValue, 0);
msglog = new StringBuilder("Encrypted Test Value=").append(encString);
addLog(0, null, null, msglog.toString());
String clearString = SecureEngine.decrypt(encString);
String clearString = SecureEngine.decrypt(encString, 0);
if (p_TestValue.equals(clearString)){
msglog = new StringBuilder("Decrypted=").append(clearString)
.append(" (same as test value)");
@ -181,7 +181,7 @@ public class ColumnEncryption extends SvrProcess {
.append("Test=").append(testClear.toString()).append(" (").append(p_MaxLength).append(")");
log.config(msglog.toString());
//
String encString = SecureEngine.encrypt(testClear.toString());
String encString = SecureEngine.encrypt(testClear.toString(), 0);
int encLength = encString.length();
msglog = new StringBuilder("Test Max Length=").append(testClear.length())
.append(" -> ").append(encLength);
@ -224,7 +224,7 @@ public class ColumnEncryption extends SvrProcess {
// Check if the encryption exceeds the current length.
int oldLength = column.getFieldLength();
int newLength = encryptedColumnLength(oldLength);
if (newLength > oldLength)
if (newLength > oldLength) {
if (changeFieldLength(columnID, columnName, newLength,
tableName) == -1) {
log.warning("EncryptError [ChangeFieldLength]: "
@ -232,6 +232,7 @@ public class ColumnEncryption extends SvrProcess {
+ newLength);
throw new Exception();
}
}
// Encrypt column contents.
if (encryptColumnContents(columnName, column.getAD_Table_ID()) == -1) {
@ -295,7 +296,7 @@ public class ColumnEncryption extends SvrProcess {
StringBuilder idColumnName = new StringBuilder(tableName).append("_ID");
StringBuilder selectSql = new StringBuilder();
selectSql.append("SELECT ").append(idColumnName).append(",").append(columnName);
selectSql.append("SELECT ").append(idColumnName).append(",").append(columnName).append(",AD_Client_ID");
selectSql.append(" FROM ").append(tableName);
selectSql.append(" ORDER BY ").append(idColumnName);
@ -306,32 +307,36 @@ public class ColumnEncryption extends SvrProcess {
PreparedStatement selectStmt = null;
PreparedStatement updateStmt = null;
selectStmt = m_conn.prepareStatement(selectSql.toString(),
ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
updateStmt = m_conn.prepareStatement(updateSql.toString());
ResultSet rs = selectStmt.executeQuery();
for (recordsEncrypted = 0; rs.next(); ++recordsEncrypted) {
// Get the row id and column value
int id = rs.getInt(1);
String value = rs.getString(2);
// Encrypt the value
value = SecureEngine.encrypt(value);
// Update the row
updateStmt.setString(1, value);
updateStmt.setInt(2, id);
if (updateStmt.executeUpdate() != 1) {
log.warning("EncryptError: Table=" + tableName + ", ID=" + id);
throw new Exception();
ResultSet rs = null;
try {
selectStmt = m_conn.prepareStatement(selectSql.toString(),
ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
updateStmt = m_conn.prepareStatement(updateSql.toString());
rs = selectStmt.executeQuery();
for (recordsEncrypted = 0; rs.next(); ++recordsEncrypted) {
// Get the row id and column value
int id = rs.getInt(1);
String value = rs.getString(2);
int AD_Client_ID = rs.getInt(3);
// Encrypt the value
value = SecureEngine.encrypt(value, AD_Client_ID);
// Update the row
updateStmt.setString(1, value);
updateStmt.setInt(2, id);
if (updateStmt.executeUpdate() != 1) {
log.severe("EncryptError: Table=" + tableName + ", ID=" + id);
throw new Exception();
}
}
} finally {
DB.close(rs);
DB.close(selectStmt);
DB.close(updateStmt);
}
rs.close();
selectStmt.close();
updateStmt.close();
return recordsEncrypted;
} // encryptColumnContents
@ -348,7 +353,7 @@ public class ColumnEncryption extends SvrProcess {
for (int i = 0; i < colLength; i++) {
str.append("1");
}
str = new StringBuilder().append(SecureEngine.encrypt(str.toString()));
str = new StringBuilder().append(SecureEngine.encrypt(str.toString(), 0));
return str.length();
} // encryptedColumnLength
@ -387,34 +392,36 @@ public class ColumnEncryption extends SvrProcess {
updateSql.append(" WHERE AD_Column_ID=").append(columnID);
PreparedStatement selectStmt = null;
selectStmt = m_conn.prepareStatement(selectSql.toString(),
ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
selectStmt.setInt(1, columnID);
ResultSet rs = selectStmt.executeQuery();
if (rs.next()) {
// Change the column size physically.
if (DB.executeUpdate(alterSql.toString(), false, m_trx
.getTrxName()) == -1) {
log.warning("EncryptError [ChangeFieldLength]: ColumnID="
+ columnID + ", NewLength=" + length);
throw new Exception();
}
// Change the column size in AD.
if (DB.executeUpdate(updateSql.toString(), false, m_trx
.getTrxName()) == -1) {
log.warning("EncryptError [ChangeFieldLength]: ColumnID="
+ columnID + ", NewLength=" + length);
throw new Exception();
ResultSet rs = null;
try {
selectStmt = m_conn.prepareStatement(selectSql.toString(),
ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
selectStmt.setInt(1, columnID);
rs = selectStmt.executeQuery();
if (rs.next()) {
// Change the column size physically.
if (DB.executeUpdate(alterSql.toString(), false, m_trx
.getTrxName()) == -1) {
log.severe("EncryptError [ChangeFieldLength]: ColumnID="
+ columnID + ", NewLength=" + length);
throw new Exception();
}
// Change the column size in AD.
if (DB.executeUpdate(updateSql.toString(), false, m_trx
.getTrxName()) == -1) {
log.severe("EncryptError [ChangeFieldLength]: ColumnID="
+ columnID + ", NewLength=" + length);
throw new Exception();
}
}
} finally {
DB.close(rs, selectStmt);
}
rs.close();
selectStmt.close();
// Update number of rows effected.
rowsEffected++;

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.adempiere.base.keystore.default">
<implementation class="org.compiere.util.DefaultKeyStore"/>
<service>
<provide interface="org.adempiere.base.IKeyStore"/>
</service>
</scr:component>

View File

@ -104,6 +104,14 @@ public class Core {
return Service.locator().locate(ModelValidator.class, "org.adempiere.base.ModelValidator", serviceId, null).getService();
}
/**
*
* @return keystore
*/
public static IKeyStore getKeyStore(){
return Service.locator().locate(IKeyStore.class).getService();
}
/**
* Get payment processor instance
* @param mbap payment processor model

View File

@ -0,0 +1,39 @@
/******************************************************************************
* Copyright (C) 2013 Deepak *
* Copyright (C) 2013 Trek Global *
* 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. *
*****************************************************************************/
package org.adempiere.base;
import javax.crypto.SecretKey;
/**
*
* @author deepak
*
*/
public interface IKeyStore {
/**
*
* @param AD_Client_ID
* @return secret key
*/
public SecretKey getKey(int AD_Client_ID);
/**
* @return encryption algorithm id, for e.g AES
*/
public String getAlgorithm();
}

View File

@ -1814,7 +1814,7 @@ public class GridTable extends AbstractTableModel
else
iii = new Integer(dd.toString());
if (encrypted)
iii = (Integer)encrypt(iii);
iii = (Integer)encrypt(iii, getAD_Client_ID());
if (manualUpdate)
createUpdateSql (columnName, String.valueOf (iii));
else
@ -1834,7 +1834,7 @@ public class GridTable extends AbstractTableModel
{
BigDecimal bd = (BigDecimal)rowData[col];
if (encrypted)
bd = (BigDecimal)encrypt(bd);
bd = (BigDecimal)encrypt(bd, getAD_Client_ID());
if (manualUpdate)
createUpdateSql (columnName, bd.toString ());
else
@ -1846,7 +1846,7 @@ public class GridTable extends AbstractTableModel
{
Timestamp ts = (Timestamp)rowData[col];
if (encrypted)
ts = (Timestamp)encrypt(ts);
ts = (Timestamp)encrypt(ts, getAD_Client_ID());
if (manualUpdate)
createUpdateSql (columnName, DB.TO_DATE (ts, false));
else
@ -1884,7 +1884,7 @@ public class GridTable extends AbstractTableModel
{
String str = rowData[col].toString ();
if (encrypted)
str = (String)encrypt(str);
str = (String)encrypt(str, getAD_Client_ID());
if (manualUpdate)
createUpdateSql (columnName, DB.TO_STRING (str));
else
@ -3121,7 +3121,7 @@ public class GridTable extends AbstractTableModel
{
String str = rs.getString(j+1);
if (field.isEncryptedColumn())
str = (String)decrypt(str);
str = (String)decrypt(str, getAD_Client_ID());
rowData[j] = new Boolean ("Y".equals(str)); // Boolean
}
// LOB
@ -3152,7 +3152,7 @@ public class GridTable extends AbstractTableModel
rowData[j] = rs.getString(j+1); // String
// Encrypted
if (field.isEncryptedColumn() && displayType != DisplayType.YesNo)
rowData[j] = decrypt(rowData[j]);
rowData[j] = decrypt(rowData[j], getAD_Client_ID());
}
}
catch (SQLException e)
@ -3167,11 +3167,11 @@ public class GridTable extends AbstractTableModel
* @param xx clear data
* @return encrypted value
*/
private Object encrypt (Object xx)
private Object encrypt (Object xx, int AD_Client_ID)
{
if (xx == null)
return null;
return SecureEngine.encrypt(xx);
return SecureEngine.encrypt(xx, AD_Client_ID);
} // encrypt
/**
@ -3179,13 +3179,23 @@ public class GridTable extends AbstractTableModel
* @param yy encrypted data
* @return clear data
*/
private Object decrypt (Object yy)
private Object decrypt (Object yy, int AD_Client_ID)
{
if (yy == null)
return null;
return SecureEngine.decrypt(yy);
return SecureEngine.decrypt(yy, AD_Client_ID);
} // decrypt
private int getAD_Client_ID()
{
int AD_Client_ID = Env.getAD_Client_ID(Env.getCtx());
GridField field = getField("AD_Client_ID");
if (field != null && field.getValue() != null) {
AD_Client_ID = ((Number)field.getValue()).intValue();
}
return AD_Client_ID;
}
/**************************************************************************
* Remove Data Status Listener
* @param l listener

View File

@ -3020,8 +3020,9 @@ public abstract class PO
{
if (xx == null)
return null;
if (index != -1 && p_info.isEncrypted(index))
return SecureEngine.encrypt(xx);
if (index != -1 && p_info.isEncrypted(index)) {
return SecureEngine.encrypt(xx, getAD_Client_ID());
}
return xx;
} // encrypt
@ -3035,8 +3036,9 @@ public abstract class PO
{
if (yy == null)
return null;
if (index != -1 && p_info.isEncrypted(index))
return SecureEngine.decrypt(yy);
if (index != -1 && p_info.isEncrypted(index)) {
return SecureEngine.decrypt(yy, getAD_Client_ID());
}
return yy;
} // decrypt

View File

@ -0,0 +1,137 @@
/******************************************************************************
* Copyright (C) 2013 Deepak *
* Copyright (C) 2013 Heng Sin Low *
* Copyright (C) 2013 Trek Global *
* 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. *
*****************************************************************************/
package org.compiere.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.security.KeyStore;
import java.security.KeyStore.PasswordProtection;
import java.security.KeyStore.SecretKeyEntry;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import org.adempiere.base.IKeyStore;
/**
* @author deepak
* @author hengsin
*
*/
public class DefaultKeyStore implements IKeyStore {
private static final String LEGACY_ALGORITHM = "DES";
private static final String IDEMPIERE_KEYSTORE_PROPERTIES = "idempiere-ks.properties";
private static final String IDEMPIERE_KEYSTORE = "idempiere.ks";
/** Logger */
private static Logger log = Logger.getLogger (DefaultKeyStore.class.getName());
/** Adempiere Key */
private SecretKey m_key = null;
private KeyStore keyStore;
private char[] password = null;
private String algorithm;
public DefaultKeyStore(){
File file = new File(Ini.getAdempiereHome(), IDEMPIERE_KEYSTORE_PROPERTIES);
if (file.exists()) {
try{
Properties p = new Properties();
p.load(new FileInputStream(file));
String s = p.getProperty("password");
String a = p.getProperty("algorithm");
if (!Util.isEmpty(s) && !Util.isEmpty(a)) {
password = s.toCharArray();
algorithm = a;
keyStore = KeyStore.getInstance("JCEKS");
file = new File(Ini.getAdempiereHome(), IDEMPIERE_KEYSTORE);
if (file.exists()) {
FileInputStream stream = new FileInputStream(file);
keyStore.load(stream, password );
} else {
keyStore.load(null, password );
}
} else {
createLegacyKey();
}
} catch (Exception ex) {
log.log(Level.SEVERE, "", ex);
password = null;
createLegacyKey();
}
} else {
createLegacyKey();
}
}
private void createLegacyKey() {
m_key = new javax.crypto.spec.SecretKeySpec
(new byte[] {100,25,28,-122,-26,94,-3,-26}, LEGACY_ALGORITHM);
}
@Override
public SecretKey getKey(int AD_Client_ID) {
if (password != null) {
try {
PasswordProtection protParam = new PasswordProtection(password);
String alias = "ad_client_"+AD_Client_ID;
SecretKeyEntry entry = (SecretKeyEntry) keyStore.getEntry(alias, protParam);
if (entry == null) {
KeyGenerator generator = KeyGenerator.getInstance(algorithm);
SecretKey key = generator.generateKey();
entry = new SecretKeyEntry((SecretKey) key);
keyStore.setEntry(alias, entry, protParam);
File file = new File(IDEMPIERE_KEYSTORE);
FileOutputStream stream = null;
try {
stream = new FileOutputStream(file);
keyStore.store(stream, password);
stream.flush();
} finally {
if (stream != null) {
try {
stream.close();
} catch (Exception e) {}
}
}
}
return entry.getSecretKey();
} catch (Exception ex) {
log.log(Level.SEVERE, "", ex);
}
}
return m_key;
}
@Override
public String getAlgorithm() {
if (algorithm == null)
return LEGACY_ALGORITHM;
else
return algorithm;
}
}

View File

@ -515,7 +515,7 @@ public final class Ini implements Serializable
else if (!isClient())
result = s_prop.getProperty (key, SecureInterface.CLEARVALUE_START + defaultValue + SecureInterface.CLEARVALUE_END);
else
result = s_prop.getProperty (key, SecureEngine.encrypt(defaultValue));
result = s_prop.getProperty (key, SecureEngine.encrypt(defaultValue, 0));
s_prop.setProperty (key, result);
return result;
} // checkProperty
@ -577,7 +577,7 @@ public final class Ini implements Serializable
s_prop.setProperty(key, "");
else
{
String eValue = SecureEngine.encrypt(value);
String eValue = SecureEngine.encrypt(value, 0);
if (eValue == null)
s_prop.setProperty(key, "");
else
@ -619,7 +619,7 @@ public final class Ini implements Serializable
if (retStr == null || retStr.length() == 0)
return "";
//
String value = SecureEngine.decrypt(retStr);
String value = SecureEngine.decrypt(retStr, 0);
// getLogger().finer(key + "=" + value);
if (value == null)
return "";

View File

@ -304,35 +304,27 @@ public class Login
if ( user.authenticateHash(app_pwd) )
{
authenticated = true;
app_pwd = null;
}
}
else{
StringBuffer sql = new StringBuffer("SELECT AD_User.AD_User_ID,")
.append(" AD_User.ConnectionProfile ")
.append(" FROM AD_User ");
StringBuffer sql = new StringBuffer("SELECT AD_User.AD_User_ID ").append(" FROM AD_User ");
sql.append(" WHERE ").append(userNameCol).append("=?");
sql.append(" AND AD_User.IsActive='Y'").append(" AND EXISTS (SELECT * FROM AD_Client c WHERE AD_User.AD_Client_ID=c.AD_Client_ID AND c.IsActive='Y')");
if (app_pwd != null)
sql.append(" AND ((AD_User.Password=? AND (SELECT IsEncrypted FROM AD_Column WHERE AD_Column_ID=417)='N') "
+ "OR (AD_User.Password=? AND (SELECT IsEncrypted FROM AD_Column WHERE AD_Column_ID=417)='Y'))"); // #2/3
PreparedStatement pstmt1=null;
ResultSet rs1=null;
try{
pstmt1 = DB.prepareStatement(sql.toString(), null);
pstmt1.setString(1, app_user);
if (app_pwd != null)
{
pstmt1.setString(2, app_pwd);
pstmt1.setString(3, SecureEngine.encrypt(app_pwd));
}
rs1 = pstmt1.executeQuery();
while(rs1.next()){
authenticated=true;
MUser user = new MUser(m_ctx, rs1.getInt(1), null);
if (user.getPassword() != null && user.getPassword().equals(app_pwd)) {
authenticated=true;
}
}
}catch (Exception ex) {
@ -349,9 +341,8 @@ public class Login
}
if(authenticated){
StringBuffer sql = new StringBuffer("SELECT AD_User.AD_User_ID, r.AD_Role_ID,r.Name,")
.append(" AD_User.ConnectionProfile ")
.append("FROM AD_User ")
StringBuffer sql = new StringBuffer("SELECT AD_User.AD_User_ID, r.AD_Role_ID,r.Name")
.append(" FROM AD_User ")
.append(" INNER JOIN AD_User_Roles ur ON (AD_User.AD_User_ID=ur.AD_User_ID AND ur.IsActive='Y')")
.append(" INNER JOIN AD_Role r ON (ur.AD_Role_ID=r.AD_Role_ID AND r.IsActive='Y') ");
@ -359,10 +350,6 @@ public class Login
sql.append(" AND AD_User.IsActive='Y'").append(" AND EXISTS (SELECT * FROM AD_Client c WHERE AD_User.AD_Client_ID=c.AD_Client_ID AND c.IsActive='Y')");
/* if (app_pwd != null && !hash_password)
sql.append(" AND ((AD_User.Password=? AND (SELECT IsEncrypted FROM AD_Column WHERE AD_Column_ID=417)='N') "
+ "OR (AD_User.Password=? AND (SELECT IsEncrypted FROM AD_Column WHERE AD_Column_ID=417)='Y'))"); // #2/3*/
sql.append(" ORDER BY r.Name");
PreparedStatement pstmt = null;
@ -372,11 +359,6 @@ public class Login
pstmt = DB.prepareStatement(sql.toString(), null);
pstmt.setString(1, app_user);
/*if (app_pwd != null && !hash_password)
{
pstmt.setString(2, app_pwd);
pstmt.setString(3, SecureEngine.encrypt(app_pwd));
}*/
// execute a query
rs = pstmt.executeQuery();
@ -413,13 +395,16 @@ public class Login
}
do // read all roles
{
int AD_Role_ID = rs.getInt(2);
if (AD_Role_ID == 0)
Env.setContext(m_ctx, "#SysAdmin", "Y");
String Name = rs.getString(3);
KeyNamePair p = new KeyNamePair(AD_Role_ID, Name);
list.add(p);
{
MUser user = new MUser(m_ctx, rs.getInt(1), null);
if (user.getPassword() != null && user.getPassword().equals(app_pwd)) {
int AD_Role_ID = rs.getInt(2);
if (AD_Role_ID == 0)
Env.setContext(m_ctx, "#SysAdmin", "Y");
String Name = rs.getString(3);
KeyNamePair p = new KeyNamePair(AD_Role_ID, Name);
list.add(p);
}
}
while (rs.next());
//
@ -440,6 +425,7 @@ public class Login
{
DB.close(rs, pstmt);
rs = null; pstmt = null;
app_pwd = null;
}
}
//long ms = System.currentTimeMillis () - start;
@ -1333,7 +1319,7 @@ public class Login
valid = user.authenticateHash(app_pwd);
} else {
// password not hashed
valid = user.getPassword().equals(app_pwd);
valid = user.getPassword() != null && user.getPassword().equals(app_pwd);
}
if (valid ) {
if (user.isLocked())

View File

@ -26,7 +26,9 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import org.adempiere.base.Core;
import org.adempiere.base.IKeyStore;
/**
* Security Services.
@ -128,14 +130,11 @@ public class Secure implements SecureInterface
{
initCipher();
} // Secure
/** Adempiere Cipher */
private Cipher m_cipher = null;
/** Adempiere Key */
private SecretKey m_key = null;
/** Message Digest */
private MessageDigest m_md = null;
private IKeyStore m_keyStore = null;
/** Logger */
private static Logger log = Logger.getLogger (Secure.class.getName());
@ -144,34 +143,10 @@ public class Secure implements SecureInterface
*/
private synchronized void initCipher()
{
if (m_cipher != null)
return;
Cipher cc = null;
try
{
cc = Cipher.getInstance("DES/ECB/PKCS5Padding");
// Key
/*if (false)
{
KeyGenerator keygen = KeyGenerator.getInstance("DES");
m_key = keygen.generateKey();
byte[] key = m_key.getEncoded();
StringBuffer sb = new StringBuffer ("Key ")
.append(m_key.getAlgorithm())
.append("(").append(key.length).append(")= ");
for (int i = 0; i < key.length; i++)
sb.append(key[i]).append(",");
log.info(sb.toString());
}
else*/
m_key = new javax.crypto.spec.SecretKeySpec
(new byte[] {100,25,28,-122,-26,94,-3,-26}, "DES");
if(m_keyStore==null){
m_keyStore = getKeyStore();
}
catch (Exception ex)
{
log.log(Level.SEVERE, "", ex);
}
m_cipher = cc;
} // initCipher
@ -179,35 +154,35 @@ public class Secure implements SecureInterface
/**
* Encryption.
* @param value clear value
* @param AD_Client_ID
* @return encrypted String
*/
public String encrypt (String value)
{
public String encrypt (String value,int AD_Client_ID)
{
String clearText = value;
if (clearText == null)
clearText = "";
// Init
if (m_cipher == null)
// Init
if (m_keyStore == null)
initCipher();
// Encrypt
if (m_cipher != null)
{
try
{
m_cipher.init(Cipher.ENCRYPT_MODE, m_key);
byte[] encBytes = m_cipher.doFinal(clearText.getBytes("UTF8"));
String encString = convertToHexString(encBytes);
// globalqss - [ 1577737 ] Security Breach - show database password
// log.log (Level.ALL, value + " => " + encString);
return encString;
}
catch (Exception ex)
{
// log.log(Level.INFO, value, ex);
log.log(Level.INFO, "Problem encrypting string", ex);
}
// Encrypt
try {
Cipher cipher = Cipher.getInstance(m_keyStore.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, m_keyStore.getKey(AD_Client_ID));
byte[] encBytes = cipher.doFinal(clearText.getBytes("UTF8"));
String encString = convertToHexString(encBytes);
// globalqss - [ 1577737 ] Security Breach - show database password
// log.log (Level.ALL, value + " => " + encString);
return encString;
} catch (Exception ex) {
// log.log(Level.INFO, value, ex);
log.log(Level.INFO, "Problem encrypting string", ex);
}
// Fallback
// Fallback
return CLEARVALUE_START + value + CLEARVALUE_END;
} // encrypt
@ -215,9 +190,10 @@ public class Secure implements SecureInterface
* Decryption.
* The methods must recognize clear text values
* @param value encrypted value
* @param AD_Client_ID
* @return decrypted String
*/
public String decrypt (String value)
public String decrypt (String value,int AD_Client_ID)
{
if (value == null || value.length() == 0)
return value;
@ -238,17 +214,18 @@ public class Secure implements SecureInterface
return value;
}
// Init
if (m_cipher == null)
if (m_keyStore == null)
initCipher();
// Encrypt
if (m_cipher != null && value != null && value.length() > 0)
if (value != null && value.length() > 0)
{
try
{
AlgorithmParameters ap = m_cipher.getParameters();
m_cipher.init(Cipher.DECRYPT_MODE, m_key, ap);
byte[] out = m_cipher.doFinal(data);
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);
@ -267,9 +244,10 @@ public class Secure implements SecureInterface
* Encryption.
* The methods must recognize clear text values
* @param value clear value
* @param ad_client_id
* @return encrypted String
*/
public Integer encrypt (Integer value)
public Integer encrypt (Integer value,int ad_client_id)
{
return value;
} // encrypt
@ -280,7 +258,7 @@ public class Secure implements SecureInterface
* @param value encrypted value
* @return decrypted String
*/
public Integer decrypt (Integer value)
public Integer decrypt (Integer value,int ad_client_id)
{
return value;
} // decrypt
@ -289,9 +267,10 @@ public class Secure implements SecureInterface
* Encryption.
* The methods must recognize clear text values
* @param value clear value
* @param ad_client_id
* @return encrypted String
*/
public BigDecimal encrypt (BigDecimal value)
public BigDecimal encrypt (BigDecimal value,int ad_client_id)
{
return value;
} // encrypt
@ -302,7 +281,7 @@ public class Secure implements SecureInterface
* @param value encrypted value
* @return decrypted String
*/
public BigDecimal decrypt (BigDecimal value)
public BigDecimal decrypt (BigDecimal value,int ad_client_id)
{
return value;
} // decrypt
@ -311,9 +290,10 @@ public class Secure implements SecureInterface
* Encryption.
* The methods must recognize clear text values
* @param value clear value
* @param ad_client_id
* @return encrypted String
*/
public Timestamp encrypt (Timestamp value)
public Timestamp encrypt (Timestamp value,int ad_client_id)
{
return value;
} // encrypt
@ -324,7 +304,7 @@ public class Secure implements SecureInterface
* @param value encrypted value
* @return decrypted String
*/
public Timestamp decrypt (Timestamp value)
public Timestamp decrypt (Timestamp value,int ad_client_id)
{
return value;
} // decrypt
@ -412,9 +392,20 @@ public class Secure implements SecureInterface
public String toString ()
{
StringBuilder sb = new StringBuilder ("Secure[");
sb.append(m_cipher)
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

View File

@ -106,9 +106,10 @@ public class SecureEngine
* Encryption.
* The methods must recognize clear text values
* @param value clear value
* @param AD_Client_ID
* @return encrypted String
*/
public static String encrypt (String value)
public static String encrypt (String value,int AD_Client_ID)
{
if (value == null || value.length() == 0)
return value;
@ -119,19 +120,21 @@ public class SecureEngine
if (inQuotes)
value = value.substring(1, value.length()-1);
//
String retValue = s_engine.implementation.encrypt(value);
String retValue = s_engine.implementation.encrypt(value,AD_Client_ID);
if (inQuotes)
return "'" + retValue + "'";
return retValue;
} // encrypt
/**
* Decryption.
* The methods must recognize clear text values
* @param value encrypted value
* @param AD_Client_ID
* @return decrypted String
*/
public static String decrypt (String value)
public static String decrypt (String value, int AD_Client_ID)
{
if (value == null)
return null;
@ -144,22 +147,23 @@ public class SecureEngine
if (value.startsWith(SecureInterface.CLEARVALUE_START) && value.endsWith(SecureInterface.CLEARVALUE_END))
retValue = value.substring(SecureInterface.CLEARVALUE_START.length(), value.length()-SecureInterface.CLEARVALUE_END.length());
else
retValue = s_engine.implementation.decrypt(value);
retValue = s_engine.implementation.decrypt(value,AD_Client_ID);
if (inQuotes)
return "'" + retValue + "'";
return retValue;
} // decrypt
/**
* Encryption.
* The methods must recognize clear values
* @param value clear value
* @param AD_Client_ID
* @return encrypted String
*/
public static Object encrypt (Object value)
public static Object encrypt (Object value, int AD_Client_ID)
{
if (value instanceof String)
return encrypt((String) value);
return encrypt((String) value, AD_Client_ID);
return value;
} // encrypt
@ -169,10 +173,10 @@ public class SecureEngine
* @param value encrypted value
* @return decrypted String
*/
public static Object decrypt (Object value)
public static Object decrypt (Object value, int AD_Client_ID)
{
if (value instanceof String)
return decrypt((String) value);
return decrypt((String) value, AD_Client_ID);
return value;
} // decrypt
@ -204,8 +208,8 @@ public class SecureEngine
System.exit(10);
}
// See if it works
String testE = implementation.encrypt(TEST);
String testC = implementation.decrypt(testE);
String testE = implementation.encrypt(TEST,0);
String testC = implementation.decrypt(testE,0);
if (!testC.equals(TEST))
throw new IllegalStateException(realClass
+ ": " + TEST
@ -269,10 +273,10 @@ public class SecureEngine
log.info("Decrypt null =" + test(decrypt(null), null));
log.info("Decrypt test =" + test(decrypt("test"), "test"));
**/
log.info("Decrypt {test} =" + test(decrypt("af2309f390afed74"), "test"));
log.info("Decrypt ~{test}~ =" + test(decrypt(SecureInterface.ENCRYPTEDVALUE_START + "af2309f390afed74" + SecureInterface.ENCRYPTEDVALUE_END), "test"));
log.info("Decrypt {test} =" + test(decrypt("af2309f390afed74", 0), "test"));
log.info("Decrypt ~{test}~ =" + test(decrypt(SecureInterface.ENCRYPTEDVALUE_START + "af2309f390afed74" + SecureInterface.ENCRYPTEDVALUE_END, 0), "test"));
log.info("Encrypt test =" + test(encrypt("test"), "af2309f390afed74"));
log.info("Encrypt test =" + test(encrypt("test", 0), "af2309f390afed74"));

View File

@ -52,64 +52,71 @@ public interface SecureInterface
/**
* Encryption.
* @param value clear value
* @param AD_Client_ID
* @return encrypted String
*/
public String encrypt (String value);
public String encrypt (String value,int AD_Client_ID);
/**
* Decryption.
* @param value encrypted value
* @return decrypted String
*/
public String decrypt (String value);
public String decrypt (String value,int AD_Client_ID);
/**
* Encryption.
* The methods must recognize clear text values
* @param value clear value
* @param AD_Client_ID
* @return encrypted String
*/
public Integer encrypt (Integer value);
public Integer encrypt (Integer value,int AD_Client_ID);
/**
* Decryption.
* The methods must recognize clear text values
* @param value encrypted value
* @param AD_Client_ID
* @return decrypted String
*/
public Integer decrypt (Integer value);
public Integer decrypt (Integer value,int AD_Client_ID);
/**
* Encryption.
* The methods must recognize clear text values
* @param value clear value
* @param AD_Client_ID
* @return encrypted String
*/
public BigDecimal encrypt (BigDecimal value);
public BigDecimal encrypt (BigDecimal value,int AD_Client_ID);
/**
* Decryption.
* The methods must recognize clear text values
* @param value encrypted value
* @param AD_Client_ID
* @return decrypted String
*/
public BigDecimal decrypt (BigDecimal value);
public BigDecimal decrypt (BigDecimal value,int AD_Client_ID);
/**
* Encryption.
* The methods must recognize clear text values
* @param value clear value
* @param AD_Client_ID
* @return encrypted String
*/
public Timestamp encrypt (Timestamp value);
public Timestamp encrypt (Timestamp value,int AD_Client_ID);
/**
* Decryption.
* The methods must recognize clear text values
* @param value encrypted value
* @param AD_Client_ID
* @return decrypted String
*/
public Timestamp decrypt (Timestamp value);
public Timestamp decrypt (Timestamp value,int AD_Client_ID);
/**

View File

@ -682,8 +682,6 @@ public class WebUser
{
String sql = "SELECT * FROM AD_User "
+ "WHERE COALESCE(LDAPUser, Name)=? " // #1
+ " AND ((Password=? AND (SELECT IsEncrypted FROM AD_Column WHERE AD_Column_ID=417)='N') " // #2
+ "OR (Password=? AND (SELECT IsEncrypted FROM AD_Column WHERE AD_Column_ID=417)='Y'))" // #3
+ " AND IsActive='Y' " // #4
;
PreparedStatement pstmt = null;
@ -692,14 +690,17 @@ public class WebUser
{
pstmt = DB.prepareStatement (sql, null);
pstmt.setString (1, m_bpc.getName());
pstmt.setString (2, password);
pstmt.setString (3, SecureEngine.encrypt(password));
rs = pstmt.executeQuery ();
if (rs.next ())
{
retValue = true;
if (rs.next())
log.warning ("More then one user with Name/Password = " + m_bpc.getName());
do
{
MUser user = new MUser(Env.getCtx(), rs, null);
if (user.getPassword() != null && user.getPassword().equals(password)) {
retValue = true;
break;
}
} while (rs.next());
}
else
log.fine("No record");

View File

@ -1697,7 +1697,7 @@ public class FindWindow extends Window implements EventListener<Event>, ValueCha
GridField field = getTargetMField(ColumnName);
// add encryption here if the field is encrypted.
if (field.isEncryptedColumn()) {
value = SecureEngine.encrypt(value);
value = SecureEngine.encrypt(value, Env.getAD_Client_ID(Env.getCtx()));
}
boolean isProductCategoryField = isProductCategoryField(field.getAD_Column_ID());