I am trying to make this code work to encrypt an image using AES algorithm and its modes, then view the encrypted image.
So the bytes of the header is not encrypted and the content was. When writing the image to the new file, the header was used first and then the encrypted content so that we can open it as an image file.
But I am unable to open it. Any help would be appreciated. I am new to coding, learning as I go :)
Thanks
enter code here
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class test {
private static SecretKeySpec secretKey ;
private static byte[] key ;
static String encodekey = "770A8A65DA156D24EE2A093277530142";
static String IV = "AAAAAAAAAAAAAAAA";
public static void main(String[] args) {
encrypt(new File("/Users/uni/IdeaProjects/ExtendedExperimentalAPI”/src/image.jpeg"));
}
public static void encrypt(File file){
setKey(encodekey);
String fileName = file.getName();
byte[] fileBytes = fileToBytes(file);
//save the header from file so it is accessible as image after encryption
byte[] header = new byte[55];
for(int i = 0; i<55; i++){
header[i] = fileBytes[i];
}
byte[] toEncrypt = Arrays.copyOfRange(fileBytes, 55, fileBytes.length);
Cipher cipher;
try {
//block to encrypt using ECB and save file
cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] cipherDataECB = cipher.doFinal(toEncrypt);
FileOutputStream fos = new FileOutputStream("ECB" + fileName, true);//append to file
fos.write(header);
fos.write(cipherDataECB);
fos.close();
//block to encrypt using CBC and save file
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey,new IvParameterSpec(IV.getBytes("UTF-8")));
byte[] cipherDataCBC = cipher.doFinal(toEncrypt);
fos = new FileOutputStream("CBC" + fileName, true);
fos.write(header);
fos.write(cipherDataCBC);
fos.close();
//block to encrypt using CFB and save file
cipher = Cipher.getInstance("AES/CFB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey,new IvParameterSpec(IV.getBytes("UTF-8")));
byte[] cipherDataCFB = cipher.doFinal(toEncrypt);
fos = new FileOutputStream("CFB" + fileName, true);//append to file
fos.write(header);
fos.write(cipherDataCFB);
fos.close();
} catch (InvalidAlgorithmParameterException | NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | FileNotFoundException e) {
System.out.println("Error while encrypting file");
} catch (IOException e) {
System.out.println("Error writing to the file");
}
}
static void setKey(String myKey){
MessageDigest sha = null;
try {
key = myKey.getBytes("UTF-8");
sha = MessageDigest.getInstance("SHA-1");
key = sha.digest(key);
key = Arrays.copyOf(key, 16); // use only first 128 bit
secretKey = new SecretKeySpec(key, "AES");
} catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
System.out.println("Error setting the key for encryption");
}
}
static byte[] fileToBytes(File file){
FileInputStream fileInputStream=null;
byte[] bFile = new byte[(int) file.length()];
//convert file into array of bytes
try{
fileInputStream = new FileInputStream(file);
fileInputStream.read(bFile);
fileInputStream.close();
} catch(FileNotFoundException e){
System.out.println("Specified file not found");
} catch (IOException e) {
System.out.println("Error reading from the file");
}
return bFile;
}
}
Related
I am trying to decrypt a file that was encrypted in Java using AES/CBC/PKCS5Padding. However, I'm having some trouble completely decrypting the file. I think I'm missing something simple. I am pretty new to encryption, so this is highly probable:
import base64
import re
from Crypto import Random
from Crypto.Cipher import AES
# generate the key
passphrase = "my_secret_passphrase"
key = passphrase[0:16].encode()
# load in the encrypted file as bytes
file_name = "tbd/enc.csv"
with open(file_name, "rb") as in_file:
encrypted_bytes = in_file.read()
# initialize the cipher
iv = Random.new().read(AES.block_size)
cipher = AES.new(key, AES.MODE_CBC, iv)
# use the cipher to decrypt the bytes
decrypted_bytes = cipher.decrypt(encrypted_bytes)
# write to an out_file
file = re.sub("\.csv", "_decoded.csv", file)
with open(file, "wb") as binary_file:
binary_file.write(decrypted_bytes)
Here's a the first line of text from what I get:
M¢p†‘GW§'tÄ%èéired Date,Employees - Id,First,Employees - Middle,Last,Employees - Preferred Name,Job Title,Employees - Marital Status,Employees - Trade Code,...
I noticed that the first 16 chars are complete gibberish, so I know I'm close. What could I be missing that is causing the first 16 chars to not be decoded properly? The weird thing is that we are able to decrypt the entire file in java, so we know its something wrong with the python implementation.
Bonus Round: the java code used to encrypt the file (I did not code it nor do I know java):
package rpa.ipaengine.bots.cmic.test;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.Security;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TestFile {
private static Logger LOGGER = LoggerFactory.getLogger(TestFile.class);
public static void main(String[] args) {
LOGGER.info("running");
try {
Security.setProperty("crypto.policy", "unlimited");
encryptedFile("my_secret_passphrase", "/tbd/enc.csv", "tbd/dec.csv");
decryptedFile("my_secret_passphrase", "/tbd/enc.csv", "tbd/dec.csv");
} catch (Exception e) {
e.printStackTrace();
}
}
public static void encryptedFile(String secretKey, String fileInputPath, String fileOutPath)
throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IOException, IllegalBlockSizeException,
BadPaddingException {
try {
byte[] raw1 = "my_secret_passphrase"
.getBytes();
byte[] raw = new String(raw1, 0, 16).getBytes();
Key skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] iv = new byte[cipher.getBlockSize()];
IvParameterSpec ivParams = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivParams);
var fileInput = new File(fileInputPath);
var inputStream = new FileInputStream(fileInput);
var inputBytes = new byte[(int) fileInput.length()];
inputStream.read(inputBytes);
var outputBytes = cipher.doFinal(inputBytes);
var fileEncryptOut = new File(fileOutPath);
var outputStream = new FileOutputStream(fileEncryptOut);
outputStream.write(outputBytes);
inputStream.close();
outputStream.close();
System.out.println("File successfully encrypted!");
System.out.println("New File: " + fileOutPath);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void decryptedFile(String secretKey, String fileInputPath, String fileOutPath)
throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IOException, IllegalBlockSizeException,
BadPaddingException, InvalidAlgorithmParameterException {
try {
byte[] raw1 = "my_secret_passphrase"
.getBytes();
byte[] raw = new String(raw1, 0, 16).getBytes();
Key skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] iv = new byte[cipher.getBlockSize()];
IvParameterSpec ivParams = new IvParameterSpec(iv);
cipher.init(Cipher.DECRYPT_MODE, skeySpec, ivParams);
var fileInput = new File(fileInputPath);
var inputStream = new FileInputStream(fileInput);
var inputBytes = new byte[(int) fileInput.length()];
inputStream.read(inputBytes);
byte[] outputBytes = cipher.doFinal(inputBytes);
var fileEncryptOut = new File(fileOutPath);
var outputStream = new FileOutputStream(fileEncryptOut);
outputStream.write(outputBytes);
inputStream.close();
outputStream.close();
System.out.println("File successfully decrypted!");
System.out.println("New File: " + fileOutPath);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Using bytes(16) as matt suggested, I was able to decipher the text completely:
import base64
import re
from Crypto import Random
from Crypto.Cipher import AES
# generate the key
passphrase = "my_secret_passphrase"
key = passphrase[0:16].encode()
# load in the encrypted file as bytes
file_name = "tbd/enc.csv"
with open(file_name, "rb") as in_file:
encrypted_bytes = in_file.read()
# initialize the cipher
iv = bytes(16)
cipher = AES.new(key, AES.MODE_CBC, iv)
# use the cipher to decrypt the bytes
decrypted_bytes = cipher.decrypt(encrypted_bytes)
# write to an out_file
file = re.sub("\.csv", "_decoded.csv", file)
with open(file, "wb") as binary_file:
binary_file.write(decrypted_bytes)
First line of file:
Employees - Hired Date,Employees - Id,First,Employees - Middle...
However Michael provides some valid comments about the Java code used to encrypt the file. I will work with my team to make sure its more secure.
I am reading a large file in small-small bytes chunks. I am encrypting that file, chunk by chunk, using AES 128 bit encryption and writing each encrypted chunk into another file. The File is Encrypted successfully.
But when I am reading that encrypted file back in small-small bytes chunks and trying to decrypt that file- chunk by chunk, it throws an Exception
java - javax.crypto.BadPaddingException: Given final block not properly padded
But when I am trying to read the whole file and try to decrypt bytes, it decryptes successfully.
Here is my code:
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.File;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
/**
* Created by Ashish Pancholi on 22-12-2016.
*/
public class EncryDecryPtion implements Securable{
public static void main(String[] argu){
EncryDecryPtion encryDecryPtion = new EncryDecryPtion();
File file = new File("shouldbeoriginal.jpg");
try {
encryDecryPtion.encryptFile(file,"Pa$$w0rd");
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
}
File file_ = new File("shouldbeoriginal.jpg");
try {
encryDecryPtion.decryptFile(file_,"Pa$$w0rd");
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
}
}
}
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
/**
* Encrypt and decrypt file with AES algorithm
* Created by Ashish Pancholi on 20-12-2016.
*/
public interface Securable {
/**
* Read and write the file in chunk.
* Encrypts the chunks with AES algorithm.
* It creates a new a file which having encrypted data,
* deletes old original file and
* rename a new file with the old file
* #param file which is to be encrypted and password.
*/
default File encryptFile(File file, String password) throws IOException, NoSuchAlgorithmException, IllegalBlockSizeException, InvalidKeyException, BadPaddingException, NoSuchPaddingException {
AESEncryptionDecryption aesEncryptionDecryption = new AESEncryptionDecryption(password);
String encryptedFilePath = file.getAbsolutePath() + ".ENCRYPTED";
File encryptedFile = new File(encryptedFilePath);
encryptedFile.createNewFile();
try
(FileInputStream in = new FileInputStream(file)) {
try
(OutputStream out = new FileOutputStream(encryptedFile)) {
byte[] chunk = new byte[1024];
int chunkLen = 0;
while ((chunkLen = in.read(chunk)) != -1) {
byte[] encryptedChunk = aesEncryptionDecryption.encrypt(chunk);
out.write(encryptedChunk);
}
}
}
Path path_originalFile = Paths.get(file.getAbsolutePath());
Path path_encryptedFile = Paths.get(encryptedFile.getAbsolutePath());
try {
Files.delete(path_originalFile);
}catch (IOException ex){
try {
FileUtils.forceDelete(file);
}catch (IOException ex1){
//ignore
}
}
Path path = Files.move(path_encryptedFile, path_originalFile);
return path.toFile();
}
default File encryptWholeFile(File file, String password) throws IOException, NoSuchAlgorithmException, IllegalBlockSizeException, InvalidKeyException, BadPaddingException, NoSuchPaddingException {
AESEncryptionDecryption aesEncryptionDecryption = new AESEncryptionDecryption(password);
String encryptedFilePath = file.getAbsolutePath() + ".ENCRYPTED";
File encryptedFile = new File(encryptedFilePath);
encryptedFile.createNewFile();
try(FileInputStream in = new FileInputStream(file)) {
byte[] bytes = IOUtils.toByteArray(in);
byte[] encryptedChunk = aesEncryptionDecryption.encrypt(bytes);
FileUtils.writeByteArrayToFile(encryptedFile, encryptedChunk);
}
Path path_originalFile = Paths.get(file.getAbsolutePath());
Path path_encryptedFile = Paths.get(encryptedFile.getAbsolutePath());
try {
Files.delete(path_originalFile);
}catch (IOException ex){
try {
FileUtils.forceDelete(file);
}catch (IOException ex1){
//ignore
}
}
Path path = Files.move(path_encryptedFile, path_originalFile);
return path.toFile();
}
/**
* Read and write the file in chunk.
* Encrypts the chunks with AES algorithm.
* It creates a new a file which having encrypted data,
* deletes old original file and
* rename a new file with the old file
* #param inputStream of file which is to be encrypted and a password.
*/
default InputStream encryptFile(InputStream inputStream, String password) throws IOException, NoSuchAlgorithmException, IllegalBlockSizeException, InvalidKeyException, BadPaddingException, NoSuchPaddingException {
InputStream in;
try {
AESEncryptionDecryption aesEncryptionDecryption = new AESEncryptionDecryption(password);
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
byte[] chunk = new byte[1024];
int chunkLen = 0;
while ((chunkLen = inputStream.read(chunk)) != -1) {
byte[] encryptedChunk = aesEncryptionDecryption.encrypt(chunk);
baos.write(encryptedChunk);
}
baos.flush();
in = new ByteArrayInputStream(baos.toByteArray());
}
}finally {
inputStream.close();
}
return in;
}
/**
* Read and write the file in chunk.
* Encrypts the chunks with AES algorithm.
* It creates a new a file which having encrypted data,
* deletes old original file and
* rename a new file with the old file
* #param inputStream of file which is to be encrypted and a password.
*/
default File encryptFile(InputStream inputStream, String password, String targetFileName) throws IOException, NoSuchAlgorithmException, IllegalBlockSizeException, InvalidKeyException, BadPaddingException, NoSuchPaddingException {
File encryptedFile = new File(targetFileName);
try {
AESEncryptionDecryption aesEncryptionDecryption = new AESEncryptionDecryption(password);
encryptedFile.getParentFile().mkdirs();
encryptedFile.createNewFile();
try (OutputStream baos = new FileOutputStream(encryptedFile)) {
byte[] chunk = new byte[1024];
int chunkLen = 0;
while ((chunkLen = inputStream.read(chunk)) != -1) {
byte[] encryptedChunk = aesEncryptionDecryption.encrypt(chunk);
baos.write(encryptedChunk);
}
}
}finally {
inputStream.close();
}
return encryptedFile;
}
/**
* Read and write the file in chunk.
* Decrypts the chunks with AES algorithm.
* It creates a new a file which having decrypted data,
* deletes old original encrypted file and
* rename a new file with the old file
* #param file which is to be decrypted and password.
*/
default void decryptFile(File file, String password) throws IOException, NoSuchAlgorithmException, IllegalBlockSizeException, InvalidKeyException, BadPaddingException, NoSuchPaddingException {
AESEncryptionDecryption aesEncryptionDecryption = new AESEncryptionDecryption(password);
String decryptedFilePath = file.getAbsolutePath() + ".DECRYPTED";
File decryptedFile = new File(decryptedFilePath);
decryptedFile.createNewFile();
try
(FileInputStream in = new FileInputStream(file)) {
try
(OutputStream out = new FileOutputStream(decryptedFile)) {
byte[] chunk = new byte[1024];
int chunkLen = 0;
while ((chunkLen = in.read(chunk)) != -1) {
byte[] encryptedChunk = aesEncryptionDecryption.decrypt(chunk);
out.write(encryptedChunk);
}
}
}
Path path_originalFile = Paths.get(file.getAbsolutePath());
Path path_decryptedFile = Paths.get(decryptedFile.getAbsolutePath());
try {
Files.delete(path_originalFile);
}catch (IOException ex){
try {
FileUtils.forceDelete(file);
}catch (IOException ex1){
//ignore
}
}
Files.move(path_decryptedFile, path_originalFile);
}
default File decryptWholeFile(File file, String password) throws IOException, NoSuchAlgorithmException, IllegalBlockSizeException, InvalidKeyException, BadPaddingException, NoSuchPaddingException {
AESEncryptionDecryption aesEncryptionDecryption = new AESEncryptionDecryption(password);
String decryptedFilePath = file.getAbsolutePath() + ".DECRYPTED";
File decryptedFile = new File(decryptedFilePath);
decryptedFile.createNewFile();
try(FileInputStream in = new FileInputStream(file)) {
byte[] bytes = IOUtils.toByteArray(in);
byte[] encryptedChunk = aesEncryptionDecryption.decrypt(bytes);
FileUtils.writeByteArrayToFile(decryptedFile, encryptedChunk);
}
Path path_originalFile = Paths.get(file.getAbsolutePath());
Path path_decryptedFile = Paths.get(decryptedFile.getAbsolutePath());
try {
Files.delete(path_originalFile);
}catch (IOException ex){
try {
FileUtils.forceDelete(file);
}catch (IOException ex1){
//ignore
}
}
Path path = Files.move(path_decryptedFile, path_originalFile);
return path.toFile();
}
}
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
/**
* Encrypt and decrypt file with AES algorithm
* Created by Ashish Pancholi on 20-12-2016.
*/
public class AESEncryptionDecryption {
private SecretKeySpec secretKey;
private byte[] key;
public AESEncryptionDecryption(String password) throws NoSuchAlgorithmException, UnsupportedEncodingException{
MessageDigest sha = null;
key = password.getBytes("UTF-8");
sha = MessageDigest.getInstance("SHA-1");
key = sha.digest(key);
key = Arrays.copyOf(key, 16); // use only first 128 bit
this.secretKey = new SecretKeySpec(key, "AES");
}
/**
* Encrypts the file with AES algorithm
* #param bytes of file which is to encrypted
* #return byte[] which is encrypted bytes
*/
public byte[] encrypt(byte[] bytes) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, this.secretKey);
byte[] encrytedBytes = cipher.doFinal(bytes);
return encrytedBytes;
}
/**
* Decrypts the file with AES algorithm
* #param encrytedBytes of file that to be decrypted
* #return byte[] which is original data.
*/
public byte[] decrypt(byte[] encrytedBytes) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException
{
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, this.secretKey);
byte[] bytes = cipher.doFinal(encrytedBytes);
return bytes;
}
}
SO my Question is- How to encrypt a large file without loading the whole file in the memory? Please help.
EDITED
Here is the updated code but still I am getting the same exception on line cipher.doFinal() when decrypting:
public void encrypt(File sourceFile, File targetFile) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, IOException {
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, this.secretKey);
try(InputStream inputStream = new FileInputStream(sourceFile)){
try(OutputStream outputStream = new FileOutputStream(targetFile)){
byte[] chunk = new byte[8192];
int chunkLen = 0;
while ((chunkLen = inputStream.read(chunk)) != -1) {
byte[] encrytedBytes = cipher.update(chunk);
outputStream.write(encrytedBytes);
}
byte[] finalBytes = cipher.doFinal();
if(finalBytes!=null) {
outputStream.write(finalBytes);
}
}
}
}
public void decrypt(File encryptedFile, File targetFile) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, IOException {
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, this.secretKey);
try(InputStream inputStream = new FileInputStream(encryptedFile)){
try(OutputStream outputStream = new FileOutputStream(targetFile)){
byte[] chunk = new byte[8192];
int chunkLen = 0;
while ((chunkLen = inputStream.read(chunk)) != -1) {
byte[] decrytedBytes = cipher.update(chunk);
outputStream.write(decrytedBytes);
}
byte[] finalBytes = cipher.doFinal();
if(finalBytes!=null) {
outputStream.write(finalBytes);
}
}
}
}
You should use the cipher.update(...) methods when you stream through the file, and only use the cipher.doFinal(...) as the last call. The doFinal flushes the buffers + do padding etc, that you don't want to do more than one time.
If you do a doFinal(...) in your decrypt prematurely, it will (very likely) fail as a correct padding is missing in the data.
Edit:
Don't use ECB mode it's insecure. Take a look here and scroll down to the penguin.
Don't generate your keys by a simple Sha-1 - use a proper key deriviation function like PBKDF2WithHmacSHA256.
Initially I was using cipher.doFinal() for both Encryption and Decryption modes. Runtime Exceution was fine but testcases were failing with BadPaddingException(). Then I changed the code to
byte[] output = this.cipher.update(input, 0, input.length);
And now the decryption is working fine. Same goes for Encryption as well.
I have a web app which is deployed on tomcat in both Linux and windows environment . Blowfish algo has been implemented for login password encryption/security check. It works fine in windows but throws illegal key size exception in linux. key file is packed with war
I have gone through multiple post but nothing really helped me.
generating key file
/** Generate a secret TripleDES encryption/decryption key */
KeyGenerator keygen = KeyGenerator.getInstance(SecurityConstant.BLOW_FISH_ALGO);
// Use it to generate a key
SecretKey key = keygen.generateKey();
// Convert the secret key to an array of bytes like this
byte[] rawKey = key.getEncoded();
// Write the raw key to the file
String keyPath = getBlowFishKeyPath();
FileOutputStream out = new FileOutputStream(keyPath);
Writer writer = new BufferedWriter(new OutputStreamWriter(out, "UTF-8"));
Files.write( Paths.get(keyPath),rawkey,StandardOpenOption.CREATE);
writer.close();
key comparision
String hexCipher = null;
try {
byte[] byteClearText = pwd.getBytes("UTF-8");
byte[] ivBytes = SecurityUtil.hexToBytes("0000000000000000");
// read secretkey from key file
byte[] secretKeyByte = secretKey.getBytes();
Cipher cipher = null;
SecretKeySpec key = new SecretKeySpec(secretKeyByte, SecurityConstant.BLOW_FISH_ALGO);
// Create and initialize the encryption engine
cipher = Cipher.getInstance(SecurityConstant.BLOW_FISH_CBC_ZEROBYTE_ALGO, SecurityConstant.BC);
IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec); // throws exception
byte[] cipherText = new byte[cipher.getOutputSize(byteClearText.length)];
int ctLength = cipher.update(byteClearText, 0, byteClearText.length, cipherText, 0);
ctLength += cipher.doFinal(cipherText, ctLength);
hexCipher = SecurityUtil.bytesToHex(cipherText);// hexdecimal password stored in DB
} catch (Exception e) {
ExceptionLogger.logException(logger, e);
}
made it simpler to test
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.security.NoSuchAlgorithmException;
import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.io.FileUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public class SecTest {
public static void main(String[] args) throws NoSuchAlgorithmException {
/** Generate a secret TripleDES encryption/decryption key */
Security.addProvider(new BouncyCastleProvider());
KeyGenerator keygen = KeyGenerator.getInstance("Blowfish");
// Use it to generate a key
SecretKey key = keygen.generateKey();
// Convert the secret key to an array of bytes like this
byte[] rawKey = key.getEncoded();
// Write the raw key to the file
String keyPath = "/data2/key/BlowFish.key";
FileOutputStream out = null;
try {
out = new FileOutputStream(keyPath);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Writer writer = null;
try {
writer = new BufferedWriter(new OutputStreamWriter(out, "UTF-8"));
Files.write( Paths.get(keyPath),rawKey,StandardOpenOption.CREATE);
writer.close();
out.close();
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
generateHexCode("a");
}
private static void generateHexCode(String pwd) {
String hexCipher = null;
try {
byte[] byteClearText = pwd.getBytes("UTF-8");
byte[] ivBytes = hexToBytes("0000000000000000");
// read secretkey from key file
byte[] secretKeyByte = readSecretKey().getBytes();
Cipher cipher = null;
SecretKeySpec key = new SecretKeySpec(secretKeyByte, "Blowfish");
// Create and initialize the encryption engine
cipher = Cipher.getInstance("Blowfish/CBC/ZeroBytePadding", "BC");
IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec); // throws exception
byte[] cipherText = new byte[cipher.getOutputSize(byteClearText.length)];
int ctLength = cipher.update(byteClearText, 0, byteClearText.length, cipherText, 0);
ctLength += cipher.doFinal(cipherText, ctLength);
hexCipher = bytesToHex(cipherText);// hexdecimal password stored in DB
System.out.println("hex cipher is "+hexCipher);
} catch (Exception e) {
e.printStackTrace();
}
}
private static String readSecretKey() {
byte[] rawkey = null;
String file ="";
// Read the raw bytes from the keyfile
String keyFile = "/data2/key/BlowFish.key";
String is = null;
try {
is = FileUtils.readFileToString(new File(keyFile),"UTF-8");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return is;
}
public static byte[] hexToBytes(String str) {
byte[] bytes = null;
if (str != null && str.length() >= 2) {
int len = str.length() / 2;
byte[] buffer = new byte[len];
for (int i = 0; i < len; i++) {
buffer[i] = (byte) Integer.parseInt(str.substring(i * 2, i * 2 + 2), 16);
}
bytes = buffer;
}
return bytes;
}
public static String bytesToHex(byte[] data) {
if (data == null) {
return null;
} else {
int len = data.length;
StringBuilder str = new StringBuilder();
for (int i = 0; i < len; i++) {
if ((data[i] & 0xFF) < 16) {
str = str.append("0").append(java.lang.Integer.toHexString(data[i] & 0xFF));
} else {
str.append(java.lang.Integer.toHexString(data[i] & 0xFF));
}
}
return str.toString().toUpperCase();
}
}
}
Made a simple program to test it out . This also runs fine on windows but fails on linux. any clue ?
I have to do encryption of text file using JCE (Java SE 1.6). For this I have written a method aes256CBCEncrypt which returns CipherOutputstream which I write in file 'encryptedtest'. Now when I am trying to do decryption of this file(named 'encryptedtest') using the method aes256CBCDecrypt, It returns me CipherInputStream which I am writing in 'decryptedtest' to verify its content. Surprisingly, this file is empty.
Can somebody help me out what is wrong with my code.
Code Snippet:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
class MyTest{
public static OutputStream aes256CBCEncrypt(OutputStream os, String passPhrase) throws NoSuchAlgorithmException, NoSuchPaddingException, IOException, InvalidKeyException, InvalidAlgorithmParameterException
{
// MessageDigest md = MessageDigest.getInstance("SHA-256");
// md.update(passPhrase.getBytes());
// byte[] key = md.digest();
Cipher aesCipher = Cipher.getInstance("AES/CBC/ISO10126Padding");
SecureRandom secureRandom = new SecureRandom();
secureRandom.setSeed(System.currentTimeMillis());
byte[] bb = new byte[16];
secureRandom.nextBytes(bb);
os.write(bb);
aesCipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(passPhrase.getBytes(), "AES"), new IvParameterSpec(
bb));
return new CipherOutputStream(os, aesCipher);
}
public static InputStream aes256CBCDecrypt(File f, String passPhrase)
throws FileNotFoundException
{
FileInputStream fis = null;
try
{
//MessageDigest md = MessageDigest.getInstance("SHA-256");
// md.update(passPhrase.getBytes());
// byte[] key = md.digest();
Cipher aesCipher = Cipher.getInstance("AES/CBC/ISO10126Padding");
fis = new FileInputStream(f);
byte[] bb = new byte[16];
fis.read(bb);
aesCipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(passPhrase.getBytes(), "AES"), new IvParameterSpec(
bb));
return new CipherInputStream(fis, aesCipher);
}
catch (final Exception e)
{
}
return null;
}
public static void main(String args[]) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, IOException{
String keyFile = "C:\\contentProducer" + File.separator + "test";
String encryptedFile = "C:\\contentProducer" + File.separator + "encryptedtest";
String decryptedFile = "C:\\contentProducer" + File.separator + "decryptedtest";
FileInputStream in = new FileInputStream(keyFile);
FileOutputStream bos = new FileOutputStream(new File(encryptedFile));
//Call method for Encryption
OutputStream encryptedBos = aes256CBCEncrypt(bos,"0123456789abcdef");
int inByte;
while ((inByte = in.read()) != -1 ) {
encryptedBos.write(inByte);
}
in.close();
bos.close();
encryptedBos.close();
//Call Method for Decryption
InputStream inputStream = aes256CBCDecrypt(new File(encryptedFile), "0123456789abcdef");
FileOutputStream deos = new FileOutputStream(new File(decryptedFile));
while ((inByte = inputStream.read()) != -1 ) {
deos.write(inByte);
}
inputStream.close();
deos.close();
}
}
You are closing your FileOutputStream before you close your CipherOutputStream. This prevents the latter from completing its work and writing the encrypted data to disk.
bos.close();
encryptedBos.close();
should change to:
encryptedBos.close();
bos.close();
I have an application which displays image downloaded from server. the image is encrypted and kept in the server using AES. I need to decrypt the image at the client side. The code used for encryption is as follows
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.MessageDigest;
import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.imageio.ImageIO;
public class Crypto {
Cipher ecipher;
Cipher dcipher;
/**
* Input a string that will be md5 hashed to create the key.
* #return void, cipher initialized
*/
public Crypto(){
try{
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128);
this.setupCrypto(kgen.generateKey());
} catch (Exception e) {
e.printStackTrace();
}
}
public Crypto(String key){
SecretKeySpec skey = new SecretKeySpec(getMD5(key), "AES");
this.setupCrypto(skey);
}
private void setupCrypto(SecretKey key){
try
{ Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
ecipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");
dcipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");
ecipher.init(Cipher.ENCRYPT_MODE, key);
dcipher.init(Cipher.DECRYPT_MODE, key);
}
catch (Exception e)
{
e.printStackTrace();
}
}
// Buffer used to transport the bytes from one stream to another
byte[] buf = new byte[1024];
public void encrypt(InputStream in, OutputStream out){
try {
// Bytes written to out will be encrypted
out = new CipherOutputStream(out, ecipher);
// Read in the cleartext bytes and write to out to encrypt
int numRead = 0;
while ((numRead = in.read(buf)) >= 0){
out.write(buf, 0, numRead);
}
out.close();
}
catch (java.io.IOException e){
e.printStackTrace();
}
}
public void decrypt(InputStream in, OutputStream out){
try {
// Bytes read from in will be decrypted
in = new CipherInputStream(in, dcipher);
// Read in the decrypted bytes and write the cleartext to out
int numRead = 0;
while ((numRead = in.read(buf)) >= 0) {
out.write(buf, 0, numRead);
}
out.close();
} catch (java.io.IOException e) {
e.printStackTrace();
}
}
private static byte[] getMD5(String input){
try{
byte[] bytesOfMessage = input.getBytes("UTF-8");
MessageDigest md = MessageDigest.getInstance("MD5");
return md.digest(bytesOfMessage);
} catch (Exception e){
return null;
}
}
public static void main(String args[]){
try {
Crypto encrypter = new Crypto("yursxjdlbkuikeqe"); ///key for decryption logic
encrypter.encrypt(new FileInputStream("D:\\Path\\Lighthouse.jpg"),new FileOutputStream("D:\\Encryption\\iOS code base\\Lighthouse.jpg.pkcs5"));
encrypter.decrypt(new FileInputStream("D:\\Path\\Lighthouse.jpg.pkcs5"),new FileOutputStream("D:\\Encryption\\iOS code base\\Lighthouse.jpg"));
System.out.println("DONE");
}
catch (Exception e) {
e.printStackTrace();
}
}
}
I am not able to decrypt this using Blackberry AESDecryptor Engine. I am new to this crypto graphy. Is it possible to decrypt using AESDecryptor engine. I am attaching the code which I am using. Please help me in solving this
public MyScreen(){
// Set the displayed title of the screen
setTitle("MyTitle");
byte[] keyData = new String("yursxjdlbkuikeqe").getBytes();
byte[] cipherText = openFile("file:///SDCard/Lighthouse.jpg.pkcs5");
try {
imageData = decrypt(keyData, cipherText);
} catch (CryptoException e) {
System.out.println("::::::::::::::::::::::::::::::::::Crypto Exception:::::::"+e.getMessage());
} catch (IOException e) {
System.out.println("::::::::::::::::::::::::::::::::::IO Exception:::::::"+e.getMessage());
}
if(imageData!=null){
writeByteData(imageData);
// EncodedImage image = EncodedImage.createEncodedImage(imageData, 0, imageData.length);
// add(new BitmapField(image.getBitmap()));
System.out.println("------------------Image saved successfully-----------");
}else{
System.out.println("-------------------Image Data is null");
}
}
public static byte[] decrypt(byte[] keyData, byte[] ciphertext) throws CryptoException, IOException {
// First, create the AESKey again.
/*String str=new String(keyData);
System.out.println(str);*/
AESKey key = new AESKey(keyData,0,128);
System.out.println("Key is ::"+key.getAlgorithm()+"Length:"+key.getBitLength());
//
// // Now, create the decryptor engine.
AESDecryptorEngine engine = new AESDecryptorEngine(key);
PKCS5UnformatterEngine uengine = new PKCS5UnformatterEngine(engine);
/
// // Create the BlockDecryptor to hide the decryption details away.
ByteArrayInputStream input = new ByteArrayInputStream(ciphertext);
BlockDecryptor decryptor = new BlockDecryptor(engine, input);
byte[] plaintextAndHash = new byte[1024];
ByteArrayOutputStream output = new ByteArrayOutputStream();
int bytesRead=0;
do{
bytesRead =decryptor.read(plaintextAndHash);
if(bytesRead!=-1){
output.write(plaintextAndHash,0,bytesRead);
}
}
while(bytesRead!=-1);
return output.toByteArray();
}
You don't really say what your problem is, but at least the following line looks incorrect:
BlockDecryptor decryptor = new BlockDecryptor(engine, input);
It should be
BlockDecryptor decryptor = new BlockDecryptor(uengine, input);
I just changed engine to uengine
RIM's APIs make this pretty easy but it is a little tough to find the documentation. Check out the Javadocs for the package net.rim.device.api.crypto at:
http://www.blackberry.com/developers/docs/7.0.0api/net/rim/device/api/crypto/package-summary.html
You should look through all of it but the answer is in number 7: Encryptor and decryptor factories.
http://www.blackberry.com/developers/docs/7.0.0api/net/rim/device/api/crypto/doc-files/factories.html
The DecryptorFactory can create an input stream that you can just read as any InputStream.