I have an encryption method that works well and passes me an encrypted String.
KeySpec keySpec = new PBEKeySpec(encryptionPassword.toCharArray(), salt, iterations);
SecretKey key = SecretKeyFactory.getInstance("PBEWithMD5AndDES").generateSecret(keySpec);
AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, iterations);
//encryption
Cipher encoder = Cipher.getInstance(key.getAlgorithm());
encoder.init(Cipher.ENCRYPT_MODE, key, paramSpec);
String str_to_encrypt = "Hello";
byte[] enc = encoder.doFinal(str_to_encrypt.getBytes("UTF8"));
System.out.println("encrypted = " + DatatypeConverter.printBase64Binary(enc));
output: encrypted = vjXsSX0cBNc=
However I also wish to Decrypt this String I've recieved, I am having trouble with this however, especially the reverse of getBytes and printBase64Binary.
This is the first time I have attempted to decrypt, so I used a lot of Googling, I found that 'parseBase64Binary' could get bytes from a string, with 'new String(dec, "US-ASCII") then turning the bytes into a string...somewhere something went askew.
//decryption
Cipher encoder = Cipher.getInstance(key.getAlgorithm());
encoder.init(Cipher.DECRYPT_MODE, key, paramSpec);
String str_to_decrypt = "vjXsSX0cBNc=";
byte[] dec = DatatypeConverter.parseBase64Binary(str_to_decrypt);
System.out.println("decrypted = " + new String(dec, "UTF8"));
output: decrypted = ?5?I}?
The only thing I can think of is that I haven't actually decrypted the string properly, as I have not used encoder.doFinal anywhere... somewhat stumped as to where to use it.
EDIT: Answered own question for completeness, all sorted!
Played around a bit more, I was right in saying I hadn't properly decrypted the String as I hadn't used encoder.doFinal... trial and error led me to this:
String str_to_decrypt = "vjXsSX0cBNc=";
byte[] dec = encoder.doFinal(DatatypeConverter.parseBase64Binary(str_to_decrypt));
System.out.println("decrypted = " + new String(dec, "UTF8"));
output: decrypted = Hello
Related
I've been doing some learning/experimentation with the basic Java AES stuff, and I can't figure out where I'm doing things wrong. According to the docs, doFinal() should encrypt/decrypt everything in one shot, and it does appear to do so; however, on decryption, with an invalid IV, I can still decrypt most of the data. In the interest of security, please tell me where the heck I messed up in my test code?
Notes: I am not using BC or the Java Unlimited Strength Crypto Extensions. This code follows examples and guidance from The Oracle JCA Reference Guide. In the code below, I select AES with CFB (same results with CBC), generate a key, generate an IV, feed encrypt, nuke the IV, and feed decrypt, and ideally (if I understand CBC and CFB correctly) the nuked IV should render the decrypted output into garbage. But it does not...at least, not on my installation...
It should also be noted that GCM does work correctly (you'll no doubt see the commented-out algo string below), but it bothers me that CBC and CFB are acting this way. Reality-check, please?
public static void encdec() throws Exception {
// let's encrypt something!
String message = "This is a super-secret message. Don't read this message. This message will self-destruct...";
final String symmetricCipherSpec = "AES/CFB/PKCS5Padding";// "AES/GCM/NoPadding";
final String symmetricKeySpec = "AES";
System.out.println("\n\nSelecting plaintext cypher...");
Cipher cipher = Cipher.getInstance(symmetricCipherSpec);
// What did we get?
System.out.println("--> Cipher Algorithm Selected: " + cipher.getAlgorithm());
AlgorithmParameters parameters = cipher.getParameters();
System.out.println("--> Parameters for algo: " + parameters.getAlgorithm());
System.out.println("--> block size: " + cipher.getBlockSize());
final int blockSize = cipher.getBlockSize();
KeyGenerator keyGenerator = KeyGenerator.getInstance(symmetricKeySpec);
keyGenerator.init(128);
Key key = keyGenerator.generateKey();
System.out.println("\nsymmetric key = " + Hex.encodeHexString(key.getEncoded()));
// set up for encryption
int tLen = 16;
byte[] basicIV = new byte[tLen];
for (int i = 0; i < basicIV.length; i++) {
basicIV[i] = (byte) i;
}
byte[] messageToEncrypt = message.getBytes();
IvParameterSpec ivSpec = new IvParameterSpec(basicIV);
cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
byte[] encryptedMessage = cipher.doFinal(messageToEncrypt);
System.out.println("\nencrypted = " + Hex.encodeHexString(encryptedMessage));
byte[] iv = cipher.getIV();
System.out.println("iv = " + Hex.encodeHexString(iv) + " (len=" + iv.length + ")");
// reset IV to garbage.
basicIV = new byte[tLen];
ivSpec = new IvParameterSpec(basicIV);
cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
byte[] decrypted = cipher.doFinal(encryptedMessage);
System.out.println("\ndecrypted = " + new String(decrypted));
System.out.println("original = " + message);
System.out.println("iv = " + Hex.encodeHexString(cipher.getIV()) + " (len=" + cipher.getIV().length + ")");
}
Nevermind... my understanding of CBC was flawed; this the code is working as intended. Per Wikipedia:
Decrypting with the incorrect IV causes the first block of plaintext to be corrupt but subsequent plaintext blocks will be correct. This is because each block is XORed with the ciphertext of the previous block, not the plaintext, so one does not need to decrypt the previous block before using it as the IV for the decryption of the current one.
I am trying to encrypt a value using the BLOWFISH cipher. The implementation must be in java and having the same result as the php version:
require_once('/usr/share/php/Crypt/CBC.php');
....
$cipher = new Crypt_CBC($key, 'BLOWFISH');
$encryptedPassword = $cipher->encrypt($valueToEncrypt);
echo "ENCODED STRING: " . $encryptedPassword;
$encodedPassword = base64_encode($encryptedPassword);
echo "ENCRYPTED STRING: " . $encodedPassword;
I tried something like this, but I cannot manage to get something even remotely similar:
SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "Blowfish");
String IV = "RandomIV";
Cipher cipher = Cipher.getInstance("Blowfish/CBC/PKCS5Padding");
init(Cipher.ENCRYPT_MODE, keySpec
, new javax.crypto.spec.IvParameterSpec(IV.getBytes())
);
byte[] encryptedBytes = cipher.doFinal(toEncrypt.getBytes());
String encoded = Base64.getEncoder().encodeToString(encryptedBytes);
Any helping idea is appreciated
I want to duplicate the JAVA encryption code in NodeJS.
private String DEFAULT_KEY = "abcdwAYserXbzcSeqL/zPg==";
private String text = "abc";
Base64 base64decoder = new Base64();
byte[] raw = base64decoder.decode(key);
SecretKeySpec fSecretKeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, fSecretKeySpec);
byte[] encrypted = cipher.doFinal(text.getBytes());
Base64 base64encoder = new Base64();
result = base64encoder.encodeToString(encrypted);
System.out.println("result: "+ result);
The above code generate the encrypted code as: ZkojvMTW+9EEK0owxMuA7A==
I have tried few ways in NodeJS. It is not generating same code for me.
I have tried the following code.
var bKey = new Buffer('abcdwAYserXbzcSeqL/zPg==', 'base64');
var cipher = crypto.createCipher('aes-128-ecb',bKey);
//cipher.setAutoPadding(auto_padding=false);
var crypted = cipher.update('abc',null,'base64');
crypted+=cipher.final('base64');
console.log(crypted);
Can someone help me out?
You probably are running into the issue that createCipher with two arguments takes a password, not a key. This password is first run through a key derivation function before it becomes a key.
Try to use the createCipheriv method instead, using any value for the IV. ECB mode doesn't take an IV, but at least you would be using a key instead of a password.
I have a code in Java in which encryption has been done as follows:
String encrypted = "mPgzvJKbSFgP6nRRHNlTufscZiChL2KUYaNeSF27+Dg=";
String key = "9d6ea4d3e6f8c4f8";
String salt = "1c5dd32d7ba54bdd";
String transform = "AES/CBC/ISO10126PADDING";
IvParameterSpec ivspec = new IvParameterSpec(salt.getBytes());
SecretKey secretKey = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance(transform);
cipher.init(Cipher.DECRYPT_MODE, secretKey, ivspec);
byte[] encryptedBytes = DatatypeConverter.parseBase64Binary(encrypted); // hash to byte[]
byte[] data = cipher.doFinal(encryptedBytes);
System.out.println(new String(data));
Now, I need to decrypt it in javascript. The code I wrote is:
var key = '9d6ea4d3e6f8c4f8';
var iv = '1c5dd32d7ba54bdd';
var options = {iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Iso10126};
alert("key + " + key);
alert("iv + " + iv);
var encrypted = 'mPgzvJKbSFgP6nRRHNlTufscZiChL2KUYaNeSF27+Dg=';
alert("encrypted + " + encrypted);
alert("encrypted.toString() = " + encrypted.toString());
var decrypyted = CryptoJS.AES.decrypt(encrypted.toString(), key, options );//error in this line.
alert(decrypyted);
alert(decrypyted.toString(CryptoJS.enc.Utf8));
The encryption is working properly and when I try decrypting the encrypted string using javascript, I am getting an error. The JS stops working once I execute the decrypt function. Any idea what am I doing wrong?
I wrote an encrypt and a decrypt function. The encrypt works fine, but I always get IllegalBlockSizeException in the decrypt.
public static String aes_encrypt (String text, String key)
{
SecretKey skey = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding", "SunJCE");
cipher.init(Cipher.ENCRYPT_MODE, skey);
return new String((cipher.doFinal(text.getBytes())));
}
And here's the decrypt function:
public static String aes_decrypt (String text, String key)
{
SecretKey skey = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding", "SunJCE");
cipher.init(Cipher.DECRYPT_MODE, skey);
return new String((cipher.doFinal(text.getBytes())));
}
Here's the simple main method that tests this:
public static void main (String args[])
{
String text = "Hello, world!";
String key = "nv93h50sk1zh508v";
String en, de;
System.out.println("Text: " + text);
System.out.println("Encrypted: " + (en = aes_encrypt(text, key))
+ " length = " + en.length());
System.out.println("Decrypted: " + (de = aes_decrypt(en, key)));
}
Does anyone know how to "pad" the encrypted string properly so that I can decrypt it?
(I tried padding the string with 0 until the length is a multiple of 16, but got something like string not properly padded.)
Thanks
I think the problem is in your using the String constructor. This is converting to string using a text encoding mechanism, which may not preserve every value in the byte array - unsupported ones in the system default encoding may be discarded, leaving the encoded data shorter than it should be. If you want a string representation, convert to hex or base 64 encoding instead. And reverse whatever encoding you use here at the start of the decryption method.
It's not a padding issue - the encryption call will pad this fine, you are short of bytes because of your means of encoding the byte array to a string.
You'll find some base 64 instructions in answers to this SO question.