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();
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 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;
}
}
I am working on a Encryption/Decryption program in Java. I am using a key called "secret1234" to encrypt and decrypt a message from a text file. This program uses a string for the key. However, I am interested in using a number (integer) for the key so I can generate random numbers. So, how can this program be modified to allow the key to be an integer and not a string for encrypting and descrypting the message?
This is the program:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
public class Program {
public static void main(String[] args) {
try {
String key = "secret1234";// This is the key
FileInputStream fis = new FileInputStream("text.txt");//text.txt is a text file with a short message
FileOutputStream fos = new FileOutputStream("encryptedText.txt");
encrypt(key, fis, fos);
FileInputStream fis2 = new FileInputStream("encryptedText.txt");
FileOutputStream fos2 = new FileOutputStream("decryptedText.txt");
decrypt(key, fis2, fos2);
} catch (Throwable e) {
e.printStackTrace();
}
}
public static void encrypt(String key, InputStream is, OutputStream os) throws Throwable {
encryptOrDecrypt(key, Cipher.ENCRYPT_MODE, is, os);
}
public static void decrypt(String key, InputStream is, OutputStream os) throws Throwable {
encryptOrDecrypt(key, Cipher.DECRYPT_MODE, is, os);
}
public static void encryptOrDecrypt(String key, int mode, InputStream is, OutputStream os) throws Throwable {
DESKeySpec dks = new DESKeySpec(key.getBytes());
SecretKeyFactory skf = SecretKeyFactory.getInstance("DES");
SecretKey desKey = skf.generateSecret(dks);
Cipher cipher = Cipher.getInstance("DES");
if (mode == Cipher.ENCRYPT_MODE) {
cipher.init(Cipher.ENCRYPT_MODE, desKey);
CipherInputStream cis = new CipherInputStream(is, cipher);
doCopy(cis, os);
} else if (mode == Cipher.DECRYPT_MODE) {
cipher.init(Cipher.DECRYPT_MODE, desKey);
CipherOutputStream cos = new CipherOutputStream(os, cipher);
doCopy(is, cos);
}
}
public static void doCopy(InputStream is, OutputStream os) throws IOException {
byte[] bytes = new byte[64];
int numBytes;
while ((numBytes = is.read(bytes)) != -1) {
os.write(bytes, 0, numBytes);
}
os.flush();
os.close();
is.close();
}
}
Use this in your code to generate the key:
String key = String.valueOf(SecureRandom.getInstance("SHA1PRNG").nextInt());
Program is running now. It runs but then crashes. In my files folder it creates an encrypted file but it is blank. It also does not produce a decrypted file at all. I also changed the bit size to 128. What else I am missing in order to properly implement AES?
This is the modified program
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.Cipher;
import java.security.NoSuchAlgorithmException;
import java.security.InvalidKeyException;
import java.security.InvalidAlgorithmParameterException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.spec.DESKeySpec;
public class MyCiphers {
public static void main(String[] args) {
try {
BufferedReader br = new BufferedReader(new FileReader("key.txt"));
String key = br.readLine();
br.close();
FileInputStream fis = new FileInputStream("original.txt");
FileOutputStream fos = new FileOutputStream("encrypted.txt");
encrypt(key, fis, fos);
FileInputStream fis2 = new FileInputStream("encrypted.txt");
FileOutputStream fos2 = new FileOutputStream("decrypted.txt");
decrypt(key, fis2, fos2);
} catch (Throwable e) {
e.printStackTrace();
}
}
public static void encrypt(String key, InputStream is, OutputStream os) throws Throwable {
encryptOrDecrypt(key, Cipher.ENCRYPT_MODE, is, os);
}
public static void decrypt(String key, InputStream is, OutputStream os) throws Throwable {
encryptOrDecrypt(key, Cipher.DECRYPT_MODE, is, os);
}
public static void encryptOrDecrypt(String key, int mode, InputStream is, OutputStream os) throws Throwable {
SecretKeySpec dks = new SecretKeySpec(key.getBytes(),"AES");
Cipher cipher = Cipher.getInstance("AES");
if (mode == Cipher.ENCRYPT_MODE) {
cipher.init(Cipher.ENCRYPT_MODE, dks);
CipherInputStream cis = new CipherInputStream(is, cipher);
doCopy(cis, os);
} else if (mode == Cipher.DECRYPT_MODE) {
cipher.init(Cipher.DECRYPT_MODE, dks);
CipherOutputStream cos = new CipherOutputStream(os, cipher);
doCopy(is, cos);
}
}
public static void doCopy(InputStream is, OutputStream os) throws IOException {
byte[] bytes = new byte[128];
int numBytes;
while ((numBytes = is.read(bytes)) != -1) {
os.write(bytes, 0, numBytes);
}
os.flush();
os.close();
is.close();
}
}
As the error message says, there is no method getBytes() for the type InputStream.
You need to read the key and store it as a String.
eg.
rather than FileInputStream fisk ... do
BufferedReader br = new BufferedReader(new FileReader("Key.txt"));
String key = br.readLine();
br.close();
(assuming that your key file just contains the key on one line)
Then change your encrypt/decrypt and encryptOrDecrypt methods to take in the key as a String rather than InputStream
eg. encrypt(String key, InputStream is, OutputStream os)
Then you can call SecretKeySpec(key.getBytes(),"DES");
Also you realise that this is DES, not AES as you say right? If you want to use AES you will need a 128 bit key (or 192/256 bits)
O want to encrypt and decrypt files using my Java program.
These files are compiled Java .class files, I don't know what I am doing wrong. I am just testing now, but after encrypt and decrypt with the same key. It shows that file is
Exception in thread "AWT-EventQueue-0" java.lang.ClassFormatError: Truncated class file
and that class cannot be loaded.
There is my encrypter/decrypter class code:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
public class EncTool {
public static void encrypt(String key, String filename) throws Throwable {
InputStream is = new FileInputStream("SomeFile.class");
OutputStream os = new FileOutputStream("SomeFile.class");
encrypt(key, Cipher.ENCRYPT_MODE, is, os);
}
public static void decrypt(String key, String filename) throws Throwable {
InputStream is = new FileInputStream("SomeFile.class");
OutputStream os = new FileOutputStream("SomeFile.class");
decrypt(key, Cipher.DECRYPT_MODE, is, os);
}
public static void encrypt(String key, int mode, InputStream is, OutputStream os) throws Throwable {
DESKeySpec dks = new DESKeySpec(key.getBytes());
SecretKeyFactory skf = SecretKeyFactory.getInstance("DES");
SecretKey desKey = skf.generateSecret(dks);
Cipher cipher = Cipher.getInstance("DES"); // DES/ECB/PKCS5Padding for SunJCE
cipher.init(Cipher.ENCRYPT_MODE, desKey);
CipherInputStream cis = new CipherInputStream(is, cipher);
doCopy(cis, os);
}
public static void decrypt(String key, int mode, InputStream is, OutputStream os) throws Throwable {
DESKeySpec dks = new DESKeySpec(key.getBytes());
SecretKeyFactory skf = SecretKeyFactory.getInstance("DES");
SecretKey desKey = skf.generateSecret(dks);
Cipher cipher = Cipher.getInstance("DES"); // DES/ECB/PKCS5Padding for SunJCE
cipher.init(Cipher.DECRYPT_MODE, desKey);
CipherOutputStream cos = new CipherOutputStream(os, cipher);
doCopy(is, cos);
}
public static void doCopy(InputStream is, OutputStream os) throws IOException {
byte[] bytes = new byte[64];
int numBytes;
while ((numBytes = is.read(bytes)) != -1) {
os.write(bytes, 0, numBytes);
}
os.flush();
os.close();
is.close();
}
}
and for testing im executing it that way:
try {
EncTool.encrypt("somekey123", "SomeFile");
EncTool.decrypt("somekey123", "SomeFile");
} catch (Throwable e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
What am i doing wrong?
Or maybe how should it be done?
EDIT
when my code looks that:
public static void encrypt(String key, String filename) throws Throwable {
InputStream is = new FileInputStream("Somefile.class");
OutputStream os = new FileOutputStream("tempfile.class");
DESKeySpec dks = new DESKeySpec(key.getBytes());
SecretKeyFactory skf = SecretKeyFactory.getInstance("DES");
SecretKey desKey = skf.generateSecret(dks);
Cipher cipher = Cipher.getInstance("DES"); // DES/ECB/PKCS5Padding for SunJCE
cipher.init(Cipher.ENCRYPT_MODE, desKey);
CipherInputStream cis = new CipherInputStream(is, cipher);
doCopy(cis, os);
File file2 = new File("tempfile.class");
File f = new File("somefile.class");
f.delete();
file2.renameTo(f);
}
Now it works, but these deleting and renaming thing doesn't look elegant, how can I do it more efficient?
You must write the output to a new file instead of overwriting the input while you are reading it. The way your code is written now the results will be undefined.