使用AES加密和解密图像的正确方法

编辑:::问题中的代码有效,但一旦图像在相机中拍摄,返回活动大约需要10秒钟。 我放弃了这种方法,并使用Facebook的隐藏库来加密和解密图像。 链接到Facebook的解决方案: Facebook隐藏 – 图像加密和解密


我已经查看了很多示例,但仍然无法找到一种正确的加密和解密方法。 当我在互联网上使用一些随机代码时,我认为我弄错了,但在解码时,我得到了BadPaddingexception。

所以,我正在尝试解决它。 我按照以下问题进行操作,正如大多数人在SO上所建议的那样(但此代码显示了如何加密字符串)。 有人可以帮助我加密和解密图像吗? 问题中的代码是否适用于图像?

链接到问题: Java 256位AES密码加密

这是我到目前为止所做的事情:

//用于存储iv和密码的全局arraylist

static ArrayList ivandcipher = new ArrayList(); 

//生成密钥

 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 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()的参数给出什么?

如果您需要任何其他代码,请告诉我。

可以使用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"); } } 

你试图一次做太多,并且迷失在所有细节中。

首先将代码简化为加密和解密所需的最低限度:

 byte[] key = { 1, 2, 3, ... 14, 15, 16 }; byte[] IV = { 5, 5, 5, ... 5, 5, 5 }; String plaintext = "This is a secret message." 

现在减少您的代码以加密和解密该明文消息回到可读的文本字符串。

如果您的小程序正常工作,请一次添加其他一个并发症。 在每个阶段,再次检查您的代码是否可以成功加密和解密。 我建议你先添加SecretKeyFactory部分,然后完成文件的读写部分。

通过将程序分成更小的部分,您将更容易理解程序的每个部分正在做什么,并使您更容易识别出错误的位置。

问题中的代码有效,但是一旦图像在相机中拍摄,则返回活动大约需要10秒钟。 我放弃了这种方法,并使用Facebook的隐藏库来加密和解密图像。 链接到Facebook的解决方案: Facebook隐藏 – 图像加密和解密