user2694306
user2694306

Reputation: 4050

Encrypt String In Ruby and Decrypt in Python

I am brand new to Ruby, so I apologize if this question is simple. I have to update a rails app so that it encrypts a string using a key. This is passed to an api written in django, where the encrypted string will be decrypted using the same key. I have the following code in Python, but I'm not sure how to encrypt the associated message in Ruby. Any help would be appreciated.

import base64
from Crypto.Cipher import AES
from Crypto import Random

class AESCipher:
    def __init__( self, key ):
        self.key = key

    def encrypt( self, raw ):
        raw = pad(raw)
        iv = Random.new().read( AES.block_size )
        cipher = AES.new( self.key, AES.MODE_CBC, iv )
        return base64.b64encode( iv + cipher.encrypt( raw ) ) 

    def decrypt( self, enc ):
        enc = base64.b64decode(enc)
        iv = enc[:16]
        cipher = AES.new(self.key, AES.MODE_CBC, iv )
        return unpad(cipher.decrypt( enc[16:] ))

Upvotes: 1

Views: 1541

Answers (1)

Pascal
Pascal

Reputation: 8646

After feedback by ArtjomB I looked deeper into the proposed library. It is nothing but a thin wrapper around ruby openssl. So you can write a ruby version of your AESCipher on your own. It took some fiddling and research to find the right way:

require 'base64'
require 'securerandom'
require 'openssl'

class AESCipher
  attr_reader :key

  def initialize(key)
    @key = key
  end

  def encrypt(raw)
    iv = SecureRandom.random_bytes(16)
    cipher = build_encription_cipher(iv)
    encrypted = cipher.update(raw) + cipher.final
    Base64.encode64(iv + encrypted)
  end

  def decrypt(data)
    data = Base64.decode64(data)
    iv, raw = data[0..15], data[16..-1]
    cipher = build_decrypt_cipher(iv)
    cipher.update(raw) + cipher.final
  end

  private

  def build_encription_cipher(iv)
    OpenSSL::Cipher::AES.new(128, :CBC).tap do |cipher|
      cipher.encrypt
      cipher.key = key
      cipher.iv = iv
      cipher.padding = 0
    end
  end

  def build_decrypt_cipher(iv)
    OpenSSL::Cipher::AES.new(128, :CBC).tap do |cipher|
      cipher.decrypt
      cipher.key = key
      cipher.iv = iv
      cipher.padding = 0
    end
  end
end

In my testcases the ruby version decrypted strings encrypted by python and vice versa.

(i did one modification to your python code: remove the call to pad as I don't know HOW it pads. And just used strings that are length multiple of 16).

The answer by colinm in AES Python encryption and Ruby encryption - different behaviour? was very useful.

Upvotes: 2

Related Questions