I'm migrating my existing code to Python3, unfortunately the decryption shows error that IV must be 16 bytes long.
I have tried decrypting the key with sha1 then tried to decrypt.
My php5.6 code is
<?php
define('ENCR_ALGO', MCRYPT_RIJNDAEL_256);
define('ENCR_MODE', MCRYPT_MODE_CBC);
define('KEY',"This is test key");
function encryptData($plaintext){
$iv=generateIv();
$ciphertext = mcrypt_encrypt(ENCR_ALGO, getKey(), $plaintext, ENCR_MODE, $iv);
$ciphertext.=$iv;
return trim(base64_encode($ciphertext));
}
function decryptData($ciphertext){
$iv=getIvFromCiphertext($ciphertext);
$ciphertext=getActualCiphertext($ciphertext);
$plaintext = mcrypt_decrypt(ENCR_ALGO, getKey(), $ciphertext, ENCR_MODE, $iv);
return trim($plaintext);
}
function getIvFromCiphertext($encryptedData){
$encryptedData = base64_decode($encryptedData);
$cipherTextSize = strlen($encryptedData);
$ivStartIndex = $cipherTextSize-ivSize();
return substr($encryptedData, $ivStartIndex , ivSize());
}
function getActualCiphertext($encryptedData){
$encryptedData = base64_decode($encryptedData);
$cipherTextSize = strlen($encryptedData);
return substr($encryptedData, 0,$cipherTextSize-ivSize());
}
function ivSize(){
return mcrypt_get_iv_size(ENCR_ALGO, ENCR_MODE);
}
function keySize(){
return mcrypt_get_key_size(ENCR_ALGO, ENCR_MODE);
}
function generateIv(){
return mcrypt_create_iv(keySize(), MCRYPT_RAND );
}
function getKey(){
return substr(sha1(KEY), 0, keySize());
}
echo "<br/>";
echo encryptData("my pass");
echo decryptData("vuv6kZgweA2YqSU4vMOuYStrbwZayDYaL7UQ+JajFCVc2p4HW1o68OmIm2l3Rbi/IaCWtKD5m6an7LqnvwRYVA==");
?>
In my python3 file, it's like
from hashlib import sha1
import base64
from Crypto import Random
from Crypto.Cipher import AES
def actual_text(txt):
data = base64.b64decode(txt)
return data[:32], data[32:64]
passs = "vuv6kZgweA2YqSU4vMOuYStrbwZayDYaL7UQ+JajFCVc2p4HW1o68OmIm2l3Rbi/IaCWtKD5m6an7LqnvwRYVA=="
key = "This is test key"
text, iv = actual_text(passs)
class Encryptor:
def __init__(self, key):
self.key = key
def pad(self, s):
return s + b"\0" * (AES.block_size - len(s) % AES.block_size)
def encrypt(self, message, key, key_size=256):
message = self.pad(message)
iv = Random.new().read(AES.block_size)
cipher = AES.new(key, AES.MODE_CBC, iv)
return iv + cipher.encrypt(message)
def decrypt(self, ciphertext, key, iv):
# iv = ciphertext[:AES.block_size]
cipher = AES.new(key, AES.MODE_CBC, iv)
plaintext = cipher.decrypt(ciphertext[AES.block_size:])
return plaintext.rstrip(b"\0")
def make_sha1(s, encoding='utf-8'):
return sha1(s.encode(encoding)).hexdigest()
make_sha1(key, encoding='utf-8')
key2 = make_sha1(key, encoding='utf-8')[:32]
print(iv)
enc = Encryptor(key2)
enc.decrypt(text,key2,iv)
The error is showing ValueError: IV must be 16 bytes long
I've expected result is "my pass"
Related
I'm trying to write logic with Elixir and PHP to encrypt and decrypt text. My goal is to decrypt data which is encrypted in Elixir and vice versa. Both algorithms works fine, but the only problem I'm encountering is separating Initialization Vector from cipher text and conversion of binary to string in PHP and also decrypted text in Elixir.
Elixir Implementation:
defmodule Crypto.AES do
#block_size 16
#secret_key "something secret here"
def encrypt(text) do
secret_key_hash = make_hash(#secret_key, 32)
IO.inspect secret_key_hash
# create random Initialisation Vector
iv = :crypto.strong_rand_bytes(#block_size)
text = pad_pkcs7(text, #block_size)
encrypted_text = :crypto.crypto_one_time(:aes_256_cbc, secret_key_hash, iv, text, true )
encrypted_text = ( iv <> <<"::">> <> encrypted_text )
Base.encode64(encrypted_text)
end
def decrypt(ciphertext) do
secret_key_hash = make_hash(#secret_key, 32)
{:ok, ciphertext} = Base.decode64(ciphertext)
<<iv::binary-16, rp::binary-2, ciphertext::binary>> = ciphertext
decrypted_text = :crypto.crypto_one_time(:aes_256_cbc, secret_key_hash, iv, ciphertext, false)
unpad_pkcs7(decrypted_text)
end
#doc """
Pad the `message` by extending it to the nearest `blocksize` boundary,
appending the number of bytes of padding to the end of the block.
If the original `message` is a multiple of `blocksize`, an additional block
of bytes with value `blocksize` is added.
"""
def pad_pkcs7(message, blocksize) do
pad = blocksize - rem(byte_size(message), blocksize)
message <> to_string(List.duplicate(pad, pad))
end
#doc """
Remove the PKCS#7 padding from the end of `data`.
"""
def unpad_pkcs7(data) do
<<pad>> = binary_part(data, byte_size(data), -1)
binary_part(data, 0, byte_size(data) - pad)
end
def make_hash(text, length) do
:crypto.hash(:sha512, text)
|> Base.encode16
|> String.downcase
|> String.slice(0, length)
end
end
PHP Implementation:
<?php
$ENCRYPTION_KEY = 'something secret here';
$ENCRYPTION_ALGORITHM = 'AES-256-CBC';
function encrypt($plain_text) {
global $ENCRYPTION_KEY;
global $ENCRYPTION_ALGORITHM;
$EncryptionKey = make_hash($ENCRYPTION_KEY, 32);
// create random Initialisation Vector
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($ENCRYPTION_ALGORITHM));
$encrypted_text = openssl_encrypt(
$plain_text,
$ENCRYPTION_ALGORITHM,
$EncryptionKey,
0,
$iv
);
return base64_encode($encrypted_text . '::' . $iv);
}
function decrypt($ciphertext) {
global $ENCRYPTION_KEY;
global $ENCRYPTION_ALGORITHM;
$EncryptionKey = make_hash($ENCRYPTION_KEY, 32);
$split = explode('::', base64_decode($ciphertext), 2);
list($iv, $encrypted_text) = array_pad($split, 2, null);
$plain_text = openssl_decrypt(
$encrypted_text,
$ENCRYPTION_ALGORITHM,
$EncryptionKey,
0,
$iv
);
return $plain_text;
}
function make_hash($text, $length) {
$hash_key = hash("sha512", $text, false);
return substr($hash_key,0,$length);
}
$ct = encrypt("hello");
// echo $ct."\n";
echo decrypt("Sr4nMnMdDHhUQcnW6RwZ2Do6rhBh/ytW1W/x7Xx2/Xrv3A==")."\n";
?>
Please suggest some possible solutions. Thanks
The two codes are incompatible for two reasons:
The PHP code returns the ciphertext Base64 encoded by default during encryption. This must be disabled because the Base64 encoding is performed explicitly after the concatenation of IV and ciphertext. Disabling is possible by passing OPENSSL_RAW_DATA as 4th parameter in openssl_encrypt(). The same applies for decryption:
$encrypted_text = openssl_encrypt(
$plain_text,
$ENCRYPTION_ALGORITHM,
$EncryptionKey,
OPENSSL_RAW_DATA, // Fix: Don't Base64 encode the ciphertext
$iv
);
...
$plain_text = openssl_decrypt(
$encrted_text,
$ENCRYPTION_ALGORITHM,
$EncryptionKey,
OPENSSL_RAW_DATA, // Fix: Don't Base64 decode the ciphertext
$iv
);
As already noted in the comment, both codes assume a different order of IV and ciphertext when separating during decryption. Menwhile you have adapted the separation during decryption in the PHP code to that of the Elixir code.
But also for encryption, both codes use a different order of IV and ciphertext. The modification of the PHP code concerning the encryption is still missing:
...
return base64_encode($iv . '::' . $encrypted_text); // Reverse order
With these changes, the two codes are functionally identical and a ciphertext generated with the PHP code can be decrypted with the Elixir code and vice versa.
A note regarding concatenation: Both the IV and ciphertext can contain the separator :: with a certain probability, which can cause problems. It would be better to concatenate the data without a separator and use the known length of the IV for the separation.
Also, using a hash function for key derivation is insecure, better apply a reliable key derivation function like PBKDF2. Furthermore, taking the hex encoded key instead of the binary data reduces security.
With suggestions (except PBKDF2, will add later) from #Topaco, here's complete solution.
Elixir - git-link
defmodule Crypto.AES do
#block_size 16
#secret_key "put something secret here"
def encrypt(plain_text) do
secret_key_hash = make_hash(#secret_key, 32)
# create Initialisation Vector
iv = :crypto.strong_rand_bytes(#block_size)
padded_text = pad_pkcs7(plain_text, #block_size)
encrypted_text = :crypto.crypto_one_time(:aes_256_cbc, secret_key_hash, iv, padded_text, true )
# concatenate IV for decryption
encrypted_text = ( iv <> encrypted_text )
Base.encode64(encrypted_text)
end
def decrypt(ciphertext) do
secret_key_hash = make_hash(#secret_key, 32)
{:ok, ciphertext} = Base.decode64(ciphertext)
<<iv::binary-16, ciphertext::binary>> = ciphertext
decrypted_text = :crypto.crypto_one_time(:aes_256_cbc, secret_key_hash, iv, ciphertext, false)
unpad_pkcs7(decrypted_text)
end
defp pad_pkcs7(message, blocksize) do
pad = blocksize - rem(byte_size(message), blocksize)
message <> to_string(List.duplicate(pad, pad))
end
defp unpad_pkcs7(data) do
<<pad>> = binary_part(data, byte_size(data), -1)
binary_part(data, 0, byte_size(data) - pad)
end
defp make_hash(text, length) do
:crypto.hash(:sha512, text)
|> Base.encode16
|> String.downcase
|> String.slice(0, length)
end
end
PHP - gist-link
<?php
$ENCRYPTION_KEY = "put something secret here";
$ENCRYPTION_ALGORITHM = 'AES-256-CBC';
function encrypt($plain_text) {
global $ENCRYPTION_KEY;
global $ENCRYPTION_ALGORITHM;
$EncryptionKey = make_hash($ENCRYPTION_KEY, 32);
// create random Initialization Vector
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($ENCRYPTION_ALGORITHM));
$encrypted_text = openssl_encrypt(
$plain_text,
$ENCRYPTION_ALGORITHM,
$EncryptionKey,
OPENSSL_RAW_DATA,
$iv
);
# concatenate the IV for decryption
return base64_encode($iv . $encrypted_text);
}
function decrypt($ciphertext) {
global $ENCRYPTION_KEY;
global $ENCRYPTION_ALGORITHM;
$EncryptionKey = make_hash($ENCRYPTION_KEY, 32);
$ciphertext = base64_decode($ciphertext);
// get Initialization Vector part (16 bytes long)
$iv = substr($ciphertext, 0, 16);
// rest is actual cipher text
$ciphertext = substr($ciphertext, 16);
$decrypted_text = openssl_decrypt(
$ciphertext,
$ENCRYPTION_ALGORITHM,
$EncryptionKey,
OPENSSL_RAW_DATA,
$iv
);
return $decrypted_text;
}
function make_hash($text, $length) {
$hash_key = hash("sha512", $text, false);
return substr($hash_key,0,$length);
}
// $ct = encrypt("code");
// $dt = decrypt($ct);
// echo $ct."\n";
// echo $dt."\n";
?>
I'm currently implementing encryption on my API. I have to implement this the same way it is encrypted and decrypted in a specific script written in PHP.
This works all fine when I output the result in, let's say, base64. The PHP decrypt method runs against it and works just fine. The problem is that I need to output not in base64 but in binary due to certain requirements, but when I encrypt from the Nodejs side into binary the result is different than when I encrypt in the PHP into binary when it should be the same.
PHP Encryption:
function vd_encrypt($plaintext, $password) {
$method = "AES-256-CBC";
$key = hash('sha256', $password, true);
$iv = openssl_random_pseudo_bytes(16);
$ciphertext = openssl_encrypt($plaintext, $method, $key, OPENSSL_RAW_DATA, $iv);
$hash = hash_hmac('sha256', $ciphertext, $key, true);
return $iv . $hash . $ciphertext;
}
Javascript Encryption:
import crypto from 'crypto';
export function encrypt (plain_text: string): string {
const encryptionMethod = 'AES-256-CBC';
const iv = crypto.randomBytes(IV_LENGTH);
const key = crypto.createHash("sha256").update(secret).digest();
var encryptor = crypto.createCipheriv(encryptionMethod, key, iv);
const result = iv + encryptor.update(plain_text, 'utf8', 'binary') + encryptor.final('binary');
return result;
}
I've updated your code slightly to accept an iv parameter. You can generate this in the same way as before (e.g. openssl_random_pseudo_bytes).
For the purposes of demonstration I'll use a fixed IV so we can show the same result.
PHP
function vd_encrypt($plaintext, $password, $iv) {
$method = "AES-256-CBC";
$key = hash('sha256', $password, true);
$ciphertext = openssl_encrypt($plaintext, $method, $key, OPENSSL_RAW_DATA, $iv);
$hash = hash_hmac('sha256', $ciphertext, $key, true);
return $iv . $hash . $ciphertext;
}
// Replace with below code in production
// $iv = openssl_random_pseudo_bytes(16);
$iv = base64_decode("eQMrc61Gt8qRejRjhJOkVw==");
$result = vd_encrypt("He was a man take him for all in all, I shall not look upon his like again", "password", $iv);
echo "Result (base64): " . base64_encode($result) . "\n";
Node.js
import crypto from 'crypto';
export function encrypt (plaintext: string, password: string, iv: string): string {
const encryptionMethod = 'AES-256-CBC';
const key = crypto.createHash("sha256").update(password).digest();
const encryptor = crypto.createCipheriv(encryptionMethod, key, iv);
const encryptedData = Buffer.concat([encryptor.update(plaintext, 'utf8'), encryptor.final()]);
const hash = crypto.createHmac("sha256", key).update(encryptedData).digest();
return Buffer.concat([iv, hash, encryptedData]);
}
// Replace with below code in production
//const iv = crypto.randomBytes(16);
const iv = Buffer.from("eQMrc61Gt8qRejRjhJOkVw==", "base64");
const result = encrypt("He was a man take him for all in all, I shall not look upon his like again", "password", iv);
console.log("Result (base64):", result.toString("base64"));
In this case the results will be like so:
PHP:
Result (base64): eQMrc61Gt8qRejRjhJOkVxsqZTqUjSUnaL46yZDLGGK5+o7WKLyIiG4UKj0ST93Wi7UlaAyTFIjpIs0C893SFsnHeuVshG+6EJF99GrLSUCMFJG3J1pJnmxF4Pu8ZCbN7Ounp0BjhJKIpu9yQn6uEYylJLXWpzNw+aCwsnIV1h0=
Node.js:
Result (base64): eQMrc61Gt8qRejRjhJOkVxsqZTqUjSUnaL46yZDLGGK5+o7WKLyIiG4UKj0ST93Wi7UlaAyTFIjpIs0C893SFsnHeuVshG+6EJF99GrLSUCMFJG3J1pJnmxF4Pu8ZCbN7Ounp0BjhJKIpu9yQn6uEYylJLXWpzNw+aCwsnIV1h0=
I am just wondering is it possible to convert PHP encryption function to Python? I am using PHP function to encrypt USER ID and store it in Database and now I need to decrypt USER ID in Python, I using this PHP function:
function decrypt($id) {
$cryptKey = '123';
$decoded = rtrim( mcrypt_decrypt( MCRYPT_RIJNDAEL_256, md5( $cryptKey ), base64_decode( $id ), MCRYPT_MODE_CBC, md5( md5( $cryptKey ) ) ), "\0");
return( $decoded );
}
Here is your function 'translated' to python
from Crypto.Cipher import AES
from hashlib import md5
def decrypt(id):
cryptKey = '123'
cipher = AES.new(key=md5(cryptKey).hexdigest(), mode=AES.MODE_CBC, IV=md5(md5(cryptKey).hexdigest()).hexdigest()[:16])
decoded = cipher.decrypt(id.decode('base64')).rstrip('\0')
return decoded
A fiew suggestions
1. Use a random iv
2. Use a more complex key
3. Don't hardcode the key
4. Use openssl_decrypt , mcrypt_decrypt is deprecated
Note
This will not work with MCRYPT_RIJNDAEL_256 because it uses 32 byte blocks .
But you could use MCRYPT_RIJNDAEL_128 or openssl
Here is an example with openssl AES CBC in PHP :
function encrypt($data, $key) {
$method = "aes-" . strlen($key) * 8 . "-cbc";
$iv = openssl_random_pseudo_bytes(16);
$encoded = base64_encode($iv . openssl_encrypt($data, $method, $key, TRUE, $iv));
return $encoded;
}
function decrypt($data, $key) {
$method = "aes-" . strlen($key) * 8 . "-cbc";
$iv = substr(base64_decode($data), 0, 16);
$decoded = openssl_decrypt(substr(base64_decode($data), 16), $method, $key, TRUE, $iv);
return $decoded;
}
Python code :
from Crypto.Cipher import AES
from Crypto import Random
import base64
def encrypt(data, key):
pkcs7pad = lambda data: data + chr(16-(len(data)%16)).encode() * (16-(len(data)%16))
iv = Random.new().read(16)
cipher = AES.new(key=key, mode=AES.MODE_CBC, IV=iv)
encoded = base64.b64encode(iv + cipher.encrypt(pkcs7pad(data)))
return encoded
def decrypt(data, key):
pkcs7unpad = lambda data: data[:-ord(data[-1:])]
cipher = AES.new(key=key, mode=AES.MODE_CBC, IV=base64.b64decode(data)[:16])
decoded = cipher.decrypt(base64.b64decode(data)[16:])
return pkcs7unpad(decoded)
With the above functions you can encrypt in PHP - decrypt in python , and vice versa
Assuming that the key has a valid size (16, 24 or 32 bytes)
I am working on a project where PHP is used for decrypt AES-256-CBC messages
<?php
class CryptService{
private static $encryptMethod = 'AES-256-CBC';
private $key;
private $iv;
public function __construct(){
$this->key = hash('sha256', 'c7b35827805788e77e41c50df44441491098be42');
$this->iv = substr(hash('sha256', 'c09f6a9e157d253d0b2f0bcd81d338298950f246'), 0, 16);
}
public function decrypt($string){
$string = base64_decode($string);
return openssl_decrypt($string, self::$encryptMethod, $this->key, 0, $this->iv);
}
public function encrypt($string){
$output = openssl_encrypt($string, self::$encryptMethod, $this->key, 0, $this->iv);
$output = base64_encode($output);
return $output;
}
}
$a = new CryptService;
echo $a->encrypt('secret');
echo "\n";
echo $a->decrypt('S1NaeUFaUHdqc20rQWM1L2ZVMDJudz09');
echo "\n";
ouutput
>>> S1NaeUFaUHdqc20rQWM1L2ZVMDJudz09
>>> secret
Now I have to write Python 3 code for encrypting data.
I've tried use PyCrypto but without success. My code:
import base64
import hashlib
from Crypto.Cipher import AES
class AESCipher:
def __init__(self, key, iv):
self.key = hashlib.sha256(key.encode('utf-8')).digest()
self.iv = hashlib.sha256(iv.encode('utf-8')).digest()[:16]
__pad = lambda self,s: s + (AES.block_size - len(s) % AES.block_size) * chr(AES.block_size - len(s) % AES.block_size)
__unpad = lambda self,s: s[0:-ord(s[-1])]
def encrypt( self, raw ):
raw = self.__pad(raw)
cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
return base64.b64encode(cipher.encrypt(raw))
def decrypt( self, enc ):
enc = base64.b64decode(enc)
cipher = AES.new(self.key, AES.MODE_CBC, self.iv )
return self.__unpad(cipher.decrypt(enc).decode("utf-8"))
cipher = AESCipher('c7b35827805788e77e41c50df44441491098be42', 'c09f6a9e157d253d0b2f0bcd81d338298950f246')
enc_str = cipher.encrypt("secret")
print(enc_str)
output
>>> b'tnF87LsVAkzkvs+gwpCRMg=='
But I need output S1NaeUFaUHdqc20rQWM1L2ZVMDJudz09 which will PHP decrypt to secret. How to modify Python code to get expected output?
PHP's hash outputs a Hex-encoded string by default, but Python's .digest() returns bytes. You probably wanted to use .hexdigest():
def __init__(self, key, iv):
self.key = hashlib.sha256(key.encode('utf-8')).hexdigest()[:32].encode("utf-8")
self.iv = hashlib.sha256(iv.encode('utf-8')).hexdigest()[:16].encode("utf-8")
The idea of the initialization vector (IV) is to provide randomization for the encryption with the same key. If you use the same IV, an attacker may be able to deduce that you send the same message twice. This can be considered as a broken protocol.
The IV is not supposed to be secret, so you can simply send it along with the ciphertext. It is common to prepend it to the ciphertext during encryption and slice it off before decryption.
Ruby code is
require 'base64'
require 'openssl'
def ruby_dec iv, key, encrypted
decipher = OpenSSL::Cipher::AES.new(128, :CBC)
#decipher.padding = 0
decipher.decrypt
decipher.key = key
decipher.iv = iv
ciphertext = Base64.decode64 encrypted
decipher.update(ciphertext) + decipher.final
end
def ruby_enc iv, key, plaintext
enc = OpenSSL::Cipher.new 'aes-128-cbc'
enc.encrypt
enc.key = key
enc.iv = iv
Base64.encode64(enc.update(plaintext) + enc.final)
end
iv = Base64.decode64("TOB+9YNdXSbkSYIU7D/IpQ==")
key = Base64.decode64("7DxoShENB0D+8xrwOwSbi1TPQBiIaFq2yveoUkutCpM=")
plaintext = "testtesttest"
encrypted = ruby_enc iv, key, plaintext
puts "encrypted is #{encrypted}"
ruby_dec iv, key, encrypted
puts "plaintext is #{plaintext}"
then
$ ruby enc_dec.rb #the above code
encrypted is LXJmnM7t+HGKi2iI51ethA==
plaintext is testtesttest
Now PHP code is
function php_dec($iv, $key, $encrypted) {
$cipher_algorithm = 'rijndael-128';
$cipher_mode = 'cbc';
$key = base64_decode($key);
$iv = base64_decode($iv);
$ciphertext = base64_decode($enctypted);
return $ciphertext;
}
function php_enc($iv, $key, $plaintext){
$td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
$mcrypt_key = base64_decode($key);
$iv = base64_decode($iv);
mcrypt_generic_init($td, $mcrypt_key, $iv);
$ciphertext = mcrypt_generic($td, $plaintext);
retun base64_encode($ciphertext);
}
$iv = base64_decode("TOB+9YNdXSbkSYIU7D/IpQ==");
$key = base64_decode("7DxoShENB0D+8xrwOwSbi1TPQBiIaFq2yveoUkutCpM=");
$plaintext = "testtesttest";
$encrypted = php_enc($iv, $key, $plaintext);
echo "encrypted is ".$encrypted."\n";
php_dec($iv, $key, $encrypted);
echo "plaintext is ".$plaintext."\n";
$ruby_encrypted = base64_encode("LXJmnM7t+HGKi2iI51ethA==");
php_dec($iv, $key, $ruby_encrypted);
echo "plaintext is ".$plaintext."\n";
then I get
$ php enc_dec.php
encrypted is SUR33tXu32JjR9JAKIGL7w==
plaintext is testtesttest
plaintext is testtesttest
the ciphertext is different from the ruby one.
Now I try to decrypt ruby with cipher text made by PHP.
$ pry
[1] pry(main)> load 'enc_dec.rb'
[2] pry(main)> iv = Base64.decode64("TOB+9YNdXSbkSYIU7D/IpQ==")
=> "L\xE0~\xF5\x83]]&\xE4I\x82\x14\xEC?\xC8\xA5"
[3] pry(main)> key = Base64.decode64("7DxoShENB0D+8xrwOwSbi1TPQBiIaFq2yveoUkutCpM=")
=> "\xEC<hJ\x11\r\a#\xFE\xF3\x1A\xF0;\x04\x9B\x8BT\xCF#\x18\x88hZ\xB6\xCA\xF7\xA8RK\xAD\n\x93"
[4] pry(main)> ruby_dec iv, key, Base64.decode64("SUR33tXu32JjR9JAKIGL7w==")
OpenSSL::Cipher::CipherError: data not multiple of block length
from enc_dec.rb:12:in `final'
[5] pry(main)>
Is there any difference between Ruby 'AES-128-CBC' and PHP 'rijndael-128' encryption?
and how can i decrypt with ruby?
There is a difference between AES and Rijndael in the meaning of 128, in AES the 128 is the keysize, in Rijndael it is the blocksize.
The key you used is larger than 128 bits I believe.
See this article:
http://www.leaseweblabs.com/2014/02/aes-php-mcrypt-key-padding/