Skip to content

Commit 1909961

Browse files
committed
Core: port AES-256-CTR from BoringSSL
1 parent b14b1c2 commit 1909961

File tree

2 files changed

+97
-0
lines changed

2 files changed

+97
-0
lines changed
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Security.Cryptography;
5+
using System.Text;
6+
using System.Threading.Tasks;
7+
8+
namespace TgSharp.Core.MTProto.Crypto
9+
{
10+
/*
11+
* AES-256-CTR Implementation
12+
* Original implementation by OpenSSL, ported to C#
13+
*/
14+
public class AesCtr
15+
{
16+
// The input encrypted as though 128bit counter mode is being used. The extra
17+
// state information to record how much of the 128bit block we have used is
18+
// contained in number, and the encrypted counter is kept in encryptedCount. Both
19+
// *num and ecount_buf must be initialised with zeros before the first call to
20+
// CRYPTO_ctr128_encrypt().
21+
//
22+
// This algorithm assumes that the counter is in the x lower bits of the IV
23+
// (ivec), and that the application has full control over overflow and the rest
24+
// of the IV. This implementation takes NO responsibility for checking that
25+
// the counter doesn't overflow into the rest of the IV when incremented.
26+
27+
public static void Ctr128Encrypt(byte[] input, byte[] key, ref byte[] ivec, ref byte[] encryptedCount, ref int number, byte[] output)
28+
{
29+
int n;
30+
n = number;
31+
32+
int outputPos = 0, inputPos = 0;
33+
int len = input.Length;
34+
35+
while (n != 0 && len != 0)
36+
{
37+
output[outputPos++] = (byte)(input[inputPos++] ^ encryptedCount[n]);
38+
--len;
39+
n = (n + 1) % 16;
40+
}
41+
42+
while (len >= 16)
43+
{
44+
encryptedCount = EncryptBlock(ivec, key);
45+
Ctr128Inc(ivec);
46+
for (n = 0; n < 16; n += sizeof(ulong))
47+
{
48+
var xoredResult = BitConverter.GetBytes(BitConverter.ToUInt64(input, inputPos + n) ^ BitConverter.ToUInt64(encryptedCount, n));
49+
Buffer.BlockCopy(xoredResult, 0, output, outputPos + n, 8);
50+
}
51+
len -= 16;
52+
outputPos += 16;
53+
inputPos += 16;
54+
n = 0;
55+
}
56+
57+
if (len != 0)
58+
{
59+
encryptedCount = EncryptBlock(ivec, key);
60+
Ctr128Inc(ivec);
61+
while (len-- != 0)
62+
{
63+
output[outputPos + n] = (byte)(input[inputPos + n] ^ encryptedCount[n]);
64+
++n;
65+
}
66+
}
67+
number = n;
68+
}
69+
70+
// increment counter (128-bit int) by 1
71+
private static void Ctr128Inc(byte[] counter)
72+
{
73+
uint n = 16, c = 1;
74+
75+
do
76+
{
77+
--n;
78+
c += counter[n];
79+
counter[n] = (byte)c;
80+
c >>= 8;
81+
} while (n != 0);
82+
}
83+
84+
private static byte[] EncryptBlock(byte[] toEncrypt, byte[] key)
85+
{
86+
using (var aes = new RijndaelManaged())
87+
{
88+
aes.Key = key;
89+
aes.Mode = CipherMode.ECB;
90+
aes.Padding = PaddingMode.None;
91+
ICryptoTransform cTransform = aes.CreateEncryptor();
92+
return cTransform.TransformFinalBlock(toEncrypt, 0, toEncrypt.Length);
93+
}
94+
}
95+
}
96+
}

src/TgSharp.Core/TgSharp.Core.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
<Compile Include="Exceptions\InvalidPhoneCodeException.cs" />
5454
<Compile Include="Exceptions\MissingApiConfigurationException.cs" />
5555
<Compile Include="MTProto\Crypto\AES.cs" />
56+
<Compile Include="MTProto\Crypto\AesCtr.cs" />
5657
<Compile Include="MTProto\Crypto\AuthKey.cs" />
5758
<Compile Include="MTProto\Crypto\BigInteger.cs" />
5859
<Compile Include="MTProto\Crypto\Crc32.cs" />

0 commit comments

Comments
 (0)