diff --git a/TLSharp.Core/Auth/Authenticator.cs b/TLSharp.Core/Auth/Authenticator.cs
index f63523c..3fd47ba 100644
--- a/TLSharp.Core/Auth/Authenticator.cs
+++ b/TLSharp.Core/Auth/Authenticator.cs
@@ -34,4 +34,4 @@ namespace TLSharp.Core.Auth
return step3Response;
}
}
-}
+}
\ No newline at end of file
diff --git a/TLSharp.Core/Auth/Step1_PQRequest.cs b/TLSharp.Core/Auth/Step1_PQRequest.cs
index 8d61d9a..a853966 100644
--- a/TLSharp.Core/Auth/Step1_PQRequest.cs
+++ b/TLSharp.Core/Auth/Step1_PQRequest.cs
@@ -17,7 +17,7 @@ namespace TLSharp.Core.Auth
public class Step1_PQRequest
{
- private byte[] nonce;
+ private readonly byte[] nonce;
public Step1_PQRequest()
{
@@ -52,33 +52,27 @@ namespace TLSharp.Core.Auth
const int responseConstructorNumber = 0x05162463;
var responseCode = binaryReader.ReadInt32();
if (responseCode != responseConstructorNumber)
- {
throw new InvalidOperationException($"invalid response code: {responseCode}");
- }
var nonceFromServer = binaryReader.ReadBytes(16);
if (!nonceFromServer.SequenceEqual(nonce))
- {
throw new InvalidOperationException("invalid nonce from server");
- }
var serverNonce = binaryReader.ReadBytes(16);
- byte[] pqbytes = Serializers.Bytes.read(binaryReader);
+ var pqbytes = Serializers.Bytes.read(binaryReader);
var pq = new BigInteger(1, pqbytes);
var vectorId = binaryReader.ReadInt32();
const int vectorConstructorNumber = 0x1cb5c415;
if (vectorId != vectorConstructorNumber)
- {
throw new InvalidOperationException($"Invalid vector constructor number {vectorId}");
- }
var fingerprintCount = binaryReader.ReadInt32();
for (var i = 0; i < fingerprintCount; i++)
{
- byte[] fingerprint = binaryReader.ReadBytes(8);
+ var fingerprint = binaryReader.ReadBytes(8);
fingerprints.Add(fingerprint);
}
@@ -93,4 +87,4 @@ namespace TLSharp.Core.Auth
}
}
}
-}
+}
\ No newline at end of file
diff --git a/TLSharp.Core/Auth/Step2_DHExchange.cs b/TLSharp.Core/Auth/Step2_DHExchange.cs
index 53b8016..a1dc6b0 100644
--- a/TLSharp.Core/Auth/Step2_DHExchange.cs
+++ b/TLSharp.Core/Auth/Step2_DHExchange.cs
@@ -31,9 +31,9 @@ namespace TLSharp.Core.Auth
byte[] reqDhParamsBytes;
- using (MemoryStream pqInnerData = new MemoryStream(255))
+ using (var pqInnerData = new MemoryStream(255))
{
- using (BinaryWriter pqInnerDataWriter = new BinaryWriter(pqInnerData))
+ using (var pqInnerDataWriter = new BinaryWriter(pqInnerData))
{
pqInnerDataWriter.Write(0x83c95aec); // pq_inner_data
Serializers.Bytes.write(pqInnerDataWriter, pq.ToByteArrayUnsigned());
@@ -45,10 +45,10 @@ namespace TLSharp.Core.Auth
byte[] ciphertext = null;
byte[] targetFingerprint = null;
- foreach (byte[] fingerprint in fingerprints)
+ foreach (var fingerprint in fingerprints)
{
ciphertext = RSA.Encrypt(BitConverter.ToString(fingerprint).Replace("-", string.Empty),
- pqInnerData.GetBuffer(), 0, (int)pqInnerData.Position);
+ pqInnerData.GetBuffer(), 0, (int) pqInnerData.Position);
if (ciphertext != null)
{
targetFingerprint = fingerprint;
@@ -57,14 +57,13 @@ namespace TLSharp.Core.Auth
}
if (ciphertext == null)
- {
throw new InvalidOperationException(
- String.Format("not found valid key for fingerprints: {0}", String.Join(", ", fingerprints)));
- }
+ string.Format("not found valid key for fingerprints: {0}",
+ string.Join(", ", fingerprints)));
- using (MemoryStream reqDHParams = new MemoryStream(1024))
+ using (var reqDHParams = new MemoryStream(1024))
{
- using (BinaryWriter reqDHParamsWriter = new BinaryWriter(reqDHParams))
+ using (var reqDHParamsWriter = new BinaryWriter(reqDHParams))
{
reqDHParamsWriter.Write(0xd712e4be); // req_dh_params
reqDHParamsWriter.Write(nonce);
@@ -86,24 +85,19 @@ namespace TLSharp.Core.Auth
{
byte[] encryptedAnswer;
- using (MemoryStream responseStream = new MemoryStream(response, false))
+ using (var responseStream = new MemoryStream(response, false))
{
- using (BinaryReader responseReader = new BinaryReader(responseStream))
+ using (var responseReader = new BinaryReader(responseStream))
{
- uint responseCode = responseReader.ReadUInt32();
+ var responseCode = responseReader.ReadUInt32();
if (responseCode == 0x79cb045d)
- {
- // server_DH_params_fail
throw new InvalidOperationException("server_DH_params_fail: TODO");
- }
if (responseCode != 0xd0e8075c)
- {
throw new InvalidOperationException($"invalid response code: {responseCode}");
- }
- byte[] nonceFromServer = responseReader.ReadBytes(16);
+ var nonceFromServer = responseReader.ReadBytes(16);
// TODO:!
/*
@@ -115,7 +109,7 @@ namespace TLSharp.Core.Auth
*/
- byte[] serverNonceFromServer = responseReader.ReadBytes(16);
+ var serverNonceFromServer = responseReader.ReadBytes(16);
// TODO: !
/*
@@ -128,7 +122,7 @@ namespace TLSharp.Core.Auth
encryptedAnswer = Serializers.Bytes.read(responseReader);
- return new Step2_Response()
+ return new Step2_Response
{
EncryptedAnswer = encryptedAnswer,
ServerNonce = serverNonceFromServer,
@@ -139,4 +133,4 @@ namespace TLSharp.Core.Auth
}
}
}
-}
+}
\ No newline at end of file
diff --git a/TLSharp.Core/Auth/Step3_CompleteDHExchange.cs b/TLSharp.Core/Auth/Step3_CompleteDHExchange.cs
index 8ba8f5a..637eba2 100644
--- a/TLSharp.Core/Auth/Step3_CompleteDHExchange.cs
+++ b/TLSharp.Core/Auth/Step3_CompleteDHExchange.cs
@@ -11,7 +11,6 @@ namespace TLSharp.Core.Auth
{
public AuthKey AuthKey { get; set; }
public int TimeOffset { get; set; }
-
}
public class Step3_CompleteDHExchange
@@ -23,8 +22,8 @@ namespace TLSharp.Core.Auth
public byte[] ToBytes(byte[] nonce, byte[] serverNonce, byte[] newNonce, byte[] encryptedAnswer)
{
this.newNonce = newNonce;
- AESKeyData key = AES.GenerateKeyDataFromNonces(serverNonce, newNonce);
- byte[] plaintextAnswer = AES.DecryptAES(key, encryptedAnswer);
+ var key = AES.GenerateKeyDataFromNonces(serverNonce, newNonce);
+ var plaintextAnswer = AES.DecryptAES(key, encryptedAnswer);
// logger.debug("plaintext answer: {0}", BitConverter.ToString(plaintextAnswer));
@@ -32,32 +31,26 @@ namespace TLSharp.Core.Auth
BigInteger dhPrime;
BigInteger ga;
- using (MemoryStream dhInnerData = new MemoryStream(plaintextAnswer))
+ using (var dhInnerData = new MemoryStream(plaintextAnswer))
{
- using (BinaryReader dhInnerDataReader = new BinaryReader(dhInnerData))
+ using (var dhInnerDataReader = new BinaryReader(dhInnerData))
{
- byte[] hashsum = dhInnerDataReader.ReadBytes(20);
- uint code = dhInnerDataReader.ReadUInt32();
+ var hashsum = dhInnerDataReader.ReadBytes(20);
+ var code = dhInnerDataReader.ReadUInt32();
if (code != 0xb5890dba)
- {
throw new InvalidOperationException($"invalid dh_inner_data code: {code}");
- }
// logger.debug("valid code");
- byte[] nonceFromServer1 = dhInnerDataReader.ReadBytes(16);
+ var nonceFromServer1 = dhInnerDataReader.ReadBytes(16);
if (!nonceFromServer1.SequenceEqual(nonce))
- {
throw new InvalidOperationException("invalid nonce in encrypted answer");
- }
// logger.debug("valid nonce");
- byte[] serverNonceFromServer1 = dhInnerDataReader.ReadBytes(16);
+ var serverNonceFromServer1 = dhInnerDataReader.ReadBytes(16);
if (!serverNonceFromServer1.SequenceEqual(serverNonce))
- {
throw new InvalidOperationException("invalid server nonce in encrypted answer");
- }
// logger.debug("valid server nonce");
@@ -65,39 +58,43 @@ namespace TLSharp.Core.Auth
dhPrime = new BigInteger(1, Serializers.Bytes.read(dhInnerDataReader));
ga = new BigInteger(1, Serializers.Bytes.read(dhInnerDataReader));
- int serverTime = dhInnerDataReader.ReadInt32();
- timeOffset = serverTime - (int)(Convert.ToInt64((DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalMilliseconds) / 1000);
+ var serverTime = dhInnerDataReader.ReadInt32();
+ timeOffset = serverTime -
+ (int) (Convert.ToInt64((DateTime.UtcNow - new DateTime(1970, 1, 1))
+ .TotalMilliseconds) / 1000);
// logger.debug("g: {0}, dhprime: {1}, ga: {2}", g, dhPrime, ga);
}
}
- BigInteger b = new BigInteger(2048, new Random());
- BigInteger gb = BigInteger.ValueOf(g).ModPow(b, dhPrime);
+ var b = new BigInteger(2048, new Random());
+ var gb = BigInteger.ValueOf(g).ModPow(b, dhPrime);
_gab = ga.ModPow(b, dhPrime);
// logger.debug("gab: {0}", gab);
// prepare client dh inner data
byte[] clientDHInnerDataBytes;
- using (MemoryStream clientDhInnerData = new MemoryStream())
+ using (var clientDhInnerData = new MemoryStream())
{
- using (BinaryWriter clientDhInnerDataWriter = new BinaryWriter(clientDhInnerData))
+ using (var clientDhInnerDataWriter = new BinaryWriter(clientDhInnerData))
{
clientDhInnerDataWriter.Write(0x6643b654); // client_dh_inner_data
clientDhInnerDataWriter.Write(nonce);
clientDhInnerDataWriter.Write(serverNonce);
- clientDhInnerDataWriter.Write((long)0); // TODO: retry_id
+ clientDhInnerDataWriter.Write((long) 0); // TODO: retry_id
Serializers.Bytes.write(clientDhInnerDataWriter, gb.ToByteArrayUnsigned());
- using (MemoryStream clientDhInnerDataWithHash = new MemoryStream())
+ using (var clientDhInnerDataWithHash = new MemoryStream())
{
- using (BinaryWriter clientDhInnerDataWithHashWriter = new BinaryWriter(clientDhInnerDataWithHash))
+ using (var clientDhInnerDataWithHashWriter = new BinaryWriter(clientDhInnerDataWithHash))
{
using (SHA1 sha1 = new SHA1Managed())
{
- clientDhInnerDataWithHashWriter.Write(sha1.ComputeHash(clientDhInnerData.GetBuffer(), 0, (int)clientDhInnerData.Position));
- clientDhInnerDataWithHashWriter.Write(clientDhInnerData.GetBuffer(), 0, (int)clientDhInnerData.Position);
+ clientDhInnerDataWithHashWriter.Write(sha1.ComputeHash(clientDhInnerData.GetBuffer(), 0,
+ (int) clientDhInnerData.Position));
+ clientDhInnerDataWithHashWriter.Write(clientDhInnerData.GetBuffer(), 0,
+ (int) clientDhInnerData.Position);
clientDHInnerDataBytes = clientDhInnerDataWithHash.ToArray();
}
}
@@ -108,15 +105,15 @@ namespace TLSharp.Core.Auth
// logger.debug("client dh inner data papared len {0}: {1}", clientDHInnerDataBytes.Length, BitConverter.ToString(clientDHInnerDataBytes).Replace("-", ""));
// encryption
- byte[] clientDhInnerDataEncryptedBytes = AES.EncryptAES(key, clientDHInnerDataBytes);
+ var clientDhInnerDataEncryptedBytes = AES.EncryptAES(key, clientDHInnerDataBytes);
// logger.debug("inner data encrypted {0}: {1}", clientDhInnerDataEncryptedBytes.Length, BitConverter.ToString(clientDhInnerDataEncryptedBytes).Replace("-", ""));
// prepare set_client_dh_params
byte[] setclientDhParamsBytes;
- using (MemoryStream setClientDhParams = new MemoryStream())
+ using (var setClientDhParams = new MemoryStream())
{
- using (BinaryWriter setClientDhParamsWriter = new BinaryWriter(setClientDhParams))
+ using (var setClientDhParamsWriter = new BinaryWriter(setClientDhParams))
{
setClientDhParamsWriter.Write(0xf5045f1f);
setClientDhParamsWriter.Write(nonce);
@@ -134,17 +131,18 @@ namespace TLSharp.Core.Auth
public Step3_Response FromBytes(byte[] response)
{
- using (MemoryStream responseStream = new MemoryStream(response))
+ using (var responseStream = new MemoryStream(response))
{
- using (BinaryReader responseReader = new BinaryReader(responseStream))
+ using (var responseReader = new BinaryReader(responseStream))
{
- uint code = responseReader.ReadUInt32();
+ var code = responseReader.ReadUInt32();
if (code == 0x3bcbf734)
- { // dh_gen_ok
- //logger.debug("dh_gen_ok");
+ {
+ // dh_gen_ok
+ //logger.debug("dh_gen_ok");
- byte[] nonceFromServer = responseReader.ReadBytes(16);
+ var nonceFromServer = responseReader.ReadBytes(16);
// TODO
/*
if (!nonceFromServer.SequenceEqual(nonce))
@@ -154,7 +152,7 @@ namespace TLSharp.Core.Auth
}
*/
- byte[] serverNonceFromServer = responseReader.ReadBytes(16);
+ var serverNonceFromServer = responseReader.ReadBytes(16);
// TODO:
@@ -166,44 +164,33 @@ namespace TLSharp.Core.Auth
}
*/
- byte[] newNonceHash1 = responseReader.ReadBytes(16);
+ var newNonceHash1 = responseReader.ReadBytes(16);
//logger.debug("new nonce hash 1: {0}", BitConverter.ToString(newNonceHash1));
- AuthKey authKey = new AuthKey(_gab);
+ var authKey = new AuthKey(_gab);
- byte[] newNonceHashCalculated = authKey.CalcNewNonceHash(newNonce, 1);
+ var newNonceHashCalculated = authKey.CalcNewNonceHash(newNonce, 1);
if (!newNonceHash1.SequenceEqual(newNonceHashCalculated))
- {
throw new InvalidOperationException("invalid new nonce hash");
- }
//logger.info("generated new auth key: {0}", gab);
//logger.info("saving time offset: {0}", timeOffset);
//TelegramSession.Instance.TimeOffset = timeOffset;
- return new Step3_Response()
+ return new Step3_Response
{
AuthKey = authKey,
TimeOffset = timeOffset
};
}
- else if (code == 0x46dc1fb9)
- { // dh_gen_retry
+ if (code == 0x46dc1fb9)
throw new NotImplementedException("dh_gen_retry");
-
- }
- else if (code == 0xa69dae02)
- {
- // dh_gen_fail
+ if (code == 0xa69dae02)
throw new NotImplementedException("dh_gen_fail");
- }
- else
- {
- throw new InvalidOperationException($"dh_gen unknown: {code}");
- }
+ throw new InvalidOperationException($"dh_gen unknown: {code}");
}
}
}
}
-}
+}
\ No newline at end of file
diff --git a/TLSharp.Core/MTProto/Crypto/AES.cs b/TLSharp.Core/MTProto/Crypto/AES.cs
index 0efc746..3020376 100644
--- a/TLSharp.Core/MTProto/Crypto/AES.cs
+++ b/TLSharp.Core/MTProto/Crypto/AES.cs
@@ -6,24 +6,15 @@ namespace TLSharp.Core.MTProto.Crypto
{
public class AESKeyData
{
- private readonly byte[] key;
- private readonly byte[] iv;
-
public AESKeyData(byte[] key, byte[] iv)
{
- this.key = key;
- this.iv = iv;
+ Key = key;
+ Iv = iv;
}
- public byte[] Key
- {
- get { return key; }
- }
+ public byte[] Key { get; }
- public byte[] Iv
- {
- get { return iv; }
- }
+ public byte[] Iv { get; }
}
public class AES
@@ -36,16 +27,16 @@ namespace TLSharp.Core.MTProto.Crypto
newNonce.CopyTo(nonces, 0);
serverNonce.CopyTo(nonces, 32);
- byte[] hash1 = hash.ComputeHash(nonces);
+ var hash1 = hash.ComputeHash(nonces);
serverNonce.CopyTo(nonces, 0);
newNonce.CopyTo(nonces, 16);
- byte[] hash2 = hash.ComputeHash(nonces);
+ var hash2 = hash.ComputeHash(nonces);
nonces = new byte[64];
newNonce.CopyTo(nonces, 0);
newNonce.CopyTo(nonces, 32);
- byte[] hash3 = hash.ComputeHash(nonces);
+ var hash3 = hash.ComputeHash(nonces);
using (var keyBuffer = new MemoryStream(32))
using (var ivBuffer = new MemoryStream(32))
@@ -70,16 +61,16 @@ namespace TLSharp.Core.MTProto.Crypto
newNonce.CopyTo(nonces, 0);
serverNonce.CopyTo(nonces, 32);
- byte[] hash1 = hash.ComputeHash(nonces);
+ var hash1 = hash.ComputeHash(nonces);
serverNonce.CopyTo(nonces, 0);
newNonce.CopyTo(nonces, 16);
- byte[] hash2 = hash.ComputeHash(nonces);
+ var hash2 = hash.ComputeHash(nonces);
nonces = new byte[64];
newNonce.CopyTo(nonces, 0);
newNonce.CopyTo(nonces, 32);
- byte[] hash3 = hash.ComputeHash(nonces);
+ var hash3 = hash.ComputeHash(nonces);
using (var keyBuffer = new MemoryStream(32))
using (var ivBuffer = new MemoryStream(32))
@@ -114,27 +105,23 @@ namespace TLSharp.Core.MTProto.Crypto
Array.Copy(iv, 0, iv1, 0, iv1.Length);
Array.Copy(iv, iv1.Length, iv2, 0, iv2.Length);
- AesEngine aes = new AesEngine();
+ var aes = new AesEngine();
aes.Init(false, key);
- byte[] plaintext = new byte[ciphertext.Length];
- int blocksCount = ciphertext.Length / 16;
+ var plaintext = new byte[ciphertext.Length];
+ var blocksCount = ciphertext.Length / 16;
- byte[] ciphertextBlock = new byte[16];
- byte[] plaintextBlock = new byte[16];
- for (int blockIndex = 0; blockIndex < blocksCount; blockIndex++)
+ var ciphertextBlock = new byte[16];
+ var plaintextBlock = new byte[16];
+ for (var blockIndex = 0; blockIndex < blocksCount; blockIndex++)
{
- for (int i = 0; i < 16; i++)
- {
- ciphertextBlock[i] = (byte)(ciphertext[blockIndex * 16 + i] ^ iv2[i]);
- }
+ for (var i = 0; i < 16; i++)
+ ciphertextBlock[i] = (byte) (ciphertext[blockIndex * 16 + i] ^ iv2[i]);
aes.ProcessBlock(ciphertextBlock, 0, plaintextBlock, 0);
- for (int i = 0; i < 16; i++)
- {
+ for (var i = 0; i < 16; i++)
plaintextBlock[i] ^= iv1[i];
- }
Array.Copy(ciphertext, blockIndex * 16, iv1, 0, 16);
Array.Copy(plaintextBlock, 0, iv2, 0, 16);
@@ -147,18 +134,15 @@ namespace TLSharp.Core.MTProto.Crypto
public static byte[] EncryptIGE(byte[] originPlaintext, byte[] key, byte[] iv)
{
-
byte[] plaintext;
- using (MemoryStream plaintextBuffer = new MemoryStream(originPlaintext.Length + 40))
+ using (var plaintextBuffer = new MemoryStream(originPlaintext.Length + 40))
{
//using(SHA1 hash = new SHA1Managed()) {
//byte[] hashsum = hash.ComputeHash(originPlaintext);
//plaintextBuffer.Write(hashsum, 0, hashsum.Length);
plaintextBuffer.Write(originPlaintext, 0, originPlaintext.Length);
while (plaintextBuffer.Position % 16 != 0)
- {
plaintextBuffer.WriteByte(0); // TODO: random padding
- }
plaintext = plaintextBuffer.ToArray();
}
@@ -168,24 +152,22 @@ namespace TLSharp.Core.MTProto.Crypto
Array.Copy(iv, 0, iv1, 0, iv1.Length);
Array.Copy(iv, iv1.Length, iv2, 0, iv2.Length);
- AesEngine aes = new AesEngine();
+ var aes = new AesEngine();
aes.Init(true, key);
- int blocksCount = plaintext.Length / 16;
- byte[] ciphertext = new byte[plaintext.Length];
+ var blocksCount = plaintext.Length / 16;
+ var ciphertext = new byte[plaintext.Length];
- byte[] ciphertextBlock = new byte[16];
- byte[] plaintextBlock = new byte[16];
- for (int blockIndex = 0; blockIndex < blocksCount; blockIndex++)
+ var ciphertextBlock = new byte[16];
+ var plaintextBlock = new byte[16];
+ for (var blockIndex = 0; blockIndex < blocksCount; blockIndex++)
{
Array.Copy(plaintext, 16 * blockIndex, plaintextBlock, 0, 16);
//logger.info("plaintext block: {0} xor {1}", BitConverter.ToString(plaintextBlock).Replace("-", ""), BitConverter.ToString(iv1).Replace("-", ""));
- for (int i = 0; i < 16; i++)
- {
+ for (var i = 0; i < 16; i++)
plaintextBlock[i] ^= iv1[i];
- }
//logger.info("xored plaintext: {0}", BitConverter.ToString(plaintextBlock).Replace("-", ""));
@@ -193,10 +175,8 @@ namespace TLSharp.Core.MTProto.Crypto
//logger.info("encrypted plaintext: {0} xor {1}", BitConverter.ToString(ciphertextBlock).Replace("-", ""), BitConverter.ToString(iv2).Replace("-", ""));
- for (int i = 0; i < 16; i++)
- {
+ for (var i = 0; i < 16; i++)
ciphertextBlock[i] ^= iv2[i];
- }
//logger.info("xored ciphertext: {0}", BitConverter.ToString(ciphertextBlock).Replace("-", ""));
@@ -212,12 +192,10 @@ namespace TLSharp.Core.MTProto.Crypto
public static byte[] XOR(byte[] buffer1, byte[] buffer2)
{
var result = new byte[buffer1.Length];
- for (int i = 0; i < buffer1.Length; i++)
- result[i] = (byte)(buffer1[i] ^ buffer2[i]);
+ for (var i = 0; i < buffer1.Length; i++)
+ result[i] = (byte) (buffer1[i] ^ buffer2[i]);
return result;
}
-
-
}
@@ -227,11 +205,13 @@ namespace TLSharp.Core.MTProto.Crypto
{
// The S box
private const uint m1 = 0x80808080;
+
private const uint m2 = 0x7f7f7f7f;
private const uint m3 = 0x0000001b;
private const int BLOCK_SIZE = 16;
- private static readonly byte[] S = {
+ private static readonly byte[] S =
+ {
99, 124, 119, 123, 242, 107, 111, 197,
48, 1, 103, 43, 254, 215, 171, 118,
202, 130, 201, 125, 250, 89, 71, 240,
@@ -267,7 +247,8 @@ namespace TLSharp.Core.MTProto.Crypto
};
// The inverse S-box
- private static readonly byte[] Si = {
+ private static readonly byte[] Si =
+ {
82, 9, 106, 213, 48, 54, 165, 56,
191, 64, 163, 158, 129, 243, 215, 251,
124, 227, 57, 130, 155, 47, 255, 135,
@@ -303,13 +284,15 @@ namespace TLSharp.Core.MTProto.Crypto
};
// vector used in calculating key schedule (powers of x in GF(256))
- private static readonly byte[] rcon = {
+ private static readonly byte[] rcon =
+ {
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91
};
// precomputation tables of calculations for rounds
- private static readonly uint[] T0 = {
+ private static readonly uint[] T0 =
+ {
0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 0x0df2f2ff,
0xbd6b6bd6, 0xb16f6fde, 0x54c5c591, 0x50303060, 0x03010102,
0xa96767ce, 0x7d2b2b56, 0x19fefee7, 0x62d7d7b5, 0xe6abab4d,
@@ -364,7 +347,8 @@ namespace TLSharp.Core.MTProto.Crypto
0x3a16162c
};
- private static readonly uint[] Tinv0 = {
+ private static readonly uint[] Tinv0 =
+ {
0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a, 0xcb6bab3b,
0xf1459d1f, 0xab58faac, 0x9303e34b, 0x55fa3020, 0xf66d76ad,
0x9176cc88, 0x254c02f5, 0xfcd7e54f, 0xd7cb2ac5, 0x80443526,
@@ -420,19 +404,13 @@ namespace TLSharp.Core.MTProto.Crypto
};
private uint C0, C1, C2, C3;
+ private bool forEncryption;
private int ROUNDS;
private uint[,] WorkingKey;
- private bool forEncryption;
- public string AlgorithmName
- {
- get { return "AES"; }
- }
+ public string AlgorithmName => "AES";
- public bool IsPartialBlockOkay
- {
- get { return false; }
- }
+ public bool IsPartialBlockOkay => false;
private uint Shift(
uint r,
@@ -460,10 +438,10 @@ namespace TLSharp.Core.MTProto.Crypto
private uint Inv_Mcol(
uint x)
{
- uint f2 = FFmulX(x);
- uint f4 = FFmulX(f2);
- uint f8 = FFmulX(f4);
- uint f9 = x ^ f8;
+ var f2 = FFmulX(x);
+ var f4 = FFmulX(f2);
+ var f8 = FFmulX(f4);
+ var f9 = x ^ f8;
return f2 ^ f4 ^ f8 ^ Shift(f2 ^ f9, 8) ^ Shift(f4 ^ f9, 16) ^ Shift(f9, 24);
}
@@ -472,9 +450,9 @@ namespace TLSharp.Core.MTProto.Crypto
uint x)
{
return S[x & 255]
- | (((uint)S[(x >> 8) & 255]) << 8)
- | (((uint)S[(x >> 16) & 255]) << 16)
- | (((uint)S[(x >> 24) & 255]) << 24);
+ | ((uint) S[(x >> 8) & 255] << 8)
+ | ((uint) S[(x >> 16) & 255] << 16)
+ | ((uint) S[(x >> 24) & 255] << 24);
}
/**
@@ -488,10 +466,10 @@ namespace TLSharp.Core.MTProto.Crypto
byte[] key,
bool forEncryption)
{
- int KC = key.Length / 4; // key length in words
+ var KC = key.Length / 4; // key length in words
int t;
- if ((KC != 4) && (KC != 6) && (KC != 8))
+ if (KC != 4 && KC != 6 && KC != 8)
throw new ArgumentException("Key length not 128/192/256 bits.");
ROUNDS = KC + 6; // This is not always true for the generalized Rijndael that allows larger block sizes
@@ -502,7 +480,7 @@ namespace TLSharp.Core.MTProto.Crypto
//
t = 0;
- for (int i = 0; i < key.Length; t++)
+ for (var i = 0; i < key.Length; t++)
{
W[t >> 2, t & 3] = Pack.LE_To_UInt32(key, i);
i += 4;
@@ -512,32 +490,22 @@ namespace TLSharp.Core.MTProto.Crypto
// while not enough round key material calculated
// calculate new values
//
- int k = (ROUNDS + 1) << 2;
- for (int i = KC; (i < k); i++)
+ var k = (ROUNDS + 1) << 2;
+ for (var i = KC; i < k; i++)
{
- uint temp = W[(i - 1) >> 2, (i - 1) & 3];
- if ((i % KC) == 0)
- {
- temp = SubWord(Shift(temp, 8)) ^ rcon[(i / KC) - 1];
- }
- else if ((KC > 6) && ((i % KC) == 4))
- {
+ var temp = W[(i - 1) >> 2, (i - 1) & 3];
+ if (i % KC == 0)
+ temp = SubWord(Shift(temp, 8)) ^ rcon[i / KC - 1];
+ else if (KC > 6 && i % KC == 4)
temp = SubWord(temp);
- }
W[i >> 2, i & 3] = W[(i - KC) >> 2, (i - KC) & 3] ^ temp;
}
if (!forEncryption)
- {
- for (int j = 1; j < ROUNDS; j++)
- {
- for (int i = 0; i < 4; i++)
- {
- W[j, i] = Inv_Mcol(W[j, i]);
- }
- }
- }
+ for (var j = 1; j < ROUNDS; j++)
+ for (var i = 0; i < 4; i++)
+ W[j, i] = Inv_Mcol(W[j, i]);
return W;
}
@@ -556,29 +524,19 @@ namespace TLSharp.Core.MTProto.Crypto
public int ProcessBlock(byte[] input, int inOff, byte[] output, int outOff)
{
if (WorkingKey == null)
- {
throw new InvalidOperationException("AES engine not initialised");
- }
- if ((inOff + (32 / 2)) > input.Length)
- {
+ if (inOff + 32 / 2 > input.Length)
throw new InvalidOperationException("input buffer too short");
- }
- if ((outOff + (32 / 2)) > output.Length)
- {
+ if (outOff + 32 / 2 > output.Length)
throw new InvalidOperationException("output buffer too short");
- }
UnPackBlock(input, inOff);
if (forEncryption)
- {
EncryptBlock(WorkingKey);
- }
- else {
- DecryptBlock(WorkingKey);
- }
+ else DecryptBlock(WorkingKey);
PackBlock(output, outOff);
@@ -650,14 +608,14 @@ namespace TLSharp.Core.MTProto.Crypto
// the final round's table is a simple function of S so we don't use a whole other four tables for it
- C0 = S[r0 & 255] ^ (((uint)S[(r1 >> 8) & 255]) << 8) ^ (((uint)S[(r2 >> 16) & 255]) << 16) ^
- (((uint)S[(r3 >> 24) & 255]) << 24) ^ KW[r, 0];
- C1 = S[r1 & 255] ^ (((uint)S[(r2 >> 8) & 255]) << 8) ^ (((uint)S[(r3 >> 16) & 255]) << 16) ^
- (((uint)S[(r0 >> 24) & 255]) << 24) ^ KW[r, 1];
- C2 = S[r2 & 255] ^ (((uint)S[(r3 >> 8) & 255]) << 8) ^ (((uint)S[(r0 >> 16) & 255]) << 16) ^
- (((uint)S[(r1 >> 24) & 255]) << 24) ^ KW[r, 2];
- C3 = S[r3 & 255] ^ (((uint)S[(r0 >> 8) & 255]) << 8) ^ (((uint)S[(r1 >> 16) & 255]) << 16) ^
- (((uint)S[(r2 >> 24) & 255]) << 24) ^ KW[r, 3];
+ C0 = S[r0 & 255] ^ ((uint) S[(r1 >> 8) & 255] << 8) ^ ((uint) S[(r2 >> 16) & 255] << 16) ^
+ ((uint) S[(r3 >> 24) & 255] << 24) ^ KW[r, 0];
+ C1 = S[r1 & 255] ^ ((uint) S[(r2 >> 8) & 255] << 8) ^ ((uint) S[(r3 >> 16) & 255] << 16) ^
+ ((uint) S[(r0 >> 24) & 255] << 24) ^ KW[r, 1];
+ C2 = S[r2 & 255] ^ ((uint) S[(r3 >> 8) & 255] << 8) ^ ((uint) S[(r0 >> 16) & 255] << 16) ^
+ ((uint) S[(r1 >> 24) & 255] << 24) ^ KW[r, 2];
+ C3 = S[r3 & 255] ^ ((uint) S[(r0 >> 8) & 255] << 8) ^ ((uint) S[(r1 >> 16) & 255] << 16) ^
+ ((uint) S[(r2 >> 24) & 255] << 24) ^ KW[r, 3];
}
private void DecryptBlock(
@@ -702,14 +660,14 @@ namespace TLSharp.Core.MTProto.Crypto
// the final round's table is a simple function of Si so we don't use a whole other four tables for it
- C0 = Si[r0 & 255] ^ (((uint)Si[(r3 >> 8) & 255]) << 8) ^ (((uint)Si[(r2 >> 16) & 255]) << 16) ^
- (((uint)Si[(r1 >> 24) & 255]) << 24) ^ KW[0, 0];
- C1 = Si[r1 & 255] ^ (((uint)Si[(r0 >> 8) & 255]) << 8) ^ (((uint)Si[(r3 >> 16) & 255]) << 16) ^
- (((uint)Si[(r2 >> 24) & 255]) << 24) ^ KW[0, 1];
- C2 = Si[r2 & 255] ^ (((uint)Si[(r1 >> 8) & 255]) << 8) ^ (((uint)Si[(r0 >> 16) & 255]) << 16) ^
- (((uint)Si[(r3 >> 24) & 255]) << 24) ^ KW[0, 2];
- C3 = Si[r3 & 255] ^ (((uint)Si[(r2 >> 8) & 255]) << 8) ^ (((uint)Si[(r1 >> 16) & 255]) << 16) ^
- (((uint)Si[(r0 >> 24) & 255]) << 24) ^ KW[0, 3];
+ C0 = Si[r0 & 255] ^ ((uint) Si[(r3 >> 8) & 255] << 8) ^ ((uint) Si[(r2 >> 16) & 255] << 16) ^
+ ((uint) Si[(r1 >> 24) & 255] << 24) ^ KW[0, 0];
+ C1 = Si[r1 & 255] ^ ((uint) Si[(r0 >> 8) & 255] << 8) ^ ((uint) Si[(r3 >> 16) & 255] << 16) ^
+ ((uint) Si[(r2 >> 24) & 255] << 24) ^ KW[0, 1];
+ C2 = Si[r2 & 255] ^ ((uint) Si[(r1 >> 8) & 255] << 8) ^ ((uint) Si[(r0 >> 16) & 255] << 16) ^
+ ((uint) Si[(r3 >> 24) & 255] << 24) ^ KW[0, 2];
+ C3 = Si[r3 & 255] ^ ((uint) Si[(r2 >> 8) & 255] << 8) ^ ((uint) Si[(r1 >> 16) & 255] << 16) ^
+ ((uint) Si[(r0 >> 24) & 255] << 24) ^ KW[0, 3];
}
}
@@ -722,122 +680,122 @@ namespace TLSharp.Core.MTProto.Crypto
internal static void UInt32_To_BE(uint n, byte[] bs)
{
- bs[0] = (byte)(n >> 24);
- bs[1] = (byte)(n >> 16);
- bs[2] = (byte)(n >> 8);
- bs[3] = (byte)(n);
+ bs[0] = (byte) (n >> 24);
+ bs[1] = (byte) (n >> 16);
+ bs[2] = (byte) (n >> 8);
+ bs[3] = (byte) n;
}
internal static void UInt32_To_BE(uint n, byte[] bs, int off)
{
- bs[off] = (byte)(n >> 24);
- bs[++off] = (byte)(n >> 16);
- bs[++off] = (byte)(n >> 8);
- bs[++off] = (byte)(n);
+ bs[off] = (byte) (n >> 24);
+ bs[++off] = (byte) (n >> 16);
+ bs[++off] = (byte) (n >> 8);
+ bs[++off] = (byte) n;
}
internal static uint BE_To_UInt32(byte[] bs)
{
- uint n = (uint)bs[0] << 24;
- n |= (uint)bs[1] << 16;
- n |= (uint)bs[2] << 8;
+ var n = (uint) bs[0] << 24;
+ n |= (uint) bs[1] << 16;
+ n |= (uint) bs[2] << 8;
n |= bs[3];
return n;
}
internal static uint BE_To_UInt32(byte[] bs, int off)
{
- uint n = (uint)bs[off] << 24;
- n |= (uint)bs[++off] << 16;
- n |= (uint)bs[++off] << 8;
+ var n = (uint) bs[off] << 24;
+ n |= (uint) bs[++off] << 16;
+ n |= (uint) bs[++off] << 8;
n |= bs[++off];
return n;
}
internal static ulong BE_To_UInt64(byte[] bs)
{
- uint hi = BE_To_UInt32(bs);
- uint lo = BE_To_UInt32(bs, 4);
- return ((ulong)hi << 32) | lo;
+ var hi = BE_To_UInt32(bs);
+ var lo = BE_To_UInt32(bs, 4);
+ return ((ulong) hi << 32) | lo;
}
internal static ulong BE_To_UInt64(byte[] bs, int off)
{
- uint hi = BE_To_UInt32(bs, off);
- uint lo = BE_To_UInt32(bs, off + 4);
- return ((ulong)hi << 32) | lo;
+ var hi = BE_To_UInt32(bs, off);
+ var lo = BE_To_UInt32(bs, off + 4);
+ return ((ulong) hi << 32) | lo;
}
internal static void UInt64_To_BE(ulong n, byte[] bs)
{
- UInt32_To_BE((uint)(n >> 32), bs);
- UInt32_To_BE((uint)(n), bs, 4);
+ UInt32_To_BE((uint) (n >> 32), bs);
+ UInt32_To_BE((uint) n, bs, 4);
}
internal static void UInt64_To_BE(ulong n, byte[] bs, int off)
{
- UInt32_To_BE((uint)(n >> 32), bs, off);
- UInt32_To_BE((uint)(n), bs, off + 4);
+ UInt32_To_BE((uint) (n >> 32), bs, off);
+ UInt32_To_BE((uint) n, bs, off + 4);
}
internal static void UInt32_To_LE(uint n, byte[] bs)
{
- bs[0] = (byte)(n);
- bs[1] = (byte)(n >> 8);
- bs[2] = (byte)(n >> 16);
- bs[3] = (byte)(n >> 24);
+ bs[0] = (byte) n;
+ bs[1] = (byte) (n >> 8);
+ bs[2] = (byte) (n >> 16);
+ bs[3] = (byte) (n >> 24);
}
internal static void UInt32_To_LE(uint n, byte[] bs, int off)
{
- bs[off] = (byte)(n);
- bs[++off] = (byte)(n >> 8);
- bs[++off] = (byte)(n >> 16);
- bs[++off] = (byte)(n >> 24);
+ bs[off] = (byte) n;
+ bs[++off] = (byte) (n >> 8);
+ bs[++off] = (byte) (n >> 16);
+ bs[++off] = (byte) (n >> 24);
}
internal static uint LE_To_UInt32(byte[] bs)
{
uint n = bs[0];
- n |= (uint)bs[1] << 8;
- n |= (uint)bs[2] << 16;
- n |= (uint)bs[3] << 24;
+ n |= (uint) bs[1] << 8;
+ n |= (uint) bs[2] << 16;
+ n |= (uint) bs[3] << 24;
return n;
}
internal static uint LE_To_UInt32(byte[] bs, int off)
{
uint n = bs[off];
- n |= (uint)bs[++off] << 8;
- n |= (uint)bs[++off] << 16;
- n |= (uint)bs[++off] << 24;
+ n |= (uint) bs[++off] << 8;
+ n |= (uint) bs[++off] << 16;
+ n |= (uint) bs[++off] << 24;
return n;
}
internal static ulong LE_To_UInt64(byte[] bs)
{
- uint lo = LE_To_UInt32(bs);
- uint hi = LE_To_UInt32(bs, 4);
- return ((ulong)hi << 32) | lo;
+ var lo = LE_To_UInt32(bs);
+ var hi = LE_To_UInt32(bs, 4);
+ return ((ulong) hi << 32) | lo;
}
internal static ulong LE_To_UInt64(byte[] bs, int off)
{
- uint lo = LE_To_UInt32(bs, off);
- uint hi = LE_To_UInt32(bs, off + 4);
- return ((ulong)hi << 32) | lo;
+ var lo = LE_To_UInt32(bs, off);
+ var hi = LE_To_UInt32(bs, off + 4);
+ return ((ulong) hi << 32) | lo;
}
internal static void UInt64_To_LE(ulong n, byte[] bs)
{
- UInt32_To_LE((uint)(n), bs);
- UInt32_To_LE((uint)(n >> 32), bs, 4);
+ UInt32_To_LE((uint) n, bs);
+ UInt32_To_LE((uint) (n >> 32), bs, 4);
}
internal static void UInt64_To_LE(ulong n, byte[] bs, int off)
{
- UInt32_To_LE((uint)(n), bs, off);
- UInt32_To_LE((uint)(n >> 32), bs, off + 4);
+ UInt32_To_LE((uint) n, bs, off);
+ UInt32_To_LE((uint) (n >> 32), bs, off + 4);
}
}
}
\ No newline at end of file
diff --git a/TLSharp.Core/MTProto/Crypto/AuthKey.cs b/TLSharp.Core/MTProto/Crypto/AuthKey.cs
index 7d568c4..aab5019 100644
--- a/TLSharp.Core/MTProto/Crypto/AuthKey.cs
+++ b/TLSharp.Core/MTProto/Crypto/AuthKey.cs
@@ -6,21 +6,20 @@ namespace TLSharp.Core.MTProto.Crypto
{
public class AuthKey
{
- private byte[] key;
- private ulong keyId;
- private ulong auxHash;
+ private readonly ulong auxHash;
+
public AuthKey(BigInteger gab)
{
- key = gab.ToByteArrayUnsigned();
+ Data = gab.ToByteArrayUnsigned();
using (SHA1 hash = new SHA1Managed())
{
- using (MemoryStream hashStream = new MemoryStream(hash.ComputeHash(key), false))
+ using (var hashStream = new MemoryStream(hash.ComputeHash(Data), false))
{
- using (BinaryReader hashReader = new BinaryReader(hashStream))
+ using (var hashReader = new BinaryReader(hashStream))
{
auxHash = hashReader.ReadUInt64();
hashReader.ReadBytes(4);
- keyId = hashReader.ReadUInt64();
+ Id = hashReader.ReadUInt64();
}
}
}
@@ -28,34 +27,38 @@ namespace TLSharp.Core.MTProto.Crypto
public AuthKey(byte[] data)
{
- key = data;
+ Data = data;
using (SHA1 hash = new SHA1Managed())
{
- using (MemoryStream hashStream = new MemoryStream(hash.ComputeHash(key), false))
+ using (var hashStream = new MemoryStream(hash.ComputeHash(Data), false))
{
- using (BinaryReader hashReader = new BinaryReader(hashStream))
+ using (var hashReader = new BinaryReader(hashStream))
{
auxHash = hashReader.ReadUInt64();
hashReader.ReadBytes(4);
- keyId = hashReader.ReadUInt64();
+ Id = hashReader.ReadUInt64();
}
}
}
}
+ public byte[] Data { get; }
+
+ public ulong Id { get; }
+
public byte[] CalcNewNonceHash(byte[] newNonce, int number)
{
- using (MemoryStream buffer = new MemoryStream(100))
+ using (var buffer = new MemoryStream(100))
{
- using (BinaryWriter bufferWriter = new BinaryWriter(buffer))
+ using (var bufferWriter = new BinaryWriter(buffer))
{
bufferWriter.Write(newNonce);
- bufferWriter.Write((byte)number);
+ bufferWriter.Write((byte) number);
bufferWriter.Write(auxHash);
using (SHA1 sha1 = new SHA1Managed())
{
- byte[] hash = sha1.ComputeHash(buffer.GetBuffer(), 0, (int)buffer.Position);
- byte[] newNonceHash = new byte[16];
+ var hash = sha1.ComputeHash(buffer.GetBuffer(), 0, (int) buffer.Position);
+ var newNonceHash = new byte[16];
Array.Copy(hash, 4, newNonceHash, 0, 16);
return newNonceHash;
}
@@ -63,25 +66,9 @@ namespace TLSharp.Core.MTProto.Crypto
}
}
- public byte[] Data
- {
- get
- {
- return key;
- }
- }
-
- public ulong Id
- {
- get
- {
- return keyId;
- }
- }
-
public override string ToString()
{
- return string.Format("(Key: {0}, KeyId: {1}, AuxHash: {2})", key, keyId, auxHash);
+ return string.Format("(Key: {0}, KeyId: {1}, AuxHash: {2})", Data, Id, auxHash);
}
}
-}
+}
\ No newline at end of file
diff --git a/TLSharp.Core/MTProto/Crypto/BigInteger.cs b/TLSharp.Core/MTProto/Crypto/BigInteger.cs
index e09a3b7..a147275 100644
--- a/TLSharp.Core/MTProto/Crypto/BigInteger.cs
+++ b/TLSharp.Core/MTProto/Crypto/BigInteger.cs
@@ -8,10 +8,17 @@ using System.Text;
namespace TLSharp.Core.MTProto.Crypto
{
#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+
[Serializable]
#endif
public class BigInteger
{
+ private const long IMASK = 0xffffffffL;
+
+ private const int BitsPerByte = 8;
+ private const int BitsPerInt = 32;
+
+ private const int BytesPerInt = 4;
// The primes b/w 2 and ~2^10
/*
3 5 7 11 13 17 19 23 29
@@ -35,76 +42,74 @@ namespace TLSharp.Core.MTProto.Crypto
*/
// Each list has a product < 2^31
- private static readonly int[][] primeLists = new int[][]
+ private static readonly int[][] primeLists =
{
- new int[]{ 3, 5, 7, 11, 13, 17, 19, 23 },
- new int[]{ 29, 31, 37, 41, 43 },
- new int[]{ 47, 53, 59, 61, 67 },
- new int[]{ 71, 73, 79, 83 },
- new int[]{ 89, 97, 101, 103 },
+ new[] {3, 5, 7, 11, 13, 17, 19, 23},
+ new[] {29, 31, 37, 41, 43},
+ new[] {47, 53, 59, 61, 67},
+ new[] {71, 73, 79, 83},
+ new[] {89, 97, 101, 103},
- new int[]{ 107, 109, 113, 127 },
- new int[]{ 131, 137, 139, 149 },
- new int[]{ 151, 157, 163, 167 },
- new int[]{ 173, 179, 181, 191 },
- new int[]{ 193, 197, 199, 211 },
+ new[] {107, 109, 113, 127},
+ new[] {131, 137, 139, 149},
+ new[] {151, 157, 163, 167},
+ new[] {173, 179, 181, 191},
+ new[] {193, 197, 199, 211},
- new int[]{ 223, 227, 229 },
- new int[]{ 233, 239, 241 },
- new int[]{ 251, 257, 263 },
- new int[]{ 269, 271, 277 },
- new int[]{ 281, 283, 293 },
+ new[] {223, 227, 229},
+ new[] {233, 239, 241},
+ new[] {251, 257, 263},
+ new[] {269, 271, 277},
+ new[] {281, 283, 293},
- new int[]{ 307, 311, 313 },
- new int[]{ 317, 331, 337 },
- new int[]{ 347, 349, 353 },
- new int[]{ 359, 367, 373 },
- new int[]{ 379, 383, 389 },
+ new[] {307, 311, 313},
+ new[] {317, 331, 337},
+ new[] {347, 349, 353},
+ new[] {359, 367, 373},
+ new[] {379, 383, 389},
- new int[]{ 397, 401, 409 },
- new int[]{ 419, 421, 431 },
- new int[]{ 433, 439, 443 },
- new int[]{ 449, 457, 461 },
- new int[]{ 463, 467, 479 },
+ new[] {397, 401, 409},
+ new[] {419, 421, 431},
+ new[] {433, 439, 443},
+ new[] {449, 457, 461},
+ new[] {463, 467, 479},
- new int[]{ 487, 491, 499 },
- new int[]{ 503, 509, 521 },
- new int[]{ 523, 541, 547 },
- new int[]{ 557, 563, 569 },
- new int[]{ 571, 577, 587 },
+ new[] {487, 491, 499},
+ new[] {503, 509, 521},
+ new[] {523, 541, 547},
+ new[] {557, 563, 569},
+ new[] {571, 577, 587},
- new int[]{ 593, 599, 601 },
- new int[]{ 607, 613, 617 },
- new int[]{ 619, 631, 641 },
- new int[]{ 643, 647, 653 },
- new int[]{ 659, 661, 673 },
+ new[] {593, 599, 601},
+ new[] {607, 613, 617},
+ new[] {619, 631, 641},
+ new[] {643, 647, 653},
+ new[] {659, 661, 673},
- new int[]{ 677, 683, 691 },
- new int[]{ 701, 709, 719 },
- new int[]{ 727, 733, 739 },
- new int[]{ 743, 751, 757 },
- new int[]{ 761, 769, 773 },
+ new[] {677, 683, 691},
+ new[] {701, 709, 719},
+ new[] {727, 733, 739},
+ new[] {743, 751, 757},
+ new[] {761, 769, 773},
- new int[]{ 787, 797, 809 },
- new int[]{ 811, 821, 823 },
- new int[]{ 827, 829, 839 },
- new int[]{ 853, 857, 859 },
- new int[]{ 863, 877, 881 },
+ new[] {787, 797, 809},
+ new[] {811, 821, 823},
+ new[] {827, 829, 839},
+ new[] {853, 857, 859},
+ new[] {863, 877, 881},
- new int[]{ 883, 887, 907 },
- new int[]{ 911, 919, 929 },
- new int[]{ 937, 941, 947 },
- new int[]{ 953, 967, 971 },
- new int[]{ 977, 983, 991 },
+ new[] {883, 887, 907},
+ new[] {911, 919, 929},
+ new[] {937, 941, 947},
+ new[] {953, 967, 971},
+ new[] {977, 983, 991},
- new int[]{ 997, 1009, 1013 },
- new int[]{ 1019, 1021, 1031 },
+ new[] {997, 1009, 1013},
+ new[] {1019, 1021, 1031}
};
private static readonly int[] primeProducts;
-
- private const long IMASK = 0xffffffffL;
- private static readonly ulong UIMASK = (ulong)IMASK;
+ private static readonly ulong UIMASK = IMASK;
private static readonly int[] ZeroMagnitude = new int[0];
private static readonly byte[] ZeroEncoding = new byte[0];
@@ -129,38 +134,41 @@ namespace TLSharp.Core.MTProto.Crypto
private static readonly Random RandomSource = new Random();
- private const int BitsPerByte = 8;
- private const int BitsPerInt = 32;
- private const int BytesPerInt = 4;
+ private static readonly byte[] rndMask = {255, 127, 63, 31, 15, 7, 3, 1};
+
+ private static readonly byte[] bitCounts =
+ {
+ 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1,
+ 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4,
+ 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3,
+ 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5,
+ 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2,
+ 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3,
+ 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6,
+ 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6,
+ 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5,
+ 6, 6, 7, 6, 7, 7, 8
+ };
+
+ private int[] magnitude; // array of ints with [0] being the most significant
+ private long mQuote = -1L; // -m^(-1) mod b, b = 2^32 (see Montgomery mult.)
+ private int nBitLength = -1; // cache calcBitLength() value
+ private int nBits = -1; // cache BitCount() value
static BigInteger()
{
primeProducts = new int[primeLists.Length];
- for (int i = 0; i < primeLists.Length; ++i)
+ for (var i = 0; i < primeLists.Length; ++i)
{
- int[] primeList = primeLists[i];
- int product = 1;
- for (int j = 0; j < primeList.Length; ++j)
- {
+ var primeList = primeLists[i];
+ var product = 1;
+ for (var j = 0; j < primeList.Length; ++j)
product *= primeList[j];
- }
primeProducts[i] = product;
}
}
- private int sign; // -1 means -ve; +1 means +ve; 0 means 0;
- private int[] magnitude; // array of ints with [0] being the most significant
- private int nBits = -1; // cache BitCount() value
- private int nBitLength = -1; // cache calcBitLength() value
- private long mQuote = -1L; // -m^(-1) mod b, b = 2^32 (see Montgomery mult.)
-
- private static int GetByteLength(
- int nBits)
- {
- return (nBits + BitsPerByte - 1) / BitsPerByte;
- }
-
private BigInteger()
{
}
@@ -172,34 +180,35 @@ namespace TLSharp.Core.MTProto.Crypto
{
if (checkMag)
{
- int i = 0;
+ var i = 0;
while (i < mag.Length && mag[i] == 0)
- {
++i;
- }
if (i == mag.Length)
{
// this.sign = 0;
- this.magnitude = ZeroMagnitude;
+ magnitude = ZeroMagnitude;
}
- else {
- this.sign = signum;
+ else
+ {
+ SignValue = signum;
if (i == 0)
{
- this.magnitude = mag;
+ magnitude = mag;
}
- else {
+ else
+ {
// strip leading 0 words
- this.magnitude = new int[mag.Length - i];
- Array.Copy(mag, i, this.magnitude, 0, this.magnitude.Length);
+ magnitude = new int[mag.Length - i];
+ Array.Copy(mag, i, magnitude, 0, magnitude.Length);
}
}
}
- else {
- this.sign = signum;
- this.magnitude = mag;
+ else
+ {
+ SignValue = signum;
+ magnitude = mag;
}
}
@@ -249,28 +258,26 @@ namespace TLSharp.Core.MTProto.Crypto
}
- int index = 0;
- sign = 1;
+ var index = 0;
+ SignValue = 1;
if (str[0] == '-')
{
if (str.Length == 1)
throw new FormatException("Zero length BigInteger");
- sign = -1;
+ SignValue = -1;
index = 1;
}
// strip leading zeros from the string str
- while (index < str.Length && Int32.Parse(str[index].ToString(), style) == 0)
- {
+ while (index < str.Length && int.Parse(str[index].ToString(), style) == 0)
index++;
- }
if (index >= str.Length)
{
// zero value - we're done
- sign = 0;
+ SignValue = 0;
magnitude = ZeroMagnitude;
return;
}
@@ -281,18 +288,17 @@ namespace TLSharp.Core.MTProto.Crypto
// storage in one hit?, then Generate the magnitude in one hit too?
//////
- BigInteger b = Zero;
+ var b = Zero;
- int next = index + chunk;
+ var next = index + chunk;
if (next <= str.Length)
- {
do
{
- string s = str.Substring(index, chunk);
- ulong i = ulong.Parse(s, style);
- BigInteger bi = createUValueOf(i);
+ var s = str.Substring(index, chunk);
+ var i = ulong.Parse(s, style);
+ var bi = createUValueOf(i);
switch (radix)
{
@@ -316,37 +322,26 @@ namespace TLSharp.Core.MTProto.Crypto
index = next;
next += chunk;
- }
- while (next <= str.Length);
- }
+ } while (next <= str.Length);
if (index < str.Length)
{
- string s = str.Substring(index);
- ulong i = ulong.Parse(s, style);
- BigInteger bi = createUValueOf(i);
+ var s = str.Substring(index);
+ var i = ulong.Parse(s, style);
+ var bi = createUValueOf(i);
- if (b.sign > 0)
+ if (b.SignValue > 0)
{
if (radix == 2)
- {
- // NB: Can't reach here since we are parsing one char at a time
Debug.Assert(false);
-
- // TODO Parse all bits at once
- // b = b.ShiftLeft(s.Length);
- }
else if (radix == 16)
- {
b = b.ShiftLeft(s.Length << 2);
- }
- else {
- b = b.Multiply(r.Pow(s.Length));
- }
+ else b = b.Multiply(r.Pow(s.Length));
b = b.Add(bi);
}
- else {
+ else
+ {
b = bi;
}
}
@@ -380,108 +375,49 @@ namespace TLSharp.Core.MTProto.Crypto
throw new FormatException("Zero length BigInteger");
// TODO Move this processing into MakeMagnitude (provide sign argument)
- if ((sbyte)bytes[offset] < 0)
+ if ((sbyte) bytes[offset] < 0)
{
- this.sign = -1;
+ SignValue = -1;
- int end = offset + length;
+ var end = offset + length;
int iBval;
// strip leading sign bytes
- for (iBval = offset; iBval < end && ((sbyte)bytes[iBval] == -1); iBval++)
+ for (iBval = offset; iBval < end && (sbyte) bytes[iBval] == -1; iBval++)
{
}
if (iBval >= end)
{
- this.magnitude = One.magnitude;
+ magnitude = One.magnitude;
}
- else {
- int numBytes = end - iBval;
- byte[] inverse = new byte[numBytes];
+ else
+ {
+ var numBytes = end - iBval;
+ var inverse = new byte[numBytes];
- int index = 0;
+ var index = 0;
while (index < numBytes)
- {
- inverse[index++] = (byte)~bytes[iBval++];
- }
+ inverse[index++] = (byte) ~bytes[iBval++];
Debug.Assert(iBval == end);
while (inverse[--index] == byte.MaxValue)
- {
inverse[index] = byte.MinValue;
- }
inverse[index]++;
- this.magnitude = MakeMagnitude(inverse, 0, inverse.Length);
+ magnitude = MakeMagnitude(inverse, 0, inverse.Length);
}
}
- else {
+ else
+ {
// strip leading zero bytes and return magnitude bytes
- this.magnitude = MakeMagnitude(bytes, offset, length);
- this.sign = this.magnitude.Length > 0 ? 1 : 0;
+ magnitude = MakeMagnitude(bytes, offset, length);
+ SignValue = magnitude.Length > 0 ? 1 : 0;
}
}
- private static int[] MakeMagnitude(
- byte[] bytes,
- int offset,
- int length)
- {
- int end = offset + length;
-
- // strip leading zeros
- int firstSignificant;
- for (firstSignificant = offset; firstSignificant < end
- && bytes[firstSignificant] == 0; firstSignificant++)
- {
- }
-
- if (firstSignificant >= end)
- {
- return ZeroMagnitude;
- }
-
- int nInts = (end - firstSignificant + 3) / BytesPerInt;
- int bCount = (end - firstSignificant) % BytesPerInt;
- if (bCount == 0)
- {
- bCount = BytesPerInt;
- }
-
- if (nInts < 1)
- {
- return ZeroMagnitude;
- }
-
- int[] mag = new int[nInts];
-
- int v = 0;
- int magnitudeIndex = 0;
- for (int i = firstSignificant; i < end; ++i)
- {
- v <<= 8;
- v |= bytes[i] & 0xff;
- bCount--;
- if (bCount <= 0)
- {
- mag[magnitudeIndex] = v;
- magnitudeIndex++;
- bCount = BytesPerInt;
- v = 0;
- }
- }
-
- if (magnitudeIndex < mag.Length)
- {
- mag[magnitudeIndex] = v;
- }
-
- return mag;
- }
-
public BigInteger(
int sign,
byte[] bytes)
@@ -501,12 +437,13 @@ namespace TLSharp.Core.MTProto.Crypto
if (sign == 0)
{
//this.sign = 0;
- this.magnitude = ZeroMagnitude;
+ magnitude = ZeroMagnitude;
}
- else {
+ else
+ {
// copy bytes
- this.magnitude = MakeMagnitude(bytes, offset, length);
- this.sign = this.magnitude.Length < 1 ? 0 : sign;
+ magnitude = MakeMagnitude(bytes, offset, length);
+ SignValue = magnitude.Length < 1 ? 0 : sign;
}
}
@@ -517,29 +454,27 @@ namespace TLSharp.Core.MTProto.Crypto
if (sizeInBits < 0)
throw new ArgumentException("sizeInBits must be non-negative");
- this.nBits = -1;
- this.nBitLength = -1;
+ nBits = -1;
+ nBitLength = -1;
if (sizeInBits == 0)
{
// this.sign = 0;
- this.magnitude = ZeroMagnitude;
+ magnitude = ZeroMagnitude;
return;
}
- int nBytes = GetByteLength(sizeInBits);
- byte[] b = new byte[nBytes];
+ var nBytes = GetByteLength(sizeInBits);
+ var b = new byte[nBytes];
random.NextBytes(b);
// strip off any excess bits in the MSB
b[0] &= rndMask[BitsPerByte * nBytes - sizeInBits];
- this.magnitude = MakeMagnitude(b, 0, b.Length);
- this.sign = this.magnitude.Length < 1 ? 0 : 1;
+ magnitude = MakeMagnitude(b, 0, b.Length);
+ SignValue = magnitude.Length < 1 ? 0 : 1;
}
- private static readonly byte[] rndMask = { 255, 127, 63, 31, 15, 7, 3, 1 };
-
public BigInteger(
int bitLength,
int certainty,
@@ -548,22 +483,22 @@ namespace TLSharp.Core.MTProto.Crypto
if (bitLength < 2)
throw new ArithmeticException("bitLength < 2");
- this.sign = 1;
- this.nBitLength = bitLength;
+ SignValue = 1;
+ nBitLength = bitLength;
if (bitLength == 2)
{
- this.magnitude = random.Next(2) == 0
+ magnitude = random.Next(2) == 0
? Two.magnitude
: Three.magnitude;
return;
}
- int nBytes = GetByteLength(bitLength);
- byte[] b = new byte[nBytes];
+ var nBytes = GetByteLength(bitLength);
+ var b = new byte[nBytes];
- int xBits = BitsPerByte * nBytes - bitLength;
- byte mask = rndMask[xBits];
+ var xBits = BitsPerByte * nBytes - bitLength;
+ var mask = rndMask[xBits];
for (;;)
{
@@ -573,14 +508,14 @@ namespace TLSharp.Core.MTProto.Crypto
b[0] &= mask;
// ensure the leading bit is 1 (to meet the strength requirement)
- b[0] |= (byte)(1 << (7 - xBits));
+ b[0] |= (byte) (1 << (7 - xBits));
// ensure the trailing bit is 1 (i.e. must be odd)
b[nBytes - 1] |= 1;
- this.magnitude = MakeMagnitude(b, 0, b.Length);
- this.nBits = -1;
- this.mQuote = -1L;
+ magnitude = MakeMagnitude(b, 0, b.Length);
+ nBits = -1;
+ mQuote = -1L;
if (certainty < 1)
break;
@@ -589,767 +524,64 @@ namespace TLSharp.Core.MTProto.Crypto
break;
if (bitLength > 32)
- {
- for (int rep = 0; rep < 10000; ++rep)
+ for (var rep = 0; rep < 10000; ++rep)
{
- int n = 33 + random.Next(bitLength - 2);
- this.magnitude[this.magnitude.Length - (n >> 5)] ^= (1 << (n & 31));
- this.magnitude[this.magnitude.Length - 1] ^= ((random.Next() + 1) << 1);
- this.mQuote = -1L;
+ var n = 33 + random.Next(bitLength - 2);
+ magnitude[magnitude.Length - (n >> 5)] ^= 1 << (n & 31);
+ magnitude[magnitude.Length - 1] ^= (random.Next() + 1) << 1;
+ mQuote = -1L;
if (CheckProbablePrime(certainty, random))
return;
}
- }
}
}
- public BigInteger Abs()
- {
- return sign >= 0 ? this : Negate();
- }
-
- /**
- * return a = a + b - b preserved.
- */
- private static int[] AddMagnitudes(
- int[] a,
- int[] b)
- {
- int tI = a.Length - 1;
- int vI = b.Length - 1;
- long m = 0;
-
- while (vI >= 0)
- {
- m += ((long)(uint)a[tI] + (long)(uint)b[vI--]);
- a[tI--] = (int)m;
- m = (long)((ulong)m >> 32);
- }
-
- if (m != 0)
- {
- while (tI >= 0 && ++a[tI--] == 0)
- {
- }
- }
-
- return a;
- }
-
- public BigInteger Add(
- BigInteger value)
- {
- if (this.sign == 0)
- return value;
-
- if (this.sign != value.sign)
- {
- if (value.sign == 0)
- return this;
-
- if (value.sign < 0)
- return Subtract(value.Negate());
-
- return value.Subtract(Negate());
- }
-
- return AddToMagnitude(value.magnitude);
- }
-
- private BigInteger AddToMagnitude(
- int[] magToAdd)
- {
- int[] big, small;
- if (this.magnitude.Length < magToAdd.Length)
- {
- big = magToAdd;
- small = this.magnitude;
- }
- else {
- big = this.magnitude;
- small = magToAdd;
- }
-
- // Conservatively avoid over-allocation when no overflow possible
- uint limit = uint.MaxValue;
- if (big.Length == small.Length)
- limit -= (uint)small[0];
-
- bool possibleOverflow = (uint)big[0] >= limit;
-
- int[] bigCopy;
- if (possibleOverflow)
- {
- bigCopy = new int[big.Length + 1];
- big.CopyTo(bigCopy, 1);
- }
- else {
- bigCopy = (int[])big.Clone();
- }
-
- bigCopy = AddMagnitudes(bigCopy, small);
-
- return new BigInteger(this.sign, bigCopy, possibleOverflow);
- }
-
- public BigInteger And(
- BigInteger value)
- {
- if (this.sign == 0 || value.sign == 0)
- {
- return Zero;
- }
-
- int[] aMag = this.sign > 0
- ? this.magnitude
- : Add(One).magnitude;
-
- int[] bMag = value.sign > 0
- ? value.magnitude
- : value.Add(One).magnitude;
-
- bool resultNeg = sign < 0 && value.sign < 0;
- int resultLength = System.Math.Max(aMag.Length, bMag.Length);
- int[] resultMag = new int[resultLength];
-
- int aStart = resultMag.Length - aMag.Length;
- int bStart = resultMag.Length - bMag.Length;
-
- for (int i = 0; i < resultMag.Length; ++i)
- {
- int aWord = i >= aStart ? aMag[i - aStart] : 0;
- int bWord = i >= bStart ? bMag[i - bStart] : 0;
-
- if (this.sign < 0)
- {
- aWord = ~aWord;
- }
-
- if (value.sign < 0)
- {
- bWord = ~bWord;
- }
-
- resultMag[i] = aWord & bWord;
-
- if (resultNeg)
- {
- resultMag[i] = ~resultMag[i];
- }
- }
-
- BigInteger result = new BigInteger(1, resultMag, true);
-
- // TODO Optimise this case
- if (resultNeg)
- {
- result = result.Not();
- }
-
- return result;
- }
-
- public BigInteger AndNot(
- BigInteger val)
- {
- return And(val.Not());
- }
-
public int BitCount
{
get
{
if (nBits == -1)
- {
- if (sign < 0)
+ if (SignValue < 0)
{
// TODO Optimise this case
nBits = Not().BitCount;
}
- else {
- int sum = 0;
- for (int i = 0; i < magnitude.Length; i++)
+ else
+ {
+ var sum = 0;
+ for (var i = 0; i < magnitude.Length; i++)
{
- sum += bitCounts[(byte)magnitude[i]];
- sum += bitCounts[(byte)(magnitude[i] >> 8)];
- sum += bitCounts[(byte)(magnitude[i] >> 16)];
- sum += bitCounts[(byte)(magnitude[i] >> 24)];
+ sum += bitCounts[(byte) magnitude[i]];
+ sum += bitCounts[(byte) (magnitude[i] >> 8)];
+ sum += bitCounts[(byte) (magnitude[i] >> 16)];
+ sum += bitCounts[(byte) (magnitude[i] >> 24)];
}
nBits = sum;
}
- }
return nBits;
}
}
- private readonly static byte[] bitCounts =
- {
- 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1,
- 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4,
- 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3,
- 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5,
- 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2,
- 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3,
- 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6,
- 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6,
- 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5,
- 6, 6, 7, 6, 7, 7, 8
- };
-
- private int calcBitLength(
- int indx,
- int[] mag)
- {
- for (;;)
- {
- if (indx >= mag.Length)
- return 0;
-
- if (mag[indx] != 0)
- break;
-
- ++indx;
- }
-
- // bit length for everything after the first int
- int bitLength = 32 * ((mag.Length - indx) - 1);
-
- // and determine bitlength of first int
- int firstMag = mag[indx];
- bitLength += BitLen(firstMag);
-
- // Check for negative powers of two
- if (sign < 0 && ((firstMag & -firstMag) == firstMag))
- {
- do
- {
- if (++indx >= mag.Length)
- {
- --bitLength;
- break;
- }
- }
- while (mag[indx] == 0);
- }
-
- return bitLength;
- }
-
public int BitLength
{
get
{
if (nBitLength == -1)
- {
- nBitLength = sign == 0
+ nBitLength = SignValue == 0
? 0
: calcBitLength(0, magnitude);
- }
return nBitLength;
}
}
- //
- // BitLen(value) is the number of bits in value.
- //
- private static int BitLen(
- int w)
- {
- // Binary search - decision tree (5 tests, rarely 6)
- return (w < 1 << 15 ? (w < 1 << 7
- ? (w < 1 << 3 ? (w < 1 << 1
- ? (w < 1 << 0 ? (w < 0 ? 32 : 0) : 1)
- : (w < 1 << 2 ? 2 : 3)) : (w < 1 << 5
- ? (w < 1 << 4 ? 4 : 5)
- : (w < 1 << 6 ? 6 : 7)))
- : (w < 1 << 11
- ? (w < 1 << 9 ? (w < 1 << 8 ? 8 : 9) : (w < 1 << 10 ? 10 : 11))
- : (w < 1 << 13 ? (w < 1 << 12 ? 12 : 13) : (w < 1 << 14 ? 14 : 15)))) : (w < 1 << 23 ? (w < 1 << 19
- ? (w < 1 << 17 ? (w < 1 << 16 ? 16 : 17) : (w < 1 << 18 ? 18 : 19))
- : (w < 1 << 21 ? (w < 1 << 20 ? 20 : 21) : (w < 1 << 22 ? 22 : 23))) : (w < 1 << 27
- ? (w < 1 << 25 ? (w < 1 << 24 ? 24 : 25) : (w < 1 << 26 ? 26 : 27))
- : (w < 1 << 29 ? (w < 1 << 28 ? 28 : 29) : (w < 1 << 30 ? 30 : 31)))));
- }
-
- // private readonly static byte[] bitLengths =
- // {
- // 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
- // 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- // 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- // 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- // 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8,
- // 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- // 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- // 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- // 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- // 8, 8, 8, 8, 8, 8, 8, 8
- // };
-
- private bool QuickPow2Check()
- {
- return sign > 0 && nBits == 1;
- }
-
- public int CompareTo(
- object obj)
- {
- return CompareTo((BigInteger)obj);
- }
-
- /**
- * unsigned comparison on two arrays - note the arrays may
- * start with leading zeros.
- */
- private static int CompareTo(
- int xIndx,
- int[] x,
- int yIndx,
- int[] y)
- {
- while (xIndx != x.Length && x[xIndx] == 0)
- {
- xIndx++;
- }
-
- while (yIndx != y.Length && y[yIndx] == 0)
- {
- yIndx++;
- }
-
- return CompareNoLeadingZeroes(xIndx, x, yIndx, y);
- }
-
- private static int CompareNoLeadingZeroes(
- int xIndx,
- int[] x,
- int yIndx,
- int[] y)
- {
- int diff = (x.Length - y.Length) - (xIndx - yIndx);
-
- if (diff != 0)
- {
- return diff < 0 ? -1 : 1;
- }
-
- // lengths of magnitudes the same, test the magnitude values
-
- while (xIndx < x.Length)
- {
- uint v1 = (uint)x[xIndx++];
- uint v2 = (uint)y[yIndx++];
-
- if (v1 != v2)
- return v1 < v2 ? -1 : 1;
- }
-
- return 0;
- }
-
- public int CompareTo(
- BigInteger value)
- {
- return sign < value.sign ? -1
- : sign > value.sign ? 1
- : sign == 0 ? 0
- : sign * CompareNoLeadingZeroes(0, magnitude, 0, value.magnitude);
- }
-
- /**
- * return z = x / y - done in place (z value preserved, x contains the
- * remainder)
- */
- private int[] Divide(
- int[] x,
- int[] y)
- {
- int xStart = 0;
- while (xStart < x.Length && x[xStart] == 0)
- {
- ++xStart;
- }
-
- int yStart = 0;
- while (yStart < y.Length && y[yStart] == 0)
- {
- ++yStart;
- }
-
- Debug.Assert(yStart < y.Length);
-
- int xyCmp = CompareNoLeadingZeroes(xStart, x, yStart, y);
- int[] count;
-
- if (xyCmp > 0)
- {
- int yBitLength = calcBitLength(yStart, y);
- int xBitLength = calcBitLength(xStart, x);
- int shift = xBitLength - yBitLength;
-
- int[] iCount;
- int iCountStart = 0;
-
- int[] c;
- int cStart = 0;
- int cBitLength = yBitLength;
- if (shift > 0)
- {
- // iCount = ShiftLeft(One.magnitude, shift);
- iCount = new int[(shift >> 5) + 1];
- iCount[0] = 1 << (shift % 32);
-
- c = ShiftLeft(y, shift);
- cBitLength += shift;
- }
- else {
- iCount = new int[] { 1 };
-
- int len = y.Length - yStart;
- c = new int[len];
- Array.Copy(y, yStart, c, 0, len);
- }
-
- count = new int[iCount.Length];
-
- for (;;)
- {
- if (cBitLength < xBitLength
- || CompareNoLeadingZeroes(xStart, x, cStart, c) >= 0)
- {
- Subtract(xStart, x, cStart, c);
- AddMagnitudes(count, iCount);
-
- while (x[xStart] == 0)
- {
- if (++xStart == x.Length)
- return count;
- }
-
- //xBitLength = calcBitLength(xStart, x);
- xBitLength = 32 * (x.Length - xStart - 1) + BitLen(x[xStart]);
-
- if (xBitLength <= yBitLength)
- {
- if (xBitLength < yBitLength)
- return count;
-
- xyCmp = CompareNoLeadingZeroes(xStart, x, yStart, y);
-
- if (xyCmp <= 0)
- break;
- }
- }
-
- shift = cBitLength - xBitLength;
-
- // NB: The case where c[cStart] is 1-bit is harmless
- if (shift == 1)
- {
- uint firstC = (uint)c[cStart] >> 1;
- uint firstX = (uint)x[xStart];
- if (firstC > firstX)
- ++shift;
- }
-
- if (shift < 2)
- {
- ShiftRightOneInPlace(cStart, c);
- --cBitLength;
- ShiftRightOneInPlace(iCountStart, iCount);
- }
- else {
- ShiftRightInPlace(cStart, c, shift);
- cBitLength -= shift;
- ShiftRightInPlace(iCountStart, iCount, shift);
- }
-
- //cStart = c.Length - ((cBitLength + 31) / 32);
- while (c[cStart] == 0)
- {
- ++cStart;
- }
-
- while (iCount[iCountStart] == 0)
- {
- ++iCountStart;
- }
- }
- }
- else {
- count = new int[1];
- }
-
- if (xyCmp == 0)
- {
- AddMagnitudes(count, One.magnitude);
- Array.Clear(x, xStart, x.Length - xStart);
- }
-
- return count;
- }
-
- public BigInteger Divide(
- BigInteger val)
- {
- if (val.sign == 0)
- throw new ArithmeticException("Division by zero error");
-
- if (sign == 0)
- return Zero;
-
- if (val.QuickPow2Check()) // val is power of two
- {
- BigInteger result = this.Abs().ShiftRight(val.Abs().BitLength - 1);
- return val.sign == this.sign ? result : result.Negate();
- }
-
- int[] mag = (int[])this.magnitude.Clone();
-
- return new BigInteger(this.sign * val.sign, Divide(mag, val.magnitude), true);
- }
-
- public BigInteger[] DivideAndRemainder(
- BigInteger val)
- {
- if (val.sign == 0)
- throw new ArithmeticException("Division by zero error");
-
- BigInteger[] biggies = new BigInteger[2];
-
- if (sign == 0)
- {
- biggies[0] = Zero;
- biggies[1] = Zero;
- }
- else if (val.QuickPow2Check()) // val is power of two
- {
- int e = val.Abs().BitLength - 1;
- BigInteger quotient = this.Abs().ShiftRight(e);
- int[] remainder = this.LastNBits(e);
-
- biggies[0] = val.sign == this.sign ? quotient : quotient.Negate();
- biggies[1] = new BigInteger(this.sign, remainder, true);
- }
- else {
- int[] remainder = (int[])this.magnitude.Clone();
- int[] quotient = Divide(remainder, val.magnitude);
-
- biggies[0] = new BigInteger(this.sign * val.sign, quotient, true);
- biggies[1] = new BigInteger(this.sign, remainder, true);
- }
-
- return biggies;
- }
-
- public override bool Equals(
- object obj)
- {
- if (obj == this)
- return true;
-
- BigInteger biggie = obj as BigInteger;
- if (biggie == null)
- return false;
-
- if (biggie.sign != sign || biggie.magnitude.Length != magnitude.Length)
- return false;
-
- for (int i = 0; i < magnitude.Length; i++)
- {
- if (biggie.magnitude[i] != magnitude[i])
- {
- return false;
- }
- }
-
- return true;
- }
-
- public BigInteger Gcd(
- BigInteger value)
- {
- if (value.sign == 0)
- return Abs();
-
- if (sign == 0)
- return value.Abs();
-
- BigInteger r;
- BigInteger u = this;
- BigInteger v = value;
-
- while (v.sign != 0)
- {
- r = u.Mod(v);
- u = v;
- v = r;
- }
-
- return u;
- }
-
- public override int GetHashCode()
- {
- int hc = magnitude.Length;
- if (magnitude.Length > 0)
- {
- hc ^= magnitude[0];
-
- if (magnitude.Length > 1)
- {
- hc ^= magnitude[magnitude.Length - 1];
- }
- }
-
- return sign < 0 ? ~hc : hc;
- }
-
- // TODO Make public?
- private BigInteger Inc()
- {
- if (this.sign == 0)
- return One;
-
- if (this.sign < 0)
- return new BigInteger(-1, doSubBigLil(this.magnitude, One.magnitude), true);
-
- return AddToMagnitude(One.magnitude);
- }
-
- public int IntValue
- {
- get
- {
- return sign == 0 ? 0
- : sign > 0 ? magnitude[magnitude.Length - 1]
- : -magnitude[magnitude.Length - 1];
- }
- }
-
- /**
- * return whether or not a BigInteger is probably prime with a
- * probability of 1 - (1/2)**certainty.
- *
From Knuth Vol 2, pg 395.
- */
- public bool IsProbablePrime(
- int certainty)
- {
- if (certainty <= 0)
- return true;
-
- BigInteger n = Abs();
-
- if (!n.TestBit(0))
- return n.Equals(Two);
-
- if (n.Equals(One))
- return false;
-
- return n.CheckProbablePrime(certainty, RandomSource);
- }
-
- private bool CheckProbablePrime(
- int certainty,
- Random random)
- {
- Debug.Assert(certainty > 0);
- Debug.Assert(CompareTo(Two) > 0);
- Debug.Assert(TestBit(0));
-
-
- // Try to reduce the penalty for really small numbers
- int numLists = System.Math.Min(BitLength - 1, primeLists.Length);
-
- for (int i = 0; i < numLists; ++i)
- {
- int test = Remainder(primeProducts[i]);
-
- int[] primeList = primeLists[i];
- for (int j = 0; j < primeList.Length; ++j)
- {
- int prime = primeList[j];
- int qRem = test % prime;
- if (qRem == 0)
- {
- // We may find small numbers in the list
- return BitLength < 16 && IntValue == prime;
- }
- }
- }
-
-
- // TODO Special case for < 10^16 (RabinMiller fixed list)
- // if (BitLength < 30)
- // {
- // RabinMiller against 2, 3, 5, 7, 11, 13, 23 is sufficient
- // }
-
-
- // TODO Is it worth trying to create a hybrid of these two?
- return RabinMillerTest(certainty, random);
- // return SolovayStrassenTest(certainty, random);
-
- // bool rbTest = RabinMillerTest(certainty, random);
- // bool ssTest = SolovayStrassenTest(certainty, random);
- //
- // Debug.Assert(rbTest == ssTest);
- //
- // return rbTest;
- }
-
- internal bool RabinMillerTest(
- int certainty,
- Random random)
- {
- Debug.Assert(certainty > 0);
- Debug.Assert(BitLength > 2);
- Debug.Assert(TestBit(0));
-
- // let n = 1 + d . 2^s
- BigInteger n = this;
- BigInteger nMinusOne = n.Subtract(One);
- int s = nMinusOne.GetLowestSetBit();
- BigInteger r = nMinusOne.ShiftRight(s);
-
- Debug.Assert(s >= 1);
-
- do
- {
- // TODO Make a method for random BigIntegers in range 0 < x < n)
- // - Method can be optimized by only replacing examined bits at each trial
- BigInteger a;
- do
- {
- a = new BigInteger(n.BitLength, random);
- }
- while (a.CompareTo(One) <= 0 || a.CompareTo(nMinusOne) >= 0);
-
- BigInteger y = a.ModPow(r, n);
-
- if (!y.Equals(One))
- {
- int j = 0;
- while (!y.Equals(nMinusOne))
- {
- if (++j == s)
- return false;
-
- y = y.ModPow(Two, n);
-
- if (y.Equals(One))
- return false;
- }
- }
-
- certainty -= 2; // composites pass for only 1/4 possible 'a'
- }
- while (certainty > 0);
-
- return true;
- }
+ public int IntValue => SignValue == 0
+ ? 0
+ : SignValue > 0
+ ? magnitude[magnitude.Length - 1]
+ : -magnitude[magnitude.Length - 1];
// private bool SolovayStrassenTest(
// int certainty,
@@ -1444,21 +676,729 @@ namespace TLSharp.Core.MTProto.Crypto
{
get
{
- if (sign == 0)
+ if (SignValue == 0)
return 0;
long v;
if (magnitude.Length > 1)
- {
- v = ((long)magnitude[magnitude.Length - 2] << 32)
+ v = ((long) magnitude[magnitude.Length - 2] << 32)
| (magnitude[magnitude.Length - 1] & IMASK);
+ else v = magnitude[magnitude.Length - 1] & IMASK;
+
+ return SignValue < 0 ? -v : v;
+ }
+ }
+
+ public int SignValue { get; private set; }
+
+ private static int GetByteLength(
+ int nBits)
+ {
+ return (nBits + BitsPerByte - 1) / BitsPerByte;
+ }
+
+ private static int[] MakeMagnitude(
+ byte[] bytes,
+ int offset,
+ int length)
+ {
+ var end = offset + length;
+
+ // strip leading zeros
+ int firstSignificant;
+ for (firstSignificant = offset;
+ firstSignificant < end
+ && bytes[firstSignificant] == 0;
+ firstSignificant++)
+ {
+ }
+
+ if (firstSignificant >= end)
+ return ZeroMagnitude;
+
+ var nInts = (end - firstSignificant + 3) / BytesPerInt;
+ var bCount = (end - firstSignificant) % BytesPerInt;
+ if (bCount == 0)
+ bCount = BytesPerInt;
+
+ if (nInts < 1)
+ return ZeroMagnitude;
+
+ var mag = new int[nInts];
+
+ var v = 0;
+ var magnitudeIndex = 0;
+ for (var i = firstSignificant; i < end; ++i)
+ {
+ v <<= 8;
+ v |= bytes[i] & 0xff;
+ bCount--;
+ if (bCount <= 0)
+ {
+ mag[magnitudeIndex] = v;
+ magnitudeIndex++;
+ bCount = BytesPerInt;
+ v = 0;
}
- else {
- v = (magnitude[magnitude.Length - 1] & IMASK);
+ }
+
+ if (magnitudeIndex < mag.Length)
+ mag[magnitudeIndex] = v;
+
+ return mag;
+ }
+
+ public BigInteger Abs()
+ {
+ return SignValue >= 0 ? this : Negate();
+ }
+
+ /**
+ * return a = a + b - b preserved.
+ */
+ private static int[] AddMagnitudes(
+ int[] a,
+ int[] b)
+ {
+ var tI = a.Length - 1;
+ var vI = b.Length - 1;
+ long m = 0;
+
+ while (vI >= 0)
+ {
+ m += (uint) a[tI] + (long) (uint) b[vI--];
+ a[tI--] = (int) m;
+ m = (long) ((ulong) m >> 32);
+ }
+
+ if (m != 0)
+ while (tI >= 0 && ++a[tI--] == 0)
+ {
}
- return sign < 0 ? -v : v;
+ return a;
+ }
+
+ public BigInteger Add(
+ BigInteger value)
+ {
+ if (SignValue == 0)
+ return value;
+
+ if (SignValue != value.SignValue)
+ {
+ if (value.SignValue == 0)
+ return this;
+
+ if (value.SignValue < 0)
+ return Subtract(value.Negate());
+
+ return value.Subtract(Negate());
}
+
+ return AddToMagnitude(value.magnitude);
+ }
+
+ private BigInteger AddToMagnitude(
+ int[] magToAdd)
+ {
+ int[] big, small;
+ if (magnitude.Length < magToAdd.Length)
+ {
+ big = magToAdd;
+ small = magnitude;
+ }
+ else
+ {
+ big = magnitude;
+ small = magToAdd;
+ }
+
+ // Conservatively avoid over-allocation when no overflow possible
+ var limit = uint.MaxValue;
+ if (big.Length == small.Length)
+ limit -= (uint) small[0];
+
+ var possibleOverflow = (uint) big[0] >= limit;
+
+ int[] bigCopy;
+ if (possibleOverflow)
+ {
+ bigCopy = new int[big.Length + 1];
+ big.CopyTo(bigCopy, 1);
+ }
+ else
+ {
+ bigCopy = (int[]) big.Clone();
+ }
+
+ bigCopy = AddMagnitudes(bigCopy, small);
+
+ return new BigInteger(SignValue, bigCopy, possibleOverflow);
+ }
+
+ public BigInteger And(
+ BigInteger value)
+ {
+ if (SignValue == 0 || value.SignValue == 0)
+ return Zero;
+
+ var aMag = SignValue > 0
+ ? magnitude
+ : Add(One).magnitude;
+
+ var bMag = value.SignValue > 0
+ ? value.magnitude
+ : value.Add(One).magnitude;
+
+ var resultNeg = SignValue < 0 && value.SignValue < 0;
+ var resultLength = Math.Max(aMag.Length, bMag.Length);
+ var resultMag = new int[resultLength];
+
+ var aStart = resultMag.Length - aMag.Length;
+ var bStart = resultMag.Length - bMag.Length;
+
+ for (var i = 0; i < resultMag.Length; ++i)
+ {
+ var aWord = i >= aStart ? aMag[i - aStart] : 0;
+ var bWord = i >= bStart ? bMag[i - bStart] : 0;
+
+ if (SignValue < 0)
+ aWord = ~aWord;
+
+ if (value.SignValue < 0)
+ bWord = ~bWord;
+
+ resultMag[i] = aWord & bWord;
+
+ if (resultNeg)
+ resultMag[i] = ~resultMag[i];
+ }
+
+ var result = new BigInteger(1, resultMag, true);
+
+ // TODO Optimise this case
+ if (resultNeg)
+ result = result.Not();
+
+ return result;
+ }
+
+ public BigInteger AndNot(
+ BigInteger val)
+ {
+ return And(val.Not());
+ }
+
+ private int calcBitLength(
+ int indx,
+ int[] mag)
+ {
+ for (;;)
+ {
+ if (indx >= mag.Length)
+ return 0;
+
+ if (mag[indx] != 0)
+ break;
+
+ ++indx;
+ }
+
+ // bit length for everything after the first int
+ var bitLength = 32 * (mag.Length - indx - 1);
+
+ // and determine bitlength of first int
+ var firstMag = mag[indx];
+ bitLength += BitLen(firstMag);
+
+ // Check for negative powers of two
+ if (SignValue < 0 && (firstMag & -firstMag) == firstMag)
+ do
+ {
+ if (++indx >= mag.Length)
+ {
+ --bitLength;
+ break;
+ }
+ } while (mag[indx] == 0);
+
+ return bitLength;
+ }
+
+ //
+ // BitLen(value) is the number of bits in value.
+ //
+ private static int BitLen(
+ int w)
+ {
+ // Binary search - decision tree (5 tests, rarely 6)
+ return w < 1 << 15
+ ? (w < 1 << 7
+ ? (w < 1 << 3
+ ? (w < 1 << 1
+ ? (w < 1 << 0 ? (w < 0 ? 32 : 0) : 1)
+ : (w < 1 << 2 ? 2 : 3))
+ : (w < 1 << 5
+ ? (w < 1 << 4 ? 4 : 5)
+ : (w < 1 << 6 ? 6 : 7)))
+ : (w < 1 << 11
+ ? (w < 1 << 9 ? (w < 1 << 8 ? 8 : 9) : (w < 1 << 10 ? 10 : 11))
+ : (w < 1 << 13 ? (w < 1 << 12 ? 12 : 13) : (w < 1 << 14 ? 14 : 15))))
+ : (w < 1 << 23
+ ? (w < 1 << 19
+ ? (w < 1 << 17 ? (w < 1 << 16 ? 16 : 17) : (w < 1 << 18 ? 18 : 19))
+ : (w < 1 << 21 ? (w < 1 << 20 ? 20 : 21) : (w < 1 << 22 ? 22 : 23)))
+ : (w < 1 << 27
+ ? (w < 1 << 25 ? (w < 1 << 24 ? 24 : 25) : (w < 1 << 26 ? 26 : 27))
+ : (w < 1 << 29 ? (w < 1 << 28 ? 28 : 29) : (w < 1 << 30 ? 30 : 31))));
+ }
+
+ // private readonly static byte[] bitLengths =
+ // {
+ // 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
+ // 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ // 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ // 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ // 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8,
+ // 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ // 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ // 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ // 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ // 8, 8, 8, 8, 8, 8, 8, 8
+ // };
+
+ private bool QuickPow2Check()
+ {
+ return SignValue > 0 && nBits == 1;
+ }
+
+ public int CompareTo(
+ object obj)
+ {
+ return CompareTo((BigInteger) obj);
+ }
+
+ /**
+ * unsigned comparison on two arrays - note the arrays may
+ * start with leading zeros.
+ */
+ private static int CompareTo(
+ int xIndx,
+ int[] x,
+ int yIndx,
+ int[] y)
+ {
+ while (xIndx != x.Length && x[xIndx] == 0)
+ xIndx++;
+
+ while (yIndx != y.Length && y[yIndx] == 0)
+ yIndx++;
+
+ return CompareNoLeadingZeroes(xIndx, x, yIndx, y);
+ }
+
+ private static int CompareNoLeadingZeroes(
+ int xIndx,
+ int[] x,
+ int yIndx,
+ int[] y)
+ {
+ var diff = x.Length - y.Length - (xIndx - yIndx);
+
+ if (diff != 0)
+ return diff < 0 ? -1 : 1;
+
+ // lengths of magnitudes the same, test the magnitude values
+
+ while (xIndx < x.Length)
+ {
+ var v1 = (uint) x[xIndx++];
+ var v2 = (uint) y[yIndx++];
+
+ if (v1 != v2)
+ return v1 < v2 ? -1 : 1;
+ }
+
+ return 0;
+ }
+
+ public int CompareTo(
+ BigInteger value)
+ {
+ return SignValue < value.SignValue
+ ? -1
+ : SignValue > value.SignValue
+ ? 1
+ : SignValue == 0
+ ? 0
+ : SignValue * CompareNoLeadingZeroes(0, magnitude, 0, value.magnitude);
+ }
+
+ /**
+ * return z = x / y - done in place (z value preserved, x contains the
+ * remainder)
+ */
+ private int[] Divide(
+ int[] x,
+ int[] y)
+ {
+ var xStart = 0;
+ while (xStart < x.Length && x[xStart] == 0)
+ ++xStart;
+
+ var yStart = 0;
+ while (yStart < y.Length && y[yStart] == 0)
+ ++yStart;
+
+ Debug.Assert(yStart < y.Length);
+
+ var xyCmp = CompareNoLeadingZeroes(xStart, x, yStart, y);
+ int[] count;
+
+ if (xyCmp > 0)
+ {
+ var yBitLength = calcBitLength(yStart, y);
+ var xBitLength = calcBitLength(xStart, x);
+ var shift = xBitLength - yBitLength;
+
+ int[] iCount;
+ var iCountStart = 0;
+
+ int[] c;
+ var cStart = 0;
+ var cBitLength = yBitLength;
+ if (shift > 0)
+ {
+ // iCount = ShiftLeft(One.magnitude, shift);
+ iCount = new int[(shift >> 5) + 1];
+ iCount[0] = 1 << (shift % 32);
+
+ c = ShiftLeft(y, shift);
+ cBitLength += shift;
+ }
+ else
+ {
+ iCount = new[] {1};
+
+ var len = y.Length - yStart;
+ c = new int[len];
+ Array.Copy(y, yStart, c, 0, len);
+ }
+
+ count = new int[iCount.Length];
+
+ for (;;)
+ {
+ if (cBitLength < xBitLength
+ || CompareNoLeadingZeroes(xStart, x, cStart, c) >= 0)
+ {
+ Subtract(xStart, x, cStart, c);
+ AddMagnitudes(count, iCount);
+
+ while (x[xStart] == 0)
+ if (++xStart == x.Length)
+ return count;
+
+ //xBitLength = calcBitLength(xStart, x);
+ xBitLength = 32 * (x.Length - xStart - 1) + BitLen(x[xStart]);
+
+ if (xBitLength <= yBitLength)
+ {
+ if (xBitLength < yBitLength)
+ return count;
+
+ xyCmp = CompareNoLeadingZeroes(xStart, x, yStart, y);
+
+ if (xyCmp <= 0)
+ break;
+ }
+ }
+
+ shift = cBitLength - xBitLength;
+
+ // NB: The case where c[cStart] is 1-bit is harmless
+ if (shift == 1)
+ {
+ var firstC = (uint) c[cStart] >> 1;
+ var firstX = (uint) x[xStart];
+ if (firstC > firstX)
+ ++shift;
+ }
+
+ if (shift < 2)
+ {
+ ShiftRightOneInPlace(cStart, c);
+ --cBitLength;
+ ShiftRightOneInPlace(iCountStart, iCount);
+ }
+ else
+ {
+ ShiftRightInPlace(cStart, c, shift);
+ cBitLength -= shift;
+ ShiftRightInPlace(iCountStart, iCount, shift);
+ }
+
+ //cStart = c.Length - ((cBitLength + 31) / 32);
+ while (c[cStart] == 0)
+ ++cStart;
+
+ while (iCount[iCountStart] == 0)
+ ++iCountStart;
+ }
+ }
+ else
+ {
+ count = new int[1];
+ }
+
+ if (xyCmp == 0)
+ {
+ AddMagnitudes(count, One.magnitude);
+ Array.Clear(x, xStart, x.Length - xStart);
+ }
+
+ return count;
+ }
+
+ public BigInteger Divide(
+ BigInteger val)
+ {
+ if (val.SignValue == 0)
+ throw new ArithmeticException("Division by zero error");
+
+ if (SignValue == 0)
+ return Zero;
+
+ if (val.QuickPow2Check()) // val is power of two
+ {
+ var result = Abs().ShiftRight(val.Abs().BitLength - 1);
+ return val.SignValue == SignValue ? result : result.Negate();
+ }
+
+ var mag = (int[]) magnitude.Clone();
+
+ return new BigInteger(SignValue * val.SignValue, Divide(mag, val.magnitude), true);
+ }
+
+ public BigInteger[] DivideAndRemainder(
+ BigInteger val)
+ {
+ if (val.SignValue == 0)
+ throw new ArithmeticException("Division by zero error");
+
+ var biggies = new BigInteger[2];
+
+ if (SignValue == 0)
+ {
+ biggies[0] = Zero;
+ biggies[1] = Zero;
+ }
+ else if (val.QuickPow2Check()) // val is power of two
+ {
+ var e = val.Abs().BitLength - 1;
+ var quotient = Abs().ShiftRight(e);
+ var remainder = LastNBits(e);
+
+ biggies[0] = val.SignValue == SignValue ? quotient : quotient.Negate();
+ biggies[1] = new BigInteger(SignValue, remainder, true);
+ }
+ else
+ {
+ var remainder = (int[]) magnitude.Clone();
+ var quotient = Divide(remainder, val.magnitude);
+
+ biggies[0] = new BigInteger(SignValue * val.SignValue, quotient, true);
+ biggies[1] = new BigInteger(SignValue, remainder, true);
+ }
+
+ return biggies;
+ }
+
+ public override bool Equals(
+ object obj)
+ {
+ if (obj == this)
+ return true;
+
+ var biggie = obj as BigInteger;
+ if (biggie == null)
+ return false;
+
+ if (biggie.SignValue != SignValue || biggie.magnitude.Length != magnitude.Length)
+ return false;
+
+ for (var i = 0; i < magnitude.Length; i++)
+ if (biggie.magnitude[i] != magnitude[i])
+ return false;
+
+ return true;
+ }
+
+ public BigInteger Gcd(
+ BigInteger value)
+ {
+ if (value.SignValue == 0)
+ return Abs();
+
+ if (SignValue == 0)
+ return value.Abs();
+
+ BigInteger r;
+ var u = this;
+ var v = value;
+
+ while (v.SignValue != 0)
+ {
+ r = u.Mod(v);
+ u = v;
+ v = r;
+ }
+
+ return u;
+ }
+
+ public override int GetHashCode()
+ {
+ var hc = magnitude.Length;
+ if (magnitude.Length > 0)
+ {
+ hc ^= magnitude[0];
+
+ if (magnitude.Length > 1)
+ hc ^= magnitude[magnitude.Length - 1];
+ }
+
+ return SignValue < 0 ? ~hc : hc;
+ }
+
+ // TODO Make public?
+ private BigInteger Inc()
+ {
+ if (SignValue == 0)
+ return One;
+
+ if (SignValue < 0)
+ return new BigInteger(-1, doSubBigLil(magnitude, One.magnitude), true);
+
+ return AddToMagnitude(One.magnitude);
+ }
+
+ /**
+ * return whether or not a BigInteger is probably prime with a
+ * probability of 1 - (1/2)**certainty.
+ * From Knuth Vol 2, pg 395.
+ */
+ public bool IsProbablePrime(
+ int certainty)
+ {
+ if (certainty <= 0)
+ return true;
+
+ var n = Abs();
+
+ if (!n.TestBit(0))
+ return n.Equals(Two);
+
+ if (n.Equals(One))
+ return false;
+
+ return n.CheckProbablePrime(certainty, RandomSource);
+ }
+
+ private bool CheckProbablePrime(
+ int certainty,
+ Random random)
+ {
+ Debug.Assert(certainty > 0);
+ Debug.Assert(CompareTo(Two) > 0);
+ Debug.Assert(TestBit(0));
+
+
+ // Try to reduce the penalty for really small numbers
+ var numLists = Math.Min(BitLength - 1, primeLists.Length);
+
+ for (var i = 0; i < numLists; ++i)
+ {
+ var test = Remainder(primeProducts[i]);
+
+ var primeList = primeLists[i];
+ for (var j = 0; j < primeList.Length; ++j)
+ {
+ var prime = primeList[j];
+ var qRem = test % prime;
+ if (qRem == 0)
+ return BitLength < 16 && IntValue == prime;
+ }
+ }
+
+
+ // TODO Special case for < 10^16 (RabinMiller fixed list)
+ // if (BitLength < 30)
+ // {
+ // RabinMiller against 2, 3, 5, 7, 11, 13, 23 is sufficient
+ // }
+
+
+ // TODO Is it worth trying to create a hybrid of these two?
+ return RabinMillerTest(certainty, random);
+ // return SolovayStrassenTest(certainty, random);
+
+ // bool rbTest = RabinMillerTest(certainty, random);
+ // bool ssTest = SolovayStrassenTest(certainty, random);
+ //
+ // Debug.Assert(rbTest == ssTest);
+ //
+ // return rbTest;
+ }
+
+ internal bool RabinMillerTest(
+ int certainty,
+ Random random)
+ {
+ Debug.Assert(certainty > 0);
+ Debug.Assert(BitLength > 2);
+ Debug.Assert(TestBit(0));
+
+ // let n = 1 + d . 2^s
+ var n = this;
+ var nMinusOne = n.Subtract(One);
+ var s = nMinusOne.GetLowestSetBit();
+ var r = nMinusOne.ShiftRight(s);
+
+ Debug.Assert(s >= 1);
+
+ do
+ {
+ // TODO Make a method for random BigIntegers in range 0 < x < n)
+ // - Method can be optimized by only replacing examined bits at each trial
+ BigInteger a;
+ do
+ {
+ a = new BigInteger(n.BitLength, random);
+ } while (a.CompareTo(One) <= 0 || a.CompareTo(nMinusOne) >= 0);
+
+ var y = a.ModPow(r, n);
+
+ if (!y.Equals(One))
+ {
+ var j = 0;
+ while (!y.Equals(nMinusOne))
+ {
+ if (++j == s)
+ return false;
+
+ y = y.ModPow(Two, n);
+
+ if (y.Equals(One))
+ return false;
+ }
+ }
+
+ certainty -= 2; // composites pass for only 1/4 possible 'a'
+ } while (certainty > 0);
+
+ return true;
}
public BigInteger Max(
@@ -1476,18 +1416,18 @@ namespace TLSharp.Core.MTProto.Crypto
public BigInteger Mod(
BigInteger m)
{
- if (m.sign < 1)
+ if (m.SignValue < 1)
throw new ArithmeticException("Modulus must be positive");
- BigInteger biggie = Remainder(m);
+ var biggie = Remainder(m);
- return (biggie.sign >= 0 ? biggie : biggie.Add(m));
+ return biggie.SignValue >= 0 ? biggie : biggie.Add(m);
}
public BigInteger ModInverse(
BigInteger m)
{
- if (m.sign < 1)
+ if (m.SignValue < 1)
throw new ArithmeticException("Modulus must be positive");
// TODO Too slow at the moment
@@ -1528,15 +1468,15 @@ namespace TLSharp.Core.MTProto.Crypto
// }
// }
- BigInteger x = new BigInteger();
- BigInteger gcd = ExtEuclid(this.Mod(m), m, x, null);
+ var x = new BigInteger();
+ var gcd = ExtEuclid(Mod(m), m, x, null);
if (!gcd.Equals(One))
throw new ArithmeticException("Numbers not relatively prime.");
- if (x.sign < 0)
+ if (x.SignValue < 0)
{
- x.sign = 1;
+ x.SignValue = 1;
//x = m.Subtract(x);
x.magnitude = doSubBigLil(m.magnitude, x.magnitude);
}
@@ -1567,17 +1507,17 @@ namespace TLSharp.Core.MTProto.Crypto
BigInteger u1Out,
BigInteger u2Out)
{
- BigInteger u1 = One;
- BigInteger u3 = a;
- BigInteger v1 = Zero;
- BigInteger v3 = b;
+ var u1 = One;
+ var u3 = a;
+ var v1 = Zero;
+ var v3 = b;
- while (v3.sign > 0)
+ while (v3.SignValue > 0)
{
- BigInteger[] q = u3.DivideAndRemainder(v3);
+ var q = u3.DivideAndRemainder(v3);
- BigInteger tmp = v1.Multiply(q[0]);
- BigInteger tn = u1.Subtract(tmp);
+ var tmp = v1.Multiply(q[0]);
+ var tn = u1.Subtract(tmp);
u1 = v1;
v1 = tn;
@@ -1587,16 +1527,16 @@ namespace TLSharp.Core.MTProto.Crypto
if (u1Out != null)
{
- u1Out.sign = u1.sign;
+ u1Out.SignValue = u1.SignValue;
u1Out.magnitude = u1.magnitude;
}
if (u2Out != null)
{
- BigInteger tmp = u1.Multiply(a);
+ var tmp = u1.Multiply(a);
tmp = u3.Subtract(tmp);
- BigInteger res = tmp.Divide(b);
- u2Out.sign = res.sign;
+ var res = tmp.Divide(b);
+ u2Out.SignValue = res.SignValue;
u2Out.magnitude = res.magnitude;
}
@@ -1613,16 +1553,16 @@ namespace TLSharp.Core.MTProto.Crypto
BigInteger exponent,
BigInteger m)
{
- if (m.sign < 1)
+ if (m.SignValue < 1)
throw new ArithmeticException("Modulus must be positive");
if (m.Equals(One))
return Zero;
- if (exponent.sign == 0)
+ if (exponent.SignValue == 0)
return One;
- if (sign == 0)
+ if (SignValue == 0)
return Zero;
int[] zVal = null;
@@ -1631,24 +1571,24 @@ namespace TLSharp.Core.MTProto.Crypto
// Montgomery exponentiation is only possible if the modulus is odd,
// but AFAIK, this is always the case for crypto algo's
- bool useMonty = ((m.magnitude[m.magnitude.Length - 1] & 1) == 1);
+ var useMonty = (m.magnitude[m.magnitude.Length - 1] & 1) == 1;
long mQ = 0;
if (useMonty)
{
mQ = m.GetMQuote();
// tmp = this * R mod m
- BigInteger tmp = ShiftLeft(32 * m.magnitude.Length).Mod(m);
+ var tmp = ShiftLeft(32 * m.magnitude.Length).Mod(m);
zVal = tmp.magnitude;
- useMonty = (zVal.Length <= m.magnitude.Length);
+ useMonty = zVal.Length <= m.magnitude.Length;
if (useMonty)
{
yAccum = new int[m.magnitude.Length + 1];
if (zVal.Length < m.magnitude.Length)
{
- int[] longZ = new int[m.magnitude.Length];
+ var longZ = new int[m.magnitude.Length];
zVal.CopyTo(longZ, longZ.Length - zVal.Length);
zVal = longZ;
}
@@ -1663,11 +1603,12 @@ namespace TLSharp.Core.MTProto.Crypto
zVal = new int[m.magnitude.Length];
magnitude.CopyTo(zVal, zVal.Length - magnitude.Length);
}
- else {
+ else
+ {
//
// in normal practice we'll never see this...
//
- BigInteger tmp = Remainder(m);
+ var tmp = Remainder(m);
//zAccum = new int[m.magnitude.Length * 2];
zVal = new int[m.magnitude.Length];
@@ -1682,10 +1623,10 @@ namespace TLSharp.Core.MTProto.Crypto
//
// from LSW to MSW
//
- for (int i = 0; i < exponent.magnitude.Length; i++)
+ for (var i = 0; i < exponent.magnitude.Length; i++)
{
- int v = exponent.magnitude[i];
- int bits = 0;
+ var v = exponent.magnitude[i];
+ var bits = 0;
if (i == 0)
{
@@ -1713,7 +1654,8 @@ namespace TLSharp.Core.MTProto.Crypto
// be almost as heavy as a Montgomery mulitply.
MultiplyMonty(yAccum, yVal, yVal, m.magnitude, mQ);
}
- else {
+ else
+ {
Square(yAccum, yVal);
Remainder(yAccum, m.magnitude);
Array.Copy(yAccum, yAccum.Length - yVal.Length, yVal, 0, yVal.Length);
@@ -1722,19 +1664,18 @@ namespace TLSharp.Core.MTProto.Crypto
bits++;
if (v < 0)
- {
if (useMonty)
{
MultiplyMonty(yAccum, yVal, zVal, m.magnitude, mQ);
}
- else {
+ else
+ {
Multiply(yAccum, yVal, zVal);
Remainder(yAccum, m.magnitude);
Array.Copy(yAccum, yAccum.Length - yVal.Length, yVal, 0,
yVal.Length);
ZeroOut(yAccum);
}
- }
v <<= 1;
}
@@ -1745,7 +1686,8 @@ namespace TLSharp.Core.MTProto.Crypto
{
MultiplyMonty(yAccum, yVal, yVal, m.magnitude, mQ);
}
- else {
+ else
+ {
Square(yAccum, yVal);
Remainder(yAccum, m.magnitude);
Array.Copy(yAccum, yAccum.Length - yVal.Length, yVal, 0, yVal.Length);
@@ -1763,9 +1705,9 @@ namespace TLSharp.Core.MTProto.Crypto
MultiplyMonty(yAccum, yVal, zVal, m.magnitude, mQ);
}
- BigInteger result = new BigInteger(1, yVal, true);
+ var result = new BigInteger(1, yVal, true);
- return exponent.sign > 0
+ return exponent.SignValue > 0
? result
: result.ModInverse(m);
}
@@ -1783,61 +1725,53 @@ namespace TLSharp.Core.MTProto.Crypto
ulong u1, u2, c;
- int wBase = w.Length - 1;
+ var wBase = w.Length - 1;
- for (int i = x.Length - 1; i != 0; i--)
+ for (var i = x.Length - 1; i != 0; i--)
{
- ulong v = (ulong)(uint)x[i];
+ ulong v = (uint) x[i];
u1 = v * v;
u2 = u1 >> 32;
- u1 = (uint)u1;
+ u1 = (uint) u1;
- u1 += (ulong)(uint)w[wBase];
+ u1 += (uint) w[wBase];
- w[wBase] = (int)(uint)u1;
+ w[wBase] = (int) (uint) u1;
c = u2 + (u1 >> 32);
- for (int j = i - 1; j >= 0; j--)
+ for (var j = i - 1; j >= 0; j--)
{
--wBase;
- u1 = v * (ulong)(uint)x[j];
+ u1 = v * (uint) x[j];
u2 = u1 >> 31; // multiply by 2!
- u1 = (uint)(u1 << 1); // multiply by 2!
- u1 += c + (ulong)(uint)w[wBase];
+ u1 = (uint) (u1 << 1); // multiply by 2!
+ u1 += c + (uint) w[wBase];
- w[wBase] = (int)(uint)u1;
+ w[wBase] = (int) (uint) u1;
c = u2 + (u1 >> 32);
}
- c += (ulong)(uint)w[--wBase];
- w[wBase] = (int)(uint)c;
+ c += (uint) w[--wBase];
+ w[wBase] = (int) (uint) c;
if (--wBase >= 0)
- {
- w[wBase] = (int)(uint)(c >> 32);
- }
- else {
- Debug.Assert((uint)(c >> 32) == 0);
- }
+ w[wBase] = (int) (uint) (c >> 32);
+ else Debug.Assert((uint) (c >> 32) == 0);
wBase += i;
}
- u1 = (ulong)(uint)x[0];
+ u1 = (uint) x[0];
u1 = u1 * u1;
u2 = u1 >> 32;
u1 = u1 & IMASK;
- u1 += (ulong)(uint)w[wBase];
+ u1 += (uint) w[wBase];
- w[wBase] = (int)(uint)u1;
+ w[wBase] = (int) (uint) u1;
if (--wBase >= 0)
- {
- w[wBase] = (int)(uint)(u2 + (u1 >> 32) + (ulong)(uint)w[wBase]);
- }
- else {
- Debug.Assert((uint)(u2 + (u1 >> 32)) == 0);
- }
+ w[wBase] = (int) (uint) (u2 + (u1 >> 32) + (uint) w[wBase]);
+ else Debug.Assert((uint) (u2 + (u1 >> 32)) == 0);
return w;
}
@@ -1850,25 +1784,25 @@ namespace TLSharp.Core.MTProto.Crypto
int[] y,
int[] z)
{
- int i = z.Length;
+ var i = z.Length;
if (i < 1)
return x;
- int xBase = x.Length - y.Length;
+ var xBase = x.Length - y.Length;
for (;;)
{
- long a = z[--i] & IMASK;
+ var a = z[--i] & IMASK;
long val = 0;
- for (int j = y.Length - 1; j >= 0; j--)
+ for (var j = y.Length - 1; j >= 0; j--)
{
val += a * (y[j] & IMASK) + (x[xBase + j] & IMASK);
- x[xBase + j] = (int)val;
+ x[xBase + j] = (int) val;
- val = (long)((ulong)val >> 32);
+ val = (long) ((ulong) val >> 32);
}
--xBase;
@@ -1876,16 +1810,12 @@ namespace TLSharp.Core.MTProto.Crypto
if (i < 1)
{
if (xBase >= 0)
- {
- x[xBase] = (int)val;
- }
- else {
- Debug.Assert(val == 0);
- }
+ x[xBase] = (int) val;
+ else Debug.Assert(val == 0);
break;
}
- x[xBase] = (int)val;
+ x[xBase] = (int) val;
}
return x;
@@ -1897,9 +1827,9 @@ namespace TLSharp.Core.MTProto.Crypto
long[] uOut)
{
long u1 = 1;
- long u3 = a;
+ var u3 = a;
long v1 = 0;
- long v3 = b;
+ var v3 = b;
while (v3 > 0)
{
@@ -1907,17 +1837,17 @@ namespace TLSharp.Core.MTProto.Crypto
q = u3 / v3;
- tn = u1 - (v1 * q);
+ tn = u1 - v1 * q;
u1 = v1;
v1 = tn;
- tn = u3 - (v3 * q);
+ tn = u3 - v3 * q;
u3 = v3;
v3 = tn;
}
uOut[0] = u1;
- uOut[1] = (u3 - (u1 * a)) / b;
+ uOut[1] = (u3 - u1 * a) / b;
return u3;
}
@@ -1929,16 +1859,14 @@ namespace TLSharp.Core.MTProto.Crypto
if (m < 1)
throw new ArithmeticException("Modulus must be positive");
- long[] x = new long[2];
- long gcd = FastExtEuclid(v, m, x);
+ var x = new long[2];
+ var gcd = FastExtEuclid(v, m, x);
if (gcd != 1)
throw new ArithmeticException("Numbers not relatively prime.");
if (x[0] < 0)
- {
x[0] += m;
- }
return x[0];
}
@@ -1951,19 +1879,15 @@ namespace TLSharp.Core.MTProto.Crypto
*/
private long GetMQuote()
{
- Debug.Assert(this.sign > 0);
+ Debug.Assert(SignValue > 0);
if (mQuote != -1)
- {
return mQuote; // already calculated
- }
if (magnitude.Length == 0 || (magnitude[magnitude.Length - 1] & 1) == 0)
- {
return -1; // not for even numbers
- }
- long v = (((~this.magnitude[this.magnitude.Length - 1]) | 1) & 0xffffffffL);
+ var v = (~magnitude[magnitude.Length - 1] | 1) & 0xffffffffL;
mQuote = FastModInverse(v, 0x100000000L);
return mQuote;
@@ -1983,58 +1907,56 @@ namespace TLSharp.Core.MTProto.Crypto
* NOTE: the indices of x, y, m, a different in HAC and in Java
*/
private static void MultiplyMonty(
- int[] a,
- int[] x,
- int[] y,
- int[] m,
- long mQuote)
- // mQuote = -m^(-1) mod b
+ int[] a,
+ int[] x,
+ int[] y,
+ int[] m,
+ long mQuote)
+ // mQuote = -m^(-1) mod b
{
if (m.Length == 1)
{
- x[0] = (int)MultiplyMontyNIsOne((uint)x[0], (uint)y[0], (uint)m[0], (ulong)mQuote);
+ x[0] = (int) MultiplyMontyNIsOne((uint) x[0], (uint) y[0], (uint) m[0], (ulong) mQuote);
return;
}
- int n = m.Length;
- int nMinus1 = n - 1;
- long y_0 = y[nMinus1] & IMASK;
+ var n = m.Length;
+ var nMinus1 = n - 1;
+ var y_0 = y[nMinus1] & IMASK;
// 1. a = 0 (Notation: a = (a_{n} a_{n-1} ... a_{0})_{b} )
Array.Clear(a, 0, n + 1);
// 2. for i from 0 to (n - 1) do the following:
- for (int i = n; i > 0; i--)
+ for (var i = n; i > 0; i--)
{
- long x_i = x[i - 1] & IMASK;
+ var x_i = x[i - 1] & IMASK;
// 2.1 u = ((a[0] + (x[i] * y[0]) * mQuote) mod b
- long u = ((((a[n] & IMASK) + ((x_i * y_0) & IMASK)) & IMASK) * mQuote) & IMASK;
+ var u = ((((a[n] & IMASK) + ((x_i * y_0) & IMASK)) & IMASK) * mQuote) & IMASK;
// 2.2 a = (a + x_i * y + u * m) / b
- long prod1 = x_i * y_0;
- long prod2 = u * (m[nMinus1] & IMASK);
- long tmp = (a[n] & IMASK) + (prod1 & IMASK) + (prod2 & IMASK);
- long carry = (long)((ulong)prod1 >> 32) + (long)((ulong)prod2 >> 32) + (long)((ulong)tmp >> 32);
- for (int j = nMinus1; j > 0; j--)
+ var prod1 = x_i * y_0;
+ var prod2 = u * (m[nMinus1] & IMASK);
+ var tmp = (a[n] & IMASK) + (prod1 & IMASK) + (prod2 & IMASK);
+ var carry = (long) ((ulong) prod1 >> 32) + (long) ((ulong) prod2 >> 32) + (long) ((ulong) tmp >> 32);
+ for (var j = nMinus1; j > 0; j--)
{
prod1 = x_i * (y[j - 1] & IMASK);
prod2 = u * (m[j - 1] & IMASK);
tmp = (a[j] & IMASK) + (prod1 & IMASK) + (prod2 & IMASK) + (carry & IMASK);
- carry = (long)((ulong)carry >> 32) + (long)((ulong)prod1 >> 32) +
- (long)((ulong)prod2 >> 32) + (long)((ulong)tmp >> 32);
- a[j + 1] = (int)tmp; // division by b
+ carry = (long) ((ulong) carry >> 32) + (long) ((ulong) prod1 >> 32) +
+ (long) ((ulong) prod2 >> 32) + (long) ((ulong) tmp >> 32);
+ a[j + 1] = (int) tmp; // division by b
}
- carry += (a[0] & IMASK);
- a[1] = (int)carry;
- a[0] = (int)((ulong)carry >> 32); // OJO!!!!!
+ carry += a[0] & IMASK;
+ a[1] = (int) carry;
+ a[0] = (int) ((ulong) carry >> 32); // OJO!!!!!
}
// 3. if x >= m the x = x - m
if (CompareTo(0, a, 0, m) >= 0)
- {
Subtract(0, a, 0, m);
- }
// put the result in x
Array.Copy(a, 1, x, 0, n);
@@ -2047,74 +1969,66 @@ namespace TLSharp.Core.MTProto.Crypto
ulong mQuote)
{
ulong um = m;
- ulong prod1 = (ulong)x * (ulong)y;
- ulong u = (prod1 * mQuote) & UIMASK;
- ulong prod2 = u * um;
- ulong tmp = (prod1 & UIMASK) + (prod2 & UIMASK);
- ulong carry = (prod1 >> 32) + (prod2 >> 32) + (tmp >> 32);
+ var prod1 = x * (ulong) y;
+ var u = (prod1 * mQuote) & UIMASK;
+ var prod2 = u * um;
+ var tmp = (prod1 & UIMASK) + (prod2 & UIMASK);
+ var carry = (prod1 >> 32) + (prod2 >> 32) + (tmp >> 32);
if (carry > um)
- {
carry -= um;
- }
- return (uint)(carry & UIMASK);
+ return (uint) (carry & UIMASK);
}
public BigInteger Multiply(
BigInteger val)
{
- if (sign == 0 || val.sign == 0)
+ if (SignValue == 0 || val.SignValue == 0)
return Zero;
if (val.QuickPow2Check()) // val is power of two
{
- BigInteger result = this.ShiftLeft(val.Abs().BitLength - 1);
- return val.sign > 0 ? result : result.Negate();
+ var result = ShiftLeft(val.Abs().BitLength - 1);
+ return val.SignValue > 0 ? result : result.Negate();
}
- if (this.QuickPow2Check()) // this is power of two
+ if (QuickPow2Check()) // this is power of two
{
- BigInteger result = val.ShiftLeft(this.Abs().BitLength - 1);
- return this.sign > 0 ? result : result.Negate();
+ var result = val.ShiftLeft(Abs().BitLength - 1);
+ return SignValue > 0 ? result : result.Negate();
}
- int resLength = (this.BitLength + val.BitLength) / BitsPerInt + 1;
- int[] res = new int[resLength];
+ var resLength = (BitLength + val.BitLength) / BitsPerInt + 1;
+ var res = new int[resLength];
if (val == this)
- {
- Square(res, this.magnitude);
- }
- else {
- Multiply(res, this.magnitude, val.magnitude);
- }
+ Square(res, magnitude);
+ else Multiply(res, magnitude, val.magnitude);
- return new BigInteger(sign * val.sign, res, true);
+ return new BigInteger(SignValue * val.SignValue, res, true);
}
public BigInteger Negate()
{
- if (sign == 0)
+ if (SignValue == 0)
return this;
- return new BigInteger(-sign, magnitude, false);
+ return new BigInteger(-SignValue, magnitude, false);
}
public BigInteger NextProbablePrime()
{
- if (sign < 0)
+ if (SignValue < 0)
throw new ArithmeticException("Cannot be called on value < 0");
if (CompareTo(Two) < 0)
return Two;
- BigInteger n = Inc().SetBit(0);
+ var n = Inc().SetBit(0);
while (!n.CheckProbablePrime(100, RandomSource))
- {
n = n.Add(Two);
- }
return n;
}
@@ -2127,29 +2041,21 @@ namespace TLSharp.Core.MTProto.Crypto
public BigInteger Pow(int exp)
{
if (exp < 0)
- {
throw new ArithmeticException("Negative exponent");
- }
if (exp == 0)
- {
return One;
- }
- if (sign == 0 || Equals(One))
- {
+ if (SignValue == 0 || Equals(One))
return this;
- }
- BigInteger y = One;
- BigInteger z = this;
+ var y = One;
+ var z = this;
for (;;)
{
if ((exp & 0x1) == 1)
- {
y = y.Multiply(z);
- }
exp >>= 1;
if (exp == 0) break;
z = z.Multiply(z);
@@ -2171,13 +2077,13 @@ namespace TLSharp.Core.MTProto.Crypto
Debug.Assert(m > 0);
long acc = 0;
- for (int pos = 0; pos < magnitude.Length; ++pos)
+ for (var pos = 0; pos < magnitude.Length; ++pos)
{
- long posVal = (uint)magnitude[pos];
- acc = (acc << 32 | posVal) % m;
+ long posVal = (uint) magnitude[pos];
+ acc = ((acc << 32) | posVal) % m;
}
- return (int)acc;
+ return (int) acc;
}
/**
@@ -2187,39 +2093,36 @@ namespace TLSharp.Core.MTProto.Crypto
int[] x,
int[] y)
{
- int xStart = 0;
+ var xStart = 0;
while (xStart < x.Length && x[xStart] == 0)
- {
++xStart;
- }
- int yStart = 0;
+ var yStart = 0;
while (yStart < y.Length && y[yStart] == 0)
- {
++yStart;
- }
Debug.Assert(yStart < y.Length);
- int xyCmp = CompareNoLeadingZeroes(xStart, x, yStart, y);
+ var xyCmp = CompareNoLeadingZeroes(xStart, x, yStart, y);
if (xyCmp > 0)
{
- int yBitLength = calcBitLength(yStart, y);
- int xBitLength = calcBitLength(xStart, x);
- int shift = xBitLength - yBitLength;
+ var yBitLength = calcBitLength(yStart, y);
+ var xBitLength = calcBitLength(xStart, x);
+ var shift = xBitLength - yBitLength;
int[] c;
- int cStart = 0;
- int cBitLength = yBitLength;
+ var cStart = 0;
+ var cBitLength = yBitLength;
if (shift > 0)
{
c = ShiftLeft(y, shift);
cBitLength += shift;
Debug.Assert(c[0] != 0);
}
- else {
- int len = y.Length - yStart;
+ else
+ {
+ var len = y.Length - yStart;
c = new int[len];
Array.Copy(y, yStart, c, 0, len);
}
@@ -2232,10 +2135,8 @@ namespace TLSharp.Core.MTProto.Crypto
Subtract(xStart, x, cStart, c);
while (x[xStart] == 0)
- {
if (++xStart == x.Length)
return x;
- }
//xBitLength = calcBitLength(xStart, x);
xBitLength = 32 * (x.Length - xStart - 1) + BitLen(x[xStart]);
@@ -2257,8 +2158,8 @@ namespace TLSharp.Core.MTProto.Crypto
// NB: The case where c[cStart] is 1-bit is harmless
if (shift == 1)
{
- uint firstC = (uint)c[cStart] >> 1;
- uint firstX = (uint)x[xStart];
+ var firstC = (uint) c[cStart] >> 1;
+ var firstX = (uint) x[xStart];
if (firstC > firstX)
++shift;
}
@@ -2268,23 +2169,20 @@ namespace TLSharp.Core.MTProto.Crypto
ShiftRightOneInPlace(cStart, c);
--cBitLength;
}
- else {
+ else
+ {
ShiftRightInPlace(cStart, c, shift);
cBitLength -= shift;
}
//cStart = c.Length - ((cBitLength + 31) / 32);
while (c[cStart] == 0)
- {
++cStart;
- }
}
}
if (xyCmp == 0)
- {
Array.Clear(x, xStart, x.Length - xStart);
- }
return x;
}
@@ -2292,16 +2190,16 @@ namespace TLSharp.Core.MTProto.Crypto
public BigInteger Remainder(
BigInteger n)
{
- if (n.sign == 0)
+ if (n.SignValue == 0)
throw new ArithmeticException("Division by zero error");
- if (this.sign == 0)
+ if (SignValue == 0)
return Zero;
// For small values, use fast remainder method
if (n.magnitude.Length == 1)
{
- int val = n.magnitude[0];
+ var val = n.magnitude[0];
if (val > 0)
{
@@ -2309,11 +2207,11 @@ namespace TLSharp.Core.MTProto.Crypto
return Zero;
// TODO Make this func work on uint, and handle val == 1?
- int rem = Remainder(val);
+ var rem = Remainder(val);
return rem == 0
? Zero
- : new BigInteger(sign, new int[] { rem }, false);
+ : new BigInteger(SignValue, new[] {rem}, false);
}
}
@@ -2321,17 +2219,18 @@ namespace TLSharp.Core.MTProto.Crypto
return this;
int[] result;
- if (n.QuickPow2Check()) // n is power of two
+ if (n.QuickPow2Check()) // n is power of two
{
// TODO Move before small values branch above?
result = LastNBits(n.Abs().BitLength - 1);
}
- else {
- result = (int[])this.magnitude.Clone();
+ else
+ {
+ result = (int[]) magnitude.Clone();
result = Remainder(result, n.magnitude);
}
- return new BigInteger(sign, result, true);
+ return new BigInteger(SignValue, result, true);
}
private int[] LastNBits(
@@ -2340,17 +2239,15 @@ namespace TLSharp.Core.MTProto.Crypto
if (n < 1)
return ZeroMagnitude;
- int numWords = (n + BitsPerInt - 1) / BitsPerInt;
- numWords = System.Math.Min(numWords, this.magnitude.Length);
- int[] result = new int[numWords];
+ var numWords = (n + BitsPerInt - 1) / BitsPerInt;
+ numWords = Math.Min(numWords, magnitude.Length);
+ var result = new int[numWords];
- Array.Copy(this.magnitude, this.magnitude.Length - numWords, result, 0, numWords);
+ Array.Copy(magnitude, magnitude.Length - numWords, result, 0, numWords);
- int hiBits = n % 32;
+ var hiBits = n % 32;
if (hiBits != 0)
- {
result[0] &= ~(-1 << hiBits);
- }
return result;
}
@@ -2362,9 +2259,9 @@ namespace TLSharp.Core.MTProto.Crypto
int[] mag,
int n)
{
- int nInts = (int)((uint)n >> 5);
- int nBits = n & 0x1f;
- int magLen = mag.Length;
+ var nInts = (int) ((uint) n >> 5);
+ var nBits = n & 0x1f;
+ var magLen = mag.Length;
int[] newMag;
if (nBits == 0)
@@ -2372,26 +2269,28 @@ namespace TLSharp.Core.MTProto.Crypto
newMag = new int[magLen + nInts];
mag.CopyTo(newMag, 0);
}
- else {
- int i = 0;
- int nBits2 = 32 - nBits;
- int highBits = (int)((uint)mag[0] >> nBits2);
+ else
+ {
+ var i = 0;
+ var nBits2 = 32 - nBits;
+ var highBits = (int) ((uint) mag[0] >> nBits2);
if (highBits != 0)
{
newMag = new int[magLen + nInts + 1];
newMag[i++] = highBits;
}
- else {
+ else
+ {
newMag = new int[magLen + nInts];
}
- int m = mag[0];
- for (int j = 0; j < magLen - 1; j++)
+ var m = mag[0];
+ for (var j = 0; j < magLen - 1; j++)
{
- int next = mag[j + 1];
+ var next = mag[j + 1];
- newMag[i++] = (m << nBits) | (int)((uint)next >> nBits2);
+ newMag[i++] = (m << nBits) | (int) ((uint) next >> nBits2);
m = next;
}
@@ -2404,7 +2303,7 @@ namespace TLSharp.Core.MTProto.Crypto
public BigInteger ShiftLeft(
int n)
{
- if (sign == 0 || magnitude.Length == 0)
+ if (SignValue == 0 || magnitude.Length == 0)
return Zero;
if (n == 0)
@@ -2413,19 +2312,15 @@ namespace TLSharp.Core.MTProto.Crypto
if (n < 0)
return ShiftRight(-n);
- BigInteger result = new BigInteger(sign, ShiftLeft(magnitude, n), true);
+ var result = new BigInteger(SignValue, ShiftLeft(magnitude, n), true);
- if (this.nBits != -1)
- {
- result.nBits = sign > 0
- ? this.nBits
- : this.nBits + n;
- }
+ if (nBits != -1)
+ result.nBits = SignValue > 0
+ ? nBits
+ : nBits + n;
- if (this.nBitLength != -1)
- {
- result.nBitLength = this.nBitLength + n;
- }
+ if (nBitLength != -1)
+ result.nBitLength = nBitLength + n;
return result;
}
@@ -2438,38 +2333,34 @@ namespace TLSharp.Core.MTProto.Crypto
int[] mag,
int n)
{
- int nInts = (int)((uint)n >> 5) + start;
- int nBits = n & 0x1f;
- int magEnd = mag.Length - 1;
+ var nInts = (int) ((uint) n >> 5) + start;
+ var nBits = n & 0x1f;
+ var magEnd = mag.Length - 1;
if (nInts != start)
{
- int delta = (nInts - start);
+ var delta = nInts - start;
- for (int i = magEnd; i >= nInts; i--)
- {
+ for (var i = magEnd; i >= nInts; i--)
mag[i] = mag[i - delta];
- }
- for (int i = nInts - 1; i >= start; i--)
- {
+ for (var i = nInts - 1; i >= start; i--)
mag[i] = 0;
- }
}
if (nBits != 0)
{
- int nBits2 = 32 - nBits;
- int m = mag[magEnd];
+ var nBits2 = 32 - nBits;
+ var m = mag[magEnd];
- for (int i = magEnd; i > nInts; --i)
+ for (var i = magEnd; i > nInts; --i)
{
- int next = mag[i - 1];
+ var next = mag[i - 1];
- mag[i] = (int)((uint)m >> nBits) | (next << nBits2);
+ mag[i] = (int) ((uint) m >> nBits) | (next << nBits2);
m = next;
}
- mag[nInts] = (int)((uint)mag[nInts] >> nBits);
+ mag[nInts] = (int) ((uint) mag[nInts] >> nBits);
}
}
@@ -2480,17 +2371,17 @@ namespace TLSharp.Core.MTProto.Crypto
int start,
int[] mag)
{
- int i = mag.Length;
- int m = mag[i - 1];
+ var i = mag.Length;
+ var m = mag[i - 1];
while (--i > start)
{
- int next = mag[i - 1];
- mag[i] = ((int)((uint)m >> 1)) | (next << 31);
+ var next = mag[i - 1];
+ mag[i] = (int) ((uint) m >> 1) | (next << 31);
m = next;
}
- mag[start] = (int)((uint)mag[start] >> 1);
+ mag[start] = (int) ((uint) mag[start] >> 1);
}
public BigInteger ShiftRight(
@@ -2503,7 +2394,7 @@ namespace TLSharp.Core.MTProto.Crypto
return ShiftLeft(-n);
if (n >= BitLength)
- return (this.sign < 0 ? One.Negate() : Zero);
+ return SignValue < 0 ? One.Negate() : Zero;
// int[] res = (int[]) this.magnitude.Clone();
//
@@ -2511,39 +2402,33 @@ namespace TLSharp.Core.MTProto.Crypto
//
// return new BigInteger(this.sign, res, true);
- int resultLength = (BitLength - n + 31) >> 5;
- int[] res = new int[resultLength];
+ var resultLength = (BitLength - n + 31) >> 5;
+ var res = new int[resultLength];
- int numInts = n >> 5;
- int numBits = n & 31;
+ var numInts = n >> 5;
+ var numBits = n & 31;
if (numBits == 0)
{
- Array.Copy(this.magnitude, 0, res, 0, res.Length);
+ Array.Copy(magnitude, 0, res, 0, res.Length);
}
- else {
- int numBits2 = 32 - numBits;
+ else
+ {
+ var numBits2 = 32 - numBits;
- int magPos = this.magnitude.Length - 1 - numInts;
- for (int i = resultLength - 1; i >= 0; --i)
+ var magPos = magnitude.Length - 1 - numInts;
+ for (var i = resultLength - 1; i >= 0; --i)
{
- res[i] = (int)((uint)this.magnitude[magPos--] >> numBits);
+ res[i] = (int) ((uint) magnitude[magPos--] >> numBits);
if (magPos >= 0)
- {
- res[i] |= this.magnitude[magPos] << numBits2;
- }
+ res[i] |= magnitude[magPos] << numBits2;
}
}
Debug.Assert(res[0] != 0);
- return new BigInteger(this.sign, res, false);
- }
-
- public int SignValue
- {
- get { return sign; }
+ return new BigInteger(SignValue, res, false);
}
/**
@@ -2558,27 +2443,24 @@ namespace TLSharp.Core.MTProto.Crypto
Debug.Assert(yStart < y.Length);
Debug.Assert(x.Length - xStart >= y.Length - yStart);
- int iT = x.Length;
- int iV = y.Length;
+ var iT = x.Length;
+ var iV = y.Length;
long m;
- int borrow = 0;
+ var borrow = 0;
do
{
m = (x[--iT] & IMASK) - (y[--iV] & IMASK) + borrow;
- x[iT] = (int)m;
+ x[iT] = (int) m;
// borrow = (m < 0) ? -1 : 0;
- borrow = (int)(m >> 63);
- }
- while (iV > yStart);
+ borrow = (int) (m >> 63);
+ } while (iV > yStart);
if (borrow != 0)
- {
while (--x[--iT] == -1)
{
}
- }
return x;
}
@@ -2586,16 +2468,16 @@ namespace TLSharp.Core.MTProto.Crypto
public BigInteger Subtract(
BigInteger n)
{
- if (n.sign == 0)
+ if (n.SignValue == 0)
return this;
- if (this.sign == 0)
+ if (SignValue == 0)
return n.Negate();
- if (this.sign != n.sign)
+ if (SignValue != n.SignValue)
return Add(n.Negate());
- int compare = CompareNoLeadingZeroes(0, magnitude, 0, n.magnitude);
+ var compare = CompareNoLeadingZeroes(0, magnitude, 0, n.magnitude);
if (compare == 0)
return Zero;
@@ -2605,19 +2487,20 @@ namespace TLSharp.Core.MTProto.Crypto
bigun = n;
lilun = this;
}
- else {
+ else
+ {
bigun = this;
lilun = n;
}
- return new BigInteger(this.sign * compare, doSubBigLil(bigun.magnitude, lilun.magnitude), true);
+ return new BigInteger(SignValue * compare, doSubBigLil(bigun.magnitude, lilun.magnitude), true);
}
private static int[] doSubBigLil(
int[] bigMag,
int[] lilMag)
{
- int[] res = (int[])bigMag.Clone();
+ var res = (int[]) bigMag.Clone();
return Subtract(0, res, 0, lilMag);
}
@@ -2635,78 +2518,71 @@ namespace TLSharp.Core.MTProto.Crypto
private byte[] ToByteArray(
bool unsigned)
{
- if (sign == 0)
+ if (SignValue == 0)
return unsigned ? ZeroEncoding : new byte[1];
- int nBits = (unsigned && sign > 0)
+ var nBits = unsigned && SignValue > 0
? BitLength
: BitLength + 1;
- int nBytes = GetByteLength(nBits);
- byte[] bytes = new byte[nBytes];
+ var nBytes = GetByteLength(nBits);
+ var bytes = new byte[nBytes];
- int magIndex = magnitude.Length;
- int bytesIndex = bytes.Length;
+ var magIndex = magnitude.Length;
+ var bytesIndex = bytes.Length;
- if (sign > 0)
+ if (SignValue > 0)
{
while (magIndex > 1)
{
- uint mag = (uint)magnitude[--magIndex];
- bytes[--bytesIndex] = (byte)mag;
- bytes[--bytesIndex] = (byte)(mag >> 8);
- bytes[--bytesIndex] = (byte)(mag >> 16);
- bytes[--bytesIndex] = (byte)(mag >> 24);
+ var mag = (uint) magnitude[--magIndex];
+ bytes[--bytesIndex] = (byte) mag;
+ bytes[--bytesIndex] = (byte) (mag >> 8);
+ bytes[--bytesIndex] = (byte) (mag >> 16);
+ bytes[--bytesIndex] = (byte) (mag >> 24);
}
- uint lastMag = (uint)magnitude[0];
+ var lastMag = (uint) magnitude[0];
while (lastMag > byte.MaxValue)
{
- bytes[--bytesIndex] = (byte)lastMag;
+ bytes[--bytesIndex] = (byte) lastMag;
lastMag >>= 8;
}
- bytes[--bytesIndex] = (byte)lastMag;
+ bytes[--bytesIndex] = (byte) lastMag;
}
else // sign < 0
{
- bool carry = true;
+ var carry = true;
while (magIndex > 1)
{
- uint mag = ~((uint)magnitude[--magIndex]);
+ var mag = ~(uint) magnitude[--magIndex];
if (carry)
- {
- carry = (++mag == uint.MinValue);
- }
+ carry = ++mag == uint.MinValue;
- bytes[--bytesIndex] = (byte)mag;
- bytes[--bytesIndex] = (byte)(mag >> 8);
- bytes[--bytesIndex] = (byte)(mag >> 16);
- bytes[--bytesIndex] = (byte)(mag >> 24);
+ bytes[--bytesIndex] = (byte) mag;
+ bytes[--bytesIndex] = (byte) (mag >> 8);
+ bytes[--bytesIndex] = (byte) (mag >> 16);
+ bytes[--bytesIndex] = (byte) (mag >> 24);
}
- uint lastMag = (uint)magnitude[0];
+ var lastMag = (uint) magnitude[0];
if (carry)
- {
- // Never wraps because magnitude[0] != 0
--lastMag;
- }
while (lastMag > byte.MaxValue)
{
- bytes[--bytesIndex] = (byte)~lastMag;
+ bytes[--bytesIndex] = (byte) ~lastMag;
lastMag >>= 8;
}
- bytes[--bytesIndex] = (byte)~lastMag;
+ bytes[--bytesIndex] = (byte) ~lastMag;
if (bytesIndex > 0)
- {
bytes[--bytesIndex] = byte.MaxValue;
- }
}
return bytes;
@@ -2736,35 +2612,32 @@ namespace TLSharp.Core.MTProto.Crypto
if (magnitude == null)
return "null";
- if (sign == 0)
+ if (SignValue == 0)
return "0";
Debug.Assert(magnitude.Length > 0);
- StringBuilder sb = new StringBuilder();
+ var sb = new StringBuilder();
if (radix == 16)
{
sb.Append(magnitude[0].ToString("x"));
- for (int i = 1; i < magnitude.Length; i++)
- {
+ for (var i = 1; i < magnitude.Length; i++)
sb.Append(magnitude[i].ToString("x8"));
- }
}
else if (radix == 2)
{
sb.Append('1');
- for (int i = BitLength - 2; i >= 0; --i)
- {
+ for (var i = BitLength - 2; i >= 0; --i)
sb.Append(TestBit(i) ? '1' : '0');
- }
}
- else {
+ else
+ {
// This is algorithm 1a from chapter 4.4 in Seminumerical Algorithms, slow but it works
IList S = new List