AES_DECRYPT不能在linux上运行:可能与Hibernate有关

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)

你知道可能导致问题的原因吗?

rea*_*404 0

所以我终于设法指出问题出在哪里。

\n\n

在应用程序启动时,我将密钥存储在配置对象中。密钥存储为字符串,执行String cle = new String(key.getEncoded());

\n\n

这在 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