Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby OpenSSL::Cipher在CBC模式下给出不同结果的三重DES_Ruby_Sinatra - Fatal编程技术网

Ruby OpenSSL::Cipher在CBC模式下给出不同结果的三重DES

Ruby OpenSSL::Cipher在CBC模式下给出不同结果的三重DES,ruby,sinatra,Ruby,Sinatra,我需要在CBC模式下使用双倍长度三重DES(TDEA)对称密钥加密数据。我正在使用Ruby OpenSSl::Cipher。但与BP工具密码计算器和EMV DES计算器相比,它给出了不同的结果。下面是我的代码 有人能帮我解释为什么我的结果不同吗?我有在线检查工具来验证我的结果 它给出了与BP工具相同的结果 flavour = 'des-ede3-cbc' # key and input text are in hexadecimal key = "2315208C9110AD4023152

我需要在CBC模式下使用双倍长度三重DES(TDEA)对称密钥加密数据。我正在使用Ruby OpenSSl::Cipher。但与BP工具密码计算器和EMV DES计算器相比,它给出了不同的结果。下面是我的代码

有人能帮我解释为什么我的结果不同吗?我有在线检查工具来验证我的结果

它给出了与BP工具相同的结果

flavour = 'des-ede3-cbc'
# key and input text are in hexadecimal  
key = "2315208C9110AD402315208C9110AD40"
iv = "0000000000000000"
input_text = "2020205a4f534135366461746574696d653d32303138313032343130303332333b6578706972793d313232323b70616e3d343233363031373839303132333435362121212121212121"
begin
  c = OpenSSL::Cipher.new flavour
  c.encrypt
  c.key = key
  c.iv = iv
  str = input_text
  enc = c.update(str) + c.final
  puts "#{flavour} gives us #{enc.unpack('H*').first.upcase}"
rescue => e
    puts "#{flavour} didn't work because #{e.message}"
end

为了获得预期的结果,您需要调整代码,以便OpenSSL实际知道您正在使用十六进制编码的数据。由于OpenSSL处理普通字节,因此需要首先将十六进制字符串编码为原始字节:

key = ["2315208C9110AD402315208C9110AD40"].pack('H*')
iv = ["0000000000000000"].pack('H*')
input_text = ["2020205a4f534135366461746574696d653d32303138313032343130303332333b6578706972793d313232323b70616e3d343233363031373839303132333435362121212121212121"].pack('H*')
之后,您需要选择正确的加密算法。3DE有多种不同的口味,其中(除其他细节外)在预期的键长上有所不同。由于您正在处理一个16字节的密钥,因此您似乎正在使用OpenSSL调用的
des ede cbc

flavour = 'des-ede-cbc'
这些调整通常足以导致与您在链接的网站上看到的结果相同的结果。但是,由于我不知道的原因,他们在实际加密输入数据之前会默默地更改输入数据

我不知道他们使用的具体规则,但要获得与网站相同的密文输出,您需要删除任何尾随感叹号,并从输入字符串中删除前导空格字符

input_text # packed as you provided it originally
# => "   ZOSA56datetime=20181024100323;expiry=1222;pan=4236017890123456!!!!!!!!"

# remove trailing exclamation marks
input_text = input_text.sub(/!*$/, '') 
# remove the first character
input_text = input_text[1..-1]
最后,您现在可以对“改进的”
输入文本进行加密:

begin
  c = OpenSSL::Cipher.new(flavour)
  c.encrypt
  c.key = key
  c.iv = iv
  enc = c.update(input_text) + c.final
  puts "#{flavour} gives us #{enc.unpack('H*').first.upcase}"
rescue => e
  puts "#{flavour} didn't work because #{e.message}"
end
这将产生几乎预期的密码文本

不过,在最后一个8字节的块中,它只是略有不同。我假设该网站使用了一些奇怪的非标准填充(这是确保输入文本可以划分为完整的8字节块所必需的),这导致最终的块不同

在任何情况下,您都可以使用以下代码解密结果(以及网站上的“预期”密文):

flavour = 'des-ede-cbc'
key = ["2315208C9110AD402315208C9110AD40"].pack('H*')
iv = ["0000000000000000"].pack('H*')
encrypted = ["4A9E9B245BBDC16D76998143CB6FC1C2B8780539C1C9A100AEC3D745B8BF00DF43A4B51A29A6205845E510E18E26AB940152F90F12E86543A9E5239B30DFDBCD8D3FCDB65F603979"].pack('H*')

c = OpenSSL::Cipher.new(flavour)
c.decrypt
c.key = key
c.iv = iv

decrypted = c.update(encrypted)
如何获得正确的填充以匹配来自网站的结果将留给读者作为练习:)不幸的是,我没有找到任何文档或他们工具的源代码

在任何情况下,请注意3DES是一种非常过时的加密算法,不再被认为是安全的。除非您必须实际使用3DES,否则您应该使用更安全的算法


libnaude项目提供了加密和签名安全算法的强化实现,可以为您所需的协议提供有效和安全的基础。gem提供了Ruby绑定。

c.key=key
返回
ArgumentError:key必须是24个字节
。请提供一个有效的例子。
flavour = 'des-ede-cbc'
key = ["2315208C9110AD402315208C9110AD40"].pack('H*')
iv = ["0000000000000000"].pack('H*')
encrypted = ["4A9E9B245BBDC16D76998143CB6FC1C2B8780539C1C9A100AEC3D745B8BF00DF43A4B51A29A6205845E510E18E26AB940152F90F12E86543A9E5239B30DFDBCD8D3FCDB65F603979"].pack('H*')

c = OpenSSL::Cipher.new(flavour)
c.decrypt
c.key = key
c.iv = iv

decrypted = c.update(encrypted)