mirror of
https://github.com/wiz0u/WTelegramClient.git
synced 2025-12-06 06:52:01 +01:00
reduce allocations for encryption
This commit is contained in:
parent
0c1785596d
commit
6bdb0b9cc7
|
|
@ -16,6 +16,14 @@ namespace WTelegram
|
||||||
{
|
{
|
||||||
internal static readonly RNGCryptoServiceProvider RNG = new();
|
internal static readonly RNGCryptoServiceProvider RNG = new();
|
||||||
private static readonly Dictionary<long, RSAPublicKey> PublicKeys = new();
|
private static readonly Dictionary<long, RSAPublicKey> PublicKeys = new();
|
||||||
|
private static readonly Aes AesECB = Aes.Create();
|
||||||
|
|
||||||
|
static Encryption()
|
||||||
|
{
|
||||||
|
AesECB.Mode = CipherMode.ECB;
|
||||||
|
AesECB.Padding = PaddingMode.Zeros;
|
||||||
|
if (AesECB.BlockSize != 128) throw new ApplicationException("AES Blocksize is not 16 bytes");
|
||||||
|
}
|
||||||
|
|
||||||
internal static async Task CreateAuthorizationKey(Client client, Session.DCSession session)
|
internal static async Task CreateAuthorizationKey(Client client, Session.DCSession session)
|
||||||
{
|
{
|
||||||
|
|
@ -332,31 +340,25 @@ j4WcDuXc2CTHgH8gFTNhp/Y8/SpDOhvn9QIDAQAB
|
||||||
|
|
||||||
private static byte[] AES_IGE_EncryptDecrypt(Span<byte> input, byte[] aes_key, byte[] aes_iv, bool encrypt)
|
private static byte[] AES_IGE_EncryptDecrypt(Span<byte> input, byte[] aes_key, byte[] aes_iv, bool encrypt)
|
||||||
{
|
{
|
||||||
using var aes = Aes.Create();
|
|
||||||
aes.Mode = CipherMode.ECB;
|
|
||||||
aes.Padding = PaddingMode.Zeros;
|
|
||||||
if (aes.BlockSize != 128) throw new ApplicationException("AES Blocksize is not 16 bytes");
|
|
||||||
if (input.Length % 16 != 0) throw new ApplicationException("intput size not divisible by 16");
|
if (input.Length % 16 != 0) throw new ApplicationException("intput size not divisible by 16");
|
||||||
|
|
||||||
// code adapted from PHP implementation found at https://mgp25.com/AESIGE/
|
// code adapted from PHP implementation found at https://mgp25.com/AESIGE/
|
||||||
var output = new byte[input.Length];
|
var output = new byte[input.Length];
|
||||||
var xPrev = aes_iv.AsSpan(encrypt ? 16 : 0, 16);
|
var xPrev = aes_iv.AsSpan(encrypt ? 16 : 0, 16);
|
||||||
var yPrev = aes_iv.AsSpan(encrypt ? 0 : 16, 16);
|
var yPrev = aes_iv.AsSpan(encrypt ? 0 : 16, 16);
|
||||||
var aesCrypto = encrypt ? aes.CreateEncryptor(aes_key, null) : aes.CreateDecryptor(aes_key, null);
|
var aesCrypto = encrypt ? AesECB.CreateEncryptor(aes_key, null) : AesECB.CreateDecryptor(aes_key, null);
|
||||||
using (aesCrypto)
|
using (aesCrypto)
|
||||||
{
|
{
|
||||||
byte[] yXOR = new byte[16];
|
byte[] yXOR = new byte[16];
|
||||||
for (int i = 0; i < input.Length; i += 16)
|
for (int i = 0; i < input.Length; i += 16)
|
||||||
{
|
{
|
||||||
var x = input.Slice(i, 16);
|
|
||||||
var y = output.AsSpan(i, 16);
|
|
||||||
for (int j = 0; j < 16; j++)
|
for (int j = 0; j < 16; j++)
|
||||||
yXOR[j] = (byte)(x[j] ^ yPrev[j]);
|
yXOR[j] = (byte)(input[i + j] ^ yPrev[j]);
|
||||||
var yFinal = aesCrypto.TransformFinalBlock(yXOR, 0, 16);
|
aesCrypto.TransformBlock(yXOR, 0, 16, output, i);
|
||||||
for (int j = 0; j < 16; j++)
|
for (int j = 0; j < 16; j++)
|
||||||
y[j] = (byte)(yFinal[j] ^ xPrev[j]);
|
output[i + j] ^= xPrev[j];
|
||||||
xPrev = x;
|
xPrev = input.Slice(i, 16);
|
||||||
yPrev = y;
|
yPrev = output.AsSpan(i, 16);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
|
|
@ -367,12 +369,12 @@ j4WcDuXc2CTHgH8gFTNhp/Y8/SpDOhvn9QIDAQAB
|
||||||
{
|
{
|
||||||
readonly ICryptoTransform encryptor;
|
readonly ICryptoTransform encryptor;
|
||||||
readonly byte[] ivec;
|
readonly byte[] ivec;
|
||||||
byte[] ecount;
|
readonly byte[] ecount = new byte[16];
|
||||||
int num;
|
int num;
|
||||||
|
|
||||||
public AesCtr(Aes aes, byte[] key, byte[] iv)
|
public AesCtr(byte[] key, byte[] iv)
|
||||||
{
|
{
|
||||||
encryptor = aes.CreateEncryptor(key, null);
|
encryptor = AesECB.CreateEncryptor(key, null);
|
||||||
ivec = iv;
|
ivec = iv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -384,7 +386,7 @@ j4WcDuXc2CTHgH8gFTNhp/Y8/SpDOhvn9QIDAQAB
|
||||||
{
|
{
|
||||||
if (num == 0)
|
if (num == 0)
|
||||||
{
|
{
|
||||||
ecount = encryptor.TransformFinalBlock(ivec, 0, 16);
|
encryptor.TransformBlock(ivec, 0, 16, ecount, 0);
|
||||||
for (int n = 15; n >= 0; n--) // increment big-endian counter
|
for (int n = 15; n >= 0; n--) // increment big-endian counter
|
||||||
if (++ivec[n] != 0) break;
|
if (++ivec[n] != 0) break;
|
||||||
}
|
}
|
||||||
|
|
@ -421,12 +423,8 @@ j4WcDuXc2CTHgH8gFTNhp/Y8/SpDOhvn9QIDAQAB
|
||||||
sha256.TransformFinalBlock(secret, 0, 16);
|
sha256.TransformFinalBlock(secret, 0, 16);
|
||||||
recvKey = sha256.Hash;
|
recvKey = sha256.Hash;
|
||||||
}
|
}
|
||||||
using var aes = Aes.Create();
|
var sendCtr = new AesCtr(sendKey, sendIV);
|
||||||
aes.Mode = CipherMode.ECB;
|
var recvCtr = new AesCtr(recvKey, recvIV);
|
||||||
aes.Padding = PaddingMode.None;
|
|
||||||
if (aes.BlockSize != 128) throw new ApplicationException("AES Blocksize is not 16 bytes");
|
|
||||||
var sendCtr = new AesCtr(aes, sendKey, sendIV);
|
|
||||||
var recvCtr = new AesCtr(aes, recvKey, recvIV);
|
|
||||||
var encrypted = (byte[])preamble.Clone();
|
var encrypted = (byte[])preamble.Clone();
|
||||||
sendCtr.EncryptDecrypt(encrypted, 64);
|
sendCtr.EncryptDecrypt(encrypted, 64);
|
||||||
for (int i = 56; i < 64; i++)
|
for (int i = 56; i < 64; i++)
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ namespace WTelegram
|
||||||
private readonly SHA256 _sha256 = SHA256.Create();
|
private readonly SHA256 _sha256 = SHA256.Create();
|
||||||
private string _pathname;
|
private string _pathname;
|
||||||
private byte[] _apiHash; // used as AES key for encryption of session file
|
private byte[] _apiHash; // used as AES key for encryption of session file
|
||||||
|
private static readonly Aes aes = Aes.Create();
|
||||||
|
|
||||||
internal static Session LoadOrCreate(string pathname, byte[] apiHash)
|
internal static Session LoadOrCreate(string pathname, byte[] apiHash)
|
||||||
{
|
{
|
||||||
|
|
@ -67,7 +68,6 @@ namespace WTelegram
|
||||||
{
|
{
|
||||||
var input = File.ReadAllBytes(pathname);
|
var input = File.ReadAllBytes(pathname);
|
||||||
using var sha256 = SHA256.Create();
|
using var sha256 = SHA256.Create();
|
||||||
using var aes = Aes.Create();
|
|
||||||
using var decryptor = aes.CreateDecryptor(apiHash, input[0..16]);
|
using var decryptor = aes.CreateDecryptor(apiHash, input[0..16]);
|
||||||
var utf8Json = decryptor.TransformFinalBlock(input, 16, input.Length - 16);
|
var utf8Json = decryptor.TransformFinalBlock(input, 16, input.Length - 16);
|
||||||
if (!sha256.ComputeHash(utf8Json, 32, utf8Json.Length - 32).SequenceEqual(utf8Json[0..32]))
|
if (!sha256.ComputeHash(utf8Json, 32, utf8Json.Length - 32).SequenceEqual(utf8Json[0..32]))
|
||||||
|
|
@ -81,7 +81,6 @@ namespace WTelegram
|
||||||
var finalBlock = new byte[16];
|
var finalBlock = new byte[16];
|
||||||
var output = new byte[(16 + 32 + utf8Json.Length + 16) & ~15];
|
var output = new byte[(16 + 32 + utf8Json.Length + 16) & ~15];
|
||||||
Encryption.RNG.GetBytes(output, 0, 16);
|
Encryption.RNG.GetBytes(output, 0, 16);
|
||||||
using var aes = Aes.Create();
|
|
||||||
using var encryptor = aes.CreateEncryptor(_apiHash, output[0..16]);
|
using var encryptor = aes.CreateEncryptor(_apiHash, output[0..16]);
|
||||||
encryptor.TransformBlock(_sha256.ComputeHash(utf8Json), 0, 32, output, 16);
|
encryptor.TransformBlock(_sha256.ComputeHash(utf8Json), 0, 32, output, 16);
|
||||||
encryptor.TransformBlock(utf8Json, 0, utf8Json.Length & ~15, output, 48);
|
encryptor.TransformBlock(utf8Json, 0, utf8Json.Length & ~15, output, 48);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue