I need to encode a string in Java and php where the result must be the same.
The following conditions are given:
algorithm: RIJNDAEL-128
key: 5P443m2Q1R9A7f5r3e1z08642
mode: ECB
initialization vector: N/A (Since we're using ECB, IV's are ignored)
String to encode: 201412181656005P443m2Q1R9A7f5r3e1z08642
PHP
<?php
class Cipher
{
private $securekey, $iv;
function __construct($textkey)
{
$this->securekey = $textkey;
$this->iv = mcrypt_create_iv(32);
}
function encryptR($input)
{
$enc = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $this->securekey, $input, MCRYPT_MODE_ECB, $this->iv);
return base64_encode($enc);
}
function decryptR($input)
{
return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $this->securekey, base64_decode($input), MCRYPT_MODE_ECB, $this->iv));
}
}
$raw_text = '201412181656005P443m2Q1R9A7f5r3e1z08642';
$secretKey = '5P443m2Q1R9A7f5r3e1z08642';
$cipher = new Cipher($secretKey);
$encrypted = $cipher->encryptR($raw_text);
?>
Output: MbDHhIanWgySlMTOX+ItgVKudVLXbtj7ig2GMQacVM9JhyAPvVQxLJnHpEj/vhqW
JAVA
encrypted = encrypt("201412181656005P443m2Q1R9A7f5r3e1z08642","5P443m2Q1R9A7f5r3e1z08642");
public class Crypt {
private final String characterEncoding = "UTF-8";
private final String cipherTransformation = "AES/ECB/PKCS5Padding";
private final String aesEncryptionAlgorithm = "AES";
public byte[] decrypt(byte[] cipherText, byte[] key) throws Exception
{
Cipher cipher = Cipher.getInstance(cipherTransformation);
SecretKeySpec secretKeySpecy = new SecretKeySpec(key, aesEncryptionAlgorithm);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpecy);
cipherText = cipher.doFinal(cipherText);
return cipherText;
}
public byte[] encrypt(byte[] plainText, byte[] key) throws Exception
{
Cipher cipher = Cipher.getInstance(cipherTransformation);
SecretKeySpec secretKeySpec = new SecretKeySpec(key, aesEncryptionAlgorithm);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
plainText = cipher.doFinal(plainText);
return plainText;
}
private byte[] getKeyBytes(String key) throws UnsupportedEncodingException{
byte[] keyBytes= new byte[16];
byte[] parameterKeyBytes= key.getBytes(characterEncoding);
System.arraycopy(parameterKeyBytes, 0, keyBytes, 0, Math.min(parameterKeyBytes.length, keyBytes.length));
return keyBytes;
}
#SuppressLint("NewApi")
public String encrypt(String plainText, String key) throws Exception {
byte[] plainTextbytes = plainText.getBytes(characterEncoding);
byte[] keyBytes = getKeyBytes(key);
// Log.i("iv", ""+keyBytesIV);
return Base64.encodeToString(encrypt(plainTextbytes,keyBytes), Base64.DEFAULT);
}
#SuppressLint("NewApi")
public String decrypt(String encryptedText, String key) throws Exception {
byte[] cipheredBytes = Base64.decode(encryptedText, Base64.DEFAULT);
byte[] keyBytes = getKeyBytes(key);
return new String(decrypt(cipheredBytes, keyBytes), characterEncoding);
}
}
Output: wd0FHYpLbgdpHhcSql7VVCiKWJWN5hvP0W9F4sgKWAWeDcSjvfKWTM5LHBCZJSRw
Updated:
I changed the padding from NoPadding to PKCS5Padding
Is this correct? I'm not sure, cause if you look at the PHP code. There wasn't any padding specified(my own assumption based on syntax).
Info on Mcrypt
Additional Insight:
Read this document regarding padding(No Padding). Must've been related to the issue.
Looks like your PHP version uses AES-128, which by definition, uses 128-bit (16-byte) keys. However looks like you passed in a 25-byte key (5P443m2Q1R9A7f5r3e1z08642), which I'm not sure what PHP does when that happens.
Your Java version's getKeyBytes() method only returns the first 16 bytes of the supplied key, so it encrypts with only that.
Try truncating the key in your PHP version to 5P443m2Q1R9A7f5r and you'd get the same result. Except the end part which may be different. At that point, the issue then would be the padding. You can apply the pkcs5_pad PHP function on your plaintext so it matches your Java version.
All that said, if this was just for learning purposes, it's ok. Otherwise, for actual use it's important that you do not use ECB cipher mode.
I changed byte[] keyBytes= new byte[16]; to byte[] keyBytes= new byte[32]; in getKeyBytes method then it worked fine.
Related
I have the following code to encrypt-decrypt a string using a key and random IV. However during decrypt I get a lot of zeros at the end in my IDE.
public class Example {
private static final String AES_MODE = "AES/CBC/PKCS5Padding";
private static final String CHARSET = "UTF-8";
private static final String HASH_ALGORITHM = "SHA-256";
private static final String KEY = "SUPER_SECURE_KEY";
private static SecretKeySpec getSecretKey() throws NoSuchAlgorithmException, UnsupportedEncodingException {
final MessageDigest digest = MessageDigest.getInstance(HASH_ALGORITHM);
byte[] bytes = KEY.getBytes(CHARSET);
digest.update(bytes, 0, bytes.length);
byte[] key = digest.digest();
return new SecretKeySpec(key, "AES");
}
public static String encrypt(String message) {
if(message == null || message.isEmpty()) {
return "";
}
try {
final SecretKeySpec key = getSecretKey();
byte[] cipherText = encrypt(key, message.getBytes(CHARSET));
return Base64.getEncoder().encodeToString(cipherText);
} catch (Exception e) {
System.out.print(e.toString());
return "";
}
}
private static byte[] encrypt(final SecretKeySpec key, final byte[] message) throws GeneralSecurityException {
final Cipher cipher = Cipher.getInstance(AES_MODE);
byte[] iv = new byte[cipher.getBlockSize()];
new SecureRandom().nextBytes(iv);
IvParameterSpec ivSpec = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
byte[] ciphertext = new byte[iv.length + cipher.getOutputSize(message.length)];
System.arraycopy(iv, 0, ciphertext, 0, iv.length);
cipher.doFinal(message, 0, message.length, ciphertext, iv.length);
return ciphertext;
}
// ========================================================================================
public static String decrypt(String base64EncodedCipherText) {
if(base64EncodedCipherText == null || base64EncodedCipherText.isEmpty()) {
return "";
}
try {
final SecretKeySpec key = getSecretKey();
byte[] decodedCipherText = Base64.getDecoder().decode(base64EncodedCipherText);
byte[] decryptedBytes = decrypt(key, decodedCipherText);
return new String(decryptedBytes, CHARSET);
} catch (Exception e) {
System.out.print(e.toString());
return "";
}
}
private static byte[] decrypt(final SecretKeySpec key, final byte[] decodedCipherText) throws GeneralSecurityException {
final Cipher cipher = Cipher.getInstance(AES_MODE);
IvParameterSpec ivSpec = new IvParameterSpec(decodedCipherText, 0, cipher.getBlockSize());
cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
int plainTextLength = decodedCipherText.length - cipher.getBlockSize();
byte[] plaintext = new byte[plainTextLength];
cipher.doFinal(decodedCipherText, cipher.getBlockSize(), plainTextLength, plaintext, 0);
return plaintext;
// return cipher.doFinal(decodedCipherText);
}
// ========================================================================================
public static void main(String[] args) {
String message = "Message to encrypt.";
String encryptedText = encrypt(message);
System.out.println(encryptedText);
String decryptedText= decrypt(encryptedText);
System.out.println(decryptedText);
}
}
The output I get in IntelliJ IDEA is:
here
I think I am correctly separating the IV from the ciphertext, and decrypt the ciphertext with the key and the random IV. But still end up getting zeros in the end. Any pointers to what is wrong?
Reading is fundamental. The docs for getOutputSize indicate you can't use it for this purpose:
The actual output length of the next update or doFinal call may be smaller than the length returned by this method.
Encrypt it then check the resulting byte array, or do something with the return value of the doFinal method (which really tells you how many bytes it made), or make a ByteArrayOutputStream and send both the iv and the bytes from doFinal (taking into account what it returns) there, then ask it for the byte[], or use a ByteBuffer.
Note that CBC is dubious, as is pass hashing with SHA-256. It works, but it's 'too fast', it's very easy for a hacker to try a few billion passwords a second. In general you shouldn't be handrolling this stuff.
CBC mode as normally used requires padding, which your code correctly specifies, so the ciphertext (before adding and after removing the IV) is longer than the plaintext. You allocate a buffer for this longer size and Cipher.doFinal only stores the actual plaintext to it, leaving the remaining bytes with the value initialized by new byte[n] which is (always) zero.
You could determine the size the output will be using ciper.getOutputSize(int) much as you did for encrypt This doesn't work; Maarten is right.
You could continue to overallocate the output buffer, but save the return value from cipher.doFinal (input,off,len, output,off) which is an int that tells you the number of bytes output (decrypted), and then use only that many bytes from the buffer e.g. new String (output, 0, outlen, charset) or Arrays.copyOf(output, outlen)
But the easiest way is to use the doFinal overload that allocates the buffer itself (with the correct size) and returns it:
return cipher.doFinal(decodedCipherText, cipher.getBlockSize(), decodedCipherText.length - cipher.getBlockSize());
Concur with not using a simple hash on a password, but your example doesn't show or say if your 'key' is really a password (handled by humans, and needing 'stretching') or just a text form of something with adequate entropy, for which a simple hash is okay.
I have found a source code at stackoverflow on Rinjndael-256 encryption and decryption written in c#. It is using custom IV appending some extra string. Now I need a decryption method on Java platform. I have found some source code; tried to change and test that. Here is the encryption method on c#:
public static string Encrypt(byte[] text, string key)
{
RijndaelManaged aes = new RijndaelManaged();
aes.KeySize = 256;
aes.BlockSize = 256;
aes.Padding = PaddingMode.None;
aes.Mode = CipherMode.CBC;
aes.Key = Encoding.Default.GetBytes(key);
aes.GenerateIV();
string IV = ("-[--IV-[-" + Encoding.Default.GetString(aes.IV));
ICryptoTransform AESEncrypt = aes.CreateEncryptor(aes.Key, aes.IV);
byte[] buffer = text;
return Convert.ToBase64String(Encoding.Default.GetBytes(Encoding.Default.GetString(AESEncrypt.TransformFinalBlock(buffer, 0, buffer.Length)) + IV));
}
The decryption method on java which is not working for me is:
public static String decrypt(byte[] cipherText, String encryptionKey) throws Exception{
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding", "SunJCE");
SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES");
cipher.init(Cipher.DECRYPT_MODE, key,new IvParameterSpec(IV.getBytes("UTF-8")));
return new String(cipher.doFinal(cipherText),"UTF-8");
}
Edit 1:
I have implemented the php code for decryption.
function decrypt($text, $pkey)
{
$key = $pkey;
$text = base64_decode($text);
$IV = substr($text, strrpos($text, "-[--IV-[-") + 9);
$text = str_replace("-[--IV-[-" . $IV, "", $text);
return rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_CBC, $IV), "\0");
}
Is there any manual way of implementing Rijndael-256 in Java? As someone said that
There is no support in any of the Sun JCE providers for anything other than Rijndael with the 128-bit blocksize
I don't have an option to use library
I have an application that needs to store some secret passwords in a configuration file such as database and ftp passwords/detail. I've looked around and found a lot of encryption/decryption solutions using AES, but I can't seem to figure out how to make it work without changing the key. That means I can encrypt and decrypt (using the same SecretKey), but to maintain persistence across restarts etc. I can't seem to make the SecretKey stay the same. The example below shows my methods working:
String secret = Encryptor.encrpytString("This is secret");
String test = Encryptor.decrpytString(secret);
System.out.println(test); //This is secret is printed
So far so good. However if I run it once I might get the value of '2Vhht/L80UlQ184S3rlAWw==' as my secret, the next time it is 'MeC4zCf9S5wUUKAu8rvpCQ==', so presumably the key is changing. I'm assuming I am applying some counter-intuative logic to the problem and would appreciate if someone can shed some light on either a) what I'm doing wrong, or b) a solution that would allow me to store the password information encrypted and retrievable with the information provided.
My methods are as follows:
private static final String salt = "SaltySalt";
private static byte [] ivBytes = null;
private static byte[] getSaltBytes() throws Exception {
return salt.getBytes("UTF-8");
}
private static char[] getMasterPassword() {
return "SuperSecretPassword".toCharArray();
}
private static byte[] getIvBytes() throws Exception {
if (ivBytes == null) {
//I don't have the parameters, so I'll generate a dummy encryption to create them
encrpytString("test");
}
return ivBytes;
}
public static String encrpytString (String input) throws Exception {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
PBEKeySpec spec = new PBEKeySpec(getMasterPassword(), getSaltBytes(), 65536,256);
SecretKey secretKey = factory.generateSecret(spec);
SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
ivBytes = cipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV();
byte[] encryptedTextBytes = cipher.doFinal(input.getBytes("UTF-8"));
return DatatypeConverter.printBase64Binary(encryptedTextBytes);
}
public static String decrpytString (String input) throws Exception {
byte[] encryptedTextBytes = DatatypeConverter.parseBase64Binary(input);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
PBEKeySpec spec = new PBEKeySpec(getMasterPassword(), getSaltBytes(), 65536, 256);
SecretKey secretKey = factory.generateSecret(spec);
SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(getIvBytes()));
byte[] decryptedTextBytes = cipher.doFinal(encryptedTextBytes);
return new String(decryptedTextBytes);
}
Thanks for the help!
OK, looks like I've found the answer to my question. I sourced my information from this Stackoverflow post.
From what I understand, the IV (initialisation vector) is used to add entropy into the encryption process. Each time you create a new cipher, Java creates a slightly different IV. There are therefore two solutions:
User a fixed IV, or
Store the IV along with the encrypted data.
From what I've read, option 1 is not very good practice; so option 2 it is. I understand that it should be possible to simply append the IV to the encrypted string (as the secret is still required) and therefore the IV can be reconstructed when it comes time to decrypt.
Here is the almost complete solution. I'm still getting some padding errors on decryption (see my comment). I don't have time to spend on it now, so as a temporary measure I immediately try decrypting an encrypted string and keep on trying (iterating) until it works. It seems to have about a 50% hit rate + I'm not encrypting often enough for it to be a performance concern. Would be nice if someone could suggest a fix though (just for completeness sake).
private static final String salt = "SaltySalt";
private static final int IV_LENGTH = 16;
private static byte[] getSaltBytes() throws Exception {
return salt.getBytes("UTF-8");
}
private static char[] getMasterPassword() {
return "SuperSecretPassword".toCharArray();
}
public static String encrpytString (String input) throws Exception {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
PBEKeySpec spec = new PBEKeySpec(getMasterPassword(), getSaltBytes(), 65536,256);
SecretKey secretKey = factory.generateSecret(spec);
SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
byte[] ivBytes = cipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV();
byte[] encryptedTextBytes = cipher.doFinal(input.getBytes("UTF-8"));
byte[] finalByteArray = new byte[ivBytes.length + encryptedTextBytes.length];
System.arraycopy(ivBytes, 0, finalByteArray, 0, ivBytes.length);
System.arraycopy(encryptedTextBytes, 0, finalByteArray, ivBytes.length, encryptedTextBytes.length);
return DatatypeConverter.printBase64Binary(finalByteArray);
}
public static String decrpytString (String input) throws Exception {
if (input.length() <= IV_LENGTH) {
throw new Exception("The input string is not long enough to contain the initialisation bytes and data.");
}
byte[] byteArray = DatatypeConverter.parseBase64Binary(input);
byte[] ivBytes = new byte[IV_LENGTH];
System.arraycopy(byteArray, 0, ivBytes, 0, 16);
byte[] encryptedTextBytes = new byte[byteArray.length - ivBytes.length];
System.arraycopy(byteArray, IV_LENGTH, encryptedTextBytes, 0, encryptedTextBytes.length);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
PBEKeySpec spec = new PBEKeySpec(getMasterPassword(), getSaltBytes(), 65536, 256);
SecretKey secretKey = factory.generateSecret(spec);
SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(ivBytes));
byte[] decryptedTextBytes = cipher.doFinal(encryptedTextBytes);
return new String(decryptedTextBytes);
}
Use a static Initialization Vector, e.g. a zero IV:
cipher.init(Cipher.ENCRYPT_MODE, secret, new IvParameterSpec(new byte[16]));
cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(new byte[16]));
Since you're storing passwords you probably want to use a random IV and/or random salt and store them with the cipher text so the same passwords don't encrypt to the same ciphertext.
You need to setSeed() before
class Encryptor {
static final String salt = "SaltSalt";
public static byte[] encryptString(String input) throws Exception {
byte[] bytes = input.getBytes("UTF-8");
Cipher cipher = Cipher.getInstance("AES");
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
SecureRandom secureRandom = new SecureRandom();
secureRandom.setSeed(salt.getBytes("UTF-8"));
keyGenerator.init(256, secureRandom);
Key key = keyGenerator.generateKey();
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] a = cipher.doFinal(bytes);
return a;
}
public static String decryptString(byte[] input) throws Exception {
Cipher cipher = Cipher.getInstance("AES");
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
SecureRandom secureRandom = new SecureRandom();
secureRandom.setSeed(salt.getBytes("UTF-8"));
keyGenerator.init(256, secureRandom);
Key key = keyGenerator.generateKey();
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] decrypted = cipher.doFinal(input);
String result = new String(decrypted, "UTF-8");
return result;
}
}
I want a secure solution for caching a user's password on their PC during their session.
I have trawled numerous AES examples and know that this has been answered elsewhere but I must say it is a little confusing. My aesSecretKey or aesInitialisationVector are not working in the decryption correctly but not sure where the issue lies.
Decrypting results in a javax.crypto.BadPaddingException: Given final block not properly padded exception.
My class looks like this
public class LockManagerTest {
// Need to share the IV and key between encode and decode
private static byte[] aesInitialisationVector;
private static SecretKey aesSecretKey;
private static Cipher aesCipher;
public LockManagerTest(String sessionKey) {
try {
byte[] key = getSecretKey(sessionKey.toCharArray(), getSalt(32),
65536, 128);
aesSecretKey = new SecretKeySpec(key, "AES");
aesCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
aesCipher.init(Cipher.ENCRYPT_MODE, aesSecretKey);
AlgorithmParameters params = aesCipher.getParameters();
aesInitialisationVector =
params.getParameterSpec(IvParameterSpec.class).getIV();
} catch (Exception e) {
Util.handleException(e);
}
}
private static byte[] getSecretKey(char[] plaintext,
byte[] salt,
int iterations,
int keySize)
throws Exception {
PBEKeySpec spec = new PBEKeySpec(plaintext, salt, iterations, keySize);
SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
return skf.generateSecret(spec).getEncoded();
}
private static byte[] getSalt(int keyLength) throws Exception {
SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN");
byte[] salt = new byte[keyLength];
random.nextBytes(salt);
return salt;
}
public byte[] encryptedAes(char[] input) throws Exception {
// WRONG
// aesCipher.init(Cipher.ENCRYPT_MODE, aesSecretKey);
//
aesCipher.init(Cipher.ENCRYPT_MODE, aesSecretKey,
new IvParameterSpec(aesInitialisationVector);
CharBuffer cBuf = CharBuffer.wrap(input);
byte[] normalised = Charset.forName("UTF-8").encode(cBuf).array();
byte[] ciphertext = aesCipher.doFinal(normalised);
return ciphertext;
}
public byte[] decryptAes(byte[] ciphertext) throws Exception {
aesCipher.init(Cipher.DECRYPT_MODE,
aesSecretKey, new IvParameterSpec(aesInitialisationVector));
byte[] plaintext = aesCipher.doFinal(ciphertext);
return plaintext;
}
}
Comments regarding the level of security appreciated also.
You need to pass the IV when calling init() in encryptedAes().
AES is a CBC algorithm and divides input into blocks. These blocks must be of a specific size. In the case of AES, I believe it is 16 bytes. If the input is not a multiple of 16 bytes, it must be padded with nulls before encryption.
Instead of generating new IV while decrypting, you need to pass same IV which you use for encrypting. Remember AES is Symmetric Cipher.
Edit:
What you are doing is:
public byte[] encryptedAes(char[] input) throws Exception {
// WRONG
// aesCipher.init(Cipher.ENCRYPT_MODE, aesSecretKey);
//
aesCipher.init(Cipher.ENCRYPT_MODE, aesSecretKey,
new IvParameterSpec(aesInitialisationVector);
CharBuffer cBuf = CharBuffer.wrap(input);
byte[] normalised = Charset.forName("UTF-8").encode(cBuf).array();
byte[] ciphertext = aesCipher.doFinal(normalised);
return ciphertext;
}
Instead store the IvParameterSpec as a static, as per below (u can do proper variable declaration in your program)
public byte[] encryptedAes(char[] input) throws Exception {
//declare as static so initVector can be reused when decrypting
IvParamterSpec initVector = new IvParameterSpec(aesSecretKey);
aesCipher.init(Cipher.ENCRYPT_MODE, aesSecretKey, initVector);
CharBuffer cBuf = CharBuffer.wrap(input);
byte[] normalised = Charset.forName("UTF-8").encode(cBuf).array();
byte[] ciphertext = aesCipher.doFinal(normalised);
return ciphertext;
}
make the changes and then run your program. make sure you use the same initVector while decrypting. in your program you are creating new IvParameterSpec(...)
I am encrypting a string and storing it in a cookie at client side.. but when I send that exact encrypted string from js to java code it gives me the aforementioned exception.
The code I am using for encryption and decryption is:
public static final String UNICODE_FORMAT = "UTF8";
public static String encrypt(String Data, SecretKeySpec skeySpec,IvParameterSpec ivspec) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivspec);
byte[] plainBytes = Data.getBytes(UNICODE_FORMAT);
byte[] encrypted = cipher.doFinal(plainBytes);
String encryption = bytesToString(encrypted);
return encryption;
}
public static String decrypt(String encryptedData,SecretKeySpec skeySpec,IvParameterSpec ivspec) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, skeySpec, ivspec);
byte[] decryptval = hexToBytes(encryptedData);
byte[] decrypted = cipher.doFinal(decryptval);
return new String(decrypted);
}
public static String bytesToString(byte[] bytes) {
HexBinaryAdapter adapter = new HexBinaryAdapter();
String s = adapter.marshal(bytes);
return s;
}
public static byte[] hexToBytes(String hexString) {
HexBinaryAdapter adapter = new HexBinaryAdapter();
byte[] bytes = adapter.unmarshal(hexString);
return bytes;
}
can you tell me what the issue could be?? I have tried the solutions mentioned at stackoverflow.com and also a few other solutions but none worked.. am I getting this error because I am sending the encrypted string to JS and it is changing the padding of the string?
As # JoopEggen mentioned - creating sting from byte[] can break it.
Can you just serialize, instead of creating string from it?