DES3加密:ruby openssl :: cipher与oracle dbms_obfuscation_toolkit [英] DES3 encryption: ruby openssl::cipher vs. oracle dbms_obfuscation_toolkit

查看:625
本文介绍了DES3加密:ruby openssl :: cipher与oracle dbms_obfuscation_toolkit的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



问题是我正在使用PL / SQL和Ruby,我不知道为什么。



首先这里是PL / SQL加密的工作原理:



从Oracle关于DBMS_OBFUSCATION_TOOLKIT的文档 http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_obtool.htm



Oracle的3DES实现支持2密钥或3密钥实现,在外部加密块链接(CBC)模式。



功能签名:

  DBMS_OBFUSCATION_TOOLKIT.DES3Encrypt(
input_string IN VARCHAR2,
key_string IN VARCHAR2,
encrypted_string OUT VARCHAR2,
IN PLS_INTEGER DEFAULT TwoKeyMode
iv_string IN VARCHAR2 DEFAULT NULL);

注意参数:
If = 0,(默认),然后TwoKeyMode如果= 1,则使用ThreeKeyMode。
这有助于我在ruby版本中选择密码。



这是应用程序如何进行该调用:

 设置serveroutput; 
声明
v_encrypted varchar2(100);
begin
dbms_obfuscation_toolkit.des3encrypt(
input_string =>'abcdefgh', - 要加密的数据
key_string =>'16_byte_string_k', - 16字节= 128位密钥需要DES3Encrypt
encrypted_string => v_encrypted,
iv_string =>'xxxxxxxx'); - 初始化向量
dbms_output.put_line(lower(utl_raw.cast_to_raw(v_encrypted)));
- 打印23ff779e88e2dbe1
结束;

其次是Ruby在Ruby中的尝试:



OpenSSL :: Cipher文档:
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-ede-cbc CBC模式下的两个三重DES EDE

  require'openssl'

cipher = OpenSSL :: Cipher.new('des-ede-cbc')
cipher.encrypt
input ='abcdefgh'
cipher.key ='16_byte_string_k'
cipher.iv ='xxxxxxxx'

#我注意到cipher.update返回与PL / SQL
#相同长度的哈希值,如果调用无cipher.final,但您不应该这样做
#encrypted = cipher.update(input)
encrypted = $($)

放入hex_representation
#打印a5cfc96485d7203eb929c28ceb9fcd53

如代码所示,ruby版本会计算不同的哈希值。为什么?有什么需要改变以使它们保持一致?



积分我不确定:




    是否des-ede-cbc实际上与Oracle所做的一样。
  • utl_raw.cast_to_raw和unpack(H *)将执行相同的操作
    加密的二进制数据。

  • 什么是cipher.final附加,如果有任何等价的
    方式将该数据附加到PL / SQL。



注意:我知道DES是不安全的,AES已经取代了它。我的使用案例不需要这些哈希即可。重要的要求是使哈希值保持一致,以便PL / SQL应用程序可以解密由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']。
begin
c = OpenSSL :: Cipher.new flavor
c.encrypt
c.key ='16_byte_string_k'
c.iv ='xxxxxxxx'
str ='abcdefgh'
enc = c.update(str)+ c.final
puts#{flavor}给我们#{enc.unpack('H *')}
rescue => e
put#{flavor}没有工作,因为#{e.message}
end
end

结果:

  des-cbc给我们[a5cfc96485d7203eb929c28ceb9fcd53] 
