I am implementing encryption/decryption to my files. code is given below. I can't find out the problem.
Am I missing anything? I need to implement 128 bit AES Encryption.
Is there anything wrong?
It end up with error
"javax.crypto.BadPaddingException: error:1e06b065:Cipher functions:EVP_DecryptFinal_ex:BAD_DECRYPT"
Please help me.
private static byte[] encodeFile(byte[] yourKey, byte[] fileData)
throws Exception {
byte[] encrypted = null;
SecretKeySpec skeySpec = new SecretKeySpec(yourKey, 0, yourKey.length, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7PADDING");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
encrypted = cipher.doFinal(fileData);
return encrypted;
}
private static byte[] generateKey() throws NoSuchAlgorithmException {
byte[] keyStart = "This is my key".getBytes();
String id = "dummypass";
int iterationCount = 1000;
int saltLength = 32;
int keyLength = 128;
SecureRandom random = new SecureRandom();
byte[] salt = Arrays.copyOf(keyStart,saltLength);
random.nextBytes(salt);
KeySpec keySpec = new PBEKeySpec(id.toCharArray(), salt,
iterationCount, keyLength);
SecretKeyFactory keyFactory = SecretKeyFactory
.getInstance("PBKDF2WithHmacSHA1");
byte[] keyBytes = new byte[0];
try {
keyBytes = keyFactory.generateSecret(keySpec).getEncoded();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
}
SecretKey key = new SecretKeySpec(keyBytes, "AES");
return key.getEncoded();
}
private static byte[] decodeFile(byte[] yourKey, byte[] encryptedData)
throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(yourKey, 0, yourKey.length,
"AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7PADDING");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal(encryptedData);
return decrypted;
}
public static void Encrypt(byte[] bytesToEncrypt, File target) {
try {
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(target));
byte[] key = generateKey();
byte[] encryptedBytes = encodeFile(key, bytesToEncrypt);
bos.write(encryptedBytes);
bos.flush();
bos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
public static byte[] DecryptFile(byte[] bytesToDecrypt) {
byte[] decodedData = new byte[0];
try {
byte[] key = generateKey();
decodedData = decodeFile(key, bytesToDecrypt);
} catch (Exception e) {
e.printStackTrace();
}
return decodedData;
}
Verify that key is the same in both Encrypt and DecryptFile.
Since both call generateKey and generateKey calls SecureRandom nextBytes the keys are going to be different.
You need to save the encryption key for use during decryption.
Related
I wanna encrypt the string with secret key and Iv. But i am not getting correct encryption. can any one tell me how to do this.
My string is abc but when decrypt the string it is contain special charaters in this.
i followed this link:
https://www.cuelogic.com/blog/using-cipher-to-implement-cryptography-in-android/
package com.reshhhjuuitos.mhhhkoiyrestos.footer;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class MCrypt {
private String iv = "1234567890123456"; // Dummy iv (CHANGE IT!)
private IvParameterSpec ivspec;
private SecretKeySpec keyspec;
private Cipher cipher;
private String SecretKey = "1&BZ6pqSu1w2%7!8w0oQHJ7FF79%+MO2";
public MCrypt() {
ivspec = new IvParameterSpec(iv.getBytes());
keyspec = new SecretKeySpec(SecretKey.getBytes(), "AES");
try {
//cipher = Cipher.getInstance("AES/CBC/NoPadding");
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
catch (NoSuchPaddingException e) {
e.printStackTrace();
}
}
public byte[] encrypt(String text) throws Exception {
if (text == null || text.length() == 0)
throw new Exception("Empty string");
byte[] encrypted = null;
try {
// Cipher.ENCRYPT_MODE = Constant for encryption operation mode.
cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
encrypted = cipher.doFinal(padString(text).getBytes("UTF-8"));
} catch (Exception e) {
throw new Exception("[encrypt] " + e.getMessage());
}
return encrypted;
}
private static String padString(String source) {
char paddingChar = 0;
int size = 16;
int x = source.length() % size;
int padLength = size - x;
for (int i = 0; i < padLength; i++) {
source += paddingChar;
}
return source;
}
public static byte[] hexToBytes(String str) {
if (str == null) {
return null;
} else if (str.length() < 2) {
return null;
} else {
int len = str.length() / 2;
byte[] buffer = new byte[len];
for (int i = 0; i < len; i++) {
buffer[i] = (byte) Integer.parseInt(
str.substring(i * 2, i * 2 + 2), 16);
}
return buffer;
}
}
public static String byteArrayToHexString(byte[] array) {
StringBuffer hexString = new StringBuffer();
for (byte b : array) {
int intVal = b & 0xff;
if (intVal < 0x10)
hexString.append("0");
hexString.append(Integer.toHexString(intVal));
}
return hexString.toString();
}
public byte[] decrypt(String text) throws Exception {
if (text == null || text.length() == 0)
throw new Exception("Empty string");
byte[] decrypted = null;
try {
// Cipher.DECRYPT_MODE = Constant for decryption operation mode.
cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
decrypted = cipher.doFinal(hexToBytes(text));
} catch (Exception e) {
throw new Exception("[decrypt] " + e.getMessage());
}
return decrypted;
}
}
MainACTVITIY.JAVA
MCrypt mycrypt = new MCrypt();
String dummyStr = "abc";
try {
String encryptedStr = mycrypt.byteArrayToHexString(mycrypt.encrypt(dummyStr));
String decryptedStr = new String(mycrypt.decrypt(encryptedStr));
Log.v("Tag_en",""+encryptedStr);
Log.v("Tag_de",""+decryptedStr);
} catch (Exception e) {
e.printStackTrace();
}
output:Tag_en:5b49ac218b93ee5315c25a0e40b3e9de42e6ecadf0827062b22d4421da99dc5a
Tag_de: abc��������������������������
Okay, I thought it might be your hex encode/decode, but they work. So I wrote some quick encryption and tested it against your class.
The problem is your padding. I don't understand why you are padding your string to length 16, but it is the null characters you have appended to your string that are unprintable. So either don't pad the string, or strip the padding nulls during decryption to rebuild the exact string you encrypted.
For clarity, maintainability and re-usability, you should really do just one clear logical operation in each of your methods, i.e. padding should be done before you pass the string to the encryption method, so the encryption method just encrypts.
You could use functions like these:
private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(clear);
return encrypted;
}
private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal(encrypted);
return decrypted;
}
And invoke them like this:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.PNG, 100, baos); // bm is the bitmap object
byte[] b = baos.toByteArray();
byte[] keyStart = "this is a key".getBytes();
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(keyStart);
kgen.init(128, sr); // 192 and 256 bits may not be available
SecretKey skey = kgen.generateKey();
byte[] key = skey.getEncoded();
// encrypt
byte[] encryptedData = encrypt(key,b);
// decrypt
byte[] decryptedData = decrypt(key,encryptedData);
This should work, I use similar code in a project right now.
I want to encode and decode a File in Android but when i try to decrypt some File it returns an empty array of bytes.
The class I use to encrypt the File and decrypt:
public class CrytedClass {
public static byte[] generateKey(String pass) throws Exception{
byte [] start = pass.getBytes("UTF-8");
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(start);
kgen.init(128,sr);
SecretKey skey = kgen.generateKey();
return skey.getEncoded();
}
public static byte[] encodedFile(byte[] key, byte[] fileData)throws Exception{
SecretKeySpec skeySpec = new SecretKeySpec(key,"AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE,skeySpec);
byte [] encrypted = cipher.doFinal(fileData);
return encrypted;
}
public static byte[] decodeFile(byte[] key, byte[] fileData) throws Exception{
SecretKeySpec skeySpec = new SecretKeySpec(key,"AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE,skeySpec);
byte [] decrypted = cipher.doFinal(fileData);
return decrypted;
}
public static String generatePass(){
return new BigInteger(130, new SecureRandom()).toString(32);
}
public static byte[] createHas(byte[] ficheroEncrip){
MessageDigest msd = null;
try{
msd = MessageDigest.getInstance("SHA-1");
}catch (Exception e){
return null;
}
msd.update(ficheroEncrip);
return msd.digest();
}
}
The test code i use.
try {
String id1 = CrytedClass.generatePass();
byte[] secure = CrytedClass.generateKey(id1);
byte[] FileEncoded = CrytedClass.encodedFile(secure, ous.toByteArray());
byte[] decoded = CrytedClass.decodeFile(secure, FileEncoded);
File decodedFile = new File(Environment.getExternalStorageDirectory()+"/decoded.pdf");
FileOutputStream pdfFile = new FileOutputStream(decodedFile);
pdfFile.write(decoded);
System.out.println("Final del test");
Boolean r = pdfFile.equals(original);
}catch(Exception e){
}
Thanks for your help
I have found 2 AES encryption/decryption functions and I want to use them inside my app, but I get an error.
The functions are:
private static final String password = "test";
private static String salt;
private static int pswdIterations = 65536 ;
private static int keySize = 256;
private byte[] ivBytes;
////////////////
//encrypt AES///
////////////////
public String encrypt(String plainText) throws Exception {
//get salt
salt = generateSalt();
byte[] saltBytes = salt.getBytes("UTF-8");
// Derive the key
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
PBEKeySpec spec = new PBEKeySpec(
password.toCharArray(),
saltBytes,
pswdIterations,
keySize
);
SecretKey secretKey = factory.generateSecret(spec);
SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
//encrypt the message
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
AlgorithmParameters params = cipher.getParameters();
ivBytes = params.getParameterSpec(IvParameterSpec.class).getIV();
byte[] encryptedTextBytes = cipher.doFinal(plainText.getBytes("UTF-8"));
return new Base64().encodeAsString(encryptedTextBytes);
}
#SuppressWarnings("static-access")
public String decrypt(String encryptedText) throws Exception {
byte[] saltBytes = salt.getBytes("UTF-8");
byte[] encryptedTextBytes = new Base64().decodeBase64(encryptedText);
// Derive the key
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
PBEKeySpec spec = new PBEKeySpec(
password.toCharArray(),
saltBytes,
pswdIterations,
keySize
);
SecretKey secretKey = factory.generateSecret(spec);
SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
// Decrypt the message
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(ivBytes));
byte[] decryptedTextBytes = null;
try {
decryptedTextBytes = cipher.doFinal(encryptedTextBytes);
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return new String(decryptedTextBytes);
}
public String generateSalt() {
SecureRandom random = new SecureRandom();
byte bytes[] = new byte[20];
random.nextBytes(bytes);
String s = new String(bytes);
return s;
}
My error is at line:
return new Base64().encodeAsString(encryptedTextBytes);
and
byte[] encryptedTextBytes = new Base64().decodeBase64(encryptedText);
The error msg is : The constructor Base64() is not visible
Any idea why this happens?
I've never worked with encryption before. Actually I know nothing about encryption. I have a file encrypted with openssl tool using params:
openssl aes-256-cbc -nosalt -in fileIn -out fileOUT -p -k KEY
I need to decrypt it into memory but I don't know how. Can anyone provide me the code related to encryption?
Here's class I have written to decrypt a string encoded with params above (if I remmeber it correct):
public class CipherUtils {
public static byte[] getKey(String password, byte[] salt) {
try {
byte[] passwordSalt = EncodingUtils.getAsciiBytes(password);
passwordSalt = concatenateByteArrays(passwordSalt, salt);
byte[] hash1 = getHashForHash(null, passwordSalt);
byte[] hash2 = getHashForHash(hash1, passwordSalt);
byte[] key = concatenateByteArrays(hash1, hash2);
return key;
} catch (Exception e) {
return null;
}
}
public static byte[] getIV(String password, byte[] salt) {
try {
byte[] passwordSalt = EncodingUtils.getAsciiBytes(password);
passwordSalt = concatenateByteArrays(passwordSalt, salt);
byte[] hash1 = getHashForHash(null, passwordSalt);
byte[] hash2 = getHashForHash(hash1, passwordSalt);
byte[] hash3 = getHashForHash(hash2, passwordSalt);
return hash3;
} catch (Exception e) {
return null;
}
}
private static byte[] getHashForHash(byte[] hash, byte[] passwordSalt) {
try {
byte[] hashMaterial = concatenateByteArrays(hash, passwordSalt);
MessageDigest md = MessageDigest.getInstance("MD5");
return md.digest(hashMaterial);
} catch (Exception e) {
return null;
}
}
private static byte[] concatenateByteArrays(byte[] a, byte[] b) {
if (a == null)
return b;
if (b == null)
return a;
byte[] result = new byte[a.length + b.length];
System.arraycopy(a, 0, result, 0, a.length);
System.arraycopy(b, 0, result, a.length, b.length);
return result;
}
}
Salt is an empty bytearray in this case. It uses apache-commons-compress.jar.
Here's usage example:
byte[] key = CipherUtils.getKey(password, null);
byte[] IV = CipherUtils.getIV(password, null);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"),
new IvParameterSpec(IV));
cis = new CipherInputStream(is, cipher);
Where is is an InputStream of encrypted data.
this may helps you
public void encrypt() throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
// Here you read the cleartext.
FileInputStream fis = new FileInputStream("data/cleartext");
// This stream write the encrypted text. This stream will be wrapped by
// another stream.
FileOutputStream fos = new FileOutputStream("data/encrypted");
// Length is 16 byte
SecretKeySpec sks = new SecretKeySpec("yourkey".getBytes(), "AES");
// Create cipher
Cipher cipher = Cipher.getInstance("AES/CBC");
cipher.init(Cipher.ENCRYPT_MODE, sks);
// Wrap the output stream
CipherOutputStream cos = new CipherOutputStream(fos, cipher);
// Write bytes
int b;
byte[] d = new byte[8];
while ((b = fis.read(d)) != -1) {
cos.write(d, 0, b);
}
// Flush and close streams.
cos.flush();
cos.close();
fis.close();
}
Decrypt
public void decrypt() throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
FileInputStream fis = new FileInputStream("data/encrypted");
FileOutputStream fos = new FileOutputStream("data/decrypted");
SecretKeySpec sks = new SecretKeySpec("yourkey".getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC");
cipher.init(Cipher.DECRYPT_MODE, sks);
CipherInputStream cis = new CipherInputStream(fis, cipher);
int b;
byte[] d = new byte[8];
while((b = cis.read(d)) != -1) {
fos.write(d, 0, b);
}
fos.flush();
fos.close();
cis.close();
}
I have done an encryption using the AES but iam not able to do the decryption Iam gettin an javax.crypto.IllegalBlockSizeException: last block incomplete in decryption.....I cant trace out where is the problem.I appreciate any help.
try {
in = new FileInputStream("/sdcard/Pic 1.txt");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
File f=new File("/sdcard/Pic 1.txt");
buf = new byte[(int) f.length()+2];
try {
in.read(buf);
} catch (IOException e) {
e.printStackTrace();
}
try {
decryptedData = decrypt(key, buf);
decryptedimage = BitmapFactory.decodeByteArray(
decryptedData, 0, decryptedData.length);
loadedimage.setImageBitmap(decryptedimage);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public void Encription(Bitmap bm) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 100, baos);
b = baos.toByteArray();
try {
keyStart = ".....".getBytes();
kgen = KeyGenerator.getInstance("AES");
sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(keyStart);
kgen.init(128, sr); // 192 and 256 bits may not be available
skey = kgen.generateKey();
key = skey.getEncoded();
encryptedData = encrypt(key, b);
encryptedimage = BitmapFactory.decodeByteArray(encryptedData, 0,
encryptedData.length);
out = new FileOutputStream("/sdcard/"+"Pic "+i+".txt");
out.write(encryptedData, 0, encryptedData.length);
out.close();
} catch (Exception e) {
}
i++;
}
private byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(clear);
return encrypted;
}
private byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
long start=System.currentTimeMillis()/1000l;
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal(encrypted);
return decrypted;
}
02-19 08:27:06.972: W/System.err(12742): javax.crypto.IllegalBlockSizeException: last block incomplete in decryption