为什么桌面AES文件IO与Android AES文件IO不兼容?

我已将Android应用程序移植到桌面,使用AES加密某些私有数据。 两个应用程序都能够加密和解密数据供自己使用,但无法解密其他应用程序数据。 AES密钥,IV和算法是相同的。 这两个应用程序的主要区别在于android-sdk附带了BouncyCastle提供程序,已经添加到安全性,而桌面应用程序需要

Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); 

Android应用:

 public class AesFileIo { public final static String EOL = "\n"; public static final String AES_ALGORITHM = "AES/CTR/NoPadding"; public static final String PROVIDER = "BC"; private static final SecretKeySpec secretKeySpec = new SecretKeySpec(AES_KEY_128, "AES"); private static final IvParameterSpec ivSpec = new IvParameterSpec(IV); public String readAesFile(Context c, String fileName) { StringBuilder stringBuilder = new StringBuilder(); try { InputStream is = c.openFileInput(fileName); Cipher cipher = Cipher.getInstance(AES_ALGORITHM, PROVIDER); cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivSpec); CipherInputStream cis = new CipherInputStream(is, cipher); InputStreamReader isr = new InputStreamReader(cis); BufferedReader reader = new BufferedReader(isr); String line; while ((line = reader.readLine()) != null) { stringBuilder.append(line).append(EOL); } is.close(); } catch (java.io.FileNotFoundException e) { // OK, file probably not created yet Log.i(this.getClass().toString(), e.getMessage(), e); } catch (Exception e) { Log.e(this.getClass().toString(), e.getMessage(), e); } return stringBuilder.toString(); } public void writeAesFile(Context c, String fileName, String theFile) { try { Cipher cipher = Cipher.getInstance(AES_ALGORITHM, PROVIDER); cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivSpec); byte[] encrypted = cipher.doFinal(theFile.getBytes()); OutputStream os = c.openFileOutput(fileName, 0); os.write(encrypted); os.flush(); os.close(); } catch (Exception e) { Log.e(this.getClass().toString(), e.getMessage(), e); } } } 

桌面应用:

 public class AesFileIo { private static final String EOL = "\n"; private static final String AES_ALGORITHM = "AES/CTR/NoPadding"; private static final SecretKeySpec secretKeySpec = new SecretKeySpec(AES_KEY_128, "AES"); private static final IvParameterSpec ivSpec = new IvParameterSpec(IV); public void AesFileIo() { Security.addProvider(new org.bouncycastle.jce.provider .BouncyCastleProvider()); } public String readFile(String fileName) { StringBuilder stringBuilder = new StringBuilder(); try { ObjectInputStream is = new ObjectInputStream( new FileInputStream(fileName)); Cipher cipher = Cipher.getInstance(AES_ALGORITHM); cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivSpec); CipherInputStream cis = new CipherInputStream(is, cipher); InputStreamReader isr = new InputStreamReader(cis); BufferedReader reader = new BufferedReader(isr); String line; while ((line = reader.readLine()) != null) { stringBuilder.append(line).append(EOL); } is.close(); } catch (java.io.FileNotFoundException e) { System.out.println("FileNotFoundException: probably OK"); } catch (Exception e) { e.printStackTrace(); } return stringBuilder.toString(); } public void writeFile(String fileName, String theFile) { try { Cipher cipher = Cipher.getInstance(AES_ALGORITHM); cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivSpec); byte[] encrypted = cipher.doFinal(theFile.getBytes()); ObjectOutputStream os = new ObjectOutputStream( new FileOutputStream(fileName)); os.write(encrypted); os.flush(); os.close(); } catch (Exception e) { e.printStackTrace(); } } } 

解决了

  1. 添加适当的构造函数来初始化SecretKeySpec和IvParameterSpec。
  2. 摆脱桌面应用程序中的ObjectOutputStream和ObjectInputStream。

Android应用:

 public class AesFileIo { private static final String EOL = "\n"; private static final String AES_ALGORITHM = "AES/CTR/NoPadding"; private SecretKeySpec secretKeySpec; private IvParameterSpec ivSpec; private static final String PROVIDER = "BC"; AesFileIo(byte[] aesKey, byte[] iv) { ivSpec = new IvParameterSpec(iv); secretKeySpec = new SecretKeySpec(aesKey, "AES"); } public String readFile(Context c, String fileName) { StringBuilder stringBuilder = new StringBuilder(); try { InputStream is = c.openFileInput(fileName); Cipher cipher = Cipher.getInstance(AES_ALGORITHM, PROVIDER); cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivSpec); CipherInputStream cis = new CipherInputStream(is, cipher); InputStreamReader isr = new InputStreamReader(cis); BufferedReader reader = new BufferedReader(isr); String line; while ((line = reader.readLine()) != null) { stringBuilder.append(line).append(EOL); } is.close(); } catch (java.io.FileNotFoundException e) { // OK, file probably not created yet Log.i(this.getClass().toString(), e.getMessage(), e); } catch (Exception e) { Log.e(this.getClass().toString(), e.getMessage(), e); } return stringBuilder.toString(); } public void writeFile(Context c, String fileName, String theFile) { try { Cipher cipher = Cipher.getInstance(AES_ALGORITHM, PROVIDER); cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivSpec); byte[] encrypted = cipher.doFinal(theFile.getBytes()); OutputStream os = c.openFileOutput(fileName, 0); os.write(encrypted); os.flush(); os.close(); } catch (Exception e) { Log.e(this.getClass().toString(), e.getMessage(), e); } } } 

桌面应用:

 public class AesFileIo { private static final String EOL = "\n"; private static final String AES_ALGORITHM = "AES/CTR/NoPadding"; private SecretKeySpec secretKeySpec; private IvParameterSpec ivSpec; AesFileIo(byte[] aesKey, byte[] iv) { Security.addProvider(new org.bouncycastle.jce.provider .BouncyCastleProvider()); ivSpec = new IvParameterSpec(iv); secretKeySpec = new SecretKeySpec(aesKey, "AES"); } public String readFile(String fileName) { StringBuilder stringBuilder = new StringBuilder(); try { FileInputStream fis = new FileInputStream(fileName); Cipher cipher = Cipher.getInstance(AES_ALGORITHM); cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivSpec); CipherInputStream cis = new CipherInputStream(fis, cipher); InputStreamReader isr = new InputStreamReader(cis); BufferedReader reader = new BufferedReader(isr); String line; while ((line = reader.readLine()) != null) { stringBuilder.append(line).append(EOL); } fis.close(); } catch (java.io.FileNotFoundException e) { System.out.println("FileNotFoundException: probably OK"); } catch (Exception e) { e.printStackTrace(); } return stringBuilder.toString(); } public void writeFile(String fileName, String theFile) { try { Cipher cipher = Cipher.getInstance(AES_ALGORITHM); cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivSpec); byte[] encrypted = cipher.doFinal(theFile.getBytes()); FileOutputStream fos = new FileOutputStream(fileName); fos.write(encrypted); fos.flush(); fos.close(); } catch (Exception e) { e.printStackTrace(); } } }