feng ce feng ce - 1 month ago 8
Ruby Question

In ruby, how to do a DES encryption with PKCS5 padding

I am trying to convert some Python code into Ruby. Here is a snippet of the Python code:

# -*- coding: UTF-8 -*-
import pyDes
import base64
des3Key = '1234567887654321'
iv = des3Key[0:8]
data = r'abc'
k = pyDes.triple_des(des3Key,pyDes.CBC,iv,pad=None,padmode=pyDes.PAD_PKCS5)
d = k.encrypt(data)
print base64.b64encode(d)
#q8qN6El3X8A=


My Ruby code:

require 'digest'
require 'openssl'
require 'base64'

data = 'abc'

key = '1234567887654321'
iv = key[0..7]
# cipher = OpenSSL::Cipher::Cipher.new('DES-EDE3')
cipher = OpenSSL::Cipher::Cipher.new('DES-EDE3-CBC') # or any other algorithm?

cipher.encrypt
cipher.pkcs5_keyivgen(key, iv)
output = cipher.update(data)
output << cipher.final
p Base64.encode64(output).gsub(/\n/, "")
# y7TPhjBQO78=


The ruby result not equal python's .Which algorithm should I choose?

Answer Source

There are two issues here. First, don’t use pkcs5_keyivgen, this is an old and deprecated function for deriving a key nad iv from a password. You need to set these directly on the Cipher object:

cipher.key = key
cipher.iv = iv

Second, in your Python code the key is 16 bytes, which means you are using two key (or keying option 2) triple DES. The Python code automatically determines which to use depending on the length of the key used. In the Ruby OpenSSL bindings you need to explicitly specify which to use. des-ede3-cbc is three key (or keying option 1). You need to use des-ede-cbc as the cipher name:

cipher = OpenSSL::Cipher.new('des-ede-cbc')