我有一个用PL/SQL编写的遗留应用程序,它使用3 3DES加密和解密数据。现在,我需要执行类似的加密从红宝石应用程序。最终,生成的哈希将需要由同一个PL/SQL应用程序使用其现有算法进行解密。
问题是,我在PL/SQL和Ruby中获得了不同的加密结果,我不知道为什么。
首先,是PL/SQL加密的具体工作方式:
来自甲骨文关于DBMS_OBFUSCATION_TOOLKIT obtool.htm的文档
Oracle对3 3DES的实现支持2键或3键的实现,采用外部密码-分组链接(CBC)模式。
功能签名:
DBMS_OBFUSCATION_TOOLKIT.DES3Encrypt(
input_string IN VARCHAR2,
key_string IN VARCHAR2,
encrypted_string OUT VARCHAR2,
which IN PLS_INTEGER DEFAULT TwoKeyMode
iv_string IN VARCHAR2 DEFAULT NULL);注意参数:"If = 0,(默认),然后使用TwoKeyMode,If = 1,则使用ThreeKeyMode。“这帮助我选择了红宝石版本的密码。
下面是应用程序如何进行调用:
set serveroutput on;
declare
v_encrypted varchar2(100);
begin
dbms_obfuscation_toolkit.des3encrypt(
input_string => 'abcdefgh', -- data to encrypt
key_string => '16_byte_string_k', -- 16 byte = 128 bit key needed by DES3Encrypt
encrypted_string => v_encrypted,
iv_string => 'xxxxxxxx'); -- initialization vector
dbms_output.put_line( lower(utl_raw.cast_to_raw(v_encrypted)) );
-- prints 23ff779e88e2dbe1
end;第二,这是我正在尝试的Ruby:
OpenSSL::密码文档:http://www.ruby-doc.org/stdlib-1.9.3/libdoc/openssl/rdoc/OpenSSL/Cipher.html
OpenSSL文档给我的密码名:http://www.openssl.org/docs/apps/enc.html“DES在CBC模式下的两个关键的三重DES”。
require 'openssl'
cipher = OpenSSL::Cipher.new('des-ede-cbc')
cipher.encrypt
input = 'abcdefgh'
cipher.key = '16_byte_string_k'
cipher.iv = 'xxxxxxxx'
# i noticed that cipher.update returns same length hash as PL/SQL
# if called without cipher.final, but you are not supposed to do that
#encrypted = cipher.update(input)
encrypted = cipher.update(input) + cipher.final
hex_representation = encrypted.unpack("H*")
puts hex_representation
# prints a5cfc96485d7203eb929c28ceb9fcd53如代码所示,ruby版本计算一个不同的散列值。为什么?需要改变什么才能使它们保持一致?
我不确定的几点:
注意:我知道DES是不安全的,AES已经取代了它。我的用例不要求这些散列是不可破解的。重要的要求是使散列保持一致,以便PL/SQL应用程序可以解密由ruby应用程序生成的散列。
发布于 2013-10-31 23:40:03
我们去挖吧!
['des-cbc', 'des', 'des-cfb', 'des-ofb', 'des-ecb',
'des-ede-cbc', 'des-ede', 'des-ede-cfb', 'des-ede-ofb',
'des-ede3-cbc', 'des-ede3', 'des3', 'des-ede3-cfb',
'des-ede3-ofb', 'desx'].each do |flavour|
begin
c = OpenSSL::Cipher.new flavour
c.encrypt
c.key = '16_byte_string_k'
c.iv = 'xxxxxxxx'
str = 'abcdefgh'
enc = c.update(str) + c.final
puts "#{flavour} gives us #{enc.unpack('H*')}"
rescue => e
puts "#{flavour} didn't work because #{e.message}"
end
end结果:
des-cbc gives us ["a5cfc96485d7203eb929c28ceb9fcd53"]
des gives us ["a5cfc96485d7203eb929c28ceb9fcd53"]
des-cfb gives us ["d898369e91589ae8"]
des-ofb gives us ["d898369e91589ae8"]
des-ecb gives us ["de8579b342a528b6143594946045d91a"]
des-ede-cbc gives us ["23ff779e88e2dbe1c009dc3105d8ff88"]
des-ede gives us ["0e589e3d85ac83efbb271a2e4a77cf4e"]
des-ede-cfb gives us ["1618988004b6a948"]
des-ede-ofb gives us ["1618988004b6a948"]
des-ede3-cbc didn't work because key length too short
des-ede3 didn't work because key length too short
des3 didn't work because key length too short
des-ede3-cfb didn't work because key length too short
des-ede3-ofb didn't work because key length too short
desx didn't work because key length too shortdes-ede-cbc给你一个匹配--至少第一部分匹配。问题是,为什么加密的身体更长?我打赌这是正确的内容,PL/SQL版本被截断了--我会看看是否能找到答案。
编辑:不,是填充。当您在密码上将填充设置为0时,您将得到与PL/SQL版本相同的结果。
['des-cbc', 'des', 'des-cfb', 'des-ofb', 'des-ecb',
'des-ede-cbc', 'des-ede', 'des-ede-cfb', 'des-ede-ofb',
'des-ede3-cbc', 'des-ede3', 'des3', 'des-ede3-cfb',
'des-ede3-ofb', 'desx'].each do |flavour|
begin
c = OpenSSL::Cipher.new flavour
c.encrypt
c.key = '16_byte_string_k'
c.iv = 'xxxxxxxx'
c.padding = 0 # This is the important part!
str = 'abcdefgh'
enc = c.update(str) + c.final
puts "#{flavour} gives us #{enc.unpack('H*')}"
rescue => e
puts "#{flavour} didn't work because #{e.message}"
end
end
...
des-ede-cbc gives us ["23ff779e88e2dbe1"]
...现在您需要用不同长度的输入字符串来比较这两种算法。在这里查看填充方法的文档:http://www.ruby-doc.org/stdlib-2.0.0/libdoc/openssl/rdoc/OpenSSL/Cipher.html
发布于 2016-04-26 08:32:44
我们的一个重要区别也有同样的问题:我们的数据库过程在加密密码时没有指定初始化向量(IV)。在ruby中省略IV并不会导致与在Oracle过程调用中忽略它的结果相同,因此两者似乎都使用了不同的“默认”IVs。
默认的Oracle是“0123456789abc hex”十六进制解码,一些人在这里指出:https://community.oracle.com/thread/1528090
在Ruby中,您可以这样设置它:
['des-cbc', 'des', 'des-cfb', 'des-ofb', 'des-ecb',
'des-ede-cbc', 'des-ede', 'des-ede-cfb', 'des-ede-ofb',
'des-ede3-cbc', 'des-ede3', 'des3', 'des-ede3-cfb',
'des-ede3-ofb', 'desx'].each do |flavour|
begin
c = OpenSSL::Cipher.new flavour
c.encrypt
c.key = '16_byte_string_k'
c.iv = ['0123456789abcdef'].pack('H*') # Required if no IV is set in Oracle!
c.padding = 0
str = 'abcdefgh'
enc = c.update(str) + c.final
puts "#{flavour} gives us #{enc.unpack('H*')}"
rescue => e
puts "#{flavour} didn't work because #{e.message}"
end
endhttps://stackoverflow.com/questions/19718060
复制相似问题