I'm doing a simple encryption file transfer system and now stopped by a run time exception:
Exception in thread "main" javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:811)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:676)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:313)
at javax.crypto.Cipher.doFinal(Cipher.java:2087)
at ftpclient.FTPClient.main(FTPClient.java:82)
I tried to debug my code using a string to encrypt and decrypt with the same key and it works. However, when I tried to transfer stream from the file, this exception always comes.
Here are the codes of both sides. At first they will exchange symmetric key (AES key) via RSA and then transfer large files via AES encryption. We can focus on the last part of each code where the files are encrypted and decrypted by AES key.
Server Side:
package ftpserver;
import java.io.*;
import java.net.*;
import javax.crypto.*;
import java.security.*;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
/**
*
* #author Han
*/
public class FTPServer {
public static void main(String[] args) throws Exception {
//generate symmetric key and initialize cipher for AES
SecretKey skey = null;
Cipher aes = Cipher.getInstance("AES/ECB/PKCS5Padding");
KeyGenerator kg = KeyGenerator.getInstance("AES");
kg.init(128);
skey = kg.generateKey();
//get public key of the receive side
final String PUBLIC_KEY_PATH = "key_b.public";
PublicKey publickey = null;
try {
FileInputStream fis;
fis = new FileInputStream(PUBLIC_KEY_PATH);
ObjectInputStream oin = new ObjectInputStream(fis);
publickey = (PublicKey) oin.readObject();
oin.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
};
//encrypte symmetric key with own private key and send out
Cipher rsa = Cipher.getInstance("RSA");
rsa.init(Cipher.ENCRYPT_MODE, publickey);
byte cipherSKey[] = rsa.doFinal(skey.getEncoded());
//System.out.println(skey); //debug
//create tcp server socket
ServerSocket tcp = new ServerSocket(2000);
Socket client = tcp.accept();
//get input&output stream from the TCP connection
InputStream in = client.getInputStream();
OutputStream out = client.getOutputStream();
//generate a file input stream to get stream from file
File sentFile = new File("F:\\test.txt");
FileInputStream fin = new FileInputStream(sentFile);
//send encrypted symmetric key first
out.write("Symmetric Key:\r\n".getBytes());
out.write(cipherSKey);
DataInputStream din = new DataInputStream(in);
while(true)
{
if(din.readLine().equals("Received."))
{
System.out.println("Send key successfully.");
break;
}
};
//send files
int count;
byte[] bytearray = new byte[8192];
byte[] cipherbuffer;
while((count = fin.read(bytearray))>0)
{
cipherbuffer = Base64.encodeBase64(aes.doFinal(bytearray));
out.write(cipherbuffer,0,cipherbuffer.length);
System.out.println(count+" bytes have been sent.");
};
out.flush();
out.close();
client.close();
}
}
Client Side:
package ftpclient;
import java.io.*;
import java.net.*;
import java.security.PrivateKey;
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
/**
*
* #author Han
*/
public class FTPClient {
public static void main(String[] args) throws Exception
{
//get the private key of this side
final String PUBLIC_KEY_PATH = "key_b.privat";
PrivateKey privatkey = null;
try {
FileInputStream fis;
fis = new FileInputStream(PUBLIC_KEY_PATH);
ObjectInputStream oin = new ObjectInputStream(fis);
privatkey = (PrivateKey) oin.readObject();
oin.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
};
Cipher rsa = Cipher.getInstance("RSA");
rsa.init(Cipher.DECRYPT_MODE, privatkey);
//create tcp client socket
Socket tcp = new Socket("192.168.1.185",2000);
InputStream in = tcp.getInputStream();
OutputStream out = tcp.getOutputStream();
DataInputStream din = new DataInputStream(in);
//receive symmetric key from server
byte keybuffer[] = new byte[128];
SecretKey skey = null;
while(true)
{
if(din.readLine().equals("Symmetric Key:"))
{
System.out.println("Start to receiving key...");
in.read(keybuffer);
byte[] skeycode = rsa.doFinal(keybuffer);
skey = new SecretKeySpec(skeycode, 0, skeycode.length, "AES");
out.write("Received.\r\n".getBytes());
break;
}
};
//create cipher for symmetric decryption
Cipher aes = Cipher.getInstance("AES/ECB/PKCS5Padding");
aes.init(Cipher.DECRYPT_MODE, skey);
//System.out.println(skey); //debug
//create file stream
FileOutputStream fos = new FileOutputStream("E:\\test_cp.txt");
int count;
int i = 0;
byte[] bytearray = new byte[8192];
byte[] buffer;
while((count = in.read(bytearray)) > 0)
{
buffer = (aes.doFinal(Base64.decodeBase64(bytearray)));
fos.write(buffer,0,buffer.length);
i +=count;
System.out.println(i+" bytes have been received.");
};
fos.flush();
fos.close();
in.close();
tcp.close();
System.out.println("File Transfer completed");
}
}
you are calling doFinal multiple times. or at least trying to.
when you read data, not all data arrives or is read into the buffer at once. so you decrypt some and then read again. that is all ok.
but when you do that, you are calling doFinal each time, instead of update. this is wrong and is the cause of the error. instead, replace doFinal with update and then add an extra doFinal once you have finished reading all data (there is a doFinal() that takes no arguments for exactly this reason).
see http://docs.oracle.com/javase/7/docs/api/javax/crypto/Cipher.html
also see http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_codebook_.28ECB.29 for why ecb mode is often not a good idea (look at the penguin pictures).
Related
I am tiring to send byte encrypted data over the socket, however, It does not work, the requirement is the server reads the key from file and receives an encrypted message from client
I am facing issues with Input/Output stream:I have used one variable that read file and sockets.
Server Code
import java.io.*;
import java.net.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.*;
import java.security.KeyStore.ProtectionParameter;
import java.security.KeyStore.SecretKeyEntry;
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
public class CipherServer
{
public static void main(String[] args) throws Exception
{
int port = 7999;
ServerSocket server = new ServerSocket(port);
Socket s = server.accept();
ObjectInputStream in = new ObjectInputStream(new FileInputStream("KeyFile.xx"));
// YOU NEED TO DO THESE STEPS:
// -Read the key from the file generated by the client.
SecretKey desKey = (SecretKey)in.readObject();
// YOU NEED TO DO THESE STEPS:
ObjectOutputStream out = new ObjectOutputStream(s.getOutputStream());
in = new ObjectInputStream(s.getInputStream());
byte[] cipherText;
cipherText= (byte[]) in.readObject();
// -Use the key to decrypt the incoming message from socket s.
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, desKey);
CipherInputStream cipherIn = new CipherInputStream(s.getInputStream(), cipher);
System.out.println("Algorithm used to generate key : "+desKey.getAlgorithm());
byte[] plaintext = cipher.doFinal(cipherText);
// -Print out the decrypt String to see if it matches the orignal message.
System.out.println(plaintext.toString());
}
}
Client Code
import java.io.*;
import java.net.*;
import javax.crypto.*;
public class CipherClient
{
public static void main(String[] args) throws Exception
{
// YOU NEED TO DO THESE STEPS:
// -Generate a DES key.
KeyGenerator keygenerator = KeyGenerator.getInstance("DES");
SecretKey desKey = keygenerator.generateKey();
// -Store it in a file.
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("KeyFile.xx"));
out.writeObject(desKey);
String message = "The quick brown fox jumps over the lazy dog.";
int port = 7999;
Socket s = new Socket("127.0.0.1", port);
out = new ObjectOutputStream(s.getOutputStream());
//convert the massage to bits
byte[] messa= message.getBytes();
// -Use the key to encrypt the message above and send it over socket s to the server.
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, desKey);
byte[] cipherText = cipher.doFinal(messa);
System.out.println(new String(cipherText));
// YOU NEED TO DO THESE STEPS:
// ObjectOutputStream.reset(cipherText);
out.write(cipherText);
}
}
I receive an ERROR Message at the server side
Exception in thread "main" java.net.SocketException: Connection reset
at java.base/java.net.SocketInputStream.read(SocketInputStream.java:186)
at java.base/java.net.SocketInputStream.read(SocketInputStream.java:140)
at java.base/java.net.SocketInputStream.read(SocketInputStream.java:200)
at java.base/java.io.ObjectInputStream$PeekInputStream.peek(ObjectInputStream.java:2802)
at java.base/java.io.ObjectInputStream$BlockDataInputStream.peek(ObjectInputStream.java:3129)
at java.base/java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:3139)
at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1619)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:482)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:440)
at DES.CipherServer.main(CipherServer.java:77)
On the write side, you are calling OutputStream.write(byte[]), on the read side, you are calling readObject (then trying to convert that to a byte[]). If you are going to use ObjectStreams (which I highly discourage) you need to be consistant with writeObject and readObject on both sides
I have a JAVA code that does the AES encryption of excel file on the Windows Operating System. I want to decrypt the same file on the MacOs Operating System using NodeJS. I've written a decrypt function in NodeJs which is giving me the following error
error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt
Here is the JAVA Code
import java.security.Key;
import java.io.OutputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
public class fileEncrypter {
try {
final SecretKeySpec key = new SecretKeySpec("1234".getBytes(), "AES");
final Cipher instance = Cipher.getInstance("AES/ECB/PKCS5Padding");
final BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(name));
final BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(name2));
instance.init(1, key);
final byte[] b = new byte[4096];
for (int i = bufferedInputStream.read(b); i > -1; i = bufferedInputStream.read(b)) {
final byte[] update = instance.update(b, 0, I);
bufferedOutputStream.write(update, 0, update.length);
}
bufferedInputStream.close();
final byte[] doFinal = instance.doFinal();
bufferedOutputStream.write(doFinal, 0, doFinal.length);
bufferedOutputStream.flush();
bufferedOutputStream.close();
return "success";
} catch(Exception obj) {
System.err.println("Exception occured while encryption:" + obj);
obj.printStackTrace();
return obj.toString();
}
}
Here is the NodeJs code to decrypt
function Decrypt_AES() {
const ALGORITHM = 'aes-128-ecb';
const ENCRYPTION_KEY = "1234";
var decipher = crypto.createDecipher(ALGORITHM, ENCRYPTION_KEY);
decipher.setAutoPadding(true);
var input = fs.createReadStream('test.enc');
var output = fs.createWriteStream('test_copy.xls');
input.pipe(decipher).pipe(output);
output.on('finish', function () {
console.log('Encrypted file written to disk!');
});
output.on('error', function (e) {
console.log(e);
});
}
I've created some examples in both Java and Node.js that will encrypt and decrypt files. The code will be compatible as long as the same key and IV values are used, that is to say the Node code will decrypt the output from the Java and vice-versa.
Now I'm using text files as input here, but you can use any file type as input.
I've updated to use 128-bit AES in ECB mode.
The Key cannot be "1234" since it must be 128-bits long, so I've used the key given below (16 bytes / 128 bits).
Java
import java.io.*;
import javax.crypto.*;
import java.security.*;
import javax.crypto.spec.*;
public class fileEncrypter {
private static final String key = "0123456789ABDCEF";
public static void main(String[] args)
{
encryptFile(key, "java-input.txt", "java-output.txt");
decryptFile(key, "java-output.txt", "java-decrypted.txt");
}
public static void encryptFile(String secret, String inputFile, String outputFile)
{
try
{
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(secret.getBytes(), "AES"));
byte[] inputData = readFile(inputFile);
byte[] outputData = cipher.doFinal(inputData);
writeToFile(outputFile, outputData);
}
catch (Exception e)
{
System.out.println("Error while encrypting: " + e.toString());
}
}
public static void decryptFile(String secret, String inputFile, String outputFile)
{
try
{
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(secret.getBytes(), "AES"));
byte[] inputData = readFile(inputFile);
byte[] outputData = cipher.doFinal(inputData);
writeToFile(outputFile, outputData);
}
catch (Exception e)
{
System.out.println("Error while decrypting: " + e.toString());
}
}
private static byte[] readFile(String fileName) throws IOException {
byte[] data = new byte[(int) new File(fileName).length()];
DataInputStream dis = new DataInputStream(new FileInputStream(fileName));
dis.readFully(data);
dis.close();
return data;
}
private static void writeToFile(String fileName, byte[] data) throws IOException {
final BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(fileName));
bufferedOutputStream.write(data, 0, data.length);
bufferedOutputStream.close();
}
}
Node.js
const crypto = require("crypto");
const Algorithm = "aes-128-ecb";
const fs = require("fs");
function encryptFile(key, inputFile, outputFile) {
const inputData = fs.readFileSync(inputFile);
const cipher = crypto.createCipheriv(Algorithm, key, Buffer.alloc(0));
const output = Buffer.concat([cipher.update(inputData) , cipher.final()]);
fs.writeFileSync(outputFile, output);
}
function decryptFile(key, inputFile, outputFile) {
const inputData = fs.readFileSync(inputFile);
const cipher = crypto.createDecipheriv(Algorithm, key, Buffer.alloc(0));
const output = Buffer.concat([cipher.update(inputData) , cipher.final()]);
fs.writeFileSync(outputFile, output);
}
const KEY = Buffer.from("0123456789ABDCEF", "utf8");
encryptFile(KEY, "node-input.txt", "node-output.txt");
decryptFile(KEY, "node-output.txt", "node-decrypted.txt");
I have solved this problem with the help of Terry Lennox. A big thanks to him first.
First Error:
error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt
This was a padding issue, By default, nodeJs uses PKCS padding so I had to set auto padding to false by using decipher.setAutoPadding(false);
This solved the first error
Secondly, I was using crypto.createDecipher(ALGORITHM, ENCRYPTION_KEY) which processes the key before using it. To solve this I changed the function to
crypto.createDecipheriv(ALGORITHM, ENCRYPTION_KEY, null)
This was giving me error as we cannot pass null in place of IV value.
Since ECB does not require any IV, and we cannot pass null in place of IV I had to set my IV value to this Buffer.alloc(0)
This is the code that worked for me
function Decrypt_AES() {
const ALGORITHM = 'aes-128-ecb';
const key = "1234";
const ENCRYPTION_KEY = key;
var IV = Buffer.alloc(0);
var decipher = crypto.createDecipheriv(ALGORITHM, ENCRYPTION_KEY, IV);
decipher.setAutoPadding(false);
var input = fs.createReadStream('test.enc');
var output = fs.createWriteStream('test_copy.xls');
input.pipe(decipher).pipe(output);
output.on('finish', function () {
console.log('Decrypted file written to disk!');
});
output.on('error', function (e) {
console.log(e);
});
}
package test;
/**
* Created by
* newbme on 12/25/2018.
*/
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
public class MyJava {
/**
* IT IS THIS CLASS THAT WILL ENCRYPT OR DECRYPT
* ANY FILE
*/
private static final String SECRET_KEY_1 = "ssdkF$HUy2A#D%kd";
private static final String SECRET_KEY_2 = "weJiSEvR5yAC5ftB";
private IvParameterSpec ivParameterSpec;
private SecretKeySpec secretKeySpec;
private Cipher cipher;
private File from,to;
private static boolean trouble =false;
/**
* CBC MODE
*/
public MyJava(File from,File to) throws UnsupportedEncodingException, NoSuchPaddingException, NoSuchAlgorithmException {
ivParameterSpec = new IvParameterSpec(SECRET_KEY_1.getBytes("UTF-8"));
secretKeySpec = new SecretKeySpec(SECRET_KEY_2.getBytes("UTF-8"), "AES");
cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
//INITIALIZE THE PLACE TO READ AND SAVE FILE
this.from =from;
this.to =to;
//if the desination doesnt exists create it
if(! this.to .exists()){
try {
this.to.getParentFile().mkdirs();
this.to.createNewFile();
}catch (Exception ex){
ex.printStackTrace();
}
}
}
/**
*
* USE THIS METHOD TO ENCRYPT ANYTHING
*/
public boolean encrypt()throws Exception{
FileInputStream fis =null;
FileOutputStream fos=null;
boolean success =false;
try {
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
//read the file into memory
fis = new FileInputStream(from);
fos = new FileOutputStream(to);
byte [] inBytes = new byte[50*1024];
int count;
while( ( count = fis.read(inBytes)) > 0){
byte encrypted[] = cipher.doFinal(inBytes);
fos.write(encrypted,0,count);
fos.flush();
}
success =true;
}catch(InvalidKeyException ivke){
ivke.printStackTrace();
trouble = true;
}finally{
if(fis!=null)fis.close();
if(fos!=null)fos.close();
}
//return Base64.encodeBase64String(encrypted);
return success;
}
/**
*
* USE THIS METHOD TO DECRYPT ANYTHING
*/
public boolean decrypt() throws Exception{
FileInputStream fis =null;
FileOutputStream fos=null;
boolean success =false;
try {
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
//read the file into memory
fis = new FileInputStream(from);
fos = new FileOutputStream(to);
byte [] inBytes = new byte[50*1024];
int count;
while( ( count = fis.read(inBytes)) > 0){
byte decrypted[] = cipher.doFinal(inBytes);//this line fails
fos.write(decrypted,0,count);
fos.flush();
}
success =true;
}catch(InvalidKeyException ivke){
trouble = true;
ivke.printStackTrace();
}finally{
if(fis!=null)fis.close();
if(fos!=null)fos.close();
}
//return Base64.encodeBase64String(encrypted);
return success;
}
private static boolean isInvalidKeyException(){
return trouble;
}
public static void main(String [] R){
File f = new File(PATH);
//encrypt
new MyJava(f,new File("c:/logs1/"+f.getName())).encrypt();
//Toast.makeText(context,"to decrypt",Toast.LENGTH_LONG).show();
//decrypt
new MyJava(f,new File("c:/logs2/"+f.getName())).decrypt();
}
}
Error:
D/OpenSSLLib: OpensslErr:Module:30(101:); file:external/boringssl/src/crypto/cipher/cipher.c ;Line:460;Function:EVP_DecryptFinal_ex
W/System.err: javax.crypto.BadPaddingException: error:1e000065:Cipher functions:OPENSSL_internal:BAD_DECRYPT
W/System.err: at com.android.org.conscrypt.NativeCrypto.EVP_CipherFinal_ex(Native Method)
W/System.err: at com.android.org.conscrypt.OpenSSLCipher$EVP_CIPHER.doFinalInternal(OpenSSLCipher.java:568)
W/System.err: at com.android.org.conscrypt.OpenSSLCipher.engineDoFinal(OpenSSLCipher.java:350)
W/System.err: at javax.crypto.Cipher.doFinal(Cipher.java:2056)
W/System.err: at com.presentapps.aiapp.utility.AISCipher.decrypt(AISCipher.java:122)
W/System.err: at com.presentapps.aiapp.popups.ActionPop$1.onClick(ActionPop.java:65)
Hello, I tried to encrypt a file which could be a text file or a music file etc. The program kinda encrypts it without any exception, however when I try to decrypt, it throws an exception.
I've been trying to use CBC mode to get it working for days now, could someone help point out my errors?
And uhm, I am actually running it on Android device so I changed the root part with "c:" while posting on SO the error posted was same gotten from debugger console on A.S.
I'm a newb to java, just improving on my learning, so any help is appreciated. Thanks.
Please note that real code should use a non-secret random IV for each encryption rather than a fixed, secret IV. Passwords should use a password-hashing function to make into keys. PBKDF2 is available on Android and Java for this purpose.
There are a number of problems with your code:
You're calling Cipher.doFinal() every time through the loop. Combined with a fixed IV, the result is effectively equivalent to ECB mode and is thus insecure. Use Cipher.update() for all intermediate blocks until the final block, then call Cipher.doFinal().
You're supplying invalid data to encrypt and decrypt every time you read less than a full buffer into inBytes.
count is the number of bytes that were read in, not necessarily the size of encrypted. You should output exactly the contents of encrypted, not some piece of it.
You main method encrypts a file at PATH and writes the result to c:/logs1/PATH. It then attempts to decrypt the file at PATH, but that file is the plaintext file, not the cipher text file.
Here are the corrected encrypt and decrypt methods:
public boolean encrypt() throws Exception {
FileInputStream fis = null;
FileOutputStream fos = null;
boolean success = false;
try {
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
//read the file into memory
fis = new FileInputStream(from);
fos = new FileOutputStream(to);
byte[] inBytes = new byte[50 * 1024];
int count;
while ((count = fis.read(inBytes)) > 0) {
byte encrypted[] = cipher.update(inBytes, 0, count);
fos.write(encrypted);
}
byte encrypted[] = cipher.doFinal();
fos.write(encrypted);
fos.flush(); // redundant, since closing the stream will flush it.
success = true;
} catch (InvalidKeyException ivke) {
ivke.printStackTrace();
trouble = true;
} finally {
if (fis != null) fis.close();
if (fos != null) fos.close();
}
//return Base64.encodeBase64String(encrypted);
return success;
}
public boolean decrypt() throws Exception {
FileInputStream fis = null;
FileOutputStream fos = null;
boolean success = false;
try {
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
//read the file into memory
fis = new FileInputStream(from);
fos = new FileOutputStream(to);
byte[] inBytes = new byte[50 * 1024];
int count;
while ((count = fis.read(inBytes)) > 0) {
byte decrypted[] = cipher.update(inBytes, 0, count);
fos.write(decrypted);
}
byte decrypted[] = cipher.doFinal();
fos.write(decrypted);
fos.flush();
success = true;
} catch (InvalidKeyException ivke) {
trouble = true;
ivke.printStackTrace();
} finally {
if (fis != null) fis.close();
if (fos != null) fos.close();
}
//return Base64.encodeBase64String(encrypted);
return success;
}
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 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.