Grabación cifrada y carga descifrada de un ArrayList de objetos serializables

Ahorro y carga en la tarjeta del SD un archivo que contiene un ArrayList del objeto serializable con estos dos métodos

Guardar método

 public static void saveUserList(ArrayList<User> userList) { if (storageAvailable()) { try { createFolder(); FileOutputStream userList = new FileOutputStream( baseDir + File.separator + baseAppDir + File.separator + fileName); ObjectOutputStream oos = new ObjectOutputStream( userList); oos.writeObject(userList); oos.close(); } catch (Exception exc) { exc.printStackTrace(); } } } 

Método de carga

  public static ArrayList<User> loadUserList() { if (storageAvailable()) { ArrayList<User> userList = new ArrayList<User>(); try { FileInputStream userList = new FileInputStream(baseDir + File.separator + baseAppDir + File.separator + fileName); ObjectInputStream oos = new ObjectInputStream( userList); userList = (ArrayList<User>) oos.readObject(); oos.close(); } catch (Exception exc) { exc.printStackTrace(); } return userList; } else { return null; } } 

Ahora quiero que el método saveUserList el contenido del archivo durante la saveUserList acuerdo a una String keyword específica y el método loadUserList descifra el archivo con la misma palabra clave para devolver el arrayList.

¿Cómo podría hacer esto? He dado un vistazo a CipherOutputStream pero no he entendido cómo debo usar esto.

