| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207 | //// ASN1Convert.cs: Abstract Syntax Notation 1 convertion routines//// Authors://	Sebastien Pouliot  <sebastien@ximian.com>//	Jesper Pedersen  <jep@itplus.dk>//// (C) 2003 Motus Technologies Inc. (http://www.motus.com)// (C) 2004 IT+ A/S (http://www.itplus.dk)// Copyright (C) 2004-2007 Novell, Inc (http://www.novell.com)//// 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, sublicense, and/or sell copies of the Software, and to// permit persons to whom the Software is furnished to do so, subject to// the following conditions:// // The above copyright notice and this permission notice shall be// included in all copies or substantial portions of the Software.// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.//using System;using System.Globalization;using System.Security.Cryptography;using System.Text;namespace Emby.Server.Core.Cryptography{    // References:    // a.	ITU ASN.1 standards (free download)    //	http://www.itu.int/ITU-T/studygroups/com17/languages/    public static class ASN1Convert {		// RFC3280, section 4.2.1.5		// CAs conforming to this profile MUST always encode certificate		// validity dates through the year 2049 as UTCTime; certificate validity		// dates in 2050 or later MUST be encoded as GeneralizedTime.		// Under 1.x this API requires a Local datetime to be provided		// Under 2.0 it will also accept a Utc datetime		static public ASN1 FromDateTime (DateTime dt) 		{			if (dt.Year < 2050) {				// UTCTIME				return new ASN1 (0x17, Encoding.ASCII.GetBytes (					dt.ToUniversalTime ().ToString ("yyMMddHHmmss",					CultureInfo.InvariantCulture) + "Z"));			}			else {				// GENERALIZEDTIME				return new ASN1 (0x18, Encoding.ASCII.GetBytes (					dt.ToUniversalTime ().ToString ("yyyyMMddHHmmss", 					CultureInfo.InvariantCulture) + "Z"));			}		}		static public ASN1 FromInt32 (Int32 value) 		{			byte[] integer = BitConverterLE.GetBytes (value);			Array.Reverse (integer);			int x = 0;			while ((x < integer.Length) && (integer [x] == 0x00))				x++;			ASN1 asn1 = new ASN1 (0x02);			switch (x) {			case 0:				asn1.Value = integer;				break;			case 4:				asn1.Value = new byte [1];				break;			default:				byte[] smallerInt = new byte [4 - x];				Buffer.BlockCopy (integer, x, smallerInt, 0, smallerInt.Length);				asn1.Value = smallerInt;				break;			}			return asn1;		}		static public ASN1 FromOid (string oid) 		{			if (oid == null)				throw new ArgumentNullException ("oid");			return new ASN1 (CryptoConfig.EncodeOID (oid));		}		static public ASN1 FromUnsignedBigInteger (byte[] big) 		{			if (big == null)				throw new ArgumentNullException ("big");			// check for numbers that could be interpreted as negative (first bit)			if (big [0] >= 0x80) {				// in thie cas we add a new, empty, byte (position 0) so we're				// sure this will always be interpreted an unsigned integer.				// However we can't feed it into RSAParameters or DSAParameters				int length = big.Length + 1;				byte[] uinteger = new byte [length];				Buffer.BlockCopy (big, 0, uinteger, 1, length - 1);				big = uinteger;			}			return new ASN1 (0x02, big);		}		static public int ToInt32 (ASN1 asn1) 		{			if (asn1 == null)				throw new ArgumentNullException ("asn1");			if (asn1.Tag != 0x02)				throw new FormatException ("Only integer can be converted");			int x = 0;			for (int i=0; i < asn1.Value.Length; i++)				x = (x << 8) + asn1.Value [i];			return x;		}		// Convert a binary encoded OID to human readable string representation of 		// an OID (IETF style). Based on DUMPASN1.C from Peter Gutmann.		static public string ToOid (ASN1 asn1) 		{			if (asn1 == null)				throw new ArgumentNullException ("asn1");			byte[] aOID = asn1.Value;			StringBuilder sb = new StringBuilder ();			// Pick apart the OID			byte x = (byte) (aOID[0] / 40);			byte y = (byte) (aOID[0] % 40);			if (x > 2) {				// Handle special case for large y if x = 2				y += (byte) ((x - 2) * 40);				x = 2;			}			sb.Append (x.ToString (CultureInfo.InvariantCulture));			sb.Append (".");			sb.Append (y.ToString (CultureInfo.InvariantCulture));			ulong val = 0;			for (x = 1; x < aOID.Length; x++) {				val = ((val << 7) | ((byte) (aOID [x] & 0x7F)));				if ( !((aOID [x] & 0x80) == 0x80)) {					sb.Append (".");					sb.Append (val.ToString (CultureInfo.InvariantCulture));					val = 0;				}			}			return sb.ToString ();		}		static public DateTime ToDateTime (ASN1 time) 		{			if (time == null)				throw new ArgumentNullException ("time");			string t = Encoding.ASCII.GetString (time.Value);			// to support both UTCTime and GeneralizedTime (and not so common format)			string mask = null;			int year;			switch (t.Length) {				case 11:					// illegal format, still it's supported for compatibility					mask = "yyMMddHHmmZ";					break;				case 13: 					// RFC3280: 4.1.2.5.1  UTCTime					year = Convert.ToInt16 (t.Substring (0, 2), CultureInfo.InvariantCulture);					// Where YY is greater than or equal to 50, the 					// year SHALL be interpreted as 19YY; and 					// Where YY is less than 50, the year SHALL be 					// interpreted as 20YY.					if (year >= 50)						t = "19" + t;					else						t = "20" + t;					mask = "yyyyMMddHHmmssZ";					break;				case 15:					mask = "yyyyMMddHHmmssZ"; // GeneralizedTime					break;				case 17:					// another illegal format (990630000000+1000), again supported for compatibility					year = Convert.ToInt16 (t.Substring (0, 2), CultureInfo.InvariantCulture);					string century = (year >= 50) ? "19" : "20";					// ASN.1 (see ITU X.680 section 43.3) deals with offset differently than .NET					char sign = (t[12] == '+') ? '-' : '+';					t = String.Format ("{0}{1}{2}{3}{4}:{5}{6}", century, t.Substring (0, 12), sign, 						t[13], t[14], t[15], t[16]);					mask = "yyyyMMddHHmmsszzz";					break;			}			return DateTime.ParseExact (t, mask, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal);		}	}}
 |