You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
E2EE: text messages never decrypt for certain accounts after QR login (self privKey != registered pubKey) - deterministic "Unsupported state or unable to authenticate data" #195
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). ✅
Bnever 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
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
Usage matches SKILL.md: createPolling().listenTalkEvents() + await client.e2ee.decryptE2EEMessage(op.message) for both event types.
Version: base/e2ee/mod.ts in 3.1.3 is identical to main (same selfKeyId = isSelf ? senderKeyId : receiverKeyId, same aes-256-gcm, same AAD). Not an outdated-lib issue.
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.
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)?
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.
Environment
@evex/linejsv3.1.3 (jsr@evex/linejs)DESKTOPWINSummary
For some accounts, E2EE text decryption (
decryptE2EETextMessage->decryptE2EEMessageV2) deterministically fails withUnsupported 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:
SEND_MESSAGE+ incomingRECEIVE_MESSAGE). ✅SEND_MESSAGE(its own outgoing, echoed) throws the GCM auth error. ❌Key evidence (same message, opposite result)
Same 1:1 message B -> A:
RECEIVE_MESSAGE,isSelf=false) -> decrypts OKSEND_MESSAGE,isSelf=true) -> failsEnvelope keyIds:
senderKeyId = 5900403(B),receiverKeyId = 5883167(A).A_priv[5883167]+B_pub[5900403](fromnegotiateE2EEPublicKey) -> so B's registered public key 5900403 is correct/usable.B_priv[5900403](fromgetE2EESelfKeyDataByKeyId, stored at login ine2eeKeys:5900403) +A_pub[5883167].ECDH(B_priv, A_pub)should equalECDH(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
SKILL.md:createPolling().listenTalkEvents()+await client.e2ee.decryptE2EEMessage(op.message)for both event types.base/e2ee/mod.tsin 3.1.3 is identical tomain(sameselfKeyId = isSelf ? senderKeyId : receiverKeyId, sameaes-256-gcm, same AAD). Not an outdated-lib issue.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.respondE2EELoginRequestprimary-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 registersaveE2EESelfKeyDataByKeyIdor use E2EE Login #41?getE2EEKeyBackupInfo/getE2EEKeyBackupCertificates)?Happy to share full
e2eedebug logs or a minimal repro.