freeotp / freeotp-android

Apache License 2.0
1.37k stars 292 forks source link

Restore from backup made on old phone to new phone asks for password but doesn't import keys #283

Open sheepbop opened 1 year ago

sheepbop commented 1 year ago

Hi,

FreeOTP updated to 2.0 today. Was using previous version on Android. Backup feature looks good, thanks.

I'm trying to transfer my keys from old phone to new phone without having to type them all in again.

I've made a backup from old phone to Google Drive. Then I restore this backup from Drive to FreeOTP 2.0 running on new phone. It sees the backup, and asks me for password. But then returns to an empty screen.

How do you transfer keys to a new phone if this is not the method? The set-up process when installing FreeOTP does not say "would you like to import from backup?"

Thanks,

Sean

justin-stephenson commented 1 year ago

Hello,

Is your old phone also upgraded to FreeOTP 2.0 ? Backup and Restore only works if both phones are using FreeOTP 2.0.

Some documentation is available here: https://github.com/freeotp/freeotp-android/blob/master/BACKUP.md

You can back up manually within the App, or relying on the Android device backup to Google Drive.

sheepbop commented 1 year ago

Both are running version 2.0. AFAIK you need version 2.0 to create a backup anyway. OK, so it is designed to export to another phone, so at least there's that. Thanks, will have another look.

justin-stephenson commented 1 year ago

If you are using the Android native backup and restore via Google Drive, you may sign in to Google Drive or Google One to ensure that FreeOTP data exists in your backup before attempting to login to FreeOTP on the the new phone. If you continue having issues please document the exact steps taken so I can investigate further.

Slater91 commented 1 year ago

I can reproduce the bug. Here are the steps I took:

The result is that nothing is restored. The backup file is 4.9 KB and should contain 8 keys, so from an outsider's perspective it looks like there is at least something in the file. The old phone runs Android 8.1, while the new one runs Android 13. I'll be happy to provide further information if needed.

justin-stephenson commented 1 year ago

Thanks for the steps, I tested these steps without issues using an Android 8.1 emulator. Could you please provide logcat logs from the new phone covering the time of the restore attempt?

omrimann commented 1 year ago

I am having the same problem.

relevant logcat section:

03-08 13:20:38.014 766 766 W keymaster_tee: [WRN]start nwd_import_key
03-08 13:20:38.016 766 766 D keymaster_swd: keymaster_swd [WRN] (swd_run_cb:254) swd_import_key() returns 0 03-08 13:20:38.016 766 766 W keymaster_tee: [WRN]ret OK PARAMS: A32 P0 B32 P1 NAR1 S256 2023.03.08,13:20:38.014 03-08 13:20:38.016 763 3431 I keystore2: keystore2::security_level: In import_key. 10356, Some("masterKey") 03-08 13:20:38.017 763 3431 I keystore2: keystore2::database: In store_new_key "masterKey", uid=10356, cert=false, cert_chain=false rebound=true 03-08 13:20:38.017 1272 1272 I GestureDetector: handleMessage TAP
03-08 13:20:38.018 1272 1292 I GestureDetector: handleMessage TAP
03-08 13:20:38.020 8731 8731 I TokenPersistence: Found [50c729cb-a923-4578-b886-3ed333d26a40-token] in backup 03-08 13:20:38.020 8731 8731 I TokenPersistence: Skipping [50c729cb-a923-4578-b886-3ed333d26a40-token] 03-08 13:20:38.020 8731 8731 I TokenPersistence: Found [masterKey] in backup
03-08 13:20:38.020 8731 8731 I TokenPersistence: Skipping [masterKey]
03-08 13:20:38.020 8731 8731 I TokenPersistence: Found [14831444-c524-444a-aa74-62a1df152cf2-token] in backup 03-08 13:20:38.020 8731 8731 I TokenPersistence: Skipping [14831444-c524-444a-aa74-62a1df152cf2-token] 03-08 13:20:38.020 8731 8731 I TokenPersistence: Found [b2956383-b766-4d18-bb66-b9edfc01f790] in backup 03-08 13:20:38.021 763 3431 E keystore2: keystore2::error: Rc(ResponseCode(7)), "In get_key_entry, while trying to load key info. 10356, Some(\"b2956383-b766-4d18-bb66-b9edfc01f790\")" 03-08 13:20:38.022 8731 8731 E Adapter : Exception
03-08 13:20:38.022 8731 8731 E Adapter : javax.crypto.AEADBadTagException: error:1e000065:Cipher functions:OPENSSL_internal:BAD_DECRYPT 03-08 13:20:38.022 8731 8731 E Adapter : at java.lang.reflect.Constructor.newInstance0(Native Method) 03-08 13:20:38.022 8731 8731 E Adapter : at java.lang.reflect.Constructor.newInstance(Constructor.java:343) 03-08 13:20:38.022 8731 8731 E Adapter : at com.android.org.conscrypt.OpenSSLAeadCipher.throwAEADBadTagExceptionIfAvailable(OpenSSLAeadCipher.java:320) 03-08 13:20:38.022 8731 8731 E Adapter : at com.android.org.conscrypt.OpenSSLAeadCipher.doFinalInternal(OpenSSLAeadCipher.java:371) 03-08 13:20:38.022 8731 8731 E Adapter : at com.android.org.conscrypt.OpenSSLCipher.engineDoFinal(OpenSSLCipher.java:374) 03-08 13:20:38.022 8731 8731 E Adapter : at javax.crypto.Cipher.doFinal(Cipher.java:2056) 03-08 13:20:38.022 8731 8731 E Adapter : at org.fedorahosted.freeotp.encryptor.EncryptedKey.decrypt(EncryptedKey.java:59) 03-08 13:20:38.022 8731 8731 E Adapter : at org.fedorahosted.freeotp.TokenPersistence.restore(TokenPersistence.java:209) 03-08 13:20:38.022 8731 8731 E Adapter : at org.fedorahosted.freeotp.main.Adapter.restoreTokens(Adapter.java:265) 03-08 13:20:38.022 8731 8731 E Adapter : at org.fedorahosted.freeotp.main.Activity$5.onClick(Activity.java:404) 03-08 13:20:38.022 8731 8731 E Adapter : at androidx.appcompat.app.AlertController$ButtonHandler.handleMessage(AlertController.java:167) 03-08 13:20:38.022 8731 8731 E Adapter : at android.os.Handler.dispatchMessage(Handler.java:106) 03-08 13:20:38.022 8731 8731 E Adapter : at android.os.Looper.loopOnce(Looper.java:226) 03-08 13:20:38.022 8731 8731 E Adapter : at android.os.Looper.loop(Looper.java:313) 03-08 13:20:38.022 8731 8731 E Adapter : at android.app.ActivityThread.main(ActivityThread.java:8741) 03-08 13:20:38.022 8731 8731 E Adapter : at java.lang.reflect.Method.invoke(Native Method) 03-08 13:20:38.022 8731 8731 E Adapter : at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571) 03-08 13:20:38.022 8731 8731 E Adapter : at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067) 03-08 13:20:38.022 1272 5834 D CoreBackPreview: Window{6aaa8ff u0 org.fedorahosted.freeotp/org.fedorahosted.freeotp.main.Activity}: Setting back callback null

The problem seams to be a BadTagException which is caused by BadPaddingException inside OpenSSL

acigolotti commented 1 year ago

Hello, I'm currently facing the same problem,

My old phone is on Android 9, I was running freeOTP 1.X and has been running freeOTP 2.X since the update My new phone is also on Android 13, but i've tried in a android 9 emulator and same issue.

I'm pretty sure I haven't added a new token since the new update, but if I create a new token on my old phone, export the backup and import it in my android 13 emulator, every token except the new one fail to import with the execption bellow

I've added a try/catch/continue in TokenPersistence.java#L209 so it can skip errors

SecretKey skKey;
try {
    // Decrypt the token
    skKey = ekKey.decrypt(sk);
} catch (Exception e) {
    // Invalid JSON backup data
    Log.e(LOGTAG, "Exception", e);
    continue;
}

I still don't know where the issue is but it's probably related to the export or persistence of old tokens maybe? Hope this can help !

old Android 9.1 phone logcat ``` 03-07 21:07:54.966 589 601 E keystore2: keystore2::error: Rc(ResponseCode(7)), "In get_key_entry, while trying to load key info. 10411, Some(\"8b7ec453-444c-42e0-8feb-bffbec25bfec\")" 03-07 21:07:54.967 29545 29545 E Adapter : Exception 03-07 21:07:54.967 29545 29545 E Adapter : javax.crypto.AEADBadTagException: error:1e000065:Cipher functions:OPENSSL_internal:BAD_DECRYPT 03-07 21:07:54.967 29545 29545 E Adapter : at java.lang.reflect.Constructor.newInstance0(Native Method) 03-07 21:07:54.967 29545 29545 E Adapter : at java.lang.reflect.Constructor.newInstance(Constructor.java:343) 03-07 21:07:54.967 29545 29545 E Adapter : at com.android.org.conscrypt.OpenSSLAeadCipher.throwAEADBadTagExceptionIfAvailable(OpenSSLAeadCipher.java:320) 03-07 21:07:54.967 29545 29545 E Adapter : at com.android.org.conscrypt.OpenSSLAeadCipher.doFinalInternal(OpenSSLAeadCipher.java:371) 03-07 21:07:54.967 29545 29545 E Adapter : at com.android.org.conscrypt.OpenSSLCipher.engineDoFinal(OpenSSLCipher.java:374) 03-07 21:07:54.967 29545 29545 E Adapter : at javax.crypto.Cipher.doFinal(Cipher.java:2056) 03-07 21:07:54.967 29545 29545 E Adapter : at org.fedorahosted.freeotp.encryptor.EncryptedKey.decrypt(EncryptedKey.java:59) 03-07 21:07:54.967 29545 29545 E Adapter : at org.fedorahosted.freeotp.TokenPersistence.restore(TokenPersistence.java:209) 03-07 21:07:54.967 29545 29545 E Adapter : at org.fedorahosted.freeotp.main.Adapter.restoreTokens(Adapter.java:265) 03-07 21:07:54.967 29545 29545 E Adapter : at org.fedorahosted.freeotp.main.Activity$5.onClick(Activity.java:404) 03-07 21:07:54.967 29545 29545 E Adapter : at androidx.appcompat.app.AlertController$ButtonHandler.handleMessage(AlertController.java:167) 03-07 21:07:54.967 29545 29545 E Adapter : at android.os.Handler.dispatchMessage(Handler.java:106) 03-07 21:07:54.967 29545 29545 E Adapter : at android.os.Looper.loopOnce(Looper.java:226) 03-07 21:07:54.967 29545 29545 E Adapter : at android.os.Looper.loop(Looper.java:313) 03-07 21:07:54.967 29545 29545 E Adapter : at android.app.ActivityThread.main(ActivityThread.java:8757) 03-07 21:07:54.967 29545 29545 E Adapter : at java.lang.reflect.Method.invoke(Native Method) 03-07 21:07:54.967 29545 29545 E Adapter : at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571) 03-07 21:07:54.967 29545 29545 E Adapter : at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067) ```
Android 13 emulator logcat ``` I/TokenPersistence: Found [8b7ec453-444c-42e0-8feb-bffbec25bfec] in backup W/ahosted.freeotp: Got a deoptimization request on un-deoptimizable method int com.android.org.conscrypt.NativeCrypto.EVP_AEAD_CTX_open(long, byte[], int, byte[], int, byte[], byte[], int, int, byte[]) E/TokenPersistence: Exception javax.crypto.AEADBadTagException: error:1e000065:Cipher functions:OPENSSL_internal:BAD_DECRYPT at java.lang.reflect.Constructor.newInstance0(Native Method) at java.lang.reflect.Constructor.newInstance(Constructor.java:343) at com.android.org.conscrypt.OpenSSLAeadCipher.throwAEADBadTagExceptionIfAvailable(OpenSSLAeadCipher.java:320) at com.android.org.conscrypt.OpenSSLAeadCipher.doFinalInternal(OpenSSLAeadCipher.java:371) at com.android.org.conscrypt.OpenSSLCipher.engineDoFinal(OpenSSLCipher.java:374) at javax.crypto.Cipher.doFinal(Cipher.java:2056) at org.fedorahosted.freeotp.encryptor.EncryptedKey.decrypt(EncryptedKey.java:59) at org.fedorahosted.freeotp.TokenPersistence.restore(TokenPersistence.java:211) at org.fedorahosted.freeotp.main.Adapter.restoreTokens(Adapter.java:265) at org.fedorahosted.freeotp.main.Activity$5.onClick(Activity.java:404) at androidx.appcompat.app.AlertController$ButtonHandler.handleMessage(AlertController.java:167) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loopOnce(Looper.java:201) at android.os.Looper.loop(Looper.java:288) at android.app.ActivityThread.main(ActivityThread.java:7872) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936) ```
justin-stephenson commented 1 year ago

Thank you for the logcat logs.

This keystore error is expected because we first check if this key already exists in the app so it is expected to fail.

E keystore2: keystore2::error: Rc(ResponseCode(7)), "In get_key_entry, while trying to load key info. 10356, Some("b2956383-b766-4d18-bb66-b9edfc01f790")"

The error javax.crypto.AEADBadTagException: error:1e000065:Cipher functions:OPENSSL_internal:BAD_DECRYPT is a generic one, it is also returned if the incorrect password is provided on restore attempt.

I am interested to know if all users affected here are only seeing this issue with previously migrated tokens, and not tokens newly added in FreeOTP 2.X.

On upgrade from FreeOTP 1.X to 2.X, tokens are all added into the Android keystore, and also added into the backup file, the token secret is encrypted with the master backup password key. I speculate that there may have been an issue saving the token data into the backup file during this migration. This upgrade path happens in the compat() function in Adapter.java, which calls add() to add the token into the keystore and also save the token into the token backup file, if token backups are provisioned.

The decrypt line that fails here is attempting to decrypt the encrypted key data from the backup file (representing the token secret) with the master password key. We know the master password is correct because otherwise this line would trigger an exception.

Unfortunately I still have been unable to reproduce this issue with installing FreeOTP 1.5 from F-droid, upgrading to 2.0.1 then adding fake tokens with https://freeotp.github.io/qrcode.html backing them up and restoring to another device or emulator.

If I add code to print the keys and values of the backup shared preferences file from my working test device, the contents are:

org.fedorahosted.freeotp D/Activity: key: 88ccc1cf-db00-4a50-98f0-c2f7ee15b864-token
org.fedorahosted.freeotp D/Activity: value: {"algo":"SHA256","counter":1,"digits":6,"issuerExt":"amazon","label":"amazon","period":30,"type":"HOTP"}
org.fedorahosted.freeotp D/Activity: ==========================
org.fedorahosted.freeotp D/Activity: key: a2ee1617-057b-4cf5-b659-cd435fe9c07f
org.fedorahosted.freeotp D/Activity: value: {"key":"{\"mCipher\":\"AES\/GCM\/NoPadding\",\"mCipherText\":[59,-21,-54,60,-93,101,-81,77,-62,2,-125,5,-46,110,-3,-105,22,-126,-2,65,-128,-78,-73,-61,-8,82,-55,-55,29,106,62,68,-93,-87,-101,5,-113,29,1,-87,3,73,-101,-40,114,0,102,-82,-98,0,9],\"mParameters\":[48,17,4,12,53,-112,-44,-46,86,-108,-120,45,-71,-26,109,-93,2,1,16],\"mToken\":\"HmacSHA224\"}"}
org.fedorahosted.freeotp D/Activity: ==========================
org.fedorahosted.freeotp D/Activity: key: a2ee1617-057b-4cf5-b659-cd435fe9c07f-token
org.fedorahosted.freeotp D/Activity: value: {"algo":"SHA224","counter":0,"digits":6,"issuerExt":"redhat","label":"redhat","period":30,"type":"TOTP"}
org.fedorahosted.freeotp D/Activity: ==========================
org.fedorahosted.freeotp D/Activity: key: 88ccc1cf-db00-4a50-98f0-c2f7ee15b864
org.fedorahosted.freeotp D/Activity: value: {"key":"{\"mCipher\":\"AES\/GCM\/NoPadding\",\"mCipherText\":[-51,101,37,6,49,122,-82,99,94,6,43,-105,-33,-119,33,-18,-37,33,55,81,-104,-51,-14,51,-84,-22,96,18,-7,-40,-84,58,-95,-38,50,-45,-9,102,115,-128,122,60,-32,-89,59,79,-57,-56,105,97,-107],\"mParameters\":[48,17,4,12,-125,26,79,-111,-79,-67,-52,111,70,117,19,-105,2,1,16],\"mToken\":\"HmacSHA256\"}"}
org.fedorahosted.freeotp D/Activity: ==========================
org.fedorahosted.freeotp D/Activity: key: masterKey
org.fedorahosted.freeotp D/Activity: value: {"mAlgorithm":"PBKDF2withHmacSHA512","mEncryptedKey":{"mCipher":"AES/GCM/NoPadding","mCipherText":[8,125,101,-12,115,-83,-123,73,70,-128,35,-77,121,76,-36,-50,-64,-70,3,32,38,108,116,-52,-127,80,-63,-61,-128,99,-37,18,-55,-93,42,-111,74,-73,-76,106,-6,10,-62,45,80,-45,-72,71],"mParameters":[48,17,4,12,-41,-10,56,57,-9,27,84,-76,19,70,-109,97,2,1,16],"mToken":"AES"},"mIterations":100000,"mSalt":[-29,-127,2,48,38,-106,-46,-91,73,-118,-17,58,115,55,-128,35,-53,-115,111,-94,40,19,-67,-122,94,-80,-6,-69,-6,18,26,-7]}

