using GostCryptography.Properties; using System; using System.Collections; using System.IO; using System.Text; namespace GostCryptography.Asn1.Ber { public static class Asn1Util { private static readonly byte[] Base64DecodeTable = { 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 60, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0x10, 0x11, 0x12, 0x13, 20, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 30, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 40, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 50, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff }; private static readonly byte[] Base64EncodeTable = { 0x41, 0x42, 0x43, 0x44, 0x45, 70, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 80, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 90, 0x61, 0x62, 0x63, 100, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 110, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 120, 0x79, 0x7a, 0x30, 0x31, 50, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2b, 0x2f }; public static string BcdToString(byte[] bcd) { var index = 0; var builder = new StringBuilder(bcd.Length * 2); for (var i = 0; i < (bcd.Length * 2); i++) { byte num3; if ((i % 2) == 0) { num3 = (byte)(bcd[index] & 15); } else { num3 = (byte)UrShift(bcd[index++], 4); } if (num3 == 15) { break; } builder.Append((num3 < 10) ? ((char)(num3 + 0x30)) : ((char)((num3 + 0x41) - 10))); } return builder.ToString(); } public static byte[] DecodeBase64Array(byte[] srcArray) { var num = srcArray.Length / 4; if ((4 * num) != srcArray.Length) { throw ExceptionUtility.Argument("srcArray", Resources.Asn1InvalidEncodedDataLength); } var num2 = 0; var num3 = num; if (srcArray.Length != 0) { if (srcArray[srcArray.Length - 1] == 0x3d) { num2++; num3--; } if (srcArray[srcArray.Length - 2] == 0x3d) { num2++; } } var buffer = new byte[(3 * num) - num2]; var num4 = 0; var num5 = 0; for (var i = 0; i < num3; i++) { var num7 = DecodeBase64Char(srcArray[num4++]); var num8 = DecodeBase64Char(srcArray[num4++]); var num9 = DecodeBase64Char(srcArray[num4++]); var num10 = DecodeBase64Char(srcArray[num4++]); buffer[num5++] = (byte)((num7 << 2) | (num8 >> 4)); buffer[num5++] = (byte)((num8 << 4) | (num9 >> 2)); buffer[num5++] = (byte)((num9 << 6) | num10); } if (num2 != 0) { var num11 = DecodeBase64Char(srcArray[num4++]); var num12 = DecodeBase64Char(srcArray[num4++]); buffer[num5++] = (byte)((num11 << 2) | (num12 >> 4)); if (num2 == 1) { var num13 = DecodeBase64Char(srcArray[num4++]); buffer[num5++] = (byte)((num12 << 4) | (num13 >> 2)); } } return buffer; } private static int DecodeBase64Char(byte c) { var num = (c < 0x80) ? Base64DecodeTable[c - 40] : -1; if (num < 0) { throw ExceptionUtility.Argument("c", Resources.Asn1IllegalCharacter, c); } return num; } public static byte[] EncodeBase64Array(byte[] srcArray) { var num = srcArray.Length / 3; var num2 = srcArray.Length - (3 * num); var num3 = 4 * ((srcArray.Length + 2) / 3); var buffer = new byte[num3]; var num4 = 0; var num5 = 0; for (var i = 0; i < num; i++) { var num7 = srcArray[num4++] & 0xff; var num8 = srcArray[num4++] & 0xff; var num9 = srcArray[num4++] & 0xff; buffer[num5++] = Base64EncodeTable[num7 >> 2]; buffer[num5++] = Base64EncodeTable[((num7 << 4) & 0x3f) | (num8 >> 4)]; buffer[num5++] = Base64EncodeTable[((num8 << 2) & 0x3f) | (num9 >> 6)]; buffer[num5++] = Base64EncodeTable[num9 & 0x3f]; } if (num2 != 0) { var num10 = srcArray[num4++] & 0xff; buffer[num5++] = Base64EncodeTable[num10 >> 2]; if (num2 == 1) { buffer[num5++] = Base64EncodeTable[(num10 << 4) & 0x3f]; buffer[num5++] = 0x3d; buffer[num5++] = 0x3d; return buffer; } var num11 = srcArray[num4++] & 0xff; buffer[num5++] = Base64EncodeTable[((num10 << 4) & 0x3f) | (num11 >> 4)]; buffer[num5++] = Base64EncodeTable[(num11 << 2) & 0x3f]; buffer[num5++] = 0x3d; } return buffer; } public static byte[] GetAddressBytes(string ipaddress) { var index = 0; var buffer = new byte[4]; var tokenizer = new Tokenizer(ipaddress, "."); try { while (tokenizer.HasMoreTokens()) { buffer[index] = Convert.ToByte(tokenizer.NextToken()); index++; } } catch (Exception) { } return buffer; } public static int GetBytesCount(long val) { return Asn1RunTime.GetLongBytesCount(val); } public static int GetUlongBytesCount(long val) { return Asn1RunTime.GetUlongBytesCount(val); } // Commented out unsed method that gives compile-time warning (SL 03/06/2022) #if false public static byte[] StringToBcd(string str) { int num2; var buffer = new byte[(str.Length + 1) / 2]; byte num = 0; var num3 = num2 = 0; while (num3 < str.Length) { var c = char.ToUpper(str[num3]); var flag = char.IsDigit(c); if (!flag && ((c < 'A') || (c >= 'F'))) { throw ExceptionUtility.CryptographicException(Resources.Asn1ValueParseException, str, num3); } if ((num3 % 2) != 0) { num = (byte)(num | ((byte)(((byte)((flag != null) ? (c - 0x30) : ((c - 0x41) + 10))) << 4))); buffer[num2++] = num; } else { num = flag ? ((byte)(c - '0')) : ((byte)((c - 'A') + 10)); } num3++; } if ((num3 % 2) != 0) { buffer[num2++] = (byte)(num | 240); } return buffer; } #endif public static void ToArray(ICollection c, object[] objects) { var num = 0; var enumerator = c.GetEnumerator(); while (enumerator.MoveNext()) { objects[num++] = enumerator.Current; } } public static byte[] ToByteArray(string sourceString) { return Encoding.UTF8.GetBytes(sourceString); } public static char[] ToCharArray(byte[] byteArray) { return Encoding.UTF8.GetChars(byteArray); } public static string ToHexString(byte b) { var builder = new StringBuilder(4); var str = Convert.ToString(b, 0x10); var length = str.Length; if (length < 2) { builder.Append('0'); builder.Append(str); } else if (length > 2) { builder.Append(str[length - 2]); builder.Append(str[length - 1]); } else { builder.Append(str); } return builder.ToString(); } public static string ToHexString(byte[] b, int offset, int nbytes) { var builder = new StringBuilder(nbytes * 4); for (var i = 0; i < nbytes; i++) { builder.Append(ToHexString(b[offset + i])); builder.Append(" "); } return builder.ToString(); } public static int UrShift(int number, int bits) { if (number >= 0) { return (number >> bits); } return ((number >> bits) + (2 << ~bits)); } public static int UrShift(int number, long bits) { return UrShift(number, (int)bits); } public static long UrShift(long number, int bits) { if (number >= 0L) { return (number >> bits); } return ((number >> bits) + (2L << ~bits)); } public static long UrShift(long number, long bits) { return UrShift(number, (int)bits); } public static void WriteStackTrace(Exception throwable, TextWriter stream) { stream.Write(throwable.StackTrace); stream.Flush(); } } }