"Error storing data" on Android
See original GitHub issueHello!
I’m hooking up redux-persist-sensitive-storage
in a project. That package relies on react-native-sensitive-info
for it to do the actual storage part. On iOS it all seems to be working fine, but on Android (in the simulator at least) I get an error.
Important note: I’m using the keystore
branch of of react-native-sensitive-info
in order to have encrypted storage on Android. With the package installed through yarn I’m not running into any problems (but then the data is not encrypted).
The error I get is this:
Error storing data Error: null
at createErrorFromErrorData (NativeModules.js:121)
at NativeModules.js:78
at MessageQueue.__invokeCallback (MessageQueue.js:398)
at MessageQueue.js:137
at MessageQueue.__guardSafe (MessageQueue.js:314)
at MessageQueue.invokeCallbackAndReturnFlushedQueue (MessageQueue.js:136)
at debuggerWorker.js:70
My store configuration roughly looks like this:
import { createStore, applyMiddleware, Store } from "redux";
import { persistCombineReducers, PersistConfig, persistStore } from "redux-persist";
import thunk from "redux-thunk";
import createSensitiveStorage from "redux-persist-sensitive-storage";
import reducers from "../reducers";
// redux-persist configuration
const persistConfig: PersistConfig = {
debug: __DEV__,
storage: createSensitiveStorage({
keychainService: "ChaosKeychain",
sharedPreferencesName: "ChaosSharedPrefs"
})
};
// Time to create the store
export const store: Store = createStore(
persistCombineReducers(persistConfig, reducers),
applyMiddleware(thunk)
);
// ...aaaand, persist it as well
persistStore(store);
Tried to dig a little deeper and have a look at some logs through adb logcat
, and I noticed a javax.crypto.IllegalBlockSizeException
exception being thrown:
08-06 11:47:44.247 1328 1328 D TrustyKeymaster: Device received get_key_characteristics
08-06 11:47:44.247 1328 1328 E TrustyKeymaster: calling trusty_keymaster_call insize 199 msg size 203
08-06 11:47:44.247 1328 1328 E TrustyKeymaster: Received 158 byte response
08-06 11:47:44.247 1328 1328 D TrustyKeymaster: Device received begin
08-06 11:47:44.247 1328 1328 E TrustyKeymaster: calling trusty_keymaster_call insize 259 msg size 263
08-06 11:47:44.247 1328 1328 E TrustyKeymaster: Received 48 byte response
08-06 11:47:44.249 1328 1328 D TrustyKeymaster: Device received update
08-06 11:47:44.249 1328 1328 E TrustyKeymaster: calling trusty_keymaster_call insize 8908 msg size 8912
08-06 11:47:44.249 1328 1328 E TrustyKeymaster: Received 0 byte response
08-06 11:47:44.249 1328 1328 E TrustyKeymaster: Error deserializing response of size 0
08-06 11:47:44.251 4686 4954 D RNSensitiveInfo: javax.crypto.IllegalBlockSizeException
08-06 11:47:44.251 4686 4954 D RNSensitiveInfo: at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:519)
08-06 11:47:44.251 4686 4954 D RNSensitiveInfo: at javax.crypto.Cipher.doFinal(Cipher.java:1736)
08-06 11:47:44.251 4686 4954 D RNSensitiveInfo: at br.com.classapp.RNSensitiveInfo.RNSensitiveInfoModule.encrypt(RNSensitiveInfoModule.java:255)
08-06 11:47:44.251 4686 4954 D RNSensitiveInfo: at br.com.classapp.RNSensitiveInfo.RNSensitiveInfoModule.putExtra(RNSensitiveInfoModule.java:147)
08-06 11:47:44.251 4686 4954 D RNSensitiveInfo: at br.com.classapp.RNSensitiveInfo.RNSensitiveInfoModule.setItem(RNSensitiveInfoModule.java:90)
08-06 11:47:44.251 4686 4954 D RNSensitiveInfo: at java.lang.reflect.Method.invoke(Native Method)
08-06 11:47:44.251 4686 4954 D RNSensitiveInfo: at com.facebook.react.bridge.JavaMethodWrapper.invoke(JavaMethodWrapper.java:372)
08-06 11:47:44.251 4686 4954 D RNSensitiveInfo: at com.facebook.react.bridge.JavaModuleWrapper.invoke(JavaModuleWrapper.java:160)
08-06 11:47:44.251 4686 4954 D RNSensitiveInfo: at com.facebook.react.bridge.queue.NativeRunnable.run(Native Method)
08-06 11:47:44.251 4686 4954 D RNSensitiveInfo: at android.os.Handler.handleCallback(Handler.java:789)
08-06 11:47:44.251 4686 4954 D RNSensitiveInfo: at android.os.Handler.dispatchMessage(Handler.java:98)
08-06 11:47:44.251 4686 4954 D RNSensitiveInfo: at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(MessageQueueThreadHandler.java:29)
08-06 11:47:44.251 4686 4954 D RNSensitiveInfo: at android.os.Looper.loop(Looper.java:164)
08-06 11:47:44.251 4686 4954 D RNSensitiveInfo: at com.facebook.react.bridge.queue.MessageQueueThreadImpl$3.run(MessageQueueThreadImpl.java:192)
08-06 11:47:44.251 4686 4954 D RNSensitiveInfo: at java.lang.Thread.run(Thread.java:764)
08-06 11:47:44.251 4686 4954 D RNSensitiveInfo: Caused by: android.security.KeyStoreException: Unknown error
08-06 11:47:44.251 4686 4954 D RNSensitiveInfo: at android.security.KeyStore.getKeyStoreException(KeyStore.java:695)
08-06 11:47:44.251 4686 4954 D RNSensitiveInfo: at android.security.keystore.KeyStoreCryptoOperationChunkedStreamer.update(KeyStoreCryptoOperationChunkedStreamer.java:132)
08-06 11:47:44.251 4686 4954 D RNSensitiveInfo: at android.security.keystore.KeyStoreCryptoOperationChunkedStreamer.doFinal(KeyStoreCryptoOperationChunkedStreamer.java:217)
08-06 11:47:44.251 4686 4954 D RNSensitiveInfo: at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:506)
08-06 11:47:44.251 4686 4954 D RNSensitiveInfo: ... 14 more
When I open up a shell through adb and inspect the shared preferences file that has been generated, I see this:
$ cat AppsharedPrefs.xml
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<string name="persist:AppState">KAysHeVHYPYheW7hRa2xk0qkI+7fCxvNEDYdy4vcwuk2PICGqc+JL2aAajqlFv1FZWxAKkbUxa3a ThbLmbfK1imgBM55p5IxVtuvMZ4ebsrNi4elnhpAKBsv0LEEgndiIqBXsg6ChcVY8ucNLy5W1fQc TJ06BlDO2dJKz1o09Q== </string>
</map>
So it does look like it has stored information the first time, but if I refresh the app and do something that updates state so it gets persisted, I get the red error screen again.
I’m not sure how to continue with this yet and am hoping that you can help me out with this. Also I’m curious as to whether encrypted storage on Android will be available in the normal package.
Many thanks in advance and if I need to provide additional information then please let me know!
Issue Analytics
- State:
- Created 5 years ago
- Comments:5
Top GitHub Comments
Thanks for the heads-up! Unfortunately, #126 didn’t fix it 😦 I did some more debugging and found that it didn’t happen with little pieces of data. Only when the string to be encrypted was 4073 characters or longer, I would get the
IllegalBlockSizeException
.I came across this article: https://proandroiddev.com/security-best-practices-symmetric-encryption-with-aes-in-java-7616beaaade9
And found this piece of text:
The argumentation for using input streams is different, but I thought it would be worth the shot. So I rewrote encryption and decryption using streams and now it seems to be working on Android. You can see my changes here: https://github.com/mCodex/react-native-sensitive-info/compare/keystore...markoudev:keystore
@mCodex Any opposition to having @markoudev submit a PR for this? I’ve been experiencing the same problem trying to use the Android keystore and this fix works
Edit: just wanted to note that the intended use case was also for redux state persistence