编辑:::问题中的代码可以正常工作,但一旦图像在相机中拍摄,则需要大约10秒才能恢复活动。我放弃了这种方法,并使用Facebook的隐藏库来加密和解密图像。链接到Facebook的解决方案:Facebook Conceal - Image Encryption and Decryption
我已经查看了很多示例,但仍然无法找到一种正确的加密和解密方法。当我在互联网上使用一些随机代码时,我认为我弄错了,但在解码时,我得到了BadPadding异常。
所以,我正在努力解决这个问题。我按照下面的问题,正如大多数人在SO上所建议的那样(但这段代码显示了如何加密字符串)。有人可以帮助我加密和解密图像吗?问题中的代码是否适用于图像?
链接到问题:Java 256-bit AES Password-Based Encryption
这是我到目前为止所做的事情:
//存储iv和密码的全局arraylist
static ArrayList<byte[]> ivandcipher = new ArrayList<byte[]>();
//生成密钥
public static SecretKey generateKey() throws NoSuchAlgorithmException {
char[] password = { 'a', 'b', 'c', 'd', 'e' };
byte[] salt = { 1, 2, 3, 4, 5 };
SecretKeyFactory factory = SecretKeyFactory
.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec(password, salt, 65536, 256);
SecretKey tmp = null;
try {
tmp = factory.generateSecret(spec);
} catch (InvalidKeySpecException e) {
e.printStackTrace();
}
yourKey = new SecretKeySpec(tmp.getEncoded(), "AES");
return yourKey;
}
//编码文件
// byte [] fileData,包含转换为byte []
的位图(图像)public static ArrayList<byte[]> encodeFile(SecretKey yourKey, byte[] fileData)
throws Exception {
byte[] encrypted = null;
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, yourKey);
AlgorithmParameters params = cipher.getParameters();
byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV();
encrypted = cipher.doFinal(fileData);
ivandcipher.clear();
ivandcipher.add(iv);
ivandcipher.add(encrypted);
return ivandcipher;
}
为什么我要将iv和加密的byte []添加到ivandcipher。因为,正如链接中的答案所暗示的那样,我应该在解密时使用相同的iv。
//解码文件
//我在这个方法中调用了一个重载的decodeFile方法..请注意
private Bitmap decodeFile(String filename) {
try {
yourKey = generateKey();
} catch (NoSuchAlgorithmException e1) {
e1.printStackTrace();
}
try {
byte[] decodedData = decodeFile(yourKey, readFile(filename));
Bitmap bitmap = bytesToBitmap(decodedData);
return bitmap;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
//重载了decodeFile方法
public static byte[] decodeFile(SecretKey yourKey, byte[] fileData)
throws Exception {
byte[] decrypted = null;
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, yourKey, new IvParameterSpec(ivandcipher.get(0)));
decrypted = cipher.doFinal(fileData);
return decrypted;
}
我猜问题是fileData [],我无法正确加密和解密。对于字符串,如上面链接的答案所示,即
byte[] ciphertext = cipher.doFinal("Hello, World!".getBytes("UTF-8"));
应该作为cipher.doFinal()的参数给出什么?
如果您需要任何其他代码,请告诉我。
答案 0 :(得分:6)
使用Java库可以轻松加密和解密图像。我使用两种不同的加密和解密方法向您呈现两个单独的代码。以下代码也可以扩展为用于pdf文件。
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
public class ImageEncDec {
public static byte[] getFile() {
File f = new File("/home/bridgeit/Desktop/Olympics.jpg");
InputStream is = null;
try {
is = new FileInputStream(f);
} catch (FileNotFoundException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
byte[] content = null;
try {
content = new byte[is.available()];
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
is.read(content);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return content;
}
public static byte[] encryptPdfFile(Key key, byte[] content) {
Cipher cipher;
byte[] encrypted = null;
try {
cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key);
encrypted = cipher.doFinal(content);
} catch (Exception e) {
e.printStackTrace();
}
return encrypted;
}
public static byte[] decryptPdfFile(Key key, byte[] textCryp) {
Cipher cipher;
byte[] decrypted = null;
try {
cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, key);
decrypted = cipher.doFinal(textCryp);
} catch (Exception e) {
e.printStackTrace();
}
return decrypted;
}
public static void saveFile(byte[] bytes) throws IOException {
FileOutputStream fos = new FileOutputStream("/home/bridgeit/Desktop/Olympics-new.jpg");
fos.write(bytes);
fos.close();
}
public static void main(String args[])
throws NoSuchAlgorithmException, InstantiationException, IllegalAccessException, IOException {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(128);
Key key = keyGenerator.generateKey();
System.out.println(key);
byte[] content = getFile();
System.out.println(content);
byte[] encrypted = encryptPdfFile(key, content);
System.out.println(encrypted);
byte[] decrypted = decryptPdfFile(key, encrypted);
System.out.println(decrypted);
saveFile(decrypted);
System.out.println("Done");
}
}
` 这是生成相同输出的第二个代码,但只是一次又一次地生成相同的密钥。
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
public class Trial {
public static byte[] getFile() {
File f = new File("/home/bridgeit/Desktop/Olympics.jpg");
InputStream is = null;
try {
is = new FileInputStream(f);
} catch (FileNotFoundException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
byte[] content = null;
try {
content = new byte[is.available()];
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
is.read(content);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return content;
}
public static byte[] encryptPdfFile(SecretKey secretKey, byte[] content) {
Cipher cipher;
byte[] encrypted = null;
try {
cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
encrypted = Base64.encodeBase64(cipher.doFinal(content));
} catch (Exception e) {
System.out.println("Error while encrypting: " + e.toString());
}
return encrypted;
}
public static byte[] decryptPdfFile(SecretKey secretKey, byte[] textCryp) {
Cipher cipher;
byte[] decrypted = null;
try {
cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
decrypted = cipher.doFinal(Base64.decodeBase64(textCryp));
} catch (Exception e) {
System.out.println("Error while decrypting: " + e.toString());
}
return decrypted;
}
public static void saveFile(byte[] bytes) throws IOException {
FileOutputStream fos = new FileOutputStream("/home/bridgeit/Desktop/Olympics-new.jpg");
fos.write(bytes);
fos.close();
}
public static void main(String args[])
throws NoSuchAlgorithmException, InstantiationException, IllegalAccessException, IOException {
SecretKeySpec secretKey;
byte[] key;
String myKey = "ThisIsAStrongPasswordForEncryptionAndDecryption";
MessageDigest sha = null;
key = myKey.getBytes("UTF-8");
System.out.println(key.length);
sha = MessageDigest.getInstance("SHA-1");
key = sha.digest(key);
key = Arrays.copyOf(key, 16); // use only first 128 bit
System.out.println(key.length);
System.out.println(new String(key, "UTF-8"));
secretKey = new SecretKeySpec(key, "AES");
byte[] content = getFile();
System.out.println(content);
byte[] encrypted = encryptPdfFile(secretKey, content);
System.out.println(encrypted);
byte[] decrypted = decryptPdfFile(secretKey, encrypted);
System.out.println(decrypted);
saveFile(decrypted);
System.out.println("Done");
}
}
答案 1 :(得分:1)
你想要立刻做太多事情,并且迷失在所有细节中。
首先将代码简化为加密和解密所需的最低限度:
byte[] key = { 1, 2, 3, ... 14, 15, 16 };
byte[] IV = { 5, 5, 5, ... 5, 5, 5 };
String plaintext = "This is a secret message."
现在减少您的代码以加密和解密该明文消息回到可读的文本字符串。
如果您的小程序正常工作,请一次添加其他一个并发症。在每个阶段,再次检查您的代码是否可以成功加密和解密。我建议你首先添加SecretKeyFactory部分,然后完成文件的读写部分。
通过将程序拆分为更小的部分,您将更容易理解程序的每个部分正在做什么,并使您更容易识别出错误的位置。
答案 2 :(得分:0)
问题中的代码可以正常工作,但是一旦在相机中拍摄图像,则返回活动大约需要10秒钟。我放弃了这种方法,并使用Facebook的隐藏库来加密和解密图像。链接到Facebook的解决方案:Facebook Conceal - Image Encryption and Decryption