des给我们[a5cfc96485d7203eb929c28ceb9fcd53]
des-cfb给我们[d898369e91589ae8]
des-ofb给我们[d898369e91589ae8]
des-ecb给我们[ de8579b342a528b6143594946045d91a]
des-ede-cbc给我们[23ff779e88e2dbe1c009dc3105d8ff88]
des-ede给我们[0e589e3d85ac83efbb271a2e4a77cf4e]
des-ede-cfb给我们[1618988004b6a948]
des-ede-ofb给了我们[1618988004b6a948]
des-ede3-cbc没有工作,因为密钥长度太短
des-ede3没有工作,因为密钥长度太短
des3没有工作,因为密钥长度太短
des-ede3-cfb没有工作,因为密钥长度太短
des-ede3-ofb没有工作,因为密钥长度太短
desx没有工作,因为密钥长度太短

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



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

  [' des-cbc','des','des-cfb','des-ofb','des-ecb',
'des-ede-cbc','des-ede' cfb','des-ede-ofb',
'des-ede3-cbc','des-ede3','des3','des-ede3-cfb',
'des-ede3- ofb','desx']
begin
c = OpenSSL :: Cipher.new flavor
c.encrypt
c.key ='16_byte_string_k'
c.iv ='xxxxxxxx'
c.padding = 0#这是重要的部分!
str ='abcdefgh'
enc = c.update(str)+ c.final
puts#{flavor}给我们#{enc.unpack('H *')}
rescue => e
put#{flavor}没有工作,因为#{e.message}
end
end

...
des- ede-cbc给我们[23ff779e88e2dbe1]
...

你将需要现在比较不同长度的输入字符串的两种算法。请查看填充方法的文档: http://www.ruby-doc.org/stdlib-2.0.0/libdoc/openssl/rdoc/OpenSSL/Cipher.html


I have a legacy application written in PL/SQL that encrypts and decrypts data using 3DES. Now I need to perform similar encryption from a ruby app. Eventually the resulting hash will need to be decrypted by the same PL/SQL application using its existing algorithm.

The problem is that I'm obtaining different encrypted results in PL/SQL and Ruby and I don't know why.

First here is exactly how the PL/SQL encryption works:

From Oracle's docs about DBMS_OBFUSCATION_TOOLKIT http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_obtool.htm

"Oracle's implementation of 3DES supports either a 2-key or 3-key implementation, in outer cipher-block-chaining (CBC) mode."

Function signature:

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);

Note about the parameter which: "If = 0, (default), then TwoKeyMode is used. If = 1, then ThreeKeyMode is used." This helped me choose the cipher in the ruby version.

Here is how the application makes that call:

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;

Second here is what I'm trying in Ruby:

OpenSSL::Cipher docs: http://www.ruby-doc.org/stdlib-1.9.3/libdoc/openssl/rdoc/OpenSSL/Cipher.html

OpenSSL docs to give me the cipher name: From http://www.openssl.org/docs/apps/enc.html "des-ede-cbc Two key triple DES EDE in CBC mode"

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

As shown in the code the ruby version computes a different hash value. Why? What needs to change to make them consistent?

Points I'm unsure about:

  • Whether des-ede-cbc is in fact the same as what Oracle does.
  • Whether utl_raw.cast_to_raw and unpack("H*") will do the same thing to the encrypted binary data.
  • What exactly cipher.final appends and if there's any equivalent way to append that data in PL/SQL.

Note: I am aware that DES is insecure and that AES has superseded it. My use case does not require these hashes to be unbreakable. The important requirement is to make the hashes consistent so that the PL/SQL app can decrypt hashes generated by the ruby app.

解决方案

Let's go digging!

['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

The results:

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 gives you a match--at least the first part matches. The question is, why is the encrypted body longer? I'm going to bet this is the correct content and the PL/SQL version is truncated somehow--I'll see if I can figure it out.

Edit: nope, it's the padding. When you set the padding to 0 on the cipher, you get the same results as the PL/SQL version, e.g.

['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"]
...

You will need to compare the two algorithms with different lengths of input string now. Take a look at the documentation for the padding method here: http://www.ruby-doc.org/stdlib-2.0.0/libdoc/openssl/rdoc/OpenSSL/Cipher.html

这篇关于DES3加密:ruby openssl :: cipher与oracle dbms_obfuscation_toolkit的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