Migrate openssl to java - java

I need to migrate a crypto package from C++/openssl to pure java implementation. However, I am having some issues that I don't know how to solve.
Below is a C++ list that outlines a decryption scheme that I am currently trying to migrate.
#include <openssl/evp.h>
#include <openssl/aes.h>
#include <openssl/rand.h>
#include <openssl/bio.h>
#include <openssl/buffer.h>
// set master key
AES_KEY master_key;
const int AES128_KEY_SIZE = 16;
unsigned char* master_secret = "averysecretmastersecret";
AES_set_encrypt_key(master_secret, AES128_KEY_SIZE * 8 , &master_key);
// Base64 decode; encryptedInput is the original input text
// b64_output consists of two parts: a leading salt (16 bytes) and the following actual data
char* b64_output = base64Decode(encryptedInput); // base64Decode(const char* encodedText) -> char* decodedText
// prepare salt
const char SALT_LEN = 16; // first byte is reserved. Actually only use 15 bytes = 120 bit
unsigned char salt[SALT_LEN];
memcpy(salt, b64_output, SALT_LEN); // read salt
// generate key
const int AES128_KEY_SIZE = 16;
unsigned char key[AES128_KEY_SIZE];
salt[0] = 1; //
AES_ecb_encrypt(salt, key, &master_key, AES_ENCRYPT);
// generate iv
const int AES128_IV_SIZE = 16;
unsigned char iv[AES128_IV_SIZE];
salt[0] = 2; // ensure that key and iv are different
AES_ecb_encrypt(salt, iv, &master_key, AES_ENCRYPT);
// initialize cipher context
EVP_CIPHER_CTX *de;
de = EVP_CIPHER_CTX_new();
EVP_CIPHER_CTX_init(de);
EVP_DecryptInit_ex(de, EVP_aes_128_cbc(), NULL, key, iv)
aes_decrypt(b64_output + SALT_LEN, length - SALT_LEN);
// plaintext is a buffer to contain the output
int plaintext_size = DEFAULT_BUFFER_SIZE;
char *plaintext = (char*)malloc(plaintext_size);
int aes_decrypt(const char *ciphertext, int len)
{
int p_len = len, f_len = 0;
// allocate an extra cipher block size of memory because padding is ON
// #define AES_BLOCK_SIZE 16
if(p_len + AES_BLOCK_SIZE > plaintext_size) {
ASSERT_CALL(enlarge_buffer(plaintext, plaintext_size, p_len + AES_BLOCK_SIZE), "enlarge plaintext buffer failed");
}
ASSERT_OPENSSL( EVP_DecryptInit_ex(de, NULL, NULL, NULL, NULL), "sets up decode context failed");
ASSERT_OPENSSL( EVP_DecryptUpdate(de, (unsigned char*)plaintext, &p_len, (unsigned char*)ciphertext, len), "decrypt failed");
EVP_DecryptFinal_ex(de, (unsigned char*)plaintext+p_len, &f_len);
return EY_SUCCESS;
}
EVP_CIPHER_CTX_free(de);
dec_result = std::string(plaintext);
Below is a java code list that I currently have (not working, of course) to reproduce above C++ logic:
String encrypted = "AtUKTnCF18kFTJIycg/RXKJ82IVCtaa+eKNVl8FhT0k+wvpc+cBIs5jb/QlLRMf4";
String secret = "averysecretmastersecret";
int SALT_LEN = 16;
String keyAlgorithm = "AES";
String ECB_TRANSFORM = "AES/ECB/NoPadding";
String CBC_TRANSFORM = "AES/CBC/NoPadding";
byte[] bytesOfSecret = Arrays.copyOf(secret.getBytes(), 16);
Key key =new SecretKeySpec(bytesOfSecret, keyAlgorithm);
Cipher ecbCipher = Cipher.getInstance(ECB_TRANSFORM);
Cipher cbcCipher = Cipher.getInstance(CBC_TRANSFORM);
// decode
byte[] decoded = Base64.getDecoder().decode(encrypted);
byte[] salt = Arrays.copyOf(decoded, SALT_LEN);
byte[] data = Arrays.copyOfRange(decoded, SALT_LEN, decoded.length);
// get iv
salt[0] = 2;
ecbCipher.init(Cipher.ENCRYPT_MODE, key);
byte[] iv = ecbCipher.doFinal(salt);
iv = Arrays.copyOf(iv, 16);
AlgorithmParameterSpec parameterSpec = new IvParameterSpec(iv);
cbcCipher.init(Cipher.DECRYPT_MODE, key, parameterSpec);
byte[] bytes = cbcCipher.doFinal(data);
String decrypted = new String(bytes);
System.out.println(decrypted);
There are a couple places that I don't know how to map from C++ to java right now. First, in the C++ code, it uses a salt to generate a key and an iv, which are subsequently used to initialize EVP cipher context as in EVP_DecryptInit_ex(de, EVP_aes_128_cbc(), NULL, key, iv). I don't know the equivalent operation in java.
Second, there is no direct mentioning in the C++ code whether padding is used. I tried both NoPadding and PKCS5Padding, but not sure which one is the right one.
So, how can I reproduce the C++ logic in java? Is there any example out there?
update
I also tried BouncyCastle. It is still not working. Below is my code:
int SALT_LEN = 16;
String encrypted = "AtUKTnCF18kFTJIycg/RXKJ82IVCtaa+eKNVl8FhT0k+wvpc+cBIs5jb/QlLRMf4";
String password = "averysecretmastersecret";
// decode
byte[] decoded = Base64.getDecoder().decode(encrypted);
byte[] salt = Arrays.copyOf(decoded, SALT_LEN);
byte[] data = Arrays.copyOfRange(decoded, SALT_LEN, decoded.length);
BufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new AESEngine()));
PBEParametersGenerator generator = new OpenSSLPBEParametersGenerator();
byte[] bytesOfSecret = PBEParametersGenerator.PKCS5PasswordToBytes(password.toCharArray());
generator.init(bytesOfSecret, salt, 1);
ParametersWithIV parametersWithIV = (ParametersWithIV) generator.generateDerivedParameters(128, 128);
// for decryption
cipher.init(false, parametersWithIV);
byte[] decrypted = new byte[cipher.getOutputSize(data.length)];
System.out.println("expected decrypted size = " + decrypted.length); // prints ... size = 32
int processedBytes = cipher.processBytes(data, 0, data.length, decrypted, 0);
System.out.println("processed bytes = " + processedBytes); // prints ... bytes = 16
cipher.doFinal(decrypted, processedBytes); // Line 59, run into exception
String output = new String(decrypted);
System.out.println(output);
Line 59, as marked above, gives this exception:
org.bouncycastle.crypto.InvalidCipherTextException: pad block corrupted
at org.bouncycastle.crypto.paddings.PKCS7Padding.padCount(Unknown Source)
at org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher.doFinal(Unknown Source)
...

