4

I'm trying to encrypt then base64_encode a string using Python, and base64_decode then decrypt the result with Ruby, but the string is messed up.

I don't see any difference in the two methods. I tried using the 128-bit AES-CFB algorithm, but had no success.

Here's my Python code:

from Crypto.Cipher import AES
from Crypto.Util.randpool import RandomPool
from base64 import standard_b64encode, standard_b64decode

key = "abcdefghijklmnop"
en = AES.new(key, AES.MODE_CFB, "0000000000000000")
cipher = en.encrypt("apple")
cipher64 = standard_b64encode(cipher)

cipher64 contains: WqF9Zj0=

My Ruby code is:

require "openssl"
require 'digest/sha2'
require 'base64'


de = OpenSSL::Cipher::Cipher.new("aes-128-cfb")
de.decrypt
de.key = "abcdefghijklmnop"
de.iv = "0000000000000000"
plain = de.update("WqF9Zj0=".unpack('m')[0])
de.final
puts plain

plain contains a different string than "apple". I get the same result if my string's length is 16, to avoid a padding problem.

I guess it's a parameter problem, but I can't figure out what. Does anyone have an idea?

1 Answer 1

1

PyCrypto uses a different segment_size

When encoding, specify segment_size, and pad the plain text.

from base64 import standard_b64encode

from Crypto.Cipher import AES

def pad(x, n=16):
    p = n - (len(x) % n)
    return x + chr(p) * p

key = "abcdefghijklmnop"
en = AES.new(key=key, mode=AES.MODE_CFB, IV="0" * 16, segment_size=128)
cipher = en.encrypt(pad("apple"))
cipher64 = standard_b64encode(cipher)
print cipher64

Using the above code, you will get apple\x03\x03\x03. On the Ruby side, you should remove the padding.

Ruby part (decoding):

require "openssl"

de = OpenSSL::Cipher::Cipher.new("aes-128-cfb")
de.decrypt
de.key = "abcdefghijklmnop"
de.iv = "0000000000000000"
plain = de.update(ARGV[0].unpack('m')[0]) + de.final
plain = plain[0...-plain[-1].ord]
puts plain

Alternatively, you can use M2Crypto, which has no need to remove the padding on the Ruby side:

from base64 import standard_b64encode

import M2Crypto.EVP

key = "abcdefghijklmnop"
iv = "0000000000000000"
en = M2Crypto.EVP.Cipher('aes_128_cfb', key, iv, 1)
cipher = en.update('apple') + en.final()
cipher64 = standard_b64encode(cipher)
print cipher64
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks, but i still have problem if the input apple string is longer than 8 characters. On python side i' ve: from Crypto.Cipher import AES en = AES.new(key, AES.MODE_CFB, "0000000000000000", segment_size = 64) cipher = en.encrypt(pad(sys.argv[1])) and on ruby side i' ve: require "openssl" decryptobj = OpenSSL::Cipher::Cipher.new("AES-256-CFB") . Unfortunately M2Crypto is not reachable in my case.
Ah, found the solution finally: i need to use segment_size = 128 by encoding and 16 byte long padding as well :- ).
@user2194805, I fixed that. I also added ruby code that strip padding.
Note for future users - this answer almost tripped me up. The segment size is ONLY an issue in CFB mode.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.