A key-recovery attack for LINE for Android's chat backup encryption.
LINE for Android has a feature to back up individual chats to a ZIP file. Each backup contains images in plaintext and a weakly encrypted chat database, which can be recovered in fifteen minutes at most on a CPU supporting AES-NI.
Before anything else, compile the package with
go build and extract the
backup archive (
LINE_Android-backup-chat<id>.zip). The encrypted chat
database is the
linebackup/chat/chat<id> file (and not the one with the
.extra extension). Note:
chat<id>.extra need to be in the
same directory for the decryption program to work.
Decrypt an encrypted chat database (requires both your MID and your chat partner's):
./memories -source <path to the encrypted chat db> -oid <your MID> -tid <your chat partner's MID>
Recover the key of an encrypted chat database and decrypt it:
./memories -bruteforce -source <path to the encrypted chat db>
Every LINE user has an internal ID that starts with
u followed by 32 hex
u61726520762e206375746520f09f929c), which is refered to as
tmId in the Android app. (This ID is different from the one
you can set in the app, and from the
userId exposed by the LINE Messaging
API.) While it isn't visible to end users, it isn't secret either: I recovered
mine and my chat partners' using LINE for Google Chrome and Chrome's developer
When a chat backup is created, both IDs are concatenated and
The resulting 32-bit integer is then used as an initialization vector (IV) to
derive a 128-bit encryption key, and the chat database is encrypted using
AES-ECB with PKCS#5 padding.
After finding both IDs and reimplementing the encryption scheme, I was able to successfully decrypt a backup made from my account.
On top of the encryption key being derived from a 32-bit integer, the key derivation function (KDF) is fast and only called once. This effectively reduces the size of the key space to 2^32, which can be searched quickly.
A simple way to search the key space is to derive a key from every possible IV,
and use it to try to decrypt the first 16-byte block of the ciphertext (which
is expected to be
SQLite format 3\x00).
Using this attack, I was able to recover a key in less than 4 minutes on a 7 years old laptop (i5-2540M @ 2.60GHz).
The KDF has collisions (e.g. the IVs -1147136985, -1147146969, -1147157209... all yield the same key), which leads me to believe this attack could be improved.
hashCode()as a cryptographic hash function.
This project is licensed under the terms of the MIT license, except for the
contents of the
crypto directory which are licensed under the
Go BSD-style license.