AES encryption in java [duplicate] - java

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 7 years ago.
I have a program that encrypts and decrypts using the AES algorithm, but I have to specify the name of the encrypted file, and also specify the format of the original file as part of the name of the encrypted file. I will like to know how how to implement the following features into my code:
I want the name of the encrypted file to be in cipherText
I want the computer to be able to decide the file type(extension eg.txt) without me having to specify it, for example in my code if I am encrypting a .jpg file, I have to specify the name of the encrypted file as encrypt.jpg
Here is my code which i have tried to implement:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.CipherOutputStream;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.Scanner;
public class EncryptDecrypt {
static Cipher cipher;
static byte[] cipherText;
static byte[] input;
static byte k[]="2305ty6345663ty0".getBytes();
static SecretKeySpec key = new SecretKeySpec(k, "AES");
static int ctLength;
static String filePath = "C:/inddexfolder/casie.jpg";
static String encryptionPath = "C:/indexfolder1/encrypt.jpg";
public static void main(String[] args) {
EncryptDecrypt.encrypt();
EncryptDecrypt.decrypt();
}
public static void encrypt() {
try{
input = filePath.getBytes();
FileInputStream file = new FileInputStream(filePath);
FileOutputStream outStream = new FileOutputStream(encryptionPath);
cipher = Cipher.getInstance("AES/ECB/PKCS5Padding", "SunJCE");
cipher.init(Cipher.ENCRYPT_MODE, key);
cipherText = new byte[cipher.getOutputSize(input.length)];
ctLength = cipher.update(input, 0, input.length, cipherText, 0);
ctLength+= cipher.doFinal(cipherText, ctLength);
String encrypted = new String (cipherText);
CipherOutputStream cos = new CipherOutputStream(outStream, cipher);
byte[] buf = new byte[1024];
int read;
while((read=file.read(buf))!=-1){
cos.write(buf,0,read);
}
file.close();
outStream.flush();
cos.close();
}
catch(IOException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (NoSuchProviderException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (ShortBufferException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
}
public static void decrypt() {
try {
FileInputStream file = new FileInputStream(encryptionPath);
FileOutputStream outStream = new FileOutputStream("casenc1.jpg");
byte k[]="2305ty6345663ty0".getBytes();
SecretKeySpec key = new SecretKeySpec(k, "AES");
cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, key);
CipherOutputStream cos = new CipherOutputStream(outStream, cipher);
byte[] buf = new byte[1024];
int read;
while((read=file.read(buf))!=-1) {
cos.write(buf,0,read);
}
file.close();
outStream.flush();
cos.close();
Runtime.getRuntime().exec("rundll32 url.dll, FiProtocolHandler
"+"casenc1.jpg");
} catch(IOException e) {
System.out.println(" not decrypted Successfully");
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
}
}
}
For the FileOutputStream in the encrypt method , i tried:
FileOutputStream outStream
= new FileOutputStream(encryptionPath = new String(cipherText));
…to see if I could get the file name to be in cipher text but I got these errors:
Exception in thread "main" java.lang.NullPointerException
at java.lang.String.<init>(Unknown Source)
at EncryptDecrypt.encrypt(EncryptDecrypt.java:48)
at EncryptDecrypt.main(EncryptDecrypt.java:37)
Thanks!

Your cipherText is null. Please check whether you try assign it before encrypt it.
FileOutputStream outStream
= new FileOutputStream(encryptionPath = new String(cipherText));

Related

AES Encryption Decryption takes longer time

I am using below code for encryption & decryption in Spring boot project with conveter annotation on attributes which I want to encrypt & decrypt
import org.apache.commons.codec.binary.Base64;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.InvalidParameterSpecException;
#Converter
public class CryptoConverter implements AttributeConverter<String, String> {
#Override
public String convertToDatabaseColumn(String attribute) {
if(attribute == null){
return null;
}
try {
byte[] ivBytes;
//String password="Hello";
String password = EncryptionUtil.key.get();
SecureRandom random = new SecureRandom();
byte bytes[] = new byte[20];
random.nextBytes(bytes);
byte[] saltBytes = bytes;
// Derive the key
SecretKeyFactory factory = null;
factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
PBEKeySpec spec = new PBEKeySpec(password.toCharArray(),saltBytes,65556,256);
SecretKey secretKey = factory.generateSecret(spec);
SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
//encrypting the word
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
AlgorithmParameters params = cipher.getParameters();
ivBytes = params.getParameterSpec(IvParameterSpec.class).getIV();
byte[] encryptedTextBytes = cipher.doFinal(attribute.getBytes("UTF-8"));
//prepend salt and vi
byte[] buffer = new byte[saltBytes.length + ivBytes.length + encryptedTextBytes.length];
System.arraycopy(saltBytes, 0, buffer, 0, saltBytes.length);
System.arraycopy(ivBytes, 0, buffer, saltBytes.length, ivBytes.length);
System.arraycopy(encryptedTextBytes, 0, buffer, saltBytes.length + ivBytes.length, encryptedTextBytes.length);
return new Base64().encodeToString(buffer);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (InvalidParameterSpecException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
}
return null;
}
#Override
public String convertToEntityAttribute(String dbData) {
if(dbData == null){
return null;
}
try {
String password = EncryptionUtil.key.get();
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
//strip off the salt and iv
ByteBuffer buffer = ByteBuffer.wrap(new Base64().decode(dbData));
byte[] saltBytes = new byte[20];
buffer.get(saltBytes, 0, saltBytes.length);
byte[] ivBytes1 = new byte[cipher.getBlockSize()];
buffer.get(ivBytes1, 0, ivBytes1.length);
byte[] encryptedTextBytes = new byte[buffer.capacity() - saltBytes.length - ivBytes1.length];
buffer.get(encryptedTextBytes);
// Deriving the key
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), saltBytes, 65556, 256);
SecretKey secretKey = factory.generateSecret(spec);
SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(ivBytes1));
byte[] decryptedTextBytes = null;
decryptedTextBytes = cipher.doFinal(encryptedTextBytes);
return new String(decryptedTextBytes);
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
}
return null;
}
}
The issue is this code takes a lot of time to encrypt & decrypt.
With this I am getting a serious performance hit.
If you want to encrypt faster than simply use an actual randomly generated key instead of a password. You can store that in a KeyStore instance that you protect with a password if you like.
You could also simply move the PBKDF2 key derivation out of the encryption method itself and store the resulting SecretKey instance in a field if and only if the password doesn't change in between calls. That way you only have to derive the key once.
PBKDF2 currently uses 65556 iterations each time you want to encrypt/decrypt anything. And PBKDF2 consists of a single hash - in this case SHA-1 - taking 64 bytes at a time. So even before you start encrypting you've hashed at least 65556 (or 64Ki + 20 for some reason) times 64 bytes. That's 4 MiB of hashing you're doing before starting to encrypt. Compared to that you won't even notice the AES encryption.

Hi I'm trying to do AES Encryption using JAVA Code Help me in converting?

I'm trying to convert JAVA Code into Objective - C language. I have a requirement where I should Use the same code that Android developers are using. Code follows as
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
public class EncDec {
public static void main(String args[])
{
String reqMessage="{\"accountType\":\"ALL\",\"uId\":\"c8ff46be-a083-4009-8a33-fc2d22cc40e3|123456784\",\"deviceId\":\"qvxy1234\"}";
Map requestMap=new HashMap();
requestMap.put("body", reqMessage);
String bodyString=(String) requestMap.get("body");
String authKey="M/98hZivBqJQftMHsPvMgg&&";
String encString= encode(authKey,bodyString);
System.out.println("encString ::: "+ encString);
String decString= decode(authKey,encString);
System.out.println("decString ::: "+ decString);
}
public static String encode(String keyString, String stringToEncode) throws NullPointerException {
if (keyString.length() == 0 || keyString == null) {
throw new NullPointerException("Please give Password");
}
if (stringToEncode.length() == 0 || stringToEncode == null) {
throw new NullPointerException("Please give text");
}
try {
SecretKeySpec skeySpec = getKey(keyString);
byte[] clearText = stringToEncode.getBytes("UTF8");
// IMPORTANT TO GET SAME RESULTS ON iOS and ANDROID
final byte[] iv = new byte[16];
Arrays.fill(iv, (byte) 0x00);
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
// Cipher is not thread safe
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivParameterSpec);
byte[] encryptedByte=cipher.doFinal(clearText);
String encrypedValue = new String(Base64.encodeBase64(encryptedByte));
System.out.println("Encrypted: " + stringToEncode + " -> " + encrypedValue);
return encrypedValue;
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
return "";
}
/**
* Decodes a String using AES-128 and Base64
*
* #param context
* #param password
* #param text
* #return desoded String
*/
public static String decode(String password, String text) throws NullPointerException {
if (password.length() == 0 || password == null) {
throw new NullPointerException("Please give Password");
}
if (text.length() == 0 || text == null) {
throw new NullPointerException("Please give text");
}
try {
SecretKey key = getKey(password);
// IMPORTANT TO GET SAME RESULTS ON iOS and ANDROID
final byte[] iv = new byte[16];
Arrays.fill(iv, (byte) 0x00);
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
byte[] encrypedPwdBytes = Base64.decodeBase64(text.getBytes());
// cipher is not thread safe
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, key, ivParameterSpec);
byte[] decrypedValueBytes = (cipher.doFinal(encrypedPwdBytes));
String decrypedValue = new String(decrypedValueBytes);
System.out.println("Decrypted: " + text + " -> " + decrypedValue);
return decrypedValue;
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
return "";
}
/**
* Generates a SecretKeySpec for given password
*
* #param password
* #return SecretKeySpec
* #throws UnsupportedEncodingException
*/
private static SecretKeySpec getKey(String password) throws UnsupportedEncodingException {
// You can change it to 256 if you wish
int keyLength = 128;
byte[] keyBytes = new byte[keyLength / 8];
// explicitly fill with zeros
Arrays.fill(keyBytes, (byte) 0x0);
// if password is shorter then key length, it will be zero-padded
// to key length
byte[] passwordBytes = password.getBytes("UTF-8");
int length = passwordBytes.length < keyBytes.length ? passwordBytes.length : keyBytes.length;
System.arraycopy(passwordBytes, 0, keyBytes, 0, length);
SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");
return key;
}
}
So I want this to be converted in to Objective C. I don't know how to do this. Help me out in this !!
I have searched some code in JAVA And I tried of doing it. But the problem is it will give some other decrypted data but not the exact one that gives using this code. So If I convert the same thing I may get the exact code I guess.
People might be knowing JAVA as well as Objective c here. Those people can help me i guess.
I'm not sure, but you can try it :).
For the encode phase :
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
// Cipher is not thread safe
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivParameterSpec);
byte[] encryptedByte=cipher.doFinal(clearText);
String encrypedValue = new String(Base64.encodeBase64(encryptedByte));
Using CCCrypt in Obj-C :
CCCryptorStatus CCCrypt(
CCOperation op, //is kCCEncrypt in your case
CCAlgorithm alg, //is kCCAlgorithmAES128
CCOptions options, //is kCCModeCBC
const void *key, //may be skeySpec
size_t keyLength,
const void *iv, // is your iv key : ivParameterSpec
const void *dataIn,
size_t dataInLength,
void *dataOut, /* data RETURNED here */
size_t dataOutAvailable,
size_t *dataOutMoved)
__OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_2_0);
Please reference : CCCrypt decrypting in AES CBC works even without IV
for more information, Hope this help you.
Hey I got the answer go through these links below you will get the exact code for Android and IOS...
https://gist.github.com/m1entus/f70d4d1465b90d9ee024