Here you can see the token metadata is stored in the key $UUID-token, while the encrypted key is stored in $UUID. The master backup password key is also stored.

I don't have much idea yet but I am writing comments here to track this initial investigation. Also, the FreeOTP upgrade path 1.X to 2.X is a one-time operation, troubleshooting this requires essentially rolling back to this 1.X version which is not something that can be done safely.

acigolotti commented 1 year ago

Thank you for your time !

I've been trying to debug this issue almost every evening for the last 2 weeks I don't know if it's the right way, but when the compat() happens, the master key is recovered from the keystore, with the associated KeyProtection So I was wondering if there was some funky keystore magick and edited TokenPersistence#L176 as follow:

KeyProtection kp = new KeyProtection.Builder(KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
                .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
                .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
                .build();

mKeyStore.setEntry(MASTER, new KeyStore.SecretKeyEntry(sk), kp);
sk = (SecretKey) mKeyStore.getKey(MASTER, null);
and got this exception : ``` javax.crypto.AEADBadTagException at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:517) at javax.crypto.Cipher.doFinal(Cipher.java:2055) at org.fedorahosted.freeotp.encryptor.EncryptedKey.decrypt(EncryptedKey.java:68) at org.fedorahosted.freeotp.TokenPersistence.restore(TokenPersistence.java:213) at org.fedorahosted.freeotp.main.Adapter.restoreTokens(Adapter.java:265) at org.fedorahosted.freeotp.main.Activity$5.onClick(Activity.java:404) at androidx.appcompat.app.AlertController$ButtonHandler.handleMessage(AlertController.java:167) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loop(Looper.java:193) at android.app.ActivityThread.main(ActivityThread.java:6669) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858) Caused by: android.security.KeyStoreException: Signature/MAC verification failed at android.security.KeyStore.getKeyStoreException(KeyStore.java:839) at android.security.keystore.KeyStoreCryptoOperationChunkedStreamer.doFinal(KeyStoreCryptoOperationChunkedStreamer.java:224) at android.security.keystore.AndroidKeyStoreAuthenticatedAESCipherSpi$BufferAllOutputUntilDoFinalStreamer.doFinal(AndroidKeyStoreAuthenticatedAESCipherSpi.java:373) at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:506) at javax.crypto.Cipher.doFinal(Cipher.java:2055)  at org.fedorahosted.freeotp.encryptor.EncryptedKey.decrypt(EncryptedKey.java:68)  at org.fedorahosted.freeotp.TokenPersistence.restore(TokenPersistence.java:213)  at org.fedorahosted.freeotp.main.Adapter.restoreTokens(Adapter.java:265)  at org.fedorahosted.freeotp.main.Activity$5.onClick(Activity.java:404)  at androidx.appcompat.app.AlertController$ButtonHandler.handleMessage(AlertController.java:167)  at android.os.Handler.dispatchMessage(Handler.java:106)  at android.os.Looper.loop(Looper.java:193)  at android.app.ActivityThread.main(ActivityThread.java:6669)  at java.lang.reflect.Method.invoke(Native Method)  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)  ```

Even try other purposes like KeyProperties.PURPOSE_VERIFY without success

I found this article from another OTP app https://alexbakker.me/post/mysterious-google-titan-m-bug-cve-2019-9465.html It's similar but not quite, I've check all ciphers and ivs, they seems fine, I've tried waiting after the cipher init, creating a brand new GCMParameterSpec just from the IV and tag length Adding buffers, etc…

But it might be related to my old phone ? it was a Huawei Honor 9 STF-L09

BTW, all my token are SHA1 also, might be related or might not

The screen broke on my old phone and I've got a new phone, so I don't realy care if I brick it, I've tried to root it, unfortunatly it's not as easy as I was hopping for, I'm pretty sure I'm almost there but I don't know what I'm doing

If you think you can help me, I'll take it, If I can be useful, I will gladly help

omrimann commented 1 year ago

My case is also of an upgraded software, where tokens were created on 1.x and then upgraded to 2.0

justin-stephenson commented 1 year ago

I'm still trying to figure out what may cause this.

If someone has a throwaway phone and they can reproduce this problem with these steps below, then I could create a test build which adds additional logging and sanity checks in the upgrade path code.

This same process could be repeated with tokens from https://freeotp.github.io/qrcode.html to determine if the token data is related or unrelated to the issue.

justin-stephenson commented 1 year ago

Could someone provide some examples of 2FA providers for tokens which are not being backed up properly? (i.e, Github, Slack, Paypal, etc).

Slater91 commented 1 year ago

In my case there's no provider which works. Amazon, Facebook, Nextcloud, WordPress... Nothing actually works. I've tried creating new tokens after the update to version 2.0, but those aren't restored either on the new device.

justin-stephenson commented 1 year ago

In my case there's no provider which works. Amazon, Facebook, Nextcloud, WordPress... Nothing actually works. I've tried creating new tokens after the update to version 2.0, but those aren't restored either on the new device.

Could you please provide your backup file, you can email to jstephen@redhat.com (your token secrets are encrypted with your backup password so I, or others, cannot decrypt them)

m-from-space commented 1 year ago

I have the same issue here.

Upgraded my phone to a newer LineageOS and I am not able to manually restore my externalBackup using the "Restore" button.

  1. Keys were created with an old FreeOTP version.
  2. FreeOTP was updated to 2.x version
  3. Made externalBackup on my phone with "Backup" button and saved that file elsewhere
  4. Installed new FreeOTP on the new OS and used the same master password (don't know if that is necessary)
  5. Tried restoring the externalBackup file. If I put in a wrong password an error occurs (as expected). If I provide the correct password, nothing happens and no message or keys appear.

I really want my keys back.

justin-stephenson commented 1 year ago

It would be great if someone having this issue would be able to run the FreeOTP Unit tests in Android Studio to see if any backup related encryption/decryption operations fail.

I still have not been able to reproduce this issue therefore I don't have a reliable way to troubleshoot exactly what is failing.

m-from-space commented 1 year ago

It would be great if someone having this issue would be able to run the FreeOTP Unit tests in Android Studio to see if any backup related encryption/decryption operations fail.

Would you be able to explain what exactly I have to do to help out?

justin-stephenson commented 1 year ago

It would be great if someone having this issue would be able to run the FreeOTP Unit tests in Android Studio to see if any backup related encryption/decryption operations fail.

Would you be able to explain what exactly I have to do to help out?

Connect your phone to your laptop/desktop over USB/Bluetooth. Install Android Studio, clone this repo and open it as a Project. Select your phone as the device in Android Studio, right-click org.fedorahosted.freeotp (androidTest) and Run tests.

m-from-space commented 1 year ago

Connect your phone to your laptop/desktop over USB/Bluetooth. Install Android Studio, clone this repo and open it as a Project. Select your phone as the device in Android Studio, right-click org.fedorahosted.freeotp (androidTest) and Run tests.

Alright, I did run the tests. Out of 214 tests on my phone (OnePlus One) 209 were successful, 1 failed and I don't know about the rest, because it just stopped after the fail. Here is the log:

05-24 20:25:37.530 21410 21431 I TestRunner: started: tokenCompatBackupRestore[38](org.fedorahosted.freeotp.TokenCompatTest)
05-24 20:25:38.380 26967 26981 E ocessService0:: failed to create Unix domain socket: Operation not permitted
05-24 20:25:40.380 26967 26981 I chatty  : uid=99075(u0_i9075) ADB-JDWP Connec identical 1 line
05-24 20:25:42.381 26967 26981 E ocessService0:: failed to create Unix domain socket: Operation not permitted
05-24 20:25:43.211 21410 21422 I ahosted.freeot: Background concurrent copying GC freed 82803(6475KB) AllocSpace objects, 0(0B) LOS objects, 62% free, 3651KB/9795KB, paused 405us total 199.605ms
05-24 20:25:44.381 26967 26981 E ocessService0:: failed to create Unix domain socket: Operation not permitted
05-24 20:25:45.306 21410 21422 I ahosted.freeot: Background young concurrent copying GC freed 73736(5791KB) AllocSpace objects, 0(0B) LOS objects, 60% free, 3843KB/9795KB, paused 410us total 139.239ms
05-24 20:25:46.382 26967 26981 E ocessService0:: failed to create Unix domain socket: Operation not permitted
05-24 20:25:47.445 21410 21422 I ahosted.freeot: Background concurrent copying GC freed 80850(6336KB) AllocSpace objects, 0(0B) LOS objects, 62% free, 3650KB/9794KB, paused 388us total 196.418ms
05-24 20:25:48.383 26967 26981 E ocessService0:: failed to create Unix domain socket: Operation not permitted
05-24 20:25:48.564   442   442 I keystore: del USRPKEY_masterKey 10168
05-24 20:25:48.566   442   442 I keystore: del USRCERT_masterKey 10168
05-24 20:25:48.566   442   442 I keystore: del CACERT_masterKey 10168
05-24 20:25:48.567   442   442 I keystore: del USRPKEY_masterKey 10168
05-24 20:25:48.567   442   442 I keystore: del USRSKEY_masterKey 10168
05-24 20:25:48.567   442   442 I keystore: del USRCERT_masterKey 10168
05-24 20:25:48.568   442   442 I keystore: del CACERT_masterKey 10168
05-24 20:25:48.617 21410 21431 I Adapter : Adding token uuid [c52fa7e2-d2f2-4365-9d73-11c0d654ec9c]
05-24 20:25:48.618   442   442 I keystore: del USRPKEY_c52fa7e2-d2f2-4365-9d73-11c0d654ec9c 10168
05-24 20:25:48.619   442   442 I keystore: del USRSKEY_c52fa7e2-d2f2-4365-9d73-11c0d654ec9c 10168
05-24 20:25:48.619   442   442 I keystore: del USRCERT_c52fa7e2-d2f2-4365-9d73-11c0d654ec9c 10168
05-24 20:25:48.620   442   442 I keystore: del CACERT_c52fa7e2-d2f2-4365-9d73-11c0d654ec9c 10168
05-24 20:25:48.620   442   442 I keystore: del USRPKEY_c52fa7e2-d2f2-4365-9d73-11c0d654ec9c 10168
05-24 20:25:48.621   442   442 I keystore: del USRSKEY_c52fa7e2-d2f2-4365-9d73-11c0d654ec9c 10168
05-24 20:25:48.621   442   442 I keystore: del USRCERT_c52fa7e2-d2f2-4365-9d73-11c0d654ec9c 10168
05-24 20:25:48.621   442   442 I keystore: del CACERT_c52fa7e2-d2f2-4365-9d73-11c0d654ec9c 10168
05-24 20:25:48.652 21410 21431 I TokenPersistence: Saving [c52fa7e2-d2f2-4365-9d73-11c0d654ec9c] token backup
05-24 20:25:48.653 21410 21431 I Adapter : Token added uuid [c52fa7e2-d2f2-4365-9d73-11c0d654ec9c]
05-24 20:25:48.654   442   442 I keystore: del USRPKEY_c52fa7e2-d2f2-4365-9d73-11c0d654ec9c 10168
05-24 20:25:48.655   442   442 I keystore: del USRCERT_c52fa7e2-d2f2-4365-9d73-11c0d654ec9c 10168
05-24 20:25:48.656   442   442 I keystore: del CACERT_c52fa7e2-d2f2-4365-9d73-11c0d654ec9c 10168
05-24 20:25:50.383 26967 26981 E ocessService0:: failed to create Unix domain socket: Operation not permitted
05-24 20:25:51.653 21410 21422 I ahosted.freeot: Background concurrent copying GC freed 81018(6355KB) AllocSpace objects, 0(0B) LOS objects, 62% free, 3621KB/9765KB, paused 153us total 126.379ms
05-24 20:25:52.384 26967 26981 E ocessService0:: failed to create Unix domain socket: Operation not permitted
05-24 20:25:54.125 21410 21431 I TokenPersistence: Found [c52fa7e2-d2f2-4365-9d73-11c0d654ec9c] in backup
05-24 20:25:54.131 21410 21431 I TokenPersistence: Added [c52fa7e2-d2f2-4365-9d73-11c0d654ec9c] token to backup list
05-24 20:25:54.131 21410 21431 I TokenPersistence: Found [masterKey] in backup
05-24 20:25:54.131 21410 21431 I TokenPersistence: Skipping [masterKey]
05-24 20:25:54.131 21410 21431 I TokenPersistence: Found [c52fa7e2-d2f2-4365-9d73-11c0d654ec9c-token] in backup
05-24 20:25:54.131 21410 21431 I TokenPersistence: Skipping [c52fa7e2-d2f2-4365-9d73-11c0d654ec9c-token]
05-24 20:25:54.132 21410 21431 I Adapter : Adding token uuid [c52fa7e2-d2f2-4365-9d73-11c0d654ec9c]
05-24 20:25:54.132   442   442 I keystore: del USRPKEY_c52fa7e2-d2f2-4365-9d73-11c0d654ec9c 10168
05-24 20:25:54.133   442   442 I keystore: del USRSKEY_c52fa7e2-d2f2-4365-9d73-11c0d654ec9c 10168
05-24 20:25:54.133   442   442 I keystore: del USRCERT_c52fa7e2-d2f2-4365-9d73-11c0d654ec9c 10168
05-24 20:25:54.133   442   442 I keystore: del CACERT_c52fa7e2-d2f2-4365-9d73-11c0d654ec9c 10168
05-24 20:25:54.149 21410 21431 E Adapter : Exception
05-24 20:25:54.149 21410 21431 E Adapter : java.security.KeyStoreException: java.lang.IllegalStateException: Secure lock screen must be enabled to create keys requiring user authentication
05-24 20:25:54.149 21410 21431 E Adapter :  at android.security.keystore.AndroidKeyStoreSpi.setSecretKeyEntry(AndroidKeyStoreSpi.java:737)
05-24 20:25:54.149 21410 21431 E Adapter :  at android.security.keystore.AndroidKeyStoreSpi.engineSetEntry(AndroidKeyStoreSpi.java:1076)
05-24 20:25:54.149 21410 21431 E Adapter :  at java.security.KeyStore.setEntry(KeyStore.java:1596)
05-24 20:25:54.149 21410 21431 E Adapter :  at org.fedorahosted.freeotp.main.Adapter.add(Adapter.java:195)
05-24 20:25:54.149 21410 21431 E Adapter :  at org.fedorahosted.freeotp.main.Adapter.restoreTokens(Adapter.java:268)
05-24 20:25:54.149 21410 21431 E Adapter :  at org.fedorahosted.freeotp.TokenCompatTest.tokenCompatBackupRestore(TokenCompatTest.java:333)
05-24 20:25:54.149 21410 21431 E Adapter :  at java.lang.reflect.Method.invoke(Native Method)
05-24 20:25:54.149 21410 21431 E Adapter :  at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
05-24 20:25:54.149 21410 21431 E Adapter :  at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
05-24 20:25:54.149 21410 21431 E Adapter :  at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
05-24 20:25:54.149 21410 21431 E Adapter :  at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
05-24 20:25:54.149 21410 21431 E Adapter :  at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
05-24 20:25:54.149 21410 21431 E Adapter :  at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
05-24 20:25:54.149 21410 21431 E Adapter :  at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
05-24 20:25:54.149 21410 21431 E Adapter :  at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
05-24 20:25:54.149 21410 21431 E Adapter :  at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
05-24 20:25:54.149 21410 21431 E Adapter :  at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
05-24 20:25:54.149 21410 21431 E Adapter :  at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
05-24 20:25:54.149 21410 21431 E Adapter :  at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
05-24 20:25:54.149 21410 21431 E Adapter :  at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
05-24 20:25:54.149 21410 21431 E Adapter :  at org.junit.runners.Suite.runChild(Suite.java:128)
05-24 20:25:54.149 21410 21431 E Adapter :  at org.junit.runners.Suite.runChild(Suite.java:27)
05-24 20:25:54.149 21410 21431 E Adapter :  at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
05-24 20:25:54.149 21410 21431 E Adapter :  at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
05-24 20:25:54.149 21410 21431 E Adapter :  at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
05-24 20:25:54.149 21410 21431 E Adapter :  at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
05-24 20:25:54.149 21410 21431 E Adapter :  at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
05-24 20:25:54.149 21410 21431 E Adapter :  at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
05-24 20:25:54.149 21410 21431 E Adapter :  at org.junit.runners.Suite.runChild(Suite.java:128)
05-24 20:25:54.149 21410 21431 E Adapter :  at org.junit.runners.Suite.runChild(Suite.java:27)
05-24 20:25:54.149 21410 21431 E Adapter :  at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
05-24 20:25:54.149 21410 21431 E Adapter :  at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
05-24 20:25:54.149 21410 21431 E Adapter :  at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
05-24 20:25:54.149 21410 21431 E Adapter :  at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
05-24 20:25:54.149 21410 21431 E Adapter :  at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
05-24 20:25:54.149 21410 21431 E Adapter :  at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
05-24 20:25:54.149 21410 21431 E Adapter :  at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
05-24 20:25:54.149 21410 21431 E Adapter :  at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
05-24 20:25:54.149 21410 21431 E Adapter :  at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
05-24 20:25:54.149 21410 21431 E Adapter :  at androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:389)
05-24 20:25:54.149 21410 21431 E Adapter :  at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2205)
05-24 20:25:54.149 21410 21431 E Adapter : Caused by: java.lang.IllegalStateException: Secure lock screen must be enabled to create keys requiring user authentication
05-24 20:25:54.149 21410 21431 E Adapter :  at android.security.keystore.KeymasterUtils.getRootSid(KeymasterUtils.java:236)
05-24 20:25:54.149 21410 21431 E Adapter :  at android.security.keystore.KeymasterUtils.addSids(KeymasterUtils.java:96)
05-24 20:25:54.149 21410 21431 E Adapter :  at android.security.keystore.KeymasterUtils.addUserAuthArgs(KeymasterUtils.java:182)
05-24 20:25:54.149 21410 21431 E Adapter :  at android.security.keystore.AndroidKeyStoreSpi.setSecretKeyEntry(AndroidKeyStoreSpi.java:718)
05-24 20:25:54.149 21410 21431 E Adapter :  ... 40 more
05-24 20:25:54.150 21410 21431 I TestRunner: failed: tokenCompatBackupRestore[38](org.fedorahosted.freeotp.TokenCompatTest)
05-24 20:25:54.150 21410 21431 I TestRunner: ----- begin exception -----
05-24 20:25:54.153 21410 21431 I TestRunner: java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.String.length()' on a null object reference
05-24 20:25:54.153 21410 21431 I TestRunner:    at org.json.JSONTokener.nextCleanInternal(JSONTokener.java:121)
05-24 20:25:54.153 21410 21431 I TestRunner:    at org.json.JSONTokener.nextValue(JSONTokener.java:98)
05-24 20:25:54.153 21410 21431 I TestRunner:    at org.json.JSONArray.<init>(JSONArray.java:94)
05-24 20:25:54.153 21410 21431 I TestRunner:    at org.json.JSONArray.<init>(JSONArray.java:110)
05-24 20:25:54.153 21410 21431 I TestRunner:    at org.fedorahosted.freeotp.TokenCompatTest.tokenCompatBackupRestore(TokenCompatTest.java:336)
05-24 20:25:54.153 21410 21431 I TestRunner:    at java.lang.reflect.Method.invoke(Native Method)
05-24 20:25:54.153 21410 21431 I TestRunner:    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
05-24 20:25:54.153 21410 21431 I TestRunner:    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
05-24 20:25:54.153 21410 21431 I TestRunner:    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
05-24 20:25:54.153 21410 21431 I TestRunner:    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
05-24 20:25:54.153 21410 21431 I TestRunner:    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
05-24 20:25:54.153 21410 21431 I TestRunner:    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
05-24 20:25:54.153 21410 21431 I TestRunner:    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
05-24 20:25:54.153 21410 21431 I TestRunner:    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
05-24 20:25:54.153 21410 21431 I TestRunner:    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
05-24 20:25:54.153 21410 21431 I TestRunner:    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
05-24 20:25:54.153 21410 21431 I TestRunner:    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
05-24 20:25:54.153 21410 21431 I TestRunner:    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
05-24 20:25:54.153 21410 21431 I TestRunner:    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
05-24 20:25:54.153 21410 21431 I TestRunner:    at org.junit.runners.Suite.runChild(Suite.java:128)
05-24 20:25:54.153 21410 21431 I TestRunner:    at org.junit.runners.Suite.runChild(Suite.java:27)
05-24 20:25:54.153 21410 21431 I TestRunner:    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
05-24 20:25:54.153 21410 21431 I TestRunner:    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
05-24 20:25:54.153 21410 21431 I TestRunner:    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
05-24 20:25:54.153 21410 21431 I TestRunner:    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
05-24 20:25:54.153 21410 21431 I TestRunner:    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
05-24 20:25:54.153 21410 21431 I TestRunner:    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
05-24 20:25:54.153 21410 21431 I TestRunner:    at org.junit.runners.Suite.runChild(Suite.java:128)
05-24 20:25:54.153 21410 21431 I TestRunner:    at org.junit.runners.Suite.runChild(Suite.java:27)
05-24 20:25:54.153 21410 21431 I TestRunner:    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
05-24 20:25:54.153 21410 21431 I TestRunner:    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
05-24 20:25:54.153 21410 21431 I TestRunner:    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
05-24 20:25:54.153 21410 21431 I TestRunner:    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
05-24 20:25:54.153 21410 21431 I TestRunner:    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
05-24 20:25:54.153 21410 21431 I TestRunner:    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
05-24 20:25:54.153 21410 21431 I TestRunner:    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
05-24 20:25:54.153 21410 21431 I TestRunner:    at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
05-24 20:25:54.153 21410 21431 I TestRunner:    at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
05-24 20:25:54.153 21410 21431 I TestRunner:    at androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:389)
05-24 20:25:54.153 21410 21431 I TestRunner:    at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2205)
05-24 20:25:54.153 21410 21431 I TestRunner: ----- end exception -----
05-24 20:25:54.157 21410 21431 I TestRunner: finished: tokenCompatBackupRestore[38](org.fedorahosted.freeotp.TokenCompatTest)

java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.String.length()' on a null object reference
at org.json.JSONTokener.nextCleanInternal(JSONTokener.java:121)
at org.json.JSONTokener.nextValue(JSONTokener.java:98)
at org.json.JSONArray.<init>(JSONArray.java:94)
at org.json.JSONArray.<init>(JSONArray.java:110)
at org.fedorahosted.freeotp.TokenCompatTest.tokenCompatBackupRestore(TokenCompatTest.java:336)
at java.lang.reflect.Method.invoke(Native Method)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
at androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:389)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2205)
acigolotti commented 1 year ago

Sorry for the lack of response from me, I didn't had time anymore.

I had to change the applicationId otherwise I couldn't run the tests.

Caused by: com.android.ddmlib.InstallException: INSTALL_FAILED_UPDATE_INCOMPATIBLE: Package org.fedorahosted.freeotp signatures do not match previously installed version; ignoring!

I have a secure lockscreen setup on my old phone, so all 210 tests ran successfully

lemenkov commented 10 months ago

The same issue for me (described in #352). Eventually some tokens (just a few of them) cannot be restored even using the same password.

Slater91 commented 10 months ago

Version 2.0.2 has fixed this issue for me. I was able to import all of the tokens on the new phone without any problem. It should be noted that the files were the same ones I created back in January.

bfdb commented 9 months ago

I believe I have the same issue:

I got a new phone a couple of months ago, installed version 2.0.2 (43) on Android 13, and added a whole bunch of OTPs. As the phone needed repairs, I backed up the database, and restored it on my factory reset previous phone (version 2.0.2 (43) on Android 8) with password.

While the password is accepted, the restored database is empty.

Moreover, as I'm restoring to an older version of Android, I cannot make use of restoring the database through Google. Instead, I have to manually restore.

m-from-space commented 8 months ago

Version 2.0.2 has fixed this issue for me. I was able to import all of the tokens on the new phone without any problem. It should be noted that the files were the same ones I created back in January.

That's nice to hear. But I still have the same issue. Version 2.0.2 (43) is still not able to import my old backup of keys. It just tries to import and then finishes without throwing an error and without having the keys back.

How come none of the developers can fix this serious issue here?

rotdrop commented 8 months ago

I have the very same problem. One Lenovo tablet and one Fairphone, both using version 2.0.2. Both installed from play-store, however, the previously install version from F-Droid (app-version 2.0.2) also is not able to restore the backup.

I was also brave enough to try the restore on the tablet -- but well, it is hard to tell whether just nothing happen or if all keys are restored ;) Sad story. Luckily the tablet has all data still available. I think I will gradually migrate to another app.

