rea*_*404 5 java mysql environment hibernate aes
我在我的数据库中加密了数据,我正在尝试执行一个请求,允许我在phpmyadmin中显示清除值.
我使用以下请求:
SELECT CAST(AES_DECRYPT(`my_encrypted_colum`, UNHEX('pass_in_hexa') AS CHAR) AS clear_value
FROM `my_table`
Run Code Online (Sandbox Code Playgroud)
当我在开发环境(windows)上使用它时,它运行良好.但是一旦我在pre-prod环境(linux)上使用它,我就会得到所有值的NULL.
我很确定它与不同的环境有关,但我无法弄清楚是什么.我甚至不知道哪个功能没有按预期运行:UNHEX或AES_DECRYPT(我的猜测是UNHEX)?
以下是我的dev和preprod环境的配置:
开发:
Serveur : localhost via TCP/IP
Type de serveur : MySQL
Version du serveur : 5.6.15-log - MySQL Community Server (GPL)
Version du protocole : 10
Utilisateur : root@localhost
Jeu de caractères du serveur : UTF-8 Unicode (utf8)
Apache/2.2.25 (Win32) PHP/5.3.19
Version du client de base de données : libmysql - mysqlnd 5.0.8-dev - 20102224 - $Id: 65fe78e70ce53d27a6cd578597722950e490b0d0 $
Extension PHP : mysqli
Run Code Online (Sandbox Code Playgroud)
预制:
Serveur: Localhost via UNIX socket
Logiciel: MySQL
Version du logiciel: 5.6.14 - MySQL Community Server (GPL)
Version du protocole: 10
Utilisateur: root@localhost
Jeu de caractères du serveur: UTF-8 Unicode (utf8)
Apache/2.2.15 (CentOS)
Version du client de base de données: libmysql - 5.1.72
Extension PHP: mysqli
Run Code Online (Sandbox Code Playgroud)
编辑:
我继续我的研究,它接缝方法AES_DECRYPT和UNHEX 无罪.确实,如果我直接从phpMyAdmin中添加表中的加密值,如下所示:
INSERT INTO `my_table` (`my_encrypted_column`) VALUES (AES_ENCRYPT('blabla', UNHEX('pass_in_hexa'))
Run Code Online (Sandbox Code Playgroud)
然后我设法使用先前的SELECT请求正确检索数据.
这意味着问题必须来自我首先插入数据的方式.为此,我使用Hibernate和nullSafeSet方法.
困扰我的是:如果我保存数据的方式有问题,那么它是如何在Windows上运行而不是在Linux上运行?
下面是我的nullSafeSet和nullSafeGet的实现
private static final String CIPHER_ALGORITHM = "AES";
// nullSafeSet
protected void noNullSet(PreparedStatement st, Object value, int index, SessionImplementor si) throws SQLException {
byte[] clearText = ((String) value).getBytes(Charset.forName("UTF-8"));
try {
Cipher encryptCipher = Cipher.getInstance(CIPHER_ALGORITHM);
encryptCipher.init(Cipher.ENCRYPT_MODE, getKey(cle));
st.setBytes(index, encryptCipher.doFinal(clearText));
}
catch (GeneralSecurityException e) {
throw new RuntimeException("should never happen", e);
}
}
@Override
public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor si, Object owner) throws HibernateException, SQLException {
byte[] bytes = rs.getBytes(names[0]);
try {
Cipher decryptCipher = Cipher.getInstance(CIPHER_ALGORITHM);
decryptCipher.init(Cipher.DECRYPT_MODE, getKey(cle));
if (bytes != null) {
return new String(decryptCipher.doFinal(bytes), Charset.forName("UTF-8"));
}
else {
return new String();
}
}
catch (GeneralSecurityException e) {
throw new RuntimeException("Mauvaise clé");
}
}
private static SecretKeySpec getKey(String secretKey) {
final byte[] finalKey = new byte[16];
int i = 0;
for (byte b : secretKey.getBytes()) {
// XOR
finalKey[i++ % 16] ^= b;
}
return new SecretKeySpec(finalKey, "AES");
}
Run Code Online (Sandbox Code Playgroud)
你知道可能导致问题的原因吗?
所以我终于设法指出问题出在哪里。
\n\n在应用程序启动时,我将密钥存储在配置对象中。密钥存储为字符串,执行String cle = new String(key.getEncoded());
这在 Windows 上工作正常并返回给我以下密钥:
\n\n*\xc2\xa3\xc3\x90t\xc3\xb4\xc2\xb5\xe2\x80\xa2\xc3\x83\n
Run Code Online (Sandbox Code Playgroud)\n\n但在Linux上特殊字符没有正确转换
\n\n*\xef\xbf\xbd\xef\xbf\xbdt\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\n
Run Code Online (Sandbox Code Playgroud)\n\n这导致在 Linux 上使用错误的密钥来完成加密/解密,因此在 MySQL 中执行“SELECT”时我无法使用“正确”的密钥值
\n