Oracle和MySQL中的AES加密给出了不同的结果
我需要比较Oracle数据库和MySQL数据库之间的数据 在Oracle中,数据首先使用Oracle和MySQL中的AES加密给出了不同的结果,mysql,oracle,encryption,plsql,Mysql,Oracle,Encryption,Plsql,我需要比较Oracle数据库和MySQL数据库之间的数据 在Oracle中,数据首先使用AES-128算法加密,然后散列。这意味着无法恢复数据并对其进行解密 相同的数据在MySQL和纯文本中都可用。因此,为了比较数据,我尝试了加密MySQL数据,然后对其进行散列,同时遵循在Oracle中完成的相同步骤 -- ORACLE: -- First the key is hashed with md5 to make it a 128bit key: raw_key := DBMS_CRYPTO.Has
AES-128
算法加密,然后散列。这意味着无法恢复数据并对其进行解密
相同的数据在MySQL和纯文本中都可用。因此,为了比较数据,我尝试了加密MySQL数据,然后对其进行散列,同时遵循在Oracle中完成的相同步骤
-- ORACLE:
-- First the key is hashed with md5 to make it a 128bit key:
raw_key := DBMS_CRYPTO.Hash (UTL_I18N.STRING_TO_RAW ('test_key', 'AL32UTF8'), DBMS_CRYPTO.HASH_MD5);
-- Initialize the encrypted result
encryption_type:= DBMS_CRYPTO.ENCRYPT_AES128 + DBMS_CRYPTO.CHAIN_CBC + DBMS_CRYPTO.PAD_PKCS5;
-- Then the data is being encrypted with AES:
encrypted_result := DBMS_CRYPTO.ENCRYPT(UTL_I18N.STRING_TO_RAW('test-data', 'AL32UTF8'), encryption_type, raw_key);
经过多次尝试,我终于发现MySQL中的aes_encrypt
返回的结果与Oracle中的不同
-- ORACLE:
-- First the key is hashed with md5 to make it a 128bit key:
raw_key := DBMS_CRYPTO.Hash (UTL_I18N.STRING_TO_RAW ('test_key', 'AL32UTF8'), DBMS_CRYPTO.HASH_MD5);
-- Initialize the encrypted result
encryption_type:= DBMS_CRYPTO.ENCRYPT_AES128 + DBMS_CRYPTO.CHAIN_CBC + DBMS_CRYPTO.PAD_PKCS5;
-- Then the data is being encrypted with AES:
encrypted_result := DBMS_CRYPTO.ENCRYPT(UTL_I18N.STRING_TO_RAW('test-data', 'AL32UTF8'), encryption_type, raw_key);
oracle代码的结果将是:8FCA326C25C8908446D28884394F2E22
-- MySQL
-- While doing the same with MySQL, I have tried the following:
SELECT hex(aes_encrypt('test-data', MD5('test_key'));
MySQL代码的结果将是:DC7ACAC07F04BBE0ECEC6B6934CF79FE
我错过什么了吗?或者不同语言之间的加密方法不一样
更新:
根据下面的评论,我认为我应该提到这样一个事实:Oracle中的DBMS\u CRYPTO.Hash
的结果与MySQL中的MD5
函数返回的结果相同
在Oracle中使用CBC
或CBE
也会得到相同的结果,因为IV没有传递给函数,因此使用了IV的默认值,即NULL
赏金:
如果有人能验证我的最后一条评论,并且如果在两边使用相同的填充,将产生相同的结果,那么将获得奖励:
@rossum MySQL中的默认填充是PKCS7,mmm。。。哦在甲骨文中 它使用的是PKCS5,真不敢相信我没有注意到。谢谢(顺便说一句 Oracle没有PAD_PKCS7选项,至少在11g中没有)
可能是CBC对ECB。本页底部的评论:mysql函数使用ECB,mysql的MD5函数返回一个由32个十六进制字符组成的字符串。它被标记为二进制字符串,但它不是人们期望的16字节二进制数据 因此,要修复它,必须将此字符串转换回二进制数据:
SELECT hex(aes_encrypt('test-data', unhex(MD5('test_key'))));
结果是:
8FCA326C25C8908446D28884394F2E22
它又是一个由32个十六进制字符组成的字符串。但在其他方面,结果与Oracle相同
顺便说一句:
- MySQL使用PKCS7填充
- PKCS5填充和PKCS7填充是相同的。因此,Oracle填充选项是正确的
- MySQL使用ECB分组密码模式。因此,您必须相应地修改代码。(前16个字节没有任何区别。)
- MySQL不使用初始化向量(与Oracle代码相同)
- MySQL使用非标准的折叠键。因此,要在MySQL和Oracle(或.NET或Java)中实现相同的结果,只需使用16字节长的密钥
encryption_type:= DBMS_CRYPTO.ENCRYPT_AES128 + DBMS_CRYPTO.CHAIN_ECB + DBMS_CRYPTO.PAD_PKCS5;
--严格地说,这真的是PKCS7
/*我选择欧洲央行是因为如果应用和
@科多说这是正确的,但作为标准(甲骨文)AES128将只接受
16字节密钥,CBC也可以工作,因为我相信它们不适用于16字节密钥。
有人能证实这一点吗*/
--然后使用AES对数据进行加密:
encrypted_result := DBMS_CRYPTO.ENCRYPT(UTL_I18N.STRING_TO_RAW('test-data', 'AL32UTF8'), encryption_type, raw_key);
--结果是二进制的(varbinary,blob)
--如果您想用十六进制字符表示,可以使用RAWTOHEX()来表示
如果直接使用十六进制字符表示的16字节散列密码短语或32个十六进制随机字符:
raw_key := HEXTORAW(32_hex_key)
encryption_type := 6 + 768 + 4096 -- (same as above in numbers; see Oracle Docum.)
raw_data := UTL_I18N.STRING_TO_RAW('test-data', 'AL32UTF8')
encrypted_result := DBMS_CRYPTO.ENCRYPT( raw_data, encryption_type, raw_key )
--ORACLE解密:
decrypted_result := UTL_I18N.RAW_TO_CHAR( CRYPTO.DECRYPT( raw_data, encryption_type, raw_key ), 'AL32UTF8' )
--在SQL中:
--####MySQL解密:
decrypted_result := UTL_I18N.RAW_TO_CHAR( CRYPTO.DECRYPT( raw_data, encryption_type, raw_key ), 'AL32UTF8' )
--MySQL的MD5函数返回一个由32个十六进制字符组成的字符串(=16字节=128位)
--它被标记为二进制字符串,但它不是人们期望的16字节二进制数据
--注意:请注意,MD5、SHA1等函数的返回类型在5.3.x之后的一些版本中发生了变化。请参阅MySQL 5.7手册
--因此,要修复它,必须使用unHex()将该字符串从十六进制转换回二进制数据:
附言:
我建议阅读MySQL 5.7手册中改进的解释,而且现在允许更多的配置。
乍一看,我怀疑问题出在这里:
'test_key',AL32UTF8'
我认为MySQL在加密之前对您的数据有不同的字符集,因此不同的数据。我怀疑加密应该是相同的,所以我会确保密钥是相同的。i、 MD5是否返回十六进制字符串或原始字节。如果是十六进制,那么情况如何?不幸的是,在安装了DBMS_CRYPTO的情况下,我无法访问Oracle。@是的,MD5哈希在两个数据库中给出了相同的结果,即8C32D1183251DF982
SELECT hex(aes_encrypt('test-data', unhex(MD5('test_key')));