Reputation: 4050
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
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