2

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:] ))
2
  • i think it's really not that simple of a question to the everyday ruby user. Maybe it's easier to delegate the encryption / decryption to the underlying system (i.e. run shell commands). That way both Ruby and Python can use the same API. Commented Jun 15, 2016 at 4:40
  • The answer was updated and should fully answer your question. Commented Jun 15, 2016 at 19:11

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

Comments

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.