I am trying to encrypt data in java and decrypt data in ruby.
I found almost same asks, but my case is little bit different.
Encrypt in Ruby and Decrypt in Java - Why is it not working?
AES/CBC encrypt in Java, decrypt in Ruby
My code is ...
Encrypt in java
import java.util.HashMap;
import java.util.Map;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import net.sf.json.JSONObject;
import org.apache.commons.codec.binary.Hex;
class Crypt {
public static void main(String[] args) throws Exception {
Map<String, String> node = new HashMap<String, String>();
node.put("timestamp", "1377499097199");
JSONObject jsonObject = JSONObject.fromObject(node);
String json = jsonObject.toString();
System.out.println(json);
//key
String skeyString = "97128424897797a166913557a6f4cc8e";
byte[] skey = Hex.decodeHex(skeyString.toCharArray());
System.out.println("key : " + skeyString);
//iv
String ivString = "84e8c3ea8859a0e293941d1cb00a39c3";
byte[] iv = Hex.decodeHex(ivString.toCharArray());
System.out.println("iv : " + ivString);
//encrypt
SecretKeySpec skeySpec1 = new SecretKeySpec(skey, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec1, new IvParameterSpec(iv));
byte[] encrypted = cipher.doFinal(json.getBytes());
String encryptedString = Hex.encodeHexString(encrypted);
System.out.println("=============>");
System.out.println("encrypted string: " + encryptedString);
}
}
Result is
{"timestamp":"1377499097199"}
key : 97128424897797a166913557a6f4cc8e
iv : 84e8c3ea8859a0e293941d1cb00a39c3
=============>
encrypted string: 395f6c0e8ad27f57c4a5a8975aa633e5b26f288d37ce18c6971779951f3b3527
and I hope to decrypt (encrypted string) in Ruby
Ruby code is ...(got error)
require 'openssl'
key = "97128424897797a166913557a6f4cc8e"
iv = "84e8c3ea8859a0e293941d1cb00a39c3"
encrypted_string = "395f6c0e8ad27f57c4a5a8975aa633e5b26f288d37ce18c6971779951f3b3527"
de_cipher = OpenSSL::Cipher::Cipher.new("AES-256-CBC")
de_cipher.decrypt
de_cipher.key = key
de_cipher.iv = iv
de_cipher.update(encrypted_string) << de_cipher.final
I expected to get
{"timestamp":"1377499097199"}
But it returns error
`final': bad decrypt (OpenSSL::Cipher::CipherError)
I think the problem is cipher.padding and type of key/iv.
But I don't know exactly how to complete ruby code.
Please let me know How to complete this code.
Thank you.
There's two problems with your Ruby code.
First, you're using AES 256 when you should be using AES 128. Java uses AES 128 or 256 based on the size of the key you use, and you're using a 128 bit key.
Second, you need to Hex decode your key, iv, and encrypted_string values in Ruby. OpenSSL Cipher is expecting binary, not hex strings.
require 'openssl';
key = "97128424897797a166913557a6f4cc8e";
iv = "84e8c3ea8859a0e293941d1cb00a39c3";
encrypted_string = "395f6c0e8ad27f57c4a5a8975aa633e5b26f288d37ce18c6971779951f3b3527";
de_cipher = OpenSSL::Cipher::Cipher.new("AES-128-CBC");
de_cipher.decrypt;
de_cipher.key = [key].pack('H*');
de_cipher.iv = [iv].pack('H*');
puts de_cipher.update([encrypted_string].pack('H*')) << de_cipher.final;
Output:
{"timestamp":"1377499097199"}
Related
I am not a security expert.
I have a requirement to generate javax.crypto.SecretKey based on password and salt.
In the existing code, we already have logic to generate javax.crypto.SecretKey but not based on password and salt`.
Also, in the existing code we already encrypt and decrypt using the javax.crypto.SecretKey.
There is already lot of data in DB which is encrypted using existing encrypt code and I dont think I can change existing encrypt and decrypt logic.
I am getting below the error when I try to decrypt data using the key generated based on password and salt with existing decrypt code.
key.getAlgorithm(): DESede
encryptedData: [B#31dc339b
Exception in thread "main" javax.crypto.BadPaddingException: Given final block not properly padded. Such issues can arise if a bad key is used during decryption.
at com.sun.crypto.provider.CipherCore.unpad(CipherCore.java:975)
at com.sun.crypto.provider.CipherCore.fillOutputBuffer(CipherCore.java:1056)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:853)
at com.sun.crypto.provider.DESedeCipher.engineDoFinal(DESedeCipher.java:294)
at javax.crypto.Cipher.doFinal(Cipher.java:2168)
at com.arjun.mytest.PMAdminKeyTest.main(PMAdminKeyTest.java:41)
import java.security.KeyStore;
import java.security.Provider;
import java.security.spec.KeySpec;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
public class PMAdminKeyTest {
public static void main(String[] args) throws Exception {
// Requirement is to generate Key based on password and salt
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
KeySpec keySpec = new PBEKeySpec("password".toCharArray(), "salt".getBytes(), 65536, 192);
SecretKey key = new SecretKeySpec(secretKeyFactory.generateSecret(keySpec).getEncoded(), "DESede");
System.out.println("key.getAlgorithm(): " + key.getAlgorithm());
byte[] data = "12345678".getBytes("UTF8");
// Existing encrypt and decrypt code. There is already lot of data in DB
// encrypted in this manner. I dont think I can change this code.
Cipher cipher = Cipher.getInstance(key.getAlgorithm() + "/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encryptedData = cipher.doFinal(data);
System.out.println("encryptedData: " + encryptedData.toString());
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] decryptedData = cipher.doFinal(data);
System.out.println("decryptedData: " + decryptedData.toString());
}
}
The only issue I can see is that you pass the unencrypted data to the Cipher in decrypt mode, which won't work. (The cipher obviously cannot decrypt data which is not encrypted without getting odd results.)
So change
byte[] decryptedData = cipher.doFinal(data);
to
byte[] decryptedData = cipher.doFinal(encryptedData);
Then, everything works fine.
Altough I doubt this error exists in your productive code, so if you still have problems on that one, feel free to ask a new question.
You are not decrypting the encrypted data, you are simply trying to decrypt the original data.
Also while printing the data use UTF-8
import java.security.spec.KeySpec;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
public class PMAdminKeyTest {
public static void main(String[] args) throws Exception {
// Requirement is to generate Key based on password and salt
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
KeySpec keySpec = new PBEKeySpec("password".toCharArray(), "salt".getBytes(), 65536, 192);
SecretKey key = new SecretKeySpec(secretKeyFactory.generateSecret(keySpec).getEncoded(), "DESede");
System.out.println("key.getAlgorithm(): " + key.getAlgorithm());
byte[] data = "12345678".getBytes("UTF8");
// Existing encrypt and decrypt code. There is already lot of data in DB
// encrypted in this manner. I dont think I can change this code.
Cipher cipher = Cipher.getInstance(key.getAlgorithm() + "/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encryptedData = cipher.doFinal(data);
System.out.println("encryptedData: " + encryptedData.toString());
cipher.init(Cipher.DECRYPT_MODE, key);
// Notice this
byte[] decryptedData = cipher.doFinal(encryptedData);
// while printing the data use UTF-8
System.out.println("decryptedData: " + new String(decryptedData, "UTF-8"));
}
}
I'm using openssl's aes-256-cfb algorithm (from NodeJS's crypto module).
While both the NodeJS and the Java code successfully encrypt and decrypt data, the ciphertext is different, even when the iv, key and plaintext are all identical.
openssl/NodeJS cipherText:
05c2aad7bac42ed0846e9a52ce73df9ff9d7ff914feea49fed27d55ad690782a43107914c1b307ec92753227728c95b8e59c546d
Java cipherText:
05C2AAD7BAC42ED084739340D47CEC9F03D8E94AC7B1E11A56A6654F76AD2C8076BCA162303E39B44D043732E98FDD28C52D
I have guessed that openssl's aes-256-cfb translates to Java's AES/CFB/NoPadding.
The ciphertexts both share the same initial 9 bytes, which is odd - I would have expected them to share the first 16 bytes if there had been some difference in the common mode used. (I hope that "common mode" is the collective term for CFB/CBC/CTR/etc.)
Is Java's AES/CFB/NoPadding the correct translation of OpenSSL's aes-256-cfb?
Does the existence of the common first nine bytes imply that Java's AES/CFB/NoPadding is at least using AES256, as opposed to AES128?
If so, what else might account for the differing ciphertext?
Test cases follow:
OpenSSL/NodeJS:
var assert = require('assert');
var crypto = require('crypto');
describe('crypto', function() {
it('should work', function () {
var plainText = new Buffer('a secret plainText which has more than sixteen bytes');
var key = new Buffer('fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210', 'hex');
var iv = new Buffer('0123456789abcdef0123456789abcdef', 'hex');
var cipher = crypto.createCipheriv('aes-256-cfb', key, iv);
var decipher = crypto.createDecipheriv('aes-256-cfb', key, iv);
var cipherText = cipher.update(plainText);
cipher.final(); // no need to use this value with cfb, it seems to always be empty?
assert.equal(plainText.length, cipherText.length);
assert.equal('05c2aad7bac42ed0846e9a52ce73df9ff9d7ff914feea49fed27d55ad690782a43107914c1b307ec92753227728c95b8e59c546d', cipherText.toString('hex'));
var deciphered = decipher.update(cipherText);
decipher.final(); // no need to use value this with cfb, it seems to always be empty?
assert.equal(plainText, deciphered.toString('utf8'));
});
});
Java/Android:
import android.test.InstrumentationTestCase;
import com.google.protobuf.ByteString;
import bit.Twiddling;
import java.security.AlgorithmParameters;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class CryptoTest extends InstrumentationTestCase {
public void test_encrypt_and_decrypt() throws Exception {
byte[] plainText = "a secret message which has more than sixteen bytes".getBytes();
byte[] key = Twiddling.hexStringBEToBytes("fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210");
byte[] iv = Twiddling.hexStringBEToBytes("0123456789abcdef0123456789abcdef");//0123456789abcdef0123456789abcdef");
SecretKeySpec aesSecret = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding");
Cipher decipher = Cipher.getInstance("AES/CFB/NoPadding");
IvParameterSpec ivps = new IvParameterSpec(iv);
assertEquals(16, iv.length);
cipher.init(Cipher.ENCRYPT_MODE, aesSecret, ivps);
byte[] cipherText = cipher.doFinal(plainText);
assertEquals(plainText.length, cipherText.length);
assertEquals("05C2AAD7BAC42ED084739340D47CEC9F03D8E94AC7B1E11A56A6654F76AD2C8076BCA162303E39B44D043732E98FDD28C52D", Twiddling.bytesToHexStringBE(cipherText));
decipher.init(Cipher.DECRYPT_MODE, aesSecret, ivps);
byte[] deciphered = decipher.doFinal(cipherText);
assertEquals(new String(plainText), new String(deciphered));
}
}
It was a find/replace error - the two plainTexts differ after the first nine bytes.
Java's name for OpenSSL's aes-256-cfb is AES/CFB/NoPadding.
I am trying to encode using a static key say as an example: "B3FFCA612CD0C3D9050A4DE3588E2830F26BEF6D7E1CEC77DD2F22FAFC038D33" in AES and ECB mode. when i try this with openssl, I successfully get a result with no issues but when I code it in groovy or java:
Invalid AES key length: 64 bytes
when I researched this, the issue occurs because the key length can be 32 bytes at most, now I am confused because the API i am sending these encrpions to, completely works with the 64 byte key i am sending but fails with the 32 byte one. openssl encodes this too with the 64 byte key I provide as below:
openssl enc -aes-256-ecb -e -in infile.txt -a -A -K B3FFCA612CD0C3D9050A4DE3588E2830F26BEF6D7E1CEC77DD2F22FAFC038D33 -iv 0 -p
I want to be able to do the same but in groovy/java.
I am not sure what I am missing, I would really apprecaite your help on this please!
here is my code:
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.SecretKeyFactory;
import javax.crypto.SecretKey;
import javax.crypto.Cipher;
import java.security.spec.KeySpec;
import javax.crypto.spec.PBEKeySpec;
class AESCrypt {
// encrypt
def encrypt (def plainText, def secret) {
def cipher = Cipher.getInstance("AES/ECB/PKCS5Padding")
// converty string secret to SecretKeySpec
byte[] decodedKey = Base64.getDecoder().decode(secret);
SecretKeySpec key= new SecretKeySpec(decodedKey , 0, decodedKey.length,
"AES");
cipher.init(Cipher.ENCRYPT_MODE, key)
return cipher.doFinal(plainText.getBytes("UTF-8")).encodeBase64().toString()
}
}
//Main
for( int i = 0; i < dataContext.getDataCount(); i++ ) {
InputStream is = dataContext.getStream(i);
Properties props = dataContext.getProperties(i);
def c = new AESCrypt()
def secret =
"B3FFCA612CD0C3D9050A4DE3588E2830F26BEF6D7E1CEC77DD2F22FAFC038D33"
//get plaintext of payload
Scanner s = new Scanner(is).useDelimiter("\\A");
String plainPayload = s.hasNext() ? s.next() : "";
//encrypt plaintext of payload
def encryptedPayload = c.encrypt(plainPayload, secret)
println encryptedPayload + "\n"
}
openssl encodes this too with the 64 byte key I provide as below.
It's not a 64-byte key. It's a 32-byte key that's been hexadecimal encoded, which results in 64 letters.
You are trying to base64 decode your secret, which is not the same as hexadecimal.
I'm not a Java or Groovy expert, but may be able to use decodeHex() on your string to hex decode it instead of base64 decode it.
What am I doing wrong? I expected the Java program to print "private". My goal is to try to write the MessageEncryptor.decrypt ruby method in Java.
Ruby encryption (most code was taken from MessageEncryptor, but modified not to Marshal), but I've extracted it so that it's easier to see what's going on:
require 'openssl'
require 'active_support/base64'
#cipher = 'aes-256-cbc'
d = OpenSSL::Cipher.new(#cipher)
#secret = OpenSSL::PKCS5.pbkdf2_hmac_sha1("password", "some salt", 1024, d.key_len)
cipher = OpenSSL::Cipher::Cipher.new(#cipher)
iv = cipher.random_iv
cipher.encrypt
cipher.key = #secret
cipher.iv = iv
encrypted_data = cipher.update("private")
encrypted_data << cipher.final
puts [encrypted_data, iv].map {|v| ::Base64.strict_encode64(v)}.join("--")
Which printed:
tzFUIVllG2FcYD7xqGPmHQ==--UAPvdm3oN3Hog9ND9HrhEA==
Java code:
package decryptruby;
import java.security.spec.KeySpec;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
public class DecryptRuby {
public static String decrypt(String encrypted, String pwd, byte[] salt)
throws Exception {
String[] parts = encrypted.split("--");
if (parts.length != 2) return null;
byte[] encryptedData = Base64.decodeBase64(parts[0]);
byte[] iv = Base64.decodeBase64(parts[1]);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec(pwd.toCharArray(), salt, 1024, 256);
SecretKey tmp = factory.generateSecret(spec);
SecretKey aesKey = new SecretKeySpec(tmp.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, aesKey, new IvParameterSpec(iv));
byte[] result = cipher.doFinal(encryptedData);
return result.toString();
}
public static void main(String[] args) throws Exception {
String encrypted = "tzFUIVllG2FcYD7xqGPmHQ==--UAPvdm3oN3Hog9ND9HrhEA==";
System.out.println("Decrypted: " + decrypt(encrypted, "password", "some salt".getBytes()));
}
}
Which printed
Decrypted: [B#432a0f6c
This is the problem - or at least a problem:
byte[] result = cipher.doFinal(encryptedData);
return result.toString();
You're calling toString() on a byte array. Arrays don't override toString(). That won't give you what you want at all - as you can see. Instead, you need to write something like:
return new String(result, "UTF-8");
... but you need to know what encoding was used to turn the original string into bytes before encryption. It's not clear to me from the Ruby code what encoding is used, but if you can be explicit about it (ideally using UTF-8) it'll make your life a lot easier.
In short, I suspect this problem has nothing to do with encryption at all - it has everything to do with converting text to bytes in Ruby and then converting the same sequence of bytes back into a string in Java.
Of course the encryption may be failing as well but that's a different matter.
I am trying to translate the following (working) Java code to Ruby.
public static final String PROVIDER = "BC";
public static final int IV_LENGTH = 16;
private static final String HASH_ALGORITHM = "SHA-512";
private static final String PBE_ALGORITHM = "PBEWithSHA256And256BitAES-CBC-BC";
private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";
private static final String SECRET_KEY_ALGORITHM = "AES";
public String decrypt(SecretKey secret, String encrypted) {
Cipher decryptionCipher = Cipher.getInstance(CIPHER_ALGORITHM, PROVIDER);
String ivHex = encrypted.substring(0, IV_LENGTH * 2);
String encryptedHex = encrypted.substring(IV_LENGTH * 2);
IvParameterSpec ivspec = new IvParameterSpec(HexEncoder.toByte(ivHex));
decryptionCipher.init(Cipher.DECRYPT_MODE, secret, ivspec);
byte[] decryptedText = decryptionCipher.doFinal(HexEncoder.toByte(encryptedHex));
String decrypted = new String(decryptedText, "UTF-8");
return decrypted;
}
My (not working) Ruby code is this:
require 'openssl'
require 'digest/sha2'
SECRET = "MY PASSWORD AS RAW TEXT"
IV_LENGHT = 16
encoded = "45D0EC4D910C0A6FF67325FF7362DCBC4613B6F3BFDFE35930D764FB1FE62251"
iv = encoded.slice(0, IV_LENGHT * 2)
e = encoded.slice(IV_LENGHT*2..-1)
binary_iv = iv.unpack('a2'*IV_LENGHT).map{|x| x.hex}.pack('c'*IV_LENGHT)
binary_e = e.unpack('a2'*IV_LENGHT).map{|x| x.hex}.pack('c'*IV_LENGHT)
c = OpenSSL::Cipher::Cipher.new("aes-256-cbc")
c.decrypt
c.key = Digest::SHA256.digest(SECRET).slice(0, IV_LENGHT* 2 )
c.iv = binary_iv
d = c.update(binary_e)
d << c.final
puts "decrypted: #{d}\n"
I have tried the binary and non binary versions, with no luck.
Someone can point to the problem?
Based on the title here, I am going to assume that you want to be able to encrypt a message in Java, and then decrypt that message in Ruby, using password-based AES-CBC encryption.
Now, the openssl standard library in Ruby readily supports password-based key derivation function 2 based on PKCS5. You can greatly simplify your Ruby decryption code if you leverage this in your Java encryption.
Here is how you would encrypt using PBKDF2 in PKCS5 in Java:
// in Java-land
import java.security.AlgorithmParameters;
import java.security.spec.KeySpec;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
...
static String printHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02x", (b & 0xFF)));
}
return sb.toString();
}
public static Map<String,String> encrypt(String msg, String pwd, byte[] salt)
throws Exception {
Map<String,String> retval = new HashMap<String,String>();
// prepare to use PBKDF2/HMAC+SHA1, since ruby supports this readily
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
// our key is 256 bits, and can be generated knowing the password and salt
KeySpec spec = new PBEKeySpec(pwd.toCharArray(), salt, 1024, 256);
SecretKey tmp = factory.generateSecret(spec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
// given key above, our cippher will be aes-256-cbc in ruby/openssl
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
AlgorithmParameters params = cipher.getParameters();
// generate the intialization vector
byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV();
retval.put("iv", printHex(iv));
byte[] ciphertext = cipher.doFinal(msg.getBytes("UTF-8"));
retval.put("encrypted", printHex(ciphertext));
return retval;
}
public static void main(String[] args) throws Exception {
String msg = "To Ruby, from Java, with love...";
String pwd = "password";
String salt = "8 bytes!"; // in reality, you would use SecureRandom!
System.out.println("password (plaintext): " + pwd);
System.out.println("salt: " + salt);
Map<String,String> m = encrypt(msg, pwd, salt.getBytes());
System.out.println("encrypted: " + m.get("encrypted"));
System.out.println("iv: " + m.get("iv"));
}
Running the above will result in something like the following output.
password (plaintext): password
salt: 8 bytes!
encrypted: 4a39f1a967c728e11c7a5a3fb5d73ad07561f504c9d084d0b1ae600cc1f75137cbb82a4d826c060cb06e2e283449738d
iv: ecbc985b3550edc977a17acc066f2192
Hex strings are used for the encrypted message and initialization vector since you can use OpenSSL to verify the encryption/decryption process (highly recommended).
Now from a Ruby program, you would use the AES-256-CBC cipher, and derive the secret key from the password and salt strings (not byte[] as per Java). Using the output from the above-mentioned Java program, we have:
# from Ruby-land
require 'openssl'
d = OpenSSL::Cipher.new("AES-256-CBC")
d.decrypt
key = OpenSSL::PKCS5.pbkdf2_hmac_sha1("password", "8 bytes!", 1024, d.key_len)
d.key = key
d.iv = "ecbc985b3550edc977a17acc066f2192".scan(/../).map{|b|b.hex}.pack('c*')
data = "4a39f1a967c728e11c7a5a3fb5d73ad07561f504c9d084d0b1ae600cc1f75137cbb82a4d826c060cb06e2e283449738d".scan(/../).map{|b|b.hex}.pack('c*')
d.update(data) << d.final
=> "To Ruby, from Java, with love..."
NOTE: The Ruby part of this code pretty much comes verbatim from the Japanese documentation on the openssl standard library.
I once had a similar problem with CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding"; and decryption through the openSSL-library in C which I could't solve. I avoided the problem by using "AES/CBC/NoPadding" and by adding a particular padding to the plaintext manually.