2021-08-16 22:30:45 +02:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.Formats.Asn1;
|
|
|
|
|
|
using System.Net;
|
|
|
|
|
|
using System.Numerics;
|
|
|
|
|
|
using System.Security.Cryptography;
|
|
|
|
|
|
|
|
|
|
|
|
namespace WTelegram
|
|
|
|
|
|
{
|
|
|
|
|
|
static class Compat
|
|
|
|
|
|
{
|
|
|
|
|
|
#if NETCOREAPP2_1_OR_GREATER
|
2021-08-16 22:52:33 +02:00
|
|
|
|
internal static IPEndPoint IPEndPoint_Parse(string addr) => IPEndPoint.Parse(addr);
|
|
|
|
|
|
internal static BigInteger BigEndianInteger(byte[] value) => new(value, true, true);
|
2021-08-16 22:30:45 +02:00
|
|
|
|
#else
|
|
|
|
|
|
internal static BigInteger BigEndianInteger(byte[] value)
|
|
|
|
|
|
{
|
|
|
|
|
|
var data = new byte[value.Length + 1];
|
|
|
|
|
|
value.CopyTo(data, 1);
|
|
|
|
|
|
Array.Reverse(data);
|
|
|
|
|
|
return new BigInteger(data);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
internal static byte[] ToByteArray(this BigInteger bigInteger, bool isUnsigned = false, bool isBigEndian = false)
|
|
|
|
|
|
{
|
2021-08-25 12:53:36 +02:00
|
|
|
|
if (!isBigEndian || !isUnsigned) throw new ArgumentException("Unexpected parameters to ToByteArray");
|
2021-08-16 22:30:45 +02:00
|
|
|
|
var result = bigInteger.ToByteArray();
|
|
|
|
|
|
if (result[^1] == 0) result = result[0..^1];
|
|
|
|
|
|
Array.Reverse(result);
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-08-20 02:13:58 +02:00
|
|
|
|
internal static long GetBitLength(this BigInteger bigInteger)
|
2021-08-16 22:30:45 +02:00
|
|
|
|
{
|
|
|
|
|
|
var bytes = bigInteger.ToByteArray();
|
2021-08-20 02:13:58 +02:00
|
|
|
|
var length = bytes.LongLength * 8L;
|
2021-08-16 22:30:45 +02:00
|
|
|
|
int lastByte = bytes[^1];
|
|
|
|
|
|
while ((lastByte & 0x80) == 0) { length--; lastByte = (lastByte << 1) + 1; }
|
|
|
|
|
|
return length;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static V GetValueOrDefault<K, V>(this Dictionary<K, V> dictionary, K key, V defaultValue = default)
|
|
|
|
|
|
=> dictionary.TryGetValue(key, out V value) ? value : defaultValue;
|
|
|
|
|
|
|
|
|
|
|
|
public static void Deconstruct<K, V>(this KeyValuePair<K, V> kvp, out K key, out V value)
|
|
|
|
|
|
{
|
|
|
|
|
|
key = kvp.Key;
|
|
|
|
|
|
value = kvp.Value;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
internal static IPEndPoint IPEndPoint_Parse(string addr)
|
|
|
|
|
|
{
|
2021-10-01 02:22:26 +02:00
|
|
|
|
int colon = addr.LastIndexOf(':');
|
2021-08-16 22:30:45 +02:00
|
|
|
|
return new IPEndPoint(IPAddress.Parse(addr[0..colon]), int.Parse(addr[(colon + 1)..]));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
internal static void ImportFromPem(this RSA rsa, string pem)
|
|
|
|
|
|
{
|
|
|
|
|
|
var header = pem.IndexOf("-----BEGIN RSA PUBLIC KEY-----");
|
|
|
|
|
|
var footer = pem.IndexOf("-----END RSA PUBLIC KEY-----");
|
|
|
|
|
|
if (header == -1 || footer <= header) throw new ArgumentException("Invalid RSA Public Key");
|
|
|
|
|
|
byte[] bytes = System.Convert.FromBase64String(pem[(header+30)..footer]);
|
|
|
|
|
|
var reader = new AsnReader(bytes, AsnEncodingRules.BER);
|
|
|
|
|
|
reader = reader.ReadSequence(Asn1Tag.Sequence);
|
|
|
|
|
|
var m = reader.ReadIntegerBytes();
|
|
|
|
|
|
var e = reader.ReadIntegerBytes();
|
|
|
|
|
|
rsa.ImportParameters(new RSAParameters { Modulus = m.ToArray(), Exponent = e.ToArray() });
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static class Convert
|
|
|
|
|
|
{
|
|
|
|
|
|
internal static byte[] FromHexString(string hex)
|
|
|
|
|
|
{
|
|
|
|
|
|
int NumberChars = hex.Length;
|
|
|
|
|
|
byte[] bytes = new byte[NumberChars / 2];
|
|
|
|
|
|
for (int i = 0; i < NumberChars; i += 2)
|
|
|
|
|
|
bytes[i / 2] = System.Convert.ToByte(hex.Substring(i, 2), 16);
|
|
|
|
|
|
return bytes;
|
|
|
|
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2021-08-30 16:13:52 +02:00
|
|
|
|
|
|
|
|
|
|
#if NETSTANDARD2_0
|
|
|
|
|
|
namespace System.Runtime.CompilerServices
|
|
|
|
|
|
{
|
|
|
|
|
|
internal static class RuntimeHelpers
|
|
|
|
|
|
{
|
|
|
|
|
|
public static T[] GetSubArray<T>(T[] array, Range range)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (array == null) throw new ArgumentNullException();
|
|
|
|
|
|
var (offset, length) = range.GetOffsetAndLength(array.Length);
|
|
|
|
|
|
if (length == 0) return Array.Empty<T>();
|
|
|
|
|
|
var dest = typeof(T).IsValueType || typeof(T[]) == array.GetType() ? new T[length]
|
|
|
|
|
|
: (T[])Array.CreateInstance(array.GetType().GetElementType()!, length);
|
|
|
|
|
|
Array.Copy(array, offset, dest, 0, length);
|
|
|
|
|
|
return dest;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
#endif
|