last block incomplete with CipherInputStream/CipherOutputStream, even with padding AES/CBC/PKCS5Padding

Actually, I searched lot from internet and in stackoverflow too for this,
Initially I don't used padding in my encryption and decryption,
But Finally I got solution from here
https://stackoverflow.com/a/10775577/1115788
and I updated my code with padding as AES/CBC/PKCS5Padding
and the same error is coming, and last block is not decrypted...
I'm working on this for last two day, but no solution found
my Crypter Code:
package mani.droid.browsedropbox;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class Crypter {
Cipher encipher;
Cipher decipher;
CipherInputStream cis;
CipherOutputStream cos;
FileInputStream fis;
byte[] ivbytes = new byte[]{(byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g', (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n', (byte)'o', (byte)'p'};
IvParameterSpec iv = new IvParameterSpec(ivbytes);
public boolean enCrypt(String key, InputStream is, OutputStream os)
{
try {
byte[] encoded = new BigInteger(key, 16).toByteArray();
SecretKey seckey = new SecretKeySpec(encoded, "AES");
encipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
encipher.init(Cipher.ENCRYPT_MODE, seckey, iv);
cis = new CipherInputStream(is, encipher);
copyByte(cis, os);
return true;
}
catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
public boolean deCrypt(String key, InputStream is, OutputStream os)
{
try {
byte[] encoded = new BigInteger(key, 16).toByteArray();
SecretKey seckey = new SecretKeySpec(encoded, "AES");
encipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
encipher.init(Cipher.DECRYPT_MODE, seckey, iv);
cos = new CipherOutputStream(os, encipher);
copyByte(is, cos);
//cos.close();
return true;
}
catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
public void copyByte(InputStream is, OutputStream os) throws IOException
{
byte[] buf = new byte[8192];
int numbytes;
while((numbytes = is.read(buf)) != -1)
{
os.write(buf, 0, numbytes);
os.flush();
}
os.close();
is.close();
}
}
I've had exactly the same problem.
The accepted solution works because you've used cipher mode that does not require padding, but this is not a way crypto-related issues are fixed.
According to the CipherOutputStream documentation, you have to call close() method in order to finalize encryption properly (i.e., padding block is added).
This method invokes the doFinal method of the encapsulated cipher
object, which causes any bytes buffered by the encapsulated cipher to
be processed. The result is written out by calling the flush method of
this output stream.
This method resets the encapsulated cipher object to its initial state
and calls the close method of the underlying output stream.
If you want to preserve OutputStream open even after calling CipherOutputStream.close() method, you can wrap OutputStream to the stream that does not close it. For example:
public class NotClosingOutputStream extends OutputStream {
private final OutputStream os;
public NotClosingOutputStream(OutputStream os) {
this.os = os;
}
#Override
public void write(int b) throws IOException {
os.write(b);
}
#Override
public void close() throws IOException {
// not closing the stream.
}
#Override
public void flush() throws IOException {
os.flush();
}
#Override
public void write(byte[] buffer, int offset, int count) throws IOException {
os.write(buffer, offset, count);
}
#Override
public void write(byte[] buffer) throws IOException {
os.write(buffer);
}
}
Then you can use:
...
cos = new CipherOutputStream(new NotClosingOutputStream(os), encipher);
copyByte(is, cos);
cos.close();
...
Note the os stream does not get closed, you need to do it on your own when appropriate.
Finally I got answer for my own question, with trial and error
Actually here Conflict is I set Padding in encipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
and Set IV with some values.....,
Finally I got Answer only just replaced the Algorithm
From:
AES/CBC/PKCS7Paddinng
To:
AES/CFB8/NoPadding
and its worked like charm...., So I suggest this answer for others who struggling with this problem, if you solved you problem, mention here for others...
I've seen CipherInputStream fail with padding problems too. This behaviour varied across different versions of the JVM. Eg 7u55 32 bit my code worked fine, 7u55 64 bit same code failed... and I also saw failures on later 32 bit JVMs. Workaround was to use byte array methods and avoid CipherInputStream.
Not sure if this is relevant to OP's problem, but this may help someone.
When you repeatedly get that java.io.IOException: last block incomplete in decryption regardless of what you change, check if you are still using the file from some previous run. If your read/write test code appends to that file, you will always get that exception -- unless you delete the corrupt file that you write to.
Using CipherInputStream with padding is possible, switching to NoPadding is a workaround but not a solution.
Padding is applied when CipherInputStream reaches the end of the stream. The important point is that you have to call the read() method of the CipherInputStream at least twice for getting all the data.
The following example demonstrates reading a CipherInputStream with padding:
public static void test() throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecureRandom rnd = new SecureRandom();
byte[] keyData = new byte[16];
byte[] iv = new byte[16];
rnd.nextBytes(keyData);
rnd.nextBytes(iv);
SecretKeySpec key = new SecretKeySpec(keyData, "AES");
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
CipherOutputStream out = new CipherOutputStream(buffer, cipher);
byte[] plain = "Test1234567890_ABCDEFG".getBytes();
out.write(plain);
out.flush();
out.close();
byte[] encrypted = buffer.toByteArray();
System.out.println("Plaintext length: " + plain.length);
System.out.println("Padding length : " + (cipher.getBlockSize() - (plain.length % cipher.getBlockSize())));
System.out.println("Cipher length : " + encrypted.length);
cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
CipherInputStream in = new CipherInputStream(new ByteArrayInputStream(encrypted), cipher);
buffer = new ByteArrayOutputStream();
byte[] b = new byte[100];
int read;
while ((read = in.read(b)) >= 0) {
buffer.write(b, 0, read);
}
in.close();
// prints Test1234567890_ABCDEFG
System.out.println(new String(buffer.toByteArray()));
}
For those who are struggling with aes encryption / decryption with image file, here is my example, and it works like a charm.
public static String decrypt(String textToDecrypt) {
byte[] dataDecrypted = null;
try {
Cipher cipher = getCipher();
SecretKey key = getKey();
IvParameterSpec iv = getIV();
if(cipher == null) {
return null;
}
cipher.init(Cipher.DECRYPT_MODE, key, iv);
byte[] dataToDecrypt = Base64.decode(textToDecrypt, Base64.NO_WRAP);
ByteArrayInputStream bais = new ByteArrayInputStream(dataToDecrypt);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// Wrap the output stream
CipherOutputStream cos = new CipherOutputStream(baos, cipher);
// Read bytes
int count = 0;
byte[] buffer = new byte[DEFAULT_BYTE_READ_WRITE_BLOCK_BUFFER_SIZE];
while ((count = bais.read(buffer)) != -1) {
cos.write(buffer, 0, count);
}
cos.close(); // manually do close for the last bit
dataDecrypted = baos.toByteArray();
// Close streams.
baos.close();
bais.close();
} catch (Exception e) {
e.printStackTrace();
}
return (dataDecrypted == null ? "" : Base64.encodeToString(dataDecrypted, Base64.NO_WRAP));
}
public static String encrypt(String textToEncrypt) {
byte[] dataEncrypted = null;
try {
Cipher cipher = getCipher();
SecretKey key = getKey();
IvParameterSpec iv = getIV();
if (cipher == null) {
return null;
}
cipher.init(Cipher.ENCRYPT_MODE, key, iv);
byte[] dataToEncrypt = Base64.decode(textToEncrypt, Base64.NO_WRAP);
ByteArrayInputStream bais = new ByteArrayInputStream(dataToEncrypt);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// Wrap the output stream
CipherOutputStream cos = new CipherOutputStream(baos, cipher);
// Read bytes
int count = 0;
byte[] buffer = new byte[DEFAULT_BYTE_READ_WRITE_BLOCK_BUFFER_SIZE];
while ((count = bais.read(buffer)) != -1) {
cos.write(buffer, 0, count);
}
cos.close(); // manually do close for the last bit
dataEncrypted = baos.toByteArray();
// Close streams.
baos.close();
bais.close();
} catch (Exception e) {
e.printStackTrace();
}
return (dataEncrypted == null ? "" : Base64.encodeToString(dataEncrypted, Base64.NO_WRAP));
}

java AES-128-CBC decryption

Given that i know that aes-128-cbc was used to generate ciphertext, no salting was used and the IV are all zeros my goal was to write a program to find out the key used to encrypt the plain text (i was also given a dictionary of possible keys used).
So I have implemented the following
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public class myClassName123 {
/**
* #param args
* #throws Exception
*/
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
try {
BufferedReader in = new BufferedReader(new FileReader("/Users/username/Documents/f12/words.txt"));
String str;
while ((str = in.readLine()) != null && str.getBytes().length<16) { //clue given in spec
System.out.println(decrypt(getBytesFromFile(new File("/Users/username/Documents/f21/some.aes-128-cbc")),str));
}
in.close();
} catch (IOException e) {
}
}
/**
* This method decrypts the input byte [] using AES Key byte []
*
* #param byte []
* #param byte []
* #return byte []
* #throws Exception
*/
public static byte[] decrypt(byte[] text, String key) throws Exception {
Cipher cipher;
byte[] bytes = null;
Provider provider = new BouncyCastleProvider();
MessageDigest digester = MessageDigest.getInstance("SHA-256", provider);
digester.update(key.getBytes("UTF-8"));
//byte[] key = digester.digest();
SecretKeySpec spec = new SecretKeySpec(digester.digest(), "AES");
//SecretKeySpec spec = new SecretKeySpec(toByteArray(key.toCharArray()), "AES");
byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
IvParameterSpec ivspec = new IvParameterSpec(iv);
try {
// Instantiate the cipher
cipher = Cipher.getInstance("AES/CBC/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, spec, ivspec);
bytes = cipher.doFinal(text);
String value = new String(bytes, "UTF-8");
System.out.println("DEBUG HERE: "+value);
}catch (NoSuchAlgorithmException e) {
e.printStackTrace();
// throw new Exception(e);
} catch (NoSuchPaddingException e) {
e.printStackTrace();
// throw new Exception(e);
} catch (InvalidKeyException e) {
e.printStackTrace();
//throw new Exception(e);
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
//throw new Exception(e);
} catch (BadPaddingException e) {
e.printStackTrace();
//throw new Exception(e);
}
return bytes;
}
// Returns the contents of the file in a byte array.
public static byte[] getBytesFromFile(File file) throws IOException {
InputStream is = new FileInputStream(file);
// Get the size of the file
long length = file.length();
// Create the byte array to hold the data
byte[] bytes = new byte[(int)length];
// Read in the bytes
int offset = 0;
int numRead = 0;
while (offset < bytes.length
&& (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
offset += numRead;
}
// Ensure all the bytes have been read in
if (offset < bytes.length) {
throw new IOException("Could not completely read file "+file.getName());
}
// Close the input stream and return bytes
is.close();
return bytes;
}
}
However when i run this I get the following:
DEBUG HERE: (M��1�����-��e�}�p����+��
[B#4ed1e89e
I think I am not converting to String correctly but I am currently stuck with this.
any help is much appreciated, thank you very much.
If the problem is that the characters are not being displayed properly, it maybe because of the result of the decryption contains non-printable chars.
Even it the orignal was plaint text it makes sense this behaviour, as you are trying with different keys. If you choose a wrong one, you will probably get this kind of result.
You can also display the string as hex (http://stackoverflow.com/questions/923863/converting-a-string-to-hexadecimal-in-java), which may make it a bit more readable.
hope it helps

How to encrypt and decrypt URl parameter in java?

How to encrypt and decrypt URl parameter in java without having the html characters like '/,&,=?'
import java.io.UnsupportedEncodingException;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.KeySpec;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
public class DesEncrypter {
Cipher ecipher;
Cipher dcipher;
byte[] salt = {
(byte)0xA9, (byte)0x9B, (byte)0xC8, (byte)0x32,
(byte)0x56, (byte)0x35, (byte)0xE3, (byte)0x03
};
int iterationCount = 3;
public DesEncrypter(String passPhrase) {
try{
KeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(), salt, iterationCount);
SecretKey key = SecretKeyFactory.getInstance("PBEWithMD5AndDES").generateSecret(keySpec);
ecipher = Cipher.getInstance(key.getAlgorithm());
dcipher = Cipher.getInstance(key.getAlgorithm());
AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, iterationCount);
ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
} catch (java.security.InvalidAlgorithmParameterException e){
} catch (java.security.spec.InvalidKeySpecException e){
} catch (javax.crypto.NoSuchPaddingException e){
} catch (java.security.NoSuchAlgorithmException e){
} catch (java.security.InvalidKeyException e){
}
}
public String encrypt(String str){
try{
byte[] utf8 = str.getBytes("UTF8");
byte[] enc = ecipher.doFinal(utf8);
return new sun.misc.BASE64Encoder().encode(enc);
} catch (javax.crypto.BadPaddingException e){
} catch (IllegalBlockSizeException e){
} catch (UnsupportedEncodingException e){
}
return null;
}
public String decrypt(String str){
try{
byte[] dec = new sun.misc.BASE64Decoder().decodeBuffer(str);
byte[] utf8 = dcipher.doFinal(dec);
return new String(utf8,"UTF8");
} catch (javax.crypto.BadPaddingException e){
} catch (IllegalBlockSizeException e){
} catch (UnsupportedEncodingException e){
} catch (java.io.IOException e){
}
return null;
}
}
My Code is as above and i am getting encrypted result:6puu4YjzScxHsv9tI/N92g==
In the above output due to backslash i am getting the error that i want to avoid.
Instead of
byte[] utf8 = str.getBytes("UTF8");
byte[] enc = ecipher.doFinal(utf8);
return new sun.misc.BASE64Encoder().encode(enc);
Use Apache Commons URL Safe 64 bit encoder to encode after encryption.
Base64.encodeBase64URLSafeString(enc);
To decode before descryption:
Base64.decodeBase64(dec)
Please Note this is ENCODER not encryptor. But the String is URL safe.
Ideally, you should always Encode your URL using URL Encoder which will ensure that special characters are encoded. So, even if you are having a URL with restricted characters, it will be safe.

Categories