android-password-store/Android-Password-Store

[BUG] Invalid TOTP secrets can crash the app

sewnie opened this issue · 9 comments

Describe the bug

I am unable to decrypt a specific password entry of mine, the one for github.

Steps to reproduce

Unreproducable, this only happens for me.

Expected behavior

I am able to decrypt github.

Screenshots

No response

Device information

  • Device: Google Pixel 7a
  • OS: Android 14
  • App version: 2.0.0-SNAPSHOT

Additional context

03-12 08:20:00.496 19227 19227 D BiometricAuthenticator: onAuthenticationSucceeded()
03-12 08:20:00.948 19227 19275 D org.pgpainless.decryption_verification.OpenPgpMessageInputStream: Symmetrically Encrypted Data Packet at depth 0 encountered
03-12 08:20:00.949 19227 19275 D org.pgpainless.decryption_verification.OpenPgpMessageInputStream: Symmetrically Encrypted Integrity-Protected Data has 0 SKESK(s) and 1 PKESK(s) from which 0 PKESK(s) have an anonymous recipient
03-12 08:20:00.950 19227 19275 D org.pgpainless.decryption_verification.OpenPgpMessageInputStream: Encountered PKESK for recipient XXX
03-12 08:20:00.969 19227 19275 D org.pgpainless.key.info.KeyRingInfo: (Sub?)-Key XXX is not encryption-capable.
03-12 08:20:00.969 19227 19275 D org.pgpainless.decryption_verification.OpenPgpMessageInputStream: Attempt decryption using secret key XXX XXX
03-12 08:20:01.273 19227 19275 D org.pgpainless.decryption_verification.OpenPgpMessageInputStream: Successfully decrypted data with key XXX XXX
03-12 08:20:01.273 19227 19275 D org.pgpainless.decryption_verification.OpenPgpMessageInputStream: Literal Data Packet at depth 1 encountered
03-12 08:20:01.274 19227 19275 D org.pgpainless.decryption_verification.IntegrityProtectedInputStream: Integrity Protection check passed
--------- beginning of crash
03-12 08:20:01.292 19227 19227 E AndroidRuntime: FATAL EXCEPTION: main
03-12 08:20:01.292 19227 19227 E AndroidRuntime: Process: app.passwordstore, PID: 19227
03-12 08:20:01.292 19227 19227 E AndroidRuntime: java.lang.IllegalArgumentException: Last encoded character (before the paddings if any) is a valid base 32 alphabet but not a possible value. Expected the discarded bits to be zero.
03-12 08:20:01.292 19227 19227 E AndroidRuntime: 	at org.apache.commons.codec.binary.Base32.validateCharacter(Unknown Source:14)
03-12 08:20:01.292 19227 19227 E AndroidRuntime: 	at org.apache.commons.codec.binary.Base32.decode(Unknown Source:283)
03-12 08:20:01.292 19227 19227 E AndroidRuntime: 	at org.apache.commons.codec.binary.BaseNCodec.decode(SourceFile:7)
03-12 08:20:01.292 19227 19227 E AndroidRuntime: 	at app.passwordstore.data.passfile.PasswordEntry.calculateTotp(Unknown Source:144)
03-12 08:20:01.292 19227 19227 E AndroidRuntime: 	at app.passwordstore.data.passfile.PasswordEntry$totp$1.invokeSuspend(Unknown Source:56)
03-12 08:20:01.292 19227 19227 E AndroidRuntime: 	at app.passwordstore.data.passfile.PasswordEntry$totp$1.invoke(Unknown Source:12)
03-12 08:20:01.292 19227 19227 E AndroidRuntime: 	at kotlinx.coroutines.flow.SafeFlow.collect(Unknown Source:258)
03-12 08:20:01.292 19227 19227 E AndroidRuntime: 	at kotlin.ResultKt.first(SourceFile:16)
03-12 08:20:01.292 19227 19227 E AndroidRuntime: 	at app.passwordstore.ui.crypto.DecryptActivity$createPasswordUI$2.invokeSuspend(Unknown Source:126)
03-12 08:20:01.292 19227 19227 E AndroidRuntime: 	at app.passwordstore.ui.crypto.DecryptActivity$createPasswordUI$2.invoke(Unknown Source:12)
03-12 08:20:01.292 19227 19227 E AndroidRuntime: 	at logcat.ThrowablesKt.startUndispatchedOrReturn(Unknown Source:15)
03-12 08:20:01.292 19227 19227 E AndroidRuntime: 	at kotlin.TuplesKt.withContext(Unknown Source:73)
03-12 08:20:01.292 19227 19227 E AndroidRuntime: 	at app.passwordstore.ui.crypto.DecryptActivity.access$decryptWithCachedPassphrase(Unknown Source:132)
03-12 08:20:01.292 19227 19227 E AndroidRuntime: 	at app.passwordstore.ui.crypto.DecryptActivity$decryptWithCachedPassphrase$1.invokeSuspend(Unknown Source:12)
03-12 08:20:01.292 19227 19227 E AndroidRuntime: 	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(Unknown Source:8)
03-12 08:20:01.292 19227 19227 E AndroidRuntime: 	at kotlinx.coroutines.DispatchedTask.run(Unknown Source:114)
03-12 08:20:01.292 19227 19227 E AndroidRuntime: 	at android.os.Handler.handleCallback(Handler.java:959)
03-12 08:20:01.292 19227 19227 E AndroidRuntime: 	at android.os.Handler.dispatchMessage(Handler.java:100)
03-12 08:20:01.292 19227 19227 E AndroidRuntime: 	at android.os.Looper.loopOnce(Looper.java:232)
03-12 08:20:01.292 19227 19227 E AndroidRuntime: 	at android.os.Looper.loop(Looper.java:317)
03-12 08:20:01.292 19227 19227 E AndroidRuntime: 	at android.app.ActivityThread.main(ActivityThread.java:8501)
03-12 08:20:01.292 19227 19227 E AndroidRuntime: 	at java.lang.reflect.Method.invoke(Native Method)
03-12 08:20:01.292 19227 19227 E AndroidRuntime: 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
03-12 08:20:01.292 19227 19227 E AndroidRuntime: 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:878)
03-12 08:20:01.292 19227 19227 E AndroidRuntime: 	Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@ec34eb1, Dispatchers.Main]
03-12 08:20:01.317 19227 19227 I Process : Sending signal. PID: 19227 SIG: 9