esspe2 commented 8 months ago

Same kind of problem for me : impossible to transfer the database from one phone to another. On the first one (Android 8), entries were added a long time ago in V1.X, via qr-code or manually, then FreeOTP was upgraded to V2.0.2, and one entry has been added by qr-code. When launching the backup, no password was requested, and on the other phone (Android 13), the restore asks for a password which I don't have, so no way to transfer the database. Since I had a backup from v1.X, I managed to generate all qr-codes and scanned them one by one following the old guide "Backing up and recovering 2FA tokens from FreeOTP", except for the last one where I had to ask the issuer to generate another secret. Now on the Android 13 phone, no password is requested to save it in the Download directory, so same problem, no usable backup as it seems.

boszormenyip commented 7 months ago

I have the same problem. Steps I do:

Phone specification:

What really interesting is that even thought the filename has xml extension (externalBackup.xml) in fact is standard java serialized object, which I can read without any problem with a following code:

package test;

import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.util.Map;

public class Main {
    public static void main(String[] args) throws Exception {
        var input = new ObjectInputStream(new FileInputStream("externalBackup.xml"));
        Map<String, String> obj = (Map<String, String>) input.readObject();
        obj.forEach((key, value) -> {
            System.out.format("key: %s, value: %s\n", key, value);
        });
    }

}

