0

The Problem:

I'm currently writing an app for Android API Level 19 (Yeah, I know it's pretty old). I'm running into a problem with serializing settings data. Part of the problem is that some of the data is confidential and must be encrypted before being written to disk. So there is a mix of encrypted and unencrypted data. The data consists of int, Boolean, String, byte[], and other types.

For those who are interested, when the app starts up, the user must enter their PIN. The PIN is ran through a hash algorithm a few times. In the middle of the run, they crypto key is taken and then the hashing loop runs to completion. So the intermediate result is the key, and the final result is the verification. The verification is written to the settings file while the key is used to encrypt or decrypt the confidential data. There are other safeguards in place, but that is how it works in a nutshell.

Most of the implementations that I have found use HashMap and ObjectOutputStream which cannot be used because of the cryptography issue (according to the examples that I have seen thus far). I did come across the Data class in the Android developer documentation, but Android Studio says that it requires API 29 to use.

Research:

I have found quite a few answers in various places such as:

Reliably convert any object to String and then back again

https://developer.android.com/reference/androidx/work/Data

https://beginnersbook.com/2013/12/how-to-serialize-hashmap-in-java/

HashMap not Serializable

https://developer.android.com/guide/topics/security/cryptography#java

...and many others, but I can't really use them because of what I am trying to do.

Daniel Rudy
  • 1,411
  • 12
  • 23

2 Answers2

1

An answer to the question you specifically asked is:

  ByteArrayOutputStream baos = new ByteArrayOutputStream();
  ObjectOuputStream oos = new ObjectOuputStream(baos);

  oos.writeObject(someObject);
  oos.close();

  byte[] serialized = baos.toByteArray();

This serializes to a byte array. No files are used. You can then encrypt the serialization before writing it ... using whatever encryption scheme you choose.

However, a better idea is to put the encryption into the output pipeline; e.g.

  FileOutputStream fos = new FileOutputStream(path);
  Cipher c = ...
  CipherOutputStream cos = new CipherOutputStream(fos, c);
  ObjectOuputStream oos = new ObjectOuputStream(baos);

  oos.writeObject(someObject);
  oos.close();

The serialization will be encrypted before writing to the file system.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • This does seem to be the correct answer. However, I think instead of OutputStream, it should be ByteArrayOutputStream as OutputStream does not have a toByteArray method. I am working on this now. Once I confirm it, I will mark this as the accepted answer. – Daniel Rudy Jan 13 '20 at 20:02
  • Yes. My mistake. Fixed. – Stephen C Jan 16 '20 at 05:15
0

You can write and read your data through a cipheroutputstream How to use CipherOutputStream correctly to encrypt and decrypt log created with log4j (RollingFileAppender). ObjectInputStream with CipherInputStream freezing, hanging

The CipherOutputStream encrypt the data for you. You can decrypt it with a CipherInputStream.

You must place the cipheroutputstream between your object stream and the file stream.

CodingSamples
  • 194
  • 1
  • 1
  • 7
  • Because of the mix of encrypted and unencrypted data, I cannot do that. Some of the information must remain unencrypted. Otherwise I would have used the file code in the cryptography link from the Android Developer's documentation that I provided as part of my research above. – Daniel Rudy Jan 13 '20 at 18:54
  • Please think about your structure. Why do you mix encrypted data and unencrypted data together? If this is necessary please extract the data which should be encrypted and write it encrypted to your disk. The data which can be saved unencrypted you can store unencryted. If you load the data you decrypt the encrypted data and mix them together with the unencrypted data. I don't understand your issue. – CodingSamples Jan 14 '20 at 08:57
  • The issue is that you did not answer the question as asked. I asked for a way to serialize an object without using files. The accepted answer did that. I realize that the crypto issue is a red herring. However, it explains my motivations for doing what I am doing. I could have used two files: one for the public data, and one for the private data, but I didn't want to deal with the hassle of dealing with two files. – Daniel Rudy Jan 16 '20 at 05:26