I'm using CipherInputStream and CipherOutputStream to encrypt files using AES.
encrypt(...) seems to be working fine, but my decrypt(...) function only decrypt the first 16 bytes of my files.
Here is my class :
public class AESFiles {
private byte[] getKeyBytes(final byte[] key) throws Exception {
byte[] keyBytes = new byte[16];
System.arraycopy(key, 0, keyBytes, 0, Math.min(key.length, keyBytes.length));
return keyBytes;
}
public Cipher getCipherEncrypt(final byte[] key) throws Exception {
byte[] keyBytes = getKeyBytes(key);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
IvParameterSpec ivParameterSpec = new IvParameterSpec(keyBytes);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
return cipher;
}
public Cipher getCipherDecrypt(byte[] key) throws Exception {
byte[] keyBytes = getKeyBytes(key);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
IvParameterSpec ivParameterSpec = new IvParameterSpec(keyBytes);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
return cipher;
}
public void encrypt(File inputFile, File outputFile, byte[] key) throws Exception {
Cipher cipher = getCipherEncrypt(key);
FileOutputStream fos = null;
CipherOutputStream cos = null;
FileInputStream fis = null;
try {
fis = new FileInputStream(inputFile);
fos = new FileOutputStream(outputFile);
cos = new CipherOutputStream(fos, cipher);
byte[] data = new byte[1024];
int read = fis.read(data);
while (read != -1) {
cos.write(data, 0, read);
read = fis.read(data);
System.out.println(new String(data, "UTF-8").trim());
}
cos.flush();
} finally {
fos.close();
cos.close();
fis.close();
}
}
public void decrypt(File inputFile, File outputFile, byte[] key) throws Exception {
Cipher cipher = getCipherDecrypt(key);
FileOutputStream fos = null;
CipherInputStream cis = null;
FileInputStream fis = null;
try {
fis = new FileInputStream(inputFile);
cis = new CipherInputStream(fis, cipher);
fos = new FileOutputStream(outputFile);
byte[] data = new byte[1024];
int read = cis.read(data);
while (read != -1) {
fos.write(data, 0, read);
read = cis.read(data);
System.out.println(new String(data, "UTF-8").trim());
}
} finally {
fos.close();
cis.close();
fis.close();
}
}
public static void main(String args[]) throws Exception {
byte[] key = "mykey".getBytes("UTF-8");
new AESFiles().encrypt(new File("C:\\Tests\\secure.txt"), new File("C:\\Tests\\secure.txt.aes"), key);
new AESFiles().decrypt(new File("C:\\Tests\\secure.txt.aes"), new File("C:\\Tests\\secure.txt.1"), key);
}
}
So my question is, why the decrypt function only read the first 16 bytes ?
This is very subtle. Your problem is that you are closing your fos before your cos. In your encrypt(...) method you are doing:
} finally {
fos.close();
cos.close();
fis.close();
}
That closes the FileOutputStream out from under the CipherOutputStream so the final padded block of encrypted output never gets written to the output file. If you close the fos after the cos then your code should work fine.
Really, you should consider doing something like:
FileOutputStream fos = null;
CipherOutputStream cos = null;
FileInputStream fis = null;
try {
fis = new FileInputStream(inputFile);
fos = new FileOutputStream(outputFile);
cos = new CipherOutputStream(fos, cipher);
// once cos wraps the fos, you should set it to null
fos = null;
...
} finally {
if (cos != null) {
cos.close();
}
if (fos != null) {
fos.close();
}
if (fis != null) {
fis.close();
}
}
FYI: org.apache.commons.io.IOUtils has a great closeQuietly(...) method which handles null checks and catches the exceptions for you.
Related
I am trying to fetch image from the camera & want to encrypt that bitmap and want to store that bitmap in internal storage in encrypted format and store path of that file in Sqlite DB also want to decrypt that file from path receiving from the Sqlite DB.
Using code following.
For Camera I Am using normal camera code
and found a bitmap mImageCaptureBitmap
for encryption and decryption we use following.
private static String Key = "key#123";
public static byte[] encryptString(String stringToEncode) throws NullPointerException {
try {
SecretKeySpec skeySpec = getKey(Key);
byte[] clearText = stringToEncode.getBytes("UTF8");
final byte[] iv = new byte[16];
Arrays.fill(iv, (byte) 0x00);
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivParameterSpec);
byte[] encryptedValue = cipher.doFinal(clearText);
return encryptedValue;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static String decryptString(String stringToEncode) throws NullPointerException {
try {
SecretKeySpec skeySpec = getKey(Key);
final byte[] iv = new byte[16];
Arrays.fill(iv, (byte) 0x00);
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
cipher.init(Cipher.DECRYPT_MODE, skeySpec, ivParameterSpec);
byte[] cipherData = cipher.doFinal(Base64.decode(stringToEncode.getBytes("UTF-8"),
Base64.DEFAULT));
String decoded = new String(cipherData, "UTF-8");
return decoded;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static SecretKeySpec getKey(String password) throws UnsupportedEncodingException {
int keyLength = 256;
byte[] keyBytes = new byte[keyLength / 8];
Arrays.fill(keyBytes, (byte) 0x0);
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;
}
for storing file in local
public static void storeFile(Bitmap bitmap, String filename, Context ctx
,String ID,String type){
ContextWrapper cw = new ContextWrapper(ctx);
File directory = cw.getDir("IntegratorApp", Context.MODE_PRIVATE);
File file = new File(directory, filename);
DatabaseHelper mdaDatabaseHelper = new DatabaseHelper(ctx);
mdaDatabaseHelper.insertDocData(leadID,file.getAbsolutePath(),docType);
try {
StorageUnit.saveImage(ctx,bitmap,filename);
} catch (IOException e) {
e.printStackTrace();
}
}
I don't know where I am doing wrong but the image is not stored in db in encrypted format.
Thanks in advance
I'm trying to transfer an AES encrypted file through socket programming, but when I specify the file path it gives the following exception, and when I try to transfer an unencrypted file, it works fine.
java.io.FileNotFoundException: salt.ecn (The system cannot find the file specified)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at java.io.FileInputStream.<init>(FileInputStream.java:93)
at nigam.Front.server(Front.java:52)
at nigam.Front$7.run(Front.java:621)
Code:
public class SocketFileExample {
static void server() throws IOException {
ServerSocket ss = new ServerSocket(3434);
Socket socket = ss.accept();
InputStream in = new FileInputStream("salt.ecn");
OutputStream out = socket.getOutputStream();
copy(in, out);
out.close();
in.close();
}
static void client() throws IOException {
Socket socket = new Socket("localhost", 3434);
InputStream in = socket.getInputStream();
OutputStream out = new FileOutputStream("C:\\Users\\SIDDHARTH\\Documents\\NetBeansProjects\\Nigam\\salt.ecn");
copy(in, out);
out.close();
in.close();
}
static void copy(InputStream in, OutputStream out) throws IOException {
byte[] buf = new byte[8192];
int len = 0;
while ((len = in.read(buf)) != -1) {
out.write(buf, 0, len);
}
}
public static void main(String[] args) throws IOException {
new Thread() {
public void run() {
try {
server();
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
client();
}
}
'Code: Encryption code used'
Code: Encryption code used
public class AESFileEncryption {
public static void main(String[] args) throws Exception {
// file to be encrypted
FileInputStream inFile = new FileInputStream("plainfile.txt");
// encrypted file
FileOutputStream outFile = new FileOutputStream("encryptedfile.des");
// password to encrypt the file
String password = "javapapers";
// password, iv and salt should be transferred to the other end
// in a secure manner
// salt is used for encoding
// writing it to a file
// salt should be transferred to the recipient securely
// for decryption
byte[] salt = new byte[8];
SecureRandom secureRandom = new SecureRandom();
secureRandom.nextBytes(salt);
FileOutputStream saltOutFile = new FileOutputStream("salt.enc");
saltOutFile.write(salt);
saltOutFile.close();
SecretKeyFactory factory = SecretKeyFactory
.getInstance("PBKDF2WithHmacSHA1");
KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, 65536,
256);
SecretKey secretKey = factory.generateSecret(keySpec);
SecretKey secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
//
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
AlgorithmParameters params = cipher.getParameters();
// iv adds randomness to the text and just makes the mechanism more
// secure
// used while initializing the cipher
// file to store the iv
FileOutputStream ivOutFile = new FileOutputStream("iv.enc");
byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV();
ivOutFile.write(iv);
ivOutFile.close();
//file encryption
byte[] input = new byte[64];
int bytesRead;
while ((bytesRead = inFile.read(input)) != -1) {
byte[] output = cipher.update(input, 0, bytesRead);
if (output != null)
outFile.write(output);
}
byte[] output = cipher.doFinal();
if (output != null)
outFile.write(output);
inFile.close();
outFile.flush();
outFile.close();
System.out.println("File Encrypted.");
}
}
Ok guys ! There is my trouble.
I want to read data from an encrypted file and store the decrypted data in a local variable (without save it in a file).
So, when I do the operations (in the same Class) cryptingFile -> DecryptFile -> Storage : It's OK.
But, when I try to run again the code using the crypted file directly, I've got the error "BadPaddingException".
I've no idea what's going on....
Below, the working code:
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
generateKey(clef);
CryptingWithSave(Cipher.ENCRYPT_MODE,"db/db.csv",publicKey,"db/db.csv_encrypted");
decrypt_file("db/db.csv_encrypted",publicKey);
System.out.println(tab);
}
public static void generateKey (String clef) throws NoSuchAlgorithmException{
final KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128);
final SecretKey key = keyGen.generateKey();
publicKey= new SecretKeySpec(key.getEncoded(),"AES");
}
public static void CryptingWithSave (int Crypting_METHOD,String inputFile, SecretKeySpec clef, String outputFile) throws NoSuchAlgorithmException, NoSuchPaddingException, BadPaddingException, Exception{
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Crypting_METHOD, clef);
FileInputStream fis = new FileInputStream(inputFile);
FileOutputStream fos = new FileOutputStream(outputFile);
byte[] input = new byte[64];
int bytesRead;
while ((bytesRead = fis.read(input)) != -1) {
byte[] output = cipher.update(input, 0, bytesRead);
if (output != null)
fos.write(output);
}
byte[] output = cipher.doFinal();
if (output != null)
fos.write(output);
fis.close();
fos.flush();
fos.close();
}
public static void decrypt_file (String inputFile, SecretKeySpec clef) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IOException, IllegalBlockSizeException, BadPaddingException{
Cipher cipher2 = Cipher.getInstance("AES");
cipher2.init(Cipher.DECRYPT_MODE, clef);
FileInputStream fis = new FileInputStream(inputFile);
byte[] input = new byte[64];
int bytesRead;
while ((bytesRead = fis.read(input)) != -1) {
byte[] output = cipher2.update(input, 0, bytesRead);
if (output != null)
tab=tab.concat(new String(output));
}
byte[] output = cipher2.doFinal();
if (output != null)
tab=tab.concat(new String(output));
fis.close();
}
There, the unworking code (the only change is the CryptingWithSave which is commented):
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
generateKey(clef);
//CryptingWithSave(Cipher.ENCRYPT_MODE,"db/db.csv",publicKey,"db/db.csv_encrypted");
decrypt_file("db/db.csv_encrypted",publicKey);
System.out.println(tab);
}
public static void generateKey (String clef) throws NoSuchAlgorithmException{
final KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128);
final SecretKey key = keyGen.generateKey();
publicKey= new SecretKeySpec(key.getEncoded(),"AES");
}
public static void CryptingWithSave (int Crypting_METHOD,String inputFile, SecretKeySpec clef, String outputFile) throws NoSuchAlgorithmException, NoSuchPaddingException, BadPaddingException, Exception{
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Crypting_METHOD, clef);
FileInputStream fis = new FileInputStream(inputFile);
FileOutputStream fos = new FileOutputStream(outputFile);
byte[] input = new byte[64];
int bytesRead;
while ((bytesRead = fis.read(input)) != -1) {
byte[] output = cipher.update(input, 0, bytesRead);
if (output != null)
fos.write(output);
}
byte[] output = cipher.doFinal();
if (output != null)
fos.write(output);
fis.close();
fos.flush();
fos.close();
}
public static void decrypt_file (String inputFile, SecretKeySpec clef) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IOException, IllegalBlockSizeException, BadPaddingException{
Cipher cipher2 = Cipher.getInstance("AES");
cipher2.init(Cipher.DECRYPT_MODE, clef);
FileInputStream fis = new FileInputStream(inputFile);
byte[] input = new byte[64];
int bytesRead;
while ((bytesRead = fis.read(input)) != -1) {
byte[] output = cipher2.update(input, 0, bytesRead);
if (output != null)
tab=tab.concat(new String(output));
}
byte[] output = cipher2.doFinal();
if (output != null)
tab=tab.concat(new String(output));
fis.close();
}
It is because the next time you run it, it generates a new key which is different from the previous one. Try to use that old key.
Hi i hav such code that encrypt and decrypt file in DES algorithm .
i want to change my code to be triple DES encryption / decryption .
my code is below :
First, my methods are :
public class DESEncrypt
{
public static void encrypt(String key, InputStream is, OutputStream os) throws Exception {
encryptOrDecrypt(key, Cipher.ENCRYPT_MODE, is, os);
}
public static void decrypt(String key, InputStream is, OutputStream os) throws Exception {
encryptOrDecrypt(key, Cipher.DECRYPT_MODE, is, os);
}
public static void encryptOrDecrypt(String key, int mode, InputStream is, OutputStream os) throws Exception {
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);
makeFile(cis, os);
} else if (mode == Cipher.DECRYPT_MODE) {
cipher.init(Cipher.DECRYPT_MODE, desKey);
CipherOutputStream cos = new CipherOutputStream(os, cipher);
makeFile(is, cos);
}
}
public static void makeFile(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();
}
}
public class EncryptTXT extends javax.swing.JFrame {
String key="Java#123##"; //This is the Key for Encryption
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
try{
JFileChooser fc=new JFileChooser();
fc.showOpenDialog(null);
String path=fc.getSelectedFile().getAbsolutePath();
jLabel2.setText(path);
File f=fc.getSelectedFile();
FileInputStream fis=new FileInputStream(f);
FileOutputStream fos=new FileOutputStream("C:/Users/user/Desktop/encrypted.txt");
Thread.sleep(2000);
DESEncrypt.encrypt(key, fis, fos);
jLabel4.setText("C:/Users/user/Desktop/encrypted.txt");
The 3DES keys should be 16 or 24 bytes long, not 8.
Change "DES" to "DESede" as Maarten Bodewes suggested or "DESede\ECB\NoPadding" (in .getInstance() method)
I need a little question.How can I repair that code so I can use it in android too.I need just to load a file from assets folder in android projet, decrypt it and to show the size of the file and how long it takes to the application to decrypt it.
Code :
package decryption;
import java.io.*;
import javax.crypto.*;
import javax.crypto.spec.*;
public class Decryption {
public static void main(String args[]) throws Exception {
File file = new File("ecryption.pdf");
System.out.println(file.getAbsolutePath());
System.out.println("user.dir is: " + System.getProperty("user.dir"));
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
SecretKeySpec keySpec = new SecretKeySpec("01234567890abcde".getBytes(), "AES");
IvParameterSpec ivSpec = new IvParameterSpec("fedcba9876543210".getBytes());
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
FileInputStream fis = new FileInputStream(new File("ecrypted.pdf"));
long start = System.currentTimeMillis();
System.out.print(start+" ");
CipherInputStream cis = new CipherInputStream(fis, cipher);
FileOutputStream fos = new FileOutputStream(new File("decrypted.pdf"));
long end = System.currentTimeMillis();
System.out.print(end);
byte[] b = new byte[8];
int i;
while ((i = cis.read(b)) != -1) {
fos.write(b, 0, i);
}
fos.flush(); fos.close();
cis.close(); fis.close();
}
}
// File file = new File("ecryption.pdf");
// System.out.println(file.getAbsolutePath());
// System.out.println("user.dir is: " + System.getProperty("user.dir"));
// FileInputStream fis = new FileInputStream(new File("ecrypted.pdf"));
InputStream fis = getAssets().open("ecryption.pdf");
// FileOutputStream fos = new FileOutputStream(new File("decrypted.pdf"));
FileOutputStream fos = new FileOutputStream(
new File(Environment.getExternalStorageDirectory(), "decrypted.pdf"));
Then you need to compile and adjust the rest.
this will copy one file at a time... start from there..
public void copyAssets() {
try {
in = getAssets().open("aabbccdd.mp3");
File outFolder = new File(root.getAbsolutePath() + "/testfolder182");
outFolder.mkdir();
File outFile = new File(outFolder, "ooooooooohhhigetit.mp3");
out = new FileOutputStream(outFile);
copyFile(in, out);
in.close();
in = null;
out.flush();
out.close();
out = null;
} catch (IOException e) {
Log.e("tag", "Failed to copy asset file: ", e);
}
}
private void copyFile(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
}