- We use AES CBC with 256 bit key. First 16 bytes of any encrypted by library data is IV.
- As PBKDF we use Scrypt.
Note
More detailed in :doc:`remotebox` and :doc:`localbox`
- The Box is something that have BoxSalt — 32 (usually random) bytes. With this salt and user phrase we make encryption key (see :ref:`Encryption keys`).
- Box splits into two types, — the Remote and Local. They have a two states, — the Encrypted and Decrypted.
- RemoteBox store encrypted files and their metadata. LocalBox store only metadata.
- LocalBox can be restored from RemoteBox if you have decryption key.
- We start from user's
Phrase
, that can be generated viaPhrase.generate()
. Then we make theBaseKey
, withmake_basekey
. That's a Scrypt function, by default configured to use 1GB of RAM for key creation. We use salt fromconstants.SCRYPT_SALT
if not specified. If changed, may be reffered as 2FA — obtaining only Phrase will be not enough for Box decryption. - Having
BaseKey
, we make a RemoteBox and receive BoxSalt. Callingmake_mainkey(basekey, box_salt)
, we receive theMainKey
. With MainKey we make LocalBox (see :doc:`localbox`). - When we want to upload file to the Box, we make a FileSalt — random 32 bytes. With
make_filekey(mainkey, file_salt)
we receive theFileKey
. FileKey encrypts file and its metadata.
So, there is three encryption Keys: BaseKey, MainKey, FileKey.
Note
- We're always encrypt Telegram session with
BaseKey
, so attacker can't decrypt it even withMainKey
. - It's impossible to restore MainKey from FileKey, so exposing it will only give access to file, with which this key is associated.
Let's imagine that Alice have encrypted file in her RemoteBox that she want to share with Bob. As every RemoteBoxFile has unique encryption key (FileKey
) file sharing shouldn't be a big problem, but how we can make it secure? There is two ways:
- Get
FileKey
ofDecryptedRemoteBoxFile
and send it to Bob through Telegram's secret chat; - Encrypt
FileKey
with a shared secret key (see asymmetric cryptography).
Sending encryption keys via plain chats in Telegram isn't secure. Secret chat may be not available or not so conveniently. So in TGBOX we use ECDH for making shared secret. File sharing routine for users simplifies to follows:
- Alice forward file from her RemoteBox channel to Bob;
- Bob forwards received file to his RemoteBox channel;
- B gets
EncryptedRemoteBoxFile
and callsget_requestkey
on it; - A receives
RequestKey
from B (can be shared via insecure canals); - A makes
ShareKey
with B'sRequestKey
and sends it to B (can be shared via insecure canals); - B makes
ImportKey
with A'sShareKey
, decryptsEncryptedRemoteBoxFile
and imports it.
Let's analyze RemoteBox sharing, there is no difference with file sharing.
0. Bob makes BaseKey
To clone other's RemoteBox Bob firstly should create
BaseKey
for it.1. Alice invites Bob to her RemoteBox channel
This can be done with Telethon or with Telegram. If you are developer and want to make an App with TGBOX, then you need to implement this.
2. B gets EncryptedRemoteBox and calls get_requestkey on it
Every RemoteBox has BoxSalt. The RemoteBox store it in channel description, encoded by url safe base64. From concated BoxSalt and B's new
BaseKey
we make a sha256 hash. This hash acts as private key for ECDH on secp256k1 curve. We create public key from this private key, compress it, and return (get_requestkey
)RequestKey(compressed_pubkey)
. Generally,RequestKey
is compressed ECDH pubkey.3. A receives RequestKey from B
Can be done with Telethon / Telegram or any other insecure communication canal.
4. A makes ShareKey with B's RequestKey and sends it to B
- A makes own private key similarly to B, with
sha256(a_mainkey + box_salt)
, extracts B's pubkey fromRequestKey
and makes a shared 32byte-secret withECDH(a_privkey, b_pubkey, secp256k1)
. This is encryption key for AES CBC; - A makes sha256 hash from B's
RequestKey
and takes first 16 bytes from result, this is IV. - A encrypts her
MainKey
with shared secret and IV. Let's call result as eMainKey. After this she constructsShareKey
as follows:ShareKey(e_mainkey + a_pubkey)
. We don't concat IV to theShareKey
because Bob can extract it fromRequestKey
.
- A makes own private key similarly to B, with
5. B makes ImportKey with A's ShareKey, decrypts EncryptedRemoteBox and clones it.
Bob repeats second step, extracts IV and receives b_privkey. After, makes shared secret as 4.1 and decrypts
eMainKey
. This can be done withkeys.make_importkey
function. Transfer complete.
Abstract tgbox file has 13 attributes:
ID
(integer)FOLDER
(bytes)COMMENT
(bytes)DURATION
(float)FILE_IV
(bytes)FILE_KEY
(bytes/None)FILE_NAME
(bytes)FILE_SALT
(bytes)PREVIEW
(bytes)SIZE
(int)UPLOAD_TIME
(int)VERBYTE
(byte)FILE_PATH
(bytes)
FILE_KEY
is LocalBox-only field. It will be non-empty if you imported DecryptedRemoteBoxFile
from other's RemoteBox. In this case FILE_KEY encrypted with LocalBox MainKey
.
We're always encrypt FOLDERNAME
with MainKey, so when you share file, recipient will not know its folder.
As we're always encrypt FOLDERNAME
with unique IV, ciphertext will be always different, and iterating over files in specified folder (see LocalBoxFolder
) will be very painful. To make life easier, Tgbox has a FOLDER_ID
. See tools.make_folder_id
.
# Circa func. We only take first 16 bytes from result.
folder_id = sha256(sha256(mainkey) + foldername)[:16]
E.g:
- User request all files with folder "Cats"
- We're
make_folder_id(mainkey, b"Cats")
- Select all files with same
FOLDER_ID
Note
We're talking only about LocalBoxFile, RemoteBoxFile doesn't store FOLDER_ID
, but encrypted FOLDERNAME
.
It's considered to be secure, as
- Attacker must have direct access to your
EncryptedLocalBox
. - Attacker will only read that there is X unknown files in unknown folder, and their IDs.
FOLDER_ID
of sameFOLDERNAME
is unique for every BoxSalt.- Attacker will not have any access to the
EncryptedRemoteBox
. - RemoteBoxFile doesn't store
FOLDER_ID
. - Max file size defined in
constants
module, and~2GB-2MB
by default.
- Max bytesize of every property defined in
constants
module. - We can use
COMMENT
for defining file types. See #4. ID
is Telegram message ID.DURATION
stands for media duration,PREVIEW
for media preview.VERBYTE
stands for "Version byte". I.e "x00" — 0 version.
We offer three Git branches:
- Indev. This branch used for active developing. Modules almost not tested, not stable, but errors are fixed faster.
- Main. This branch has tested bugfixes and new features from Indev. Can be still some minor errors.
- Stable. This branch has well-tested bugfixes and new features. Zero errors (at least critical) expected.
VERBYTE
define compatibility, while it's not incremented, all new updates MUST support previous file formats, functions, etc. Except Version byte there can be lower versions, like 0.1
, 0.1.1
, 0.1.1.1
.... let's stop right here.
Note
The "Zero" version ("x00") will be there until first "stable" branch wasn't created. The "First" version ("x01") will be fully compatible with Zero, it's an exception from rules.