123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780 |
- //+-------------------------------------------------------------------------------+
- //| Copyright (c) 2003 Liping Dai. All rights reserved. |
- //| Web: www.lipingshare.com |
- //| Email: lipingshare@yahoo.com |
- //| |
- //| Copyright and Permission Details: |
- //| ================================= |
- //| Permission is hereby granted, free of charge, to any person obtaining a copy |
- //| of this software and associated documentation files (the "Software"), to deal |
- //| in the Software without restriction, including without limitation the rights |
- //| to use, copy, modify, merge, publish, distribute, and/or sell copies of the |
- //| Software, subject to the following conditions: |
- //| |
- //| 1. Redistributions of source code must retain the above copyright notice, this|
- //| list of conditions and the following disclaimer. |
- //| |
- //| 2. Redistributions in binary form must reproduce the above copyright notice, |
- //| this list of conditions and the following disclaimer in the documentation |
- //| and/or other materials provided with the distribution. |
- //| |
- //| THE SOFTWARE PRODUCT IS PROVIDED �AS IS� WITHOUT WARRANTY OF ANY KIND, |
- //| EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
- //| WARRANTIES OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR |
- //| A PARTICULAR PURPOSE. |
- //+-------------------------------------------------------------------------------+
-
- using System;
- using System.IO;
- using System.Text;
- using Microsoft.Win32;
-
- namespace LipingShare.LCLib.Asn1Processor
- {
- /// <summary>
- /// Utility functions.
- /// </summary>
- internal class Asn1Util
- {
-
- /// <summary>
- /// Check if the string is ASN.1 encoded hex string.
- /// </summary>
- /// <param name="dataStr">The string.</param>
- /// <returns>true:Yes, false:No.</returns>
- public static bool IsAsn1EncodedHexStr(string dataStr)
- {
- bool retval = false;
- try
- {
- byte[] data = HexStrToBytes(dataStr);
- if (data.Length > 0)
- {
- Asn1Node node = new Asn1Node();
- retval = node.LoadData(data);
- }
- }
- catch
- {
- retval = false;
- }
- return retval;
- }
-
- /// <summary>
- /// Format a string to have certain line length and character group length.
- /// Sample result FormatString(xstr,32,2):
- /// <code>07 AE 0B E7 84 5A D4 6C 6A BD DF 8F 89 88 9E F1</code>
- /// </summary>
- /// <param name="inStr">source string.</param>
- /// <param name="lineLen">line length.</param>
- /// <param name="groupLen">group length.</param>
- /// <returns></returns>
- public static string FormatString(string inStr, int lineLen, int groupLen)
- {
- char[] tmpCh = new char[inStr.Length * 2];
- int i, c = 0, linec = 0;
- int gc = 0;
- for (i = 0; i < inStr.Length; i++)
- {
- tmpCh[c++] = inStr[i];
- gc++;
- linec++;
- if (gc >= groupLen && groupLen > 0)
- {
- tmpCh[c++] = ' ';
- gc = 0;
- }
- if (linec >= lineLen)
- {
- tmpCh[c++] = '\r';
- tmpCh[c++] = '\n';
- linec = 0;
- }
- }
- string retval = new string(tmpCh);
- retval = retval.TrimEnd('\0');
- retval = retval.TrimEnd('\n');
- retval = retval.TrimEnd('\r');
- return retval;
- }
-
- /// <summary>
- /// Generate a string by duplicating <see cref="char"/> xch.
- /// </summary>
- /// <param name="len">duplicate times.</param>
- /// <param name="xch">the duplicated character.</param>
- /// <returns></returns>
- public static string GenStr(int len, char xch)
- {
- char[] ch = new char[len];
- for (int i = 0; i < len; i++)
- {
- ch[i] = xch;
- }
- return new string(ch);
- }
-
- /// <summary>
- /// Convert byte array to a <see cref="long"/> integer.
- /// </summary>
- /// <param name="bytes"></param>
- /// <returns></returns>
- public static long BytesToLong(byte[] bytes)
- {
- long tempInt = 0;
- for (int i = 0; i < bytes.Length; i++)
- {
- tempInt = tempInt << 8 | bytes[i];
- }
- return tempInt;
- }
-
- /// <summary>
- /// Convert a ASCII byte array to string, also filter out the null characters.
- /// </summary>
- /// <param name="bytes"></param>
- /// <returns></returns>
- public static string BytesToString(byte[] bytes)
- {
- string retval = "";
- if (bytes == null || bytes.Length < 1) return retval;
- char[] cretval = new char[bytes.Length];
- for (int i = 0, j = 0; i < bytes.Length; i++)
- {
- if (bytes[i] != '\0')
- {
- cretval[j++] = (char)bytes[i];
- }
- }
- retval = new string(cretval);
- retval = retval.TrimEnd('\0');
- return retval;
- }
-
- /// <summary>
- /// Convert ASCII string to byte array.
- /// </summary>
- /// <param name="msg"></param>
- /// <returns></returns>
- public static byte[] StringToBytes(string msg)
- {
- byte[] retval = new byte[msg.Length];
- for (int i = 0; i < msg.Length; i++)
- {
- retval[i] = (byte)msg[i];
- }
- return retval;
- }
-
- /// <summary>
- /// Compare source and target byte array.
- /// </summary>
- /// <param name="source"></param>
- /// <param name="target"></param>
- /// <returns></returns>
- public static bool IsEqual(byte[] source, byte[] target)
- {
- if (source == null) return false;
- if (target == null) return false;
- if (source.Length != target.Length) return false;
- for (int i = 0; i < source.Length; i++)
- {
- if (source[i] != target[i]) return false;
- }
- return true;
- }
-
- /// <summary>
- /// Constant hex digits array.
- /// </summary>
- static char[] hexDigits = { '0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
-
- /// <summary>
- /// Convert a byte array to hex string.
- /// </summary>
- /// <param name="bytes">source array.</param>
- /// <returns>hex string.</returns>
- public static string ToHexString(byte[] bytes)
- {
- if (bytes == null) return "";
- char[] chars = new char[bytes.Length * 2];
- int b, i;
- for (i = 0; i < bytes.Length; i++)
- {
- b = bytes[i];
- chars[i * 2] = hexDigits[b >> 4];
- chars[i * 2 + 1] = hexDigits[b & 0xF];
- }
- return new string(chars);
- }
-
- /// <summary>
- /// Check if the character is a valid hex digits.
- /// </summary>
- /// <param name="ch">source character.</param>
- /// <returns>true:Valid, false:Invalid.</returns>
- public static bool IsValidHexDigits(char ch)
- {
- bool retval = false;
- for (int i = 0; i < hexDigits.Length; i++)
- {
- if (hexDigits[i] == ch)
- {
- retval = true;
- break;
- }
- }
- return retval;
- }
-
- /// <summary>
- /// Get hex digits value.
- /// </summary>
- /// <param name="ch">source character.</param>
- /// <returns>hex digits value.</returns>
- public static byte GetHexDigitsVal(char ch)
- {
- byte retval = 0;
- for (int i = 0; i < hexDigits.Length; i++)
- {
- if (hexDigits[i] == ch)
- {
- retval = (byte)i;
- break;
- }
- }
- return retval;
- }
-
- /// <summary>
- /// Convert hex string to byte array.
- /// </summary>
- /// <param name="hexStr">Source hex string.</param>
- /// <returns>return byte array.</returns>
- public static byte[] HexStrToBytes(string hexStr)
- {
- hexStr = hexStr.Replace(" ", "");
- hexStr = hexStr.Replace("\r", "");
- hexStr = hexStr.Replace("\n", "");
- hexStr = hexStr.ToUpper();
- if ((hexStr.Length % 2) != 0) throw new Exception("Invalid Hex string: odd length.");
- int i;
- for (i = 0; i < hexStr.Length; i++)
- {
- if (!IsValidHexDigits(hexStr[i]))
- {
- throw new Exception("Invalid Hex string: included invalid character [" +
- hexStr[i] + "]");
- }
- }
- int bc = hexStr.Length / 2;
- byte[] retval = new byte[bc];
- int b1, b2, b;
- for (i = 0; i < bc; i++)
- {
- b1 = GetHexDigitsVal(hexStr[i * 2]);
- b2 = GetHexDigitsVal(hexStr[i * 2 + 1]);
- b = ((b1 << 4) | b2);
- retval[i] = (byte)b;
- }
- return retval;
- }
-
- /// <summary>
- /// Check if the source string is a valid hex string.
- /// </summary>
- /// <param name="hexStr">source string.</param>
- /// <returns>true:Valid, false:Invalid.</returns>
- public static bool IsHexStr(string hexStr)
- {
- byte[] bytes = null;
- try
- {
- bytes = HexStrToBytes(hexStr);
- }
- catch
- {
- return false;
- }
- if (bytes == null || bytes.Length < 0)
- {
- return false;
- }
- else
- {
- return true;
- }
- }
-
- private const string PemStartStr = "-----BEGIN";
- private const string PemEndStr = "-----END";
- /// <summary>
- /// Check if the source string is PEM formated string.
- /// </summary>
- /// <param name="pemStr">source string.</param>
- /// <returns>true:Valid, false:Invalid.</returns>
- public static bool IsPemFormated(string pemStr)
- {
- byte[] data = null;
- try
- {
- data = PemToBytes(pemStr);
- }
- catch
- {
- return false;
- }
- return (data.Length > 0);
- }
-
- /// <summary>
- /// Check if a file is PEM formated.
- /// </summary>
- /// <param name="fileName">source file name.</param>
- /// <returns>true:Yes, false:No.</returns>
- public static bool IsPemFormatedFile(string fileName)
- {
- bool retval = false;
- try
- {
- FileStream fs = new FileStream(fileName, System.IO.FileMode.Open);
- byte[] data = new byte[fs.Length];
- fs.Read(data, 0, data.Length);
- fs.Close();
- string dataStr = Asn1Util.BytesToString(data);
- retval = IsPemFormated(dataStr);
- }
- catch
- {
- retval = false;
- }
- return retval;
- }
-
- /// <summary>
- /// Convert PEM formated string into <see cref="Stream"/> and set the Stream position to 0.
- /// </summary>
- /// <param name="pemStr">source string.</param>
- /// <returns>output stream.</returns>
- public static Stream PemToStream(string pemStr)
- {
- byte[] bytes = PemToBytes(pemStr);
- MemoryStream retval = new MemoryStream(bytes);
- retval.Position = 0;
- return retval;
- }
-
- /// <summary>
- /// Convert PEM formated string into byte array.
- /// </summary>
- /// <param name="pemStr">source string.</param>
- /// <returns>output byte array.</returns>
- public static byte[] PemToBytes(string pemStr)
- {
- byte[] retval = null;
- string[] lines = pemStr.Split('\n');
- string base64Str = "";
- bool started = false, ended = false;
- string cline = "";
- for (int i = 0; i < lines.Length; i++)
- {
- cline = lines[i].ToUpper();
- if (cline == "") continue;
- if (cline.Length > PemStartStr.Length)
- {
- if (!started && cline.Substring(0, PemStartStr.Length) == PemStartStr)
- {
- started = true;
- continue;
- }
- }
- if (cline.Length > PemEndStr.Length)
- {
- if (cline.Substring(0, PemEndStr.Length) == PemEndStr)
- {
- ended = true;
- break;
- }
- }
- if (started)
- {
- base64Str += lines[i];
- }
- }
- if (!(started && ended))
- {
- throw new Exception("'BEGIN'/'END' line is missing.");
- }
- base64Str = base64Str.Replace("\r", "");
- base64Str = base64Str.Replace("\n", "");
- base64Str = base64Str.Replace("\n", " ");
- retval = Convert.FromBase64String(base64Str);
- return retval;
- }
-
- /// <summary>
- /// Convert byte array to PEM formated string.
- /// </summary>
- /// <param name="data"></param>
- /// <returns></returns>
- public static string BytesToPem(byte[] data)
- {
- return BytesToPem(data, "");
- }
-
- /// <summary>
- /// Retrieve PEM file heading.
- /// </summary>
- /// <param name="fileName">source file name.</param>
- /// <returns>heading string.</returns>
- public static string GetPemFileHeader(string fileName)
- {
- try
- {
- FileStream fs = new FileStream(fileName, FileMode.Open);
- byte[] data = new byte[fs.Length];
- fs.Read(data, 0, data.Length);
- fs.Close();
- string dataStr = Asn1Util.BytesToString(data);
- return GetPemHeader(dataStr);
- }
- catch
- {
- return "";
- }
- }
-
- /// <summary>
- /// Retrieve PEM heading from a PEM formated string.
- /// </summary>
- /// <param name="pemStr">source string.</param>
- /// <returns>heading string.</returns>
- public static string GetPemHeader(string pemStr)
- {
- string[] lines = pemStr.Split('\n');
- bool started = false;
- string cline = "";
- for (int i = 0; i < lines.Length; i++)
- {
- cline = lines[i].ToUpper().Replace("\r", "");
- if (cline == "") continue;
- if (cline.Length > PemStartStr.Length)
- {
- if (!started && cline.Substring(0, PemStartStr.Length) == PemStartStr)
- {
- started = true;
- string retstr = lines[i].Substring(PemStartStr.Length,
- lines[i].Length -
- PemStartStr.Length).Replace("-----", "");
- return retstr.Replace("\r", "");
- }
- }
- else
- {
- continue;
- }
- }
- return "";
- }
-
- /// <summary>
- /// Convert byte array to PEM formated string and set the heading as pemHeader.
- /// </summary>
- /// <param name="data">source array.</param>
- /// <param name="pemHeader">PEM heading.</param>
- /// <returns>PEM formated string.</returns>
- public static string BytesToPem(byte[] data, string pemHeader)
- {
- if (pemHeader == null || pemHeader.Length < 1)
- {
- pemHeader = "ASN.1 Editor Generated PEM File";
- }
- string retval = "";
- if (pemHeader.Length > 0 && pemHeader[0] != ' ')
- {
- pemHeader = " " + pemHeader;
- }
- retval = Convert.ToBase64String(data);
- retval = FormatString(retval, 64, 0);
- retval = "-----BEGIN" + pemHeader + "-----\r\n" +
- retval +
- "\r\n-----END" + pemHeader + "-----\r\n";
- return retval;
- }
-
- /// <summary>
- /// Calculate how many bits is enough to hold ivalue.
- /// </summary>
- /// <param name="ivalue">source value.</param>
- /// <returns>bits number.</returns>
- public static int BitPrecision(ulong ivalue)
- {
- if (ivalue == 0) return 0;
- int l = 0, h = 8 * 4; // 4: sizeof(ulong)
- while (h - l > 1)
- {
- int t = (int)(l + h) / 2;
- if ((ivalue >> t) != 0)
- l = t;
- else
- h = t;
- }
- return h;
- }
-
- /// <summary>
- /// Calculate how many bytes is enough to hold the value.
- /// </summary>
- /// <param name="value">input value.</param>
- /// <returns>bytes number.</returns>
- public static int BytePrecision(ulong value)
- {
- int i;
- for (i = 4; i > 0; --i) // 4: sizeof(ulong)
- if ((value >> (i - 1) * 8) != 0)
- break;
- return i;
- }
-
- /// <summary>
- /// ASN.1 DER length encoder.
- /// </summary>
- /// <param name="xdata">result output stream.</param>
- /// <param name="length">source length.</param>
- /// <returns>result bytes.</returns>
- public static int DERLengthEncode(Stream xdata, ulong length)
- {
- int i = 0;
- if (length <= 0x7f)
- {
- xdata.WriteByte((byte)length);
- i++;
- }
- else
- {
- xdata.WriteByte((byte)(BytePrecision(length) | 0x80));
- i++;
- for (int j = BytePrecision((ulong)length); j > 0; --j)
- {
- xdata.WriteByte((byte)(length >> (j - 1) * 8));
- i++;
- }
- }
- return i;
- }
-
- /// <summary>
- /// ASN.1 DER length decoder.
- /// </summary>
- /// <param name="bt">Source stream.</param>
- /// <param name="isIndefiniteLength">Output parameter.</param>
- /// <returns>Output length.</returns>
- public static long DerLengthDecode(Stream bt, ref bool isIndefiniteLength)
- {
- isIndefiniteLength = false;
- long length = 0;
- byte b;
- b = (byte)bt.ReadByte();
- if ((b & 0x80) == 0)
- {
- length = b;
- }
- else
- {
- long lengthBytes = b & 0x7f;
- if (lengthBytes == 0)
- {
- isIndefiniteLength = true;
- return -2; // Indefinite length.
- }
-
- length = 0;
- while (lengthBytes-- > 0)
- {
- if ((length >> (8 * (4 - 1))) > 0) // 4: sizeof(long)
- {
- return -1; // Length overflow.
- }
- b = (byte)bt.ReadByte();
- length = (length << 8) | b;
- }
-
- if (length <= 0x7f)
- {
- return -1; // Indicated false node
- }
- }
- return length;
- }
-
- /// <summary>
- /// Decode tag value to return tag name.
- /// </summary>
- /// <param name="tag">input tag.</param>
- /// <returns>tag name.</returns>
- static public string GetTagName(byte tag)
- {
- string retval = "";
- if ((tag & Asn1TagClasses.CLASS_MASK) != 0)
- {
- switch (tag & Asn1TagClasses.CLASS_MASK)
- {
- case Asn1TagClasses.CONTEXT_SPECIFIC:
- retval += "CONTEXT SPECIFIC (" + ((int)(tag & Asn1Tag.TAG_MASK)).ToString() + ")";
- break;
- case Asn1TagClasses.APPLICATION:
- retval += "APPLICATION (" + ((int)(tag & Asn1Tag.TAG_MASK)).ToString() + ")";
- break;
- case Asn1TagClasses.PRIVATE:
- retval += "PRIVATE (" + ((int)(tag & Asn1Tag.TAG_MASK)).ToString() + ")";
- break;
- case Asn1TagClasses.CONSTRUCTED:
- retval += "CONSTRUCTED (" + ((int)(tag & Asn1Tag.TAG_MASK)).ToString() + ")";
- break;
- case Asn1TagClasses.UNIVERSAL:
- retval += "UNIVERSAL (" + ((int)(tag & Asn1Tag.TAG_MASK)).ToString() + ")";
- break;
- }
- }
- else
- {
- switch (tag & Asn1Tag.TAG_MASK)
- {
- case Asn1Tag.BOOLEAN:
- retval += "BOOLEAN";
- break;
- case Asn1Tag.INTEGER:
- retval += "INTEGER";
- break;
- case Asn1Tag.BIT_STRING:
- retval += "BIT STRING";
- break;
- case Asn1Tag.OCTET_STRING:
- retval += "OCTET STRING";
- break;
- case Asn1Tag.TAG_NULL:
- retval += "NULL";
- break;
- case Asn1Tag.OBJECT_IDENTIFIER:
- retval += "OBJECT IDENTIFIER";
- break;
- case Asn1Tag.OBJECT_DESCRIPTOR:
- retval += "OBJECT DESCRIPTOR";
- break;
- case Asn1Tag.RELATIVE_OID:
- retval += "RELATIVE-OID";
- break;
- case Asn1Tag.EXTERNAL:
- retval += "EXTERNAL";
- break;
- case Asn1Tag.REAL:
- retval += "REAL";
- break;
- case Asn1Tag.ENUMERATED:
- retval += "ENUMERATED";
- break;
- case Asn1Tag.UTF8_STRING:
- retval += "UTF8 STRING";
- break;
- case (Asn1Tag.SEQUENCE):
- retval += "SEQUENCE";
- break;
- case (Asn1Tag.SET):
- retval += "SET";
- break;
- case Asn1Tag.NUMERIC_STRING:
- retval += "NUMERIC STRING";
- break;
- case Asn1Tag.PRINTABLE_STRING:
- retval += "PRINTABLE STRING";
- break;
- case Asn1Tag.T61_STRING:
- retval += "T61 STRING";
- break;
- case Asn1Tag.VIDEOTEXT_STRING:
- retval += "VIDEOTEXT STRING";
- break;
- case Asn1Tag.IA5_STRING:
- retval += "IA5 STRING";
- break;
- case Asn1Tag.UTC_TIME:
- retval += "UTC TIME";
- break;
- case Asn1Tag.GENERALIZED_TIME:
- retval += "GENERALIZED TIME";
- break;
- case Asn1Tag.GRAPHIC_STRING:
- retval += "GRAPHIC STRING";
- break;
- case Asn1Tag.VISIBLE_STRING:
- retval += "VISIBLE STRING";
- break;
- case Asn1Tag.GENERAL_STRING:
- retval += "GENERAL STRING";
- break;
- case Asn1Tag.UNIVERSAL_STRING:
- retval += "UNIVERSAL STRING";
- break;
- case Asn1Tag.BMPSTRING:
- retval += "BMP STRING";
- break;
- default:
- retval += "UNKNOWN TAG";
- break;
- };
- }
- return retval;
- }
-
- #if UNITYIAP_DISABLED
- /// <summary>
- /// Read registry information from local machine entrys.
- /// </summary>
- /// <param name="path"></param>
- /// <param name="name"></param>
- /// <returns></returns>
- static public object ReadRegInfo(string path, string name)
- {
- object retval = null;
- Microsoft.Win32.RegistryKey regKey;
- regKey = Registry.LocalMachine.OpenSubKey(path, false);
- if (regKey!=null)
- {
- retval = regKey.GetValue(name);
- }
- return retval;
- }
-
- /// <summary>
- /// Write information into local machine registry entry.
- /// </summary>
- /// <param name="path"></param>
- /// <param name="name"></param>
- /// <param name="data"></param>
- static public void WriteRegInfo(string path, string name, object data)
- {
- Microsoft.Win32.RegistryKey regKey;
- regKey = Registry.LocalMachine.OpenSubKey(path, true);
- if (regKey == null)
- {
- regKey = Registry.LocalMachine.CreateSubKey(path);
- }
- if (regKey != null)
- {
- regKey.SetValue(name, data);
- }
- }
- #endif
-
- /// <summary>
- /// Constructor.
- /// </summary>
- private Asn1Util()
- {
- //Private constructor.
- }
-
- }
- }
|