El método propuesto para utilizar la biblioteca Conceal

 public static void saveUserListCrypted(ArrayList<User> userList) { if (storageAvailable()) { try { createFolder(); Crypto crypto = new Crypto( new SharedPrefsBackedKeyChain(context), new SystemNativeCryptoLibrary()); FileOutputStream userList = new FileOutputStream( baseDir + File.separator + baseAppDir + File.separator + fileName); OutputStream cryptedStream = crypto.getCipherOutputStream( userList, new Entity("UserList"); ObjectOutputStream oos = new ObjectOutputStream( cryptedStream); oos.writeObject(userList); oos.close(); } catch (Exception exc) { exc.printStackTrace(); } } } 

Causar este error

  this error java.lang.UnsupportedOperationException 02-12 21:29:05.026 2051-2051/com.myapp W/System.err﹕ at com.facebook.crypto.streams.NativeGCMCipherOutputStream.write 

Intenta (añadiendo las comprobaciones adecuadas y prueba los bloques que he omitido para que el código sea más legible) algo así para guardar

 public static void AESObjectEncoder(Serializable object, String password, String path) { try { Cipher cipher = null; cipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); cipher.init(Cipher.ENCRYPT_MODE, fromStringToAESkey(password)); SealedObject sealedObject = null; sealedObject = new SealedObject(object, cipher); CipherOutputStream cipherOutputStream = null; cipherOutputStream = new CipherOutputStream(new BufferedOutputStream(new FileOutputStream(path)), cipher); ObjectOutputStream outputStream = null; outputStream = new ObjectOutputStream(cipherOutputStream); outputStream.writeObject(sealedObject); outputStream.close(); } 

Y esto para cargar

  public static Serializable AESObjectDedcoder(String password, String path) { Cipher cipher = null; Serializable userList = null; cipher = Cipher.getInstance("AES/CBC/PKCS7Pdding"); //Code to write your object to file cipher.init(Cipher.DECRYPT_MODE, fromStringToAESkey(password)); CipherInputStream cipherInputStream = null; cipherInputStream = new CipherInputStream(new BufferedInputStream(new FileInputStream(path)), cipher); ObjectInputStream inputStream = null; inputStream = new ObjectInputStream(cipherInputStream); SealedObject sealedObject = null; sealedObject = (SealedObject) inputStream.readObject(); userList = (Serializable) sealedObject.getObject(ciper); return userList; } 

Para crear un SecretKey partir de una String puedes usar esto

 public static SecretKey fromStringToAESkey(String s) { //256bit key need 32 byte byte[] rawKey = new byte[32]; // if you don't specify the encoding you might get weird results byte[] keyBytes = new byte[0]; try { keyBytes = s.getBytes("ASCII"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } System.arraycopy(keyBytes, 0, rawKey, 0, keyBytes.length); SecretKey key = new SecretKeySpec(rawKey, "AES"); return key; } 

Sugiero echar un vistazo a Ocultar, recientemente publicado por facebook: http://facebook.github.io/conceal/

Esto debería ser una modificación trivial para envolver un flujo de salida Conceal con un ObjectOutputStream utilizado en su código actual:

 public static void saveUserList(ArrayList<User> userList) { if (storageAvailable()) { try { createFolder(); Crypto crypto = new Crypto( new SharedPrefsBackedKeyChain(context), new SystemNativeCryptoLibrary()); FileOutputStream userList = new FileOutputStream( baseDir + File.separator + baseAppDir + File.separator + fileName); OutputStream cryptedStream = crypto.getCipherOutputStream( userList, new Entity("UserList"); ObjectOutputStream oos = new ObjectOutputStream( cryptedStream); oos.writeObject(userList); oos.close(); } catch (Exception exc) { exc.printStackTrace(); } } } 

Voy a dejar la restauración como un ejercicio para el lector. 😉

Simplemente puede usar AES Encoding:

 private static byte[] getEncrypt(final String key, final String message) throws GeneralSecurityException { final byte[] rawData = key.getBytes(Charset.forName("US-ASCII")); if (rawData.length != 16) { // If this is not 16 in length, there's a problem with the key size, nothing to do here throw new IllegalArgumentException("You've provided an invalid key size"); } final SecretKeySpec seckeySpec = new SecretKeySpec(rawData, "AES"); final Cipher ciph = Cipher.getInstance("AES/CBC/PKCS5Padding"); ciph.init(Cipher.ENCRYPT_MODE, seckeySpec, new IvParameterSpec(new byte[16])); return ciph.doFinal(message.getBytes(Charset.forName("US-ASCII"))); } private static String getDecrypt(String key, byte[] encrypted) throws GeneralSecurityException { final byte[] rawData = key.getBytes(Charset.forName("US-ASCII")); if (rawData.length != 16) { // If this is not 16 in length, there's a problem with the key size, nothing to do here throw new IllegalArgumentException("Invalid key size."); } final SecretKeySpec seckeySpec = new SecretKeySpec(rawData, "AES"); final Cipher ciph = Cipher.getInstance("AES/CBC/PKCS5Padding"); ciph.init(Cipher.DECRYPT_MODE, seckeySpec, new IvParameterSpec(new byte[16])); final byte[] decryptedmess = ciph.doFinal(encrypted); return new String(decryptedmess, Charset.forName("US-ASCII")); } 

Entonces, para probarlo, este ejemplo puede ser válido para usted:

 final String encrypt = "My16inLengthKey5"; final byte[] docrypt = getEncrypt(encrypt, "This is a phrase to be encrypted!"); final String douncrypt = getDecrypt(encrypt.toString(), docrypt); Log.d("Decryption", "Decrypted phrase: " + douncrypt); 

Por supuesto, douncrypt debe coincidir This is a phrase to be encrypted!

  • Android JobScheduler se ejecuta varias veces
  • Aplicación de Android - ¿Cómo puedo añadir soporte de pantalla Nexus 7 sin tener que definir explícitamente otros
  • ¿Cómo dibujo una flecha (en Android)?
  • Biblioteca de Android xmpp
  • IntelliJ importa proyecto de POM usando la versión incorrecta de JDK
  • Android: CursorLoader, LoaderManager, SQLite
  • Cómo pasar un argumento a una prueba junit de android (pruebas parametrizadas)
  • Dormir un hilo hasta que un evento sea asistido en otro hilo
  • Creación de LinearLayout en Java - Los elementos no se muestran
  • No se puede resolver el símbolo c882c94be45fff9d16a1cf845fc16ec5
  • ¿Cómo utilizo la API no oficial de Android Market?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.