Telegram Desktop passcode
#1
Hello everyone!

Diving into the Telegram Desktop source code I was able to write a program that decrypts and parses the local storage.
One option the client provides is to set a passcode - any string of any length - that is optionally used to encrypt a part of said local storage.

Testing whether the passcode is valid is a multi-step process (shortened for clarity):
1. Read the salt (32 bytes), encrypted data and sha1 of decrypted data from a file.
2. Compute a PKCS5_PBKDF2_HMAC_SHA1 on the UTF8(passcode), using the salt, 4000 iterations, keysize of 256 bytes
3. Use a Telegram-specific KDF to get the AesKey and AesIV (Relatively cheap - bunch of memcpy and 4x sha1)
4. Perform an AES-IGE-DECRYPT on the encrypted data using the derived key and IV from step 3.
5. Compare sha1 of decrypted data with the sha1 read in step 1. If they match - passcode is correct.

Using OpenSSL I am able to test around 100 passcodes/s on a Ryzen 1700. That is a sad number.
The obvious time-hog in this process is the 4000 iterations on the PKCS5_PBKDF2_HMAC_SHA1.
Judging from the benchmarks (that use 1000 iterations as far as I'm aware) I estimate that I could achieve a few MH/s using a GPU powered approach.

Since the process is probably too complex to be added as a whole is it possible to use hashcat (or other programs that I am unaware of) to compute the PKCS5_PBKDF2_HMAC_SHA1 keys with the mentioned parameters and pipe generated passcode-key pairs into another program that then validates the keys?

Thank you in advance,
Miha Zupan
#2
Comparison after KDF doesn't sound too complex to me (except IGE mode which I don't know what it does but block-modes tend to be simple because they have to be fast). There's much more complex kernels than what you've listed (for example LUKS). Note that 256 byte output of sha1 is really alot (your sure you don't mean bits?). Since the iteration count is almost the same compared to WPA, a more accurate performance would be to use benchmark speed / 8, because WPA needs 32 byte only.
#3
The key size is actually 256 bytes (2048 bits) - I was surprised too.
I am not really familiar with OpenCL and the library internals so is it possible to write logic to test the key in c or does key validation also happen on the gpu?
#4
Yeah, everything is done on GPU (which is written in OpenCL, which is a reduced C).
#5
This was implemented with https://github.com/hashcat/hashcat/pull/2355