Excerpt from the output of the code:

key: masterKey, value: {"mAlgorithm":"PBKDF2withHmacSHA512","mEncryptedKey":{"mCipher":"AES/GCM/NoPadding","mCipherText":[],"mParameters":[],"mToken":"AES"},"mIterations":1,"mSalt":[]}
key: 0b354d0a-b1ff-4065-9903-f215d40bc36d, value: {"key":"{\"mCipher\":\"AES\/GCM\/NoPadding\",\"mCipherText\":[19,-107,97,79,16,68,54,65,-96,118,-66,22,37,101,82,62,-26,76,58,-47,-38,-64],\"mParameters\":[48,17,4,12,-97,-73,-55,-95,43,52,55,97,82,126,-99,68,2,1,16],\"mToken\":\"HmacSHA256\"}"}
key: 0b354d0a-b1ff-4065-9903-f215d40bc36d-token, value: {"algo":"SHA256","counter":0,"digits":6,"issuerExt":"Example inc","label":"jdoe@example.com","period":30,"type":"HOTP"}

Note that I removed the content of the mCipherText, mParameters and mSalt arrays, and I changed the mIterations of the masterKey

For everyone else: You can confirm that you also have a java serialized export by opening the exported file in google drive. If you see some garbage characters, and a beginning java.util.HashMap string, then it's a serialized export.

boekhoffm commented 7 months ago
  1. I exported from latest version of FreeOtp (2.0.2).
  2. I uninstalled and re-installed it from Android marketplace.
  3. I restored from the backup file created in (1)

No keys were restored and no error returned.

After reading the above, I looked in the file and it is a Java Serialised Hashmap that I can read using the code posted above, although typing these entries in manually gives the "not valid base32" error in the new Authenticator (Aegis)

lister169126 commented 5 months ago

All what we exported from our phones (I and my friend) in version 2.0.3 (44) can't import back or to other phones. Tested on 4 different devices.

I have backup from my old phone and its working but I don't now what version was here bcs I have wiped it.

rprofijt commented 4 months ago

Exactly the same issue here. Version 2.0.3 (44). Before I wiped my phone I tried the backup/restore and it seemed to work (tokens were all there). On the clean install the password question comes up, I enter it, it gets accepted and then the token list remains empty. As you can imagine this was very disappointing.. Lucky I had my OTP restore keys in order.

Will be looking into a replacement for this app.

lister169126 commented 4 months ago

Exactly the same issue here. Version 2.0.3 (44). Before I wiped my phone I tried the backup/restore and it seemed to work (tokens were all there). On the clean install the password question comes up, I enter it, it gets accepted and then the token list remains empty. As you can imagine this was very disappointing.. Lucky I had my OTP restore keys in order.

Will be looking into a replacement for this app.

look at aegis - https://github.com/beemdevelopment/Aegis

HardDie commented 1 month ago

I seem to have started using FreeOTP when it was in version 2.0.2. I backed it up from time to time, and old backups created on version 2.0.2 could be restored on both version 2.0.2 and 2.0.3. But new backups created on version 2.0.3 could not be restored on all versions of the application.

HardDie commented 1 month ago

Is there a guides on how to import working backups into Aegis? Because Aegis shows an error on all backups, even the working one in FreeOTP.

lister169126 commented 1 month ago

Is there a guides on how to import working backups into Aegis? Because Aegis shows an error on all backups, even the working one in FreeOTP.

Sorry, from version >= 2.0 no, it's in keystorage and you don't have access to secrets, just the freeotp app.