| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 | 
							- //
 
- // 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 MediaBrowser.Server.Mono.Security {
 
- 	// 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);
 
- 		}
 
- 	}
 
- }
 
 
  |