Skip to content

E2EE: text messages never decrypt for certain accounts after QR login (self privKey != registered pubKey) - deterministic "Unsupported state or unable to authenticate data" #195

Description

@thanhnam72

Environment

  • @evex/linejs v3.1.3 (jsr @evex/linejs)
  • Node.js 20, login method: QR (ForSecure), device DESKTOPWIN
  • 1:1 USER chats with Letter Sealing (E2EE) enabled

Summary

For some accounts, E2EE text decryption (decryptE2EETextMessage -> decryptE2EEMessageV2) deterministically fails with Unsupported state or unable to authenticate data. It is not per-message flaky — a given account always decrypts or never does.

I logged two accounts A and B into the same client via QR:

  • A decrypts everything fine (own SEND_MESSAGE + incoming RECEIVE_MESSAGE). ✅
  • B never decrypts — every SEND_MESSAGE (its own outgoing, echoed) throws the GCM auth error. ❌

Key evidence (same message, opposite result)

Same 1:1 message B -> A:

  • On A's session (RECEIVE_MESSAGE, isSelf=false) -> decrypts OK
  • On B's session (SEND_MESSAGE, isSelf=true) -> fails

Envelope keyIds: senderKeyId = 5900403 (B), receiverKeyId = 5883167 (A).

  • A succeeds with A_priv[5883167] + B_pub[5900403] (from negotiateE2EEPublicKey) -> so B's registered public key 5900403 is correct/usable.
  • B fails with B_priv[5900403] (from getE2EESelfKeyDataByKeyId, stored at login in e2eeKeys:5900403) + A_pub[5883167].
  • ECDH is symmetric, so ECDH(B_priv, A_pub) should equal ECDH(A_priv, B_pub) — but it doesn't. => the private key stored for B under keyId 5900403 does not correspond to B's registered public key. The QR login saved a private key that does not match the account's registered E2EE identity.

Ruled out

Hypothesis / Questions

I suspect the E2EE key transfer / primary-side PIN authorization does not complete during QR login, so for accounts whose identity key was established earlier on the phone, decodeE2EEKeyV1 (ForSecure) stores a private key that does not match the registered public key.

  1. Is this the same root cause as respondE2EELoginRequest: primary-side PIN authorization (schema _args missing, no high-level wrapper) #155 (respondE2EELoginRequest primary-side PIN authorization)? Or related to Sync E2EE behavior with latest LINE Android (key retrieval refactor, group key recreation) #128 / Error: E2EE Key has not been saved, try register saveE2EESelfKeyDataByKeyId or use E2EE Login #41?
  2. For an already-established account, what is the correct way to obtain the matching E2EE private key on a new QR-logged device so both incoming and own messages decrypt — complete E2EE Login with the primary device's PIN, or retrieve from E2EE key backup (getE2EEKeyBackupInfo / getE2EEKeyBackupCertificates)?
  3. Is there (or planned) a high-level API for this flow? A minimal example would help a lot.

Happy to share full e2ee debug logs or a minimal repro.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions