Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Various improvements #24

Merged
merged 1 commit into from Oct 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
26 changes: 9 additions & 17 deletions README.md
Expand Up @@ -2,24 +2,15 @@

<img src="https://i.imgur.com/JyxrStE.png" width="160" align="right">

> Fast and Portable Telegram Crypto Library for Python
> Fast and Portable Cryptography Extension Library for Pyrogram

**TgCrypto** is a Telegram Crypto Library written in C89 as a Python extension. It is designed to be portable, fast, easy
to install and use. TgCrypto is intended for [Pyrogram](https://github.com/pyrogram/pyrogram) and implements the crypto
algorithms Telegram requires, namely:
**TgCrypto** is a Cryptography Library written in C as a Python extension. It is designed to be portable, fast,
easy to install and use. TgCrypto is intended for [Pyrogram](https://github.com/pyrogram/pyrogram) and implements the
cryptographic algorithms Telegram requires, namely:

- **`AES256-IGE`** - used in [MTProto v2.0](https://core.telegram.org/mtproto).
- **`AES256-CTR`** - used for [CDN encrypted files](https://core.telegram.org/cdn).
- **`AES256-CBC`** - used for [encrypted passport credentials](https://core.telegram.org/passport).

Python [wheels are available](https://pypi.org/project/TgCrypto/#files) for hassle-free installations; they are
automatically built and tested using Travis CI for Linux (i686, x86_64, AArch64), Windows (32-bit, 64-bit) and macOS
(x86_64).

Even though TgCrypto is primarily intended for use with Pyrogram, you are free and welcome to use it for any other
Python project too, as it's shipped as standalone package.

More info: https://docs.pyrogram.org/topics/tgcrypto
- **`AES-256-IGE`** - used in [MTProto v2.0](https://core.telegram.org/mtproto).
- **`AES-256-CTR`** - used for [CDN encrypted files](https://core.telegram.org/cdn).
- **`AES-256-CBC`** - used for [encrypted passport credentials](https://core.telegram.org/passport).

## Requirements

Expand Down Expand Up @@ -163,7 +154,8 @@ print(data == cbc_decrypted) # True

1. Clone this repository: `git clone https://github.com/pyrogram/tgcrypto`.
2. Enter the directory: `cd tgcrypto`.
3. Run tests: `python3 setup.py test`.
3. Install `tox`: `pip3 install tox`
4. Run tests: `tox`.

## License

Expand Down
3 changes: 3 additions & 0 deletions pyproject.toml
@@ -0,0 +1,3 @@
[build-system]
requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"
9 changes: 4 additions & 5 deletions setup.py
Expand Up @@ -24,7 +24,7 @@
setup(
name="TgCrypto",
version="1.2.2",
description="Fast Telegram Crypto Library for Python",
description="Fast and Portable Cryptography Extension Library for Pyrogram",
long_description=readme,
long_description_content_type="text/markdown",
url="https://github.com/pyrogram",
Expand All @@ -40,12 +40,11 @@
"Programming Language :: C",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.3",
"Programming Language :: Python :: 3.4",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: Implementation",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
Expand All @@ -57,7 +56,7 @@
"Topic :: Software Development :: Libraries",
"Topic :: Software Development :: Libraries :: Python Modules"
],
keywords="fast pyrogram telegram crypto mtproto api client library python",
keywords="pyrogram telegram crypto cryptography encryption mtproto extension library aes",
project_urls={
"Tracker": "https://github.com/pyrogram/tgcrypto/issues",
"Community": "https://t.me/pyrogram",
Expand Down
70 changes: 35 additions & 35 deletions tgcrypto/aes256.c
Expand Up @@ -306,25 +306,6 @@ static const uint32_t Td3[256] = {
0xa8017139, 0x0cb3de08, 0xb4e49cd8, 0x56c19064, 0xcb84617b, 0x32b670d5, 0x6c5c7448, 0xb85742d0
};

static const uint8_t Td4[256] = {
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
};

static const uint8_t SBOX[16][16] = {
{0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76},
{0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0},
Expand All @@ -344,6 +325,25 @@ static const uint8_t SBOX[16][16] = {
{0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16}
};

static const uint8_t SBOX1[256] = {
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
};

static const uint32_t RCON[10] = {
0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000,
0x20000000, 0x40000000, 0x80000000, 0x1b000000, 0x36000000
Expand Down Expand Up @@ -591,40 +591,40 @@ void aes256_decrypt(const uint8_t in[16], uint8_t out[16], const uint32_t key[60
t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ key[55];

s0 = (
((uint32_t) Td4[(t0 >> 24)] << 24)
^ ((uint32_t) Td4[(t3 >> 16) & 0xff] << 16)
^ ((uint32_t) Td4[(t2 >> 8) & 0xff] << 8)
^ ((uint32_t) Td4[(t1) & 0xff])
((uint32_t) SBOX1[(t0 >> 24)] << 24)
^ ((uint32_t) SBOX1[(t3 >> 16) & 0xff] << 16)
^ ((uint32_t) SBOX1[(t2 >> 8) & 0xff] << 8)
^ ((uint32_t) SBOX1[(t1) & 0xff])
^ key[56]
);

PUT(out, s0);

s1 = (
((uint32_t) Td4[(t1 >> 24)] << 24)
^ ((uint32_t) Td4[(t0 >> 16) & 0xff] << 16)
^ ((uint32_t) Td4[(t3 >> 8) & 0xff] << 8)
^ ((uint32_t) Td4[(t2) & 0xff])
((uint32_t) SBOX1[(t1 >> 24)] << 24)
^ ((uint32_t) SBOX1[(t0 >> 16) & 0xff] << 16)
^ ((uint32_t) SBOX1[(t3 >> 8) & 0xff] << 8)
^ ((uint32_t) SBOX1[(t2) & 0xff])
^ key[57]
);

PUT(out + 4, s1);

s2 = (
((uint32_t) Td4[(t2 >> 24)] << 24)
^ ((uint32_t) Td4[(t1 >> 16) & 0xff] << 16)
^ ((uint32_t) Td4[(t0 >> 8) & 0xff] << 8)
^ ((uint32_t) Td4[(t3) & 0xff])
((uint32_t) SBOX1[(t2 >> 24)] << 24)
^ ((uint32_t) SBOX1[(t1 >> 16) & 0xff] << 16)
^ ((uint32_t) SBOX1[(t0 >> 8) & 0xff] << 8)
^ ((uint32_t) SBOX1[(t3) & 0xff])
^ key[58]
);

PUT(out + 8, s2);

s3 = (
((uint32_t) Td4[(t3 >> 24)] << 24)
^ ((uint32_t) Td4[(t2 >> 16) & 0xff] << 16)
^ ((uint32_t) Td4[(t1 >> 8) & 0xff] << 8)
^ ((uint32_t) Td4[(t0) & 0xff])
((uint32_t) SBOX1[(t3 >> 24)] << 24)
^ ((uint32_t) SBOX1[(t2 >> 16) & 0xff] << 16)
^ ((uint32_t) SBOX1[(t1 >> 8) & 0xff] << 8)
^ ((uint32_t) SBOX1[(t0) & 0xff])
^ key[59]
);

Expand Down
71 changes: 59 additions & 12 deletions tgcrypto/tgcrypto.c
Expand Up @@ -19,13 +19,18 @@
*/

#define PY_SSIZE_T_CLEAN

#include <Python.h>

#include "aes256.h"
#include "ige256.h"
#include "ctr256.h"
#include "cbc256.h"

#define DESCRIPTION "Fast and Portable Cryptography Extension Library for Pyrogram\n" \
"TgCrypto is part of Pyrogram, a Telegram MTProto library for Python\n" \
"You can learn more about Pyrogram here: https://pyrogram.org\n"

static PyObject *ige(PyObject *args, uint8_t encrypt) {
Py_buffer data, key, iv;
uint8_t *buf;
Expand Down Expand Up @@ -55,7 +60,7 @@ static PyObject *ige(PyObject *args, uint8_t encrypt) {
}

Py_BEGIN_ALLOW_THREADS
buf = ige256(data.buf, data.len, key.buf, iv.buf, encrypt);
buf = ige256(data.buf, data.len, key.buf, iv.buf, encrypt);
Py_END_ALLOW_THREADS

PyBuffer_Release(&data);
Expand Down Expand Up @@ -110,7 +115,7 @@ static PyObject *ctr256_encrypt(PyObject *self, PyObject *args) {
}

Py_BEGIN_ALLOW_THREADS
buf = ctr256(data.buf, data.len, key.buf, iv.buf, state.buf);
buf = ctr256(data.buf, data.len, key.buf, iv.buf, state.buf);
Py_END_ALLOW_THREADS

PyBuffer_Release(&data);
Expand Down Expand Up @@ -152,7 +157,7 @@ static PyObject *cbc(PyObject *args, uint8_t encrypt) {
}

Py_BEGIN_ALLOW_THREADS
buf = cbc256(data.buf, data.len, key.buf, iv.buf, encrypt);
buf = cbc256(data.buf, data.len, key.buf, iv.buf, encrypt);
Py_END_ALLOW_THREADS

PyBuffer_Release(&data);
Expand All @@ -173,20 +178,62 @@ static PyObject *cbc256_decrypt(PyObject *self, PyObject *args) {
return cbc(args, 0);
}

PyDoc_STRVAR(
ige256_encrypt_docs,
"ige256_encrypt(data, key, iv)\n"
"--\n\n"
"AES-256-IGE Encryption"
);

PyDoc_STRVAR(
ige256_decrypt_docs,
"ige256_decrypt(data, key, iv)\n"
"--\n\n"
"AES-256-IGE Decryption"
);

PyDoc_STRVAR(
ctr256_encrypt_docs,
"ctr256_encrypt(data, key, iv, state)\n"
"--\n\n"
"AES-256-CTR Encryption"
);

PyDoc_STRVAR(
ctr256_decrypt_docs,
"ctr256_decrypt(data, key, iv, state)\n"
"--\n\n"
"AES-256-CTR Decryption"
);

PyDoc_STRVAR(
cbc256_encrypt_docs,
"cbc256_encrypt(data, key, iv)\n"
"--\n\n"
"AES-256-CBC Encryption"
);

PyDoc_STRVAR(
cbc256_decrypt_docs,
"cbc256_decrypt(data, key, iv)\n"
"--\n\n"
"AES-256-CBC Encryption"
);

static PyMethodDef methods[] = {
{"ige256_encrypt", (PyCFunction) ige256_encrypt, METH_VARARGS, "AES256-IGE Encryption"},
{"ige256_decrypt", (PyCFunction) ige256_decrypt, METH_VARARGS, "AES256-IGE Decryption"},
{"ctr256_encrypt", (PyCFunction) ctr256_encrypt, METH_VARARGS, "AES256-CTR Encryption"},
{"ctr256_decrypt", (PyCFunction) ctr256_encrypt, METH_VARARGS, "AES256-CTR Decryption"},
{"cbc256_encrypt", (PyCFunction) cbc256_encrypt, METH_VARARGS, "AES256-CBC Encryption"},
{"cbc256_decrypt", (PyCFunction) cbc256_decrypt, METH_VARARGS, "AES256-CBC Decryption"},
{NULL, NULL, 0, NULL}
{"ige256_encrypt", (PyCFunction) ige256_encrypt, METH_VARARGS, ige256_encrypt_docs},
{"ige256_decrypt", (PyCFunction) ige256_decrypt, METH_VARARGS, ige256_decrypt_docs},
{"ctr256_encrypt", (PyCFunction) ctr256_encrypt, METH_VARARGS, ctr256_encrypt_docs},
{"ctr256_decrypt", (PyCFunction) ctr256_encrypt, METH_VARARGS, ctr256_decrypt_docs},
{"cbc256_encrypt", (PyCFunction) cbc256_encrypt, METH_VARARGS, cbc256_encrypt_docs},
{"cbc256_decrypt", (PyCFunction) cbc256_decrypt, METH_VARARGS, cbc256_decrypt_docs},
{NULL}
};

static struct PyModuleDef module = {
PyModuleDef_HEAD_INIT,
"tgcrypto",
"Telegram Crypto for Pyrogram",
"TgCrypto",
DESCRIPTION,
-1,
methods
};
Expand Down
2 changes: 1 addition & 1 deletion tox.ini
@@ -1,3 +1,3 @@
[testenv]
deps = pytest
commands = pytest {posargs}
commands = pytest {posargs}