On my host system, i can derypt it with gopass fine.

This seems like an issue with the TOTP secret in the password file. If it's possible for you to rotate your 2FA credentials and share the currently broken one with me it'd be very helpful. You can attach it here or encrypt it to my PGP key and send it to googleplay@passwordstore.app.

i do not have TOTP or 2FA...

I can encrypt every other entry i have, except for the one for github.

i do not have TOTP or 2FA...

That's odd, do you have any line in there that happens to start with otpauth:// or totp:? The failing OTP calculation code should not be run in any other scenario.

I can encrypt every other entry i have, except for the one for github.

That doesn't really matter. The bug has no relation to the cryptographic aspects of pass, it is a format parsing issue.

That's odd, do you have any line in there that happens to start with otpauth:// or totp:

In the log file? No...

Please find somewhere else to be funny.

just wanted to brighten the mood a little bit :(

just wanted to brighten the mood a little bit :(

I appreciate the sentiment, but the issue title's accuracy is important for me to able to correctly triage and prioritize it for the limited time I have for this project. There are less disruptive ways to be humorous :)

After some time, installing a custom operating system, i came across this issue and only with my GitHub entry, now i'm wondering if there is something wrong with it.

This is exactly the case.

At the end of the GitHub password entry, there is a otpauth://totp/otp-secret?secret=, which actually just leads to my GitHub security key and has nothing to do with TOTP.

I apologize for not checking earlier.