The problem I am facing is that I could not get decrypted email when I call this REST service: http://localhost:8080/RestWebService/MM/decryptEmail
For more details I also add an image below.
I hope I have explained my question well
package client;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import my.web.services.KeysGeneration;
public class TestClient {
private static String keypass = "KHU12345KHU12345";
public static void callPostService()
{
try{
URL url = new URL("http://localhost:8080/RestWebService/MM");
HttpURLConnection conn =(HttpURLConnection)url.openConnection();
// Allow Inputs
conn.setDoInput(true);
// Allow Outputs
conn.setDoOutput(true);
// Don't use a cached copy.
conn.setUseCaches(false);
conn.setRequestMethod("POST");
String text;
OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream());
String email="sabah#gmail.com";
// //**********AES Encryption
// // Create key and cipher
SecretKey aesKey = KeysGeneration.getKeys(keypass);
Cipher cipher = Cipher.getInstance("AES");
// // encrypt the text
cipher.init(Cipher.ENCRYPT_MODE, aesKey);
byte[] encrypted = cipher.doFinal(email.getBytes());
System.out.println("checking encryption "+new String(encrypted));
writer.write("&email="+(encrypted));
// //**********AES Encryption
//// //**********AES Decryption
//
//// // decrypt the text
cipher.init(Cipher.DECRYPT_MODE, aesKey);
String decrypted= new String(cipher.doFinal(encrypted));
System.out.println("checking dencryption "+decrypted);
////
////// //**********AES Decryption
writer.flush();
writer.close();
InputStream stream = conn.getInputStream();
byte[] b = new byte[1024];
int len = 0;
while((len=stream.read(b, 0,1024))>0)
{
System.out.println(new String(b,0,len));
}
stream.close();
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
public static void callGETService()
{
try{
URL url = new URL("http://localhost:8080/RestWebService/MM?email=sabah#khu.ac.kr&pwd=1985");
HttpURLConnection conn =(HttpURLConnection)url.openConnection();
// Allow Inputs
conn.setDoInput(true);
// Allow Outputs
conn.setDoOutput(false);
// Don't use a cached copy.
conn.setUseCaches(false);
conn.setRequestMethod("GET");
InputStream stream = conn.getInputStream();
byte[] b = new byte[1024];
int len = 0;
while((len=stream.read(b, 0,1024))>0)
{
System.out.println(new String(b,0,len));
}
stream.close();
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
public static void main(String[] args) {
// open your connection
TestClient.callGETService();
TestClient.callPostService();
}
}
//webService
package my.web.services;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.QueryParam;
#Path("/MM")
public class WebService {
private String keypass = "KHU12345KHU12345";
//********GET Method*************
#GET
//GET method provides read only access to resources
public String validateUserGETMethod(#QueryParam("email")String email, #QueryParam("pwd")String pwd)
{
return "Using GET method \n Email address: "+email+ " and password:" +pwd;
}
//********POST Method*************
//POST method is used to create or update a new resources
//To generate encryption of email parameter
#POST
#Path("/encryptEmail")
public String validateUserPOSTMethodEncryption(#FormParam("email")String email)throws Exception
{
// Create key and cipher
SecretKey aesKey = KeysGeneration.getKeys(keypass);
Cipher cipher = Cipher.getInstance("AES");
// encrypt the text
cipher.init(Cipher.ENCRYPT_MODE, aesKey);
byte[] encrypted = cipher.doFinal(email.getBytes());
System.err.println(new String(encrypted));
return "Using POST method \n Email address (encrypted): "+new String(encrypted);
}
//POST method is used to create or update a new resources
//To generate decryption of email parameter
#POST
#Path("/decryptEmail")
public String validateUserPOSTMethodDecryption(#FormParam("email")String email)throws Exception
{
//SecretKey aesKey = KeysGeneration.getKeys(keypass);
SecretKey secKey = KeysGeneration.getKeys(keypass);//generator.generateKey();
// Create key and cipher
Cipher cipher = Cipher.getInstance("AES");
// decrypt the text
cipher.init(Cipher.DECRYPT_MODE, secKey);
String decrypted= new String(cipher.doFinal(email.getBytes()));
return "Using POST method \n Email address (decrypted): "+decrypted;
}
}
hi thank you i solved problem by your kind suggestion. I want to show you if I am calculating time correctly required for encryption: Here is my code
// //**********AES Encryption
//checking time in msec
long startTime=System.currentTimeMillis();
//System.out.println(startTime);
// // Create key and cipher
SecretKey aesKey = KeysGeneration.getKeys(keypass);
Cipher cipher = Cipher.getInstance("AES");
// // encrypt the text
cipher.init(Cipher.ENCRYPT_MODE, aesKey);
byte[] encrypted = cipher.doFinal(email.getBytes());
System.out.println("checking encryption "+new String(encrypted));
BASE64Encoder encoder = new BASE64Encoder();
email = encoder.encode(encrypted);
System.out.println("Encoded Encrypted Value="+email);
// text="&email="+URLEncoder.encode(new String(encrypted), "UTF-8");
writer.write("&email="+email);
//Calculating Encryption Time
long stopTime = System.currentTimeMillis();
Duration ms=Duration.ofMillis(stopTime);
//System.out.println(stopTime);
long elapsedTime = stopTime - startTime;
System.out.println("Time required for encryption (milliseconds)= "+elapsedTime);
Related
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);
});
}
I'm getting this error when I try to decrypt a message which has already been encrypted.
I've done this by first encrypting a message in this case "Testing message"
Then running the method again but decrypting instead of encrypting.
I've looked at the other questions regarding this but could not fix the problem
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
public class PBEusing {
public static void main(String[] args) throws Exception {
PBEusing pbe = new PBEusing();
String encrypt = pbe.pbe("encrypt", "passwordTest", "Testing message");
System.out.println(encrypt);
String decrypt = pbe.pbe("decrypt", "passwordTest", encrypt);
System.out.println(decrypt);
}
public static String pbe(String cipherMethod, String clientPassword, String clientMessage) throws Exception {
String method = cipherMethod.toUpperCase();
String output = "";
SecureRandom rnd = new SecureRandom();
byte[] iv = new byte[16];
rnd.nextBytes(iv);
byte[] plaintext = clientMessage.getBytes(StandardCharsets.UTF_8); // input message from user
byte[] salt = "01234567".getBytes(StandardCharsets.UTF_8);
IvParameterSpec ivParamSpec = new IvParameterSpec(iv);
PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, 10000, ivParamSpec);
PBEKeySpec keySpec = new PBEKeySpec(clientPassword.toCharArray());
try {
SecretKeyFactory kf = SecretKeyFactory.getInstance("PBEWithHmacSHA256AndAES_128");
SecretKey secretKey = kf.generateSecret(keySpec);
// On J2SE the SecretKeyfactory does not actually generate a key, it just wraps the password.
// The real encryption key is generated later on-the-fly when initializing the cipher
System.out.println(new String(secretKey.getEncoded()));
// Encrypt
if (method.equals("ENCRYPT")) {
Cipher enc = Cipher.getInstance("PBEWithHmacSHA256AndAES_128");
enc.init(Cipher.ENCRYPT_MODE, secretKey, pbeParamSpec);
byte[] encrypted = enc.doFinal(plaintext);
output = new BASE64Encoder().encode(encrypted);
System.out.println("Encrypted text: " + output);
} else {
// Decrypt
Cipher dec = Cipher.getInstance("PBEWithHmacSHA256AndAES_128");
dec.init(Cipher.DECRYPT_MODE, secretKey, pbeParamSpec);
byte[] decrypted = dec.doFinal(plaintext);
String test = new BASE64Encoder().encode(decrypted);
//String message = new String(test, StandardCharsets.UTF_8);
output = test;
}
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
}
return output;
}
}
You're Base64 encoding the output of the encryption but aren't Base64 decoding it again before you try to decrypt it.
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).
On the server side, the encyption/decryption of the password field is done in C#.
Now, i need to implement same functionality in my android application. So, i followed this tutorial: http://ttux.net/post/3des-java-encrypter-des-java-encryption/ as below:
import java.security.MessageDigest;
import java.security.spec.KeySpec;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;
import org.apache.commons.codec.binary.Base64;
public class Encrypter {
private KeySpec keySpec;
private SecretKey key;
private IvParameterSpec iv;
public Encrypter(String keyString, String ivString) {
try {
final MessageDigest md = MessageDigest.getInstance("md5");
final byte[] digestOfPassword = md.digest(Base64.decodeBase64(keyString.getBytes("utf-8")));
final byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);
for (int j = 0, k = 16; j < 8;) {
keyBytes[k++] = keyBytes[j++];
}
keySpec = new DESedeKeySpec(keyBytes);
key = SecretKeyFactory.getInstance("DESede").generateSecret(keySpec);
iv = new IvParameterSpec(ivString.getBytes());
} catch(Exception e) {
e.printStackTrace();
}
}
public String encrypt(String value) {
try {
Cipher ecipher = Cipher.getInstance("DESede/CBC/PKCS5Padding","SunJCE");
ecipher.init(Cipher.ENCRYPT_MODE, key, iv);
if(value==null)
return null;
// Encode the string into bytes using utf-8
byte[] utf8 = value.getBytes("UTF8");
// Encrypt
byte[] enc = ecipher.doFinal(utf8);
// Encode bytes to base64 to get a string
return new String(Base64.encodeBase64(enc),"UTF-8");
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public String decrypt(String value) {
try {
Cipher dcipher = Cipher.getInstance("DESede/CBC/PKCS5Padding","SunJCE");
dcipher.init(Cipher.DECRYPT_MODE, key, iv);
if(value==null)
return null;
// Decode base64 to get bytes
byte[] dec = Base64.decodeBase64(value.getBytes());
// Decrypt
byte[] utf8 = dcipher.doFinal(dec);
// Decode using utf-8
return new String(utf8, "UTF8");
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
but i dont know what values i need to provide for KeyValue and ivValue for the above code. Please help me...
Use this code to encrypt your string
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import android.util.Base64;
//string encryption
public class EncryptionHelper {
// Encrypts string and encode in Base64
public static String encryptText(String plainText) throws Exception {
// ---- Use specified 3DES key and IV from other source --------------
byte[] plaintext = plainText.getBytes();//input
byte[] tdesKeyData = Constants.getKey().getBytes();// your encryption key
byte[] myIV = Constants.getInitializationVector().getBytes();// initialization vector
Cipher c3des = Cipher.getInstance("DESede/CBC/PKCS5Padding");
SecretKeySpec myKey = new SecretKeySpec(tdesKeyData, "DESede");
IvParameterSpec ivspec = new IvParameterSpec(myIV);
c3des.init(Cipher.ENCRYPT_MODE, myKey, ivspec);
byte[] cipherText = c3des.doFinal(plaintext);
String encryptedString = Base64.encodeToString(cipherText,
Base64.DEFAULT);
// return Base64Coder.encodeString(new String(cipherText));
return encryptedString;
}
}
This is how you can encrypt the string
String encryptedPassword = EncryptionHelper.encryptText(edtText.getText().toString());
EDIT
Code for Constants.java
Class Constants {
private final String initializationVector = "INITALIZATION_VECTOR";
private final String ecnryptionKey = "ENCRYPTION_KEY";
public static String getInitializationVector() {
return initializationVector;
}
public static String getKey() {
return ecnryptionKey;
}
}
Triple DES is called "DESede" (DES using single DES Encrypt, Decrypt, Encrypt for encryption) in both Java and Android runtimes. So it is build in functionality which can be access through the Cipher class. It also lists the available algorithms. For triple DES you could use "DESede/CBC/PKCS5Padding"`. Don't forget to supply it a random IV of 8 bytes.
Triple DES should only be used for backwards compatibility. If you decide to use it at least supply it 24 bytes of key material, otherwise there is a chance that your ciphertext can be cracked. For a more modern approach use AES, preferably in an authenticated mode such as GCM ("AES/GCM/NoPadding"). Note that GCM requires a unique nonce of 12 bytes.
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.