首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >DES3加密: ruby::密码与甲骨文dbms_obfuscation_toolkit

DES3加密: ruby::密码与甲骨文dbms_obfuscation_toolkit
EN

Stack Overflow用户
提问于 2013-10-31 23:00:19
回答 2查看 1.4K关注 0票数 2

我有一个用PL/SQL编写的遗留应用程序,它使用3 3DES加密和解密数据。现在,我需要执行类似的加密从红宝石应用程序。最终,生成的哈希将需要由同一个PL/SQL应用程序使用其现有算法进行解密。

问题是,我在PL/SQL和Ruby中获得了不同的加密结果,我不知道为什么。

首先,是PL/SQL加密的具体工作方式:

来自甲骨文关于DBMS_OBFUSCATION_TOOLKIT obtool.htm的文档

Oracle对3 3DES的实现支持2键或3键的实现,采用外部密码-分组链接(CBC)模式。

功能签名:

代码语言:javascript
复制
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。“这帮助我选择了红宝石版本的密码。

下面是应用程序如何进行调用:

代码语言:javascript
复制
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”。

代码语言:javascript
复制
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版本计算一个不同的散列值。为什么?需要改变什么才能使它们保持一致?

我不确定的几点:

  • 实际上,是否与Oracle一样。
  • utl_raw.cast_to_raw和unpack("H*")是否会对加密的二进制数据做同样的事情。
  • cipher.final到底附加了什么,以及是否有任何类似的方法在PL/SQL中追加数据。

注意:我知道DES是不安全的,AES已经取代了它。我的用例不要求这些散列是不可破解的。重要的要求是使散列保持一致,以便PL/SQL应用程序可以解密由ruby应用程序生成的散列。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-10-31 23:40:03

我们去挖吧!

代码语言:javascript
复制
['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

结果:

代码语言:javascript
复制
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 short

des-ede-cbc给你一个匹配--至少第一部分匹配。问题是,为什么加密的身体更长?我打赌这是正确的内容,PL/SQL版本被截断了--我会看看是否能找到答案。

编辑:不,是填充。当您在密码上将填充设置为0时,您将得到与PL/SQL版本相同的结果。

代码语言:javascript
复制
['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

票数 2
EN

Stack Overflow用户

发布于 2016-04-26 08:32:44

我们的一个重要区别也有同样的问题:我们的数据库过程在加密密码时没有指定初始化向量(IV)。在ruby中省略IV并不会导致与在Oracle过程调用中忽略它的结果相同,因此两者似乎都使用了不同的“默认”IVs。

默认的Oracle是“0123456789abc hex”十六进制解码,一些人在这里指出:https://community.oracle.com/thread/1528090

在Ruby中,您可以这样设置它:

代码语言:javascript
复制
['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
end
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19718060

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档