This is an example of java AES encryption i hope this helps
String key = "HkJHBKJBvffdbv";
String IV= "qjfghftrsbdghzir";
String theMessageToCifer ="your message";
SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "AES");
IvParameterSpec ivSpec = new IvParameterSpec(IV.getBytes());
try{
//specify your mode
Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec,ivSpec);
encrypted = cipher.doFinal(theMessageToCifer.getBytes());
bytesEncoded = Base64.encode(encrypted);
System.out.println(" base64 code " +bytesEncoded);
System.out.println("encrypted string: " +encrypted);
// decryption
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec,ivSpec);
byte[] original = cipher.doFinal(encrypted);
String originalString = new String(original);
System.out.println("Original string: " + originalString );
}catch (Exception e){
e.printStackTrace();
}

Related

Unable to decrypt node js Text i Java AES-256-GCM getting Tag mismatch

Am able to encrypt and decrypt node and java code individually but when trying to decrypt the node text in java getting Tag mismatch! Am trying to encrypt and decrypt a simple Hello World text here
node js code i have :
const buffer = require('buffer');
const crypto = require('crypto');
// Demo implementation of using `aes-256-gcm` with node.js's `crypto` lib.
const aes256gcm = (key) => {
const ALGO = 'aes-256-gcm';
// encrypt returns base64-encoded ciphertext
const encrypt = (str) => {
// Hint: the `iv` should be unique (but not necessarily random).
// `randomBytes` here are (relatively) slow but convenient for
// demonstration.
const iv = new Buffer(crypto.randomBytes(16), 'utf8');
const cipher = crypto.createCipheriv(ALGO, key, iv);
// Hint: Larger inputs (it's GCM, after all!) should use the stream API
let enc = cipher.update(str, 'utf8', 'base64');
enc += cipher.final('base64');
console.log(enc);
return [enc, iv, cipher.getAuthTag()];
};
// decrypt decodes base64-encoded ciphertext into a utf8-encoded string
const decrypt = (enc, iv, authTag) => {
const decipher = crypto.createDecipheriv(ALGO, key, iv);
decipher.setAuthTag(authTag);
let str = decipher.update(enc, 'base64', 'utf8');
str += decipher.final('utf8');
return str;
};
return {
encrypt,
decrypt,
};
};
const KEY = new Buffer('fTjWnZr4u7x!z%C*F-JaNdRgUkXp2s5v', 'utf8');
const aesCipher = aes256gcm(KEY);
const [encrypted, iv, authTag] = aesCipher.encrypt('Hello World');
const decrypted = aesCipher.decrypt(encrypted, iv, authTag);
console.log(decrypted); // 'hello, world'
And the java code i have :
private final static int GCM_IV_LENGTH = 12;
private final static int GCM_TAG_LENGTH = 16;
private static String decrypt(String encrypted, SecretKey skey) throws Exception {
byte[] decoded = Base64.getDecoder().decode(encrypted);
byte[] iv = Arrays.copyOfRange(decoded, 0, GCM_IV_LENGTH);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec ivSpec = new GCMParameterSpec(GCM_TAG_LENGTH * Byte.SIZE, iv);
cipher.init(Cipher.DECRYPT_MODE, skey, ivSpec);
byte[] ciphertext = cipher.doFinal(decoded, GCM_IV_LENGTH, decoded.length - GCM_IV_LENGTH);
String result = new String(ciphertext, "UTF8");
return result;
}
The main method of the java execution code is
public static void main(String[] args) throws Exception {
String byte_key="fTjWnZr4u7x!z%C*F-JaNdRgUkXp2s5v";
SecretKey key = new SecretKeySpec(byte_key.getBytes(), "AES");
System.out.println("foo "+ decrypt("1cbKXSnEWixxFi0=", key));
}
I think i am missing something here

Encrypting Java then Decrypting C# AES256 Encryption with HMACSHA256, Padding is invalid

I'm currently running into an issue where our decryption portion of our C# site is having trouble with the padding with the encrypted string from java. The .Net code throws this error "Padding is invalid and cannot be removed". The _signKey and _encKey are both 64 bytes.
public String encryptString(String plainText) {
byte[] ciphertext;
byte[] iv = new byte[16];
byte[] plainBytes = plainText.getBytes(StandardCharsets.UTF_8);
String _signKey = "****************************************************************";
String _encKey = "****************************************************************";
try {
Mac sha256 = Mac.getInstance("HmacSHA256");
SecretKeySpec shaKS = new SecretKeySpec(_signKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
sha256.init(shaKS);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecureRandom randomSecureRandom = SecureRandom.getInstance("SHA1PRNG");
iv = new byte[cipher.getBlockSize()];
randomSecureRandom.nextBytes(iv);
IvParameterSpec ivParams = new IvParameterSpec(iv);
byte[] sessionKey = sha256.doFinal((_encKey + iv).getBytes(StandardCharsets.UTF_8));
// Perform Encryption
SecretKeySpec eks = new SecretKeySpec(sessionKey, "AES");
cipher.init(Cipher.ENCRYPT_MODE, eks, ivParams);
ciphertext = cipher.doFinal(plainBytes);
System.out.println("ciphertext= " + new String(ciphertext));
// Perform HMAC using SHA-256 on ciphertext
SecretKeySpec hks = new SecretKeySpec(_signKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(hks);
ByteArrayOutputStream outputStream2 = new ByteArrayOutputStream();
outputStream2.write(iv);
outputStream2.write(ciphertext);
outputStream2.flush();
outputStream2.write(mac.doFinal(outputStream2.toByteArray()));
return Base64.encodeBase64String(outputStream2.toByteArray());
} catch (Exception e) {
e.printStackTrace();
}
return plainText;
}
Does does encrypt the string properly as far as I can tell. We cannot change any code on the .Net side to decrypt this because this is being used today.
public static string DecryptString(string ciphertext)
{
using (HMACSHA256 sha256 = new HMACSHA256(Encoding.UTF8.GetBytes(_signKey)))
{
// Convert message to bytes
byte[] encBytes = Convert.FromBase64String(ciphertext);
// Get arrays for comparing HMAC tags
byte[] sentTag = new byte[sha256.HashSize / 8];
byte[] calcTag = sha256.ComputeHash(encBytes, 0, (encBytes.Length - sentTag.Length));
// If message length is too small return null
if (encBytes.Length < sentTag.Length + _ivLength) { return null; }
// Copy tag from end of encrypted message
Array.Copy(encBytes, (encBytes.Length - sentTag.Length), sentTag, 0, sentTag.Length);
// Compare tags with constant time comparison, return null if no match
int compare = 0;
for (int i = 0; i < sentTag.Length; i++) { compare |= sentTag[i] ^ calcTag[i]; }
if (compare != 0) { return null; }
using (AesCryptoServiceProvider csp = new AesCryptoServiceProvider())
{
// Set parameters
csp.BlockSize = _blockBits;
csp.KeySize = _keyBits;
csp.Mode = CipherMode.CBC;
csp.Padding = PaddingMode.PKCS7;
// Copy init vector from message
var iv = new byte[_ivLength];
Array.Copy(encBytes, 0, iv, 0, iv.Length);
// Derive session key
byte[] sessionKey = sha256.ComputeHash(Encoding.UTF8.GetBytes(_encKey + iv));
// Decrypt message
using (ICryptoTransform decrypt = csp.CreateDecryptor(sessionKey, iv))
{
return Encoding.UTF8.GetString(decrypt.TransformFinalBlock(encBytes, iv.Length, encBytes.Length - iv.Length - sentTag.Length));
}
}
}
}
If there is anything that sticks out it would be appreciated for the reply.
I didn't read all your code, but this line in Java:
byte[] sessionKey = sha256.doFinal((_encKey + iv).getBytes(StandardCharsets.UTF_8));
does nothing useful or sensible. The "+" operator does string concatenation, but iv is a byte[], not a String. So java uses iv.toString(), which simply returns a String containing something like [B#1188e820 which is meaningless in this context.
Refer four java code and DotNet code:
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); //Java
csp.Padding = PaddingMode.PKCS7; //.Net
You are essentially using different padding, that is the probable source of error; however, there is an alternate view, Refer this great post and this for general fundamentals on padding
The cipher suites supported by deafult Oracle JVM implementation are here
If you notice it does not have 'AES/CBC/PKCS7Padding', a PKCS#7 padding implementation is available in sun.security package, refer this, otherwise you could use Bouncy Castle packages. It would be recommendable to use Bouncy Castle as com.sun package are generally considered unsupported.

RIJNDAEL 256 CBC encryption with IV in java

I have a reference of PHP code that does Rijndael encryption. I want convert it to java code, I tried few examples but none of them worked for me.
Here is the php code:
$initialisationVector = hash("sha256", utf8_encode($myiv), TRUE);
$key = hash("sha256", utf8_encode($mykey), TRUE);
$encryptedValue = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256,$encryptKey, utf8_encode($mydata), MCRYPT_MODE_CBC, $initialisationVector));
Here is my java code that throws: Key length not 128/160/192/224/256 bits
public static String encrypt() throws Exception{
String myiv = "somevalue";
String mykey = "somevalue";
String mydata = "somevalue";
String new_text = "";
RijndaelEngine rijndael = new RijndaelEngine(256);
CBCBlockCipher cbc_rijndael = new CBCBlockCipher(rijndael);
ZeroBytePadding c = new ZeroBytePadding();
PaddedBufferedBlockCipher pbbc = new PaddedBufferedBlockCipher(cbc_rijndael, c);
byte[] iv_byte = sha256(myiv);
byte[] givenKey = sha256(mykey);
CipherParameters keyWithIV = new ParametersWithIV(new KeyParameter(givenKey), iv_byte);
pbbc.init(true, keyWithIV);
byte[] plaintext = mydata.getBytes(Charset.forName("UTF-8"));
byte[] ciphertext = new byte[pbbc.getOutputSize(plaintext.length)];
int offset = 0;
offset += pbbc.processBytes(plaintext, 0, plaintext.length, ciphertext, offset);
offset += pbbc.doFinal(ciphertext, offset);
new_text = new String(new Base64().encode(ciphertext), Charset.forName("UTF-8"));
System.out.println(new_text);
return new_text;
}
public static byte[] sha256(String input) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] messageDigest = md.digest(input.getBytes(Charset.forName("UTF-8")));
return messageDigest;
}
I am not really good with cryptography. Thanks in advance!
The error message is clear: "initialisation vector must be the same length as block size". You are specifiying a 256-bit (32-byte) block size, verify that iv_byte is 32-bytes.
There are a few problems:
For the IV get the bytes from the hash, pass the bytes to the encryption function, BigInteger has no place in that.
sha256(appId) provides a 256-bit key, just use it.
The following are not needed, the result of sha256 is 256-bits:
final int keysize = 256;
byte[] keyData = new byte[keysize];
System.arraycopy(givenKey, 0, keyData, 0, Math.min(givenKey.length, keyData.length));
sha256(appId) provides a 256-bit key, just use it.
The following are not needed:
final int keysize = 256;
byte[] keyData = new byte[keysize];
System.arraycopy(givenKey, 0, keyData, 0, Math.min(givenKey.length, keyData.length));
mcrypt "MCRYPT_RIJNDAEL_256" is specifying a 256-bit block size which means it is not AES, "MCRYPT_RIJNDAEL_128" is AES which should be used.
mcrypt uses non-standard null padding, that needs to be accommodated.
Using a SHA-256 hash is not sufficiently secure, use a password derivation function such as PBKDF2.

AES 128 Compatibility between android and Objective C

I have two applications: Android and iOS (Objective-C). And I'm trying to implement and encryption system so I can encrypt on both apps and decrypt in a server application. The problem is that I'm using AES128-ECB but the base64 key that I'm getting from android does not match with my objective c key. I have no idea what I'm missing.
Here are the snippets:
IOS
- (NSData*) EncryptAES: (NSString *) key{
char keyPtr[kCCKeySizeAES128+1];
bzero( keyPtr, sizeof(keyPtr) );
[key getCString: keyPtr maxLength: sizeof(keyPtr) encoding:NSUTF8StringEncoding];
size_t numBytesEncrypted = 0;
NSUInteger dataLength = [self length];
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
const unsigned char iv[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
CCCryptorStatus result = CCCrypt( kCCEncrypt,
kCCAlgorithmAES128,
kCCOptionPKCS7Padding,
keyPtr,
kCCKeySizeAES128,
iv,
[self bytes], [self length],
buffer, bufferSize,
&numBytesEncrypted );
if( result == kCCSuccess )
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
else {
NSLog(#"Failed AES");
}
return nil;
}
And then:
NSString *pass = #"WORD_TO_ENCRYPT";
NSString *key = #"STRING_KEY";
//Encryption - APPROACH 1
NSData *data = [pass dataUsingEncoding:NSUTF8StringEncoding];
NSData *encryptedData = [data EncryptAES:key];
NSString* encryptedBase64 = [self Base64Encode:encryptedData];
NSLog(#"%#", encryptedBase64);
This is my Java function:
String plainTextKey = "STRING_KEY";
String plainText = "WORD_TO_ENCRYPT";
// Encrypt where jo is input, and query is output and ENCRPYTION_KEy is key
//String inputtt = "some clear text data";
byte[] input = new byte[0];
String skyKey;
input = plainText.getBytes("utf-8");
MessageDigest md;
md = MessageDigest.getInstance("MD5");
byte[] thedigest = md.digest(plainTextKey.getBytes("UTF-8"));
SecretKeySpec skc = new SecretKeySpec(thedigest, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skc);
byte[] cipherText = new byte[cipher.getOutputSize(input.length)];
int ctLength = cipher.update(input, 0, input.length, cipherText, 0);
ctLength += cipher.doFinal(cipherText, ctLength);
String encode = Base64.encode(cipherText);
System.out.println(encode);
I'm banging my head against the wall without knowing what I'm missing.
Thanks in advance for your help!
PS: I don't have any particular reason to use AES128-ECB. I can use any other algorithm if the multi system compatibility is simpler.
On the Android side, when you initialize the Cipher instance, you must provide the matching IV.
byte[] iv = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
cipher.init(Cipher.ENCRYPT_MODE, skc, new IvParameterSpec(iv));
Avoid using an hardcoded IV for the encryption mechanism, at least on Android. The usage of Random Number Generators is advised, but if you can not provide a random value, at least build the IV from the key.
On the other hand, you won't have good security if everything is derived from the password; you need some randomness in every message.
Make sure to store the IV used during the encryption so you can properly apply it back on the decryption.
byte[] iv = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
cipher.init(Cipher.ENCRYPT_MODE, skc, new IvParameterSpec(iv));

DES encrypt in C/C++ vs Java

Just wondering why same plain text encrypted in Java and C doesn't generate same cipher text.
For DES algo I noticed
input text = "text", key = "test"
C cipher text len = 24
Java generates cipher text len = 8
For 256Bit AES I noticed similar difference
C cipher text len = 32
Java generates cipher text len = 16
here is my "C" code
char* enc(const char* text, const char* keyStr)
{
EVP_CIPHER_CTX ctx;
unsigned char key[32] = {0};
unsigned char iv[16] = {0};
unsigned char in[16] = {0};
unsigned char out[32]; /* at least one block longer than in[] */
memset(out, 0, 32);
int outlen1, outlen2;
memcpy(in, text, strlen(text));
memcpy(key, keyStr, strlen(keyStr));
EVP_EncryptInit(&ctx, EVP_aes_256_cbc(), key, iv);
EVP_EncryptUpdate(&ctx, out, &outlen1, in, sizeof(in));
EVP_EncryptFinal(&ctx, out + outlen1, &outlen2);
char* ret = (char*)malloc(outlen1 + outlen2+1);
memset(ret, 0, outlen1 + outlen2+1);
memcpy(ret, out, outlen1 + outlen2);
EVP_CIPHER_CTX_cleanup(&ctx);
return ret;
}
Here is the "Java" code
public static byte[] enc(byte[] input, byte[] keyStr){
byte[] output = null;
try {
byte[] newKey = getByteArrays(keyStr, 0, 32);
SecretKey secretKey = new SecretKeySpec(newKey, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
//Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
String ivStr = "";
byte[] ivKey = getByteArrays(ivStr.getBytes("UTF-8"), 0, 16);
IvParameterSpec ips = new IvParameterSpec(ivKey);
cipher.init(Cipher.ENCRYPT_MODE, secretKey, ips, null);
output = cipher.doFinal(input);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return output;
}
I have list of entries encrypted using C , I want to decrypt those entries in Java.
UPDATED
following update helped to get same length , both in 'C' and 'JAVA'
EVP_EncryptUpdate(&ctx, out, &outlen1, in, strlen(text));
No Just wondering why ciphertext returned by "C" and "JAVA" are different for same text and key, I'm expecting them tobe same
The reason the C code outputs 32 bytes of ciphertext is because you are padding your input string with zeros before passing it to the encryption function.
In this line:
EVP_EncryptUpdate(&ctx, out, &outlen1, in, sizeof(in));
the function has no idea that you padded your data with zeros. Since sizeof(in) is 16, it takes 16 as the length of your plaintext. And with PKCS5 padding (and AES), 16 bytes will pad to 32 bytes.
In your Java code you didn't manually pad your input, you just passed it straight to the encryption function. So the encryption function sees your plaintext size as 4 bytes, which pads to 16 with PKCS5 padding.
So your solution is simple: don't manually pad your input in the C code. Just pass the plaintext directly to EVP_EncryptUpdate. It's already designed to handle unpadded plaintext.

Categories