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();
|
||||
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)
|
||||
{
|
||||
|
|
@ -332,31 +340,25 @@ j4WcDuXc2CTHgH8gFTNhp/Y8/SpDOhvn9QIDAQAB
|
|||
|
||||
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");
|
||||
|
||||
// code adapted from PHP implementation found at https://mgp25.com/AESIGE/
|
||||
var output = new byte[input.Length];
|
||||
var xPrev = aes_iv.AsSpan(encrypt ? 16 : 0, 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)
|
||||
{
|
||||
byte[] yXOR = new byte[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++)
|
||||
yXOR[j] = (byte)(x[j] ^ yPrev[j]);
|
||||
var yFinal = aesCrypto.TransformFinalBlock(yXOR, 0, 16);
|
||||
yXOR[j] = (byte)(input[i + j] ^ yPrev[j]);
|
||||
aesCrypto.TransformBlock(yXOR, 0, 16, output, i);
|
||||
for (int j = 0; j < 16; j++)
|
||||
y[j] = (byte)(yFinal[j] ^ xPrev[j]);
|
||||
xPrev = x;
|
||||
yPrev = y;
|
||||
output[i + j] ^= xPrev[j];
|
||||
xPrev = input.Slice(i, 16);
|
||||
yPrev = output.AsSpan(i, 16);
|
||||
}
|
||||
}
|
||||
return output;
|
||||
|
|
@ -367,12 +369,12 @@ j4WcDuXc2CTHgH8gFTNhp/Y8/SpDOhvn9QIDAQAB
|
|||
{
|
||||
readonly ICryptoTransform encryptor;
|
||||
readonly byte[] ivec;
|
||||
byte[] ecount;
|
||||
readonly byte[] ecount = new byte[16];
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -384,7 +386,7 @@ j4WcDuXc2CTHgH8gFTNhp/Y8/SpDOhvn9QIDAQAB
|
|||
{
|
||||
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
|
||||
if (++ivec[n] != 0) break;
|
||||
}
|
||||
|
|
@ -421,12 +423,8 @@ j4WcDuXc2CTHgH8gFTNhp/Y8/SpDOhvn9QIDAQAB
|
|||
sha256.TransformFinalBlock(secret, 0, 16);
|
||||
recvKey = sha256.Hash;
|
||||
}
|
||||
using var aes = Aes.Create();
|
||||
aes.Mode = CipherMode.ECB;
|
||||
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 sendCtr = new AesCtr(sendKey, sendIV);
|
||||
var recvCtr = new AesCtr(recvKey, recvIV);
|
||||
var encrypted = (byte[])preamble.Clone();
|
||||
sendCtr.EncryptDecrypt(encrypted, 64);
|
||||
for (int i = 56; i < 64; i++)
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ namespace WTelegram
|
|||
private readonly SHA256 _sha256 = SHA256.Create();
|
||||
private string _pathname;
|
||||
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)
|
||||
{
|
||||
|
|
@ -67,7 +68,6 @@ namespace WTelegram
|
|||
{
|
||||
var input = File.ReadAllBytes(pathname);
|
||||
using var sha256 = SHA256.Create();
|
||||
using var aes = Aes.Create();
|
||||
using var decryptor = aes.CreateDecryptor(apiHash, input[0..16]);
|
||||
var utf8Json = decryptor.TransformFinalBlock(input, 16, input.Length - 16);
|
||||
if (!sha256.ComputeHash(utf8Json, 32, utf8Json.Length - 32).SequenceEqual(utf8Json[0..32]))
|
||||
|
|
@ -81,7 +81,6 @@ namespace WTelegram
|
|||
var finalBlock = new byte[16];
|
||||
var output = new byte[(16 + 32 + utf8Json.Length + 16) & ~15];
|
||||
Encryption.RNG.GetBytes(output, 0, 16);
|
||||
using var aes = Aes.Create();
|
||||
using var encryptor = aes.CreateEncryptor(_apiHash, output[0..16]);
|
||||
encryptor.TransformBlock(_sha256.ComputeHash(utf8Json), 0, 32, output, 16);
|
||||
encryptor.TransformBlock(utf8Json, 0, utf8Json.Length & ~15, output, 48);
|
||||
|
|
|
|||
Loading…
Reference in a new issue