You've already forked linux-packaging-mono
							
							
		
			
				
	
	
		
			239 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			239 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| //
 | |
| // PublicKey.cs - System.Security.Cryptography.PublicKey
 | |
| //
 | |
| // Author:
 | |
| //	Sebastien Pouliot  <sebastien@ximian.com>
 | |
| //	Tim Coleman (tim@timcoleman.com)
 | |
| //
 | |
| // (C) 2003 Motus Technologies Inc. (http://www.motus.com)
 | |
| // Copyright (C) Tim Coleman, 2004
 | |
| // Copyright (C) 2005 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.
 | |
| //
 | |
| 
 | |
| #if SECURITY_DEP
 | |
| 
 | |
| #if MONO_SECURITY_ALIAS
 | |
| extern alias MonoSecurity;
 | |
| using MonoSecurity::Mono.Security;
 | |
| using MonoSecurity::Mono.Security.Cryptography;
 | |
| using MSX = MonoSecurity::Mono.Security.X509;
 | |
| #else
 | |
| using Mono.Security;
 | |
| using Mono.Security.Cryptography;
 | |
| using MSX = Mono.Security.X509;
 | |
| #endif
 | |
| 
 | |
| #endif
 | |
| 
 | |
| namespace System.Security.Cryptography.X509Certificates {
 | |
| 
 | |
| 	public sealed class PublicKey {
 | |
| 
 | |
| #if SECURITY_DEP
 | |
| 
 | |
| 		private const string rsaOid = "1.2.840.113549.1.1.1";
 | |
| 		private const string dsaOid = "1.2.840.10040.4.1";
 | |
| 
 | |
| 		private AsymmetricAlgorithm _key;
 | |
| 		private AsnEncodedData _keyValue;
 | |
| 		private AsnEncodedData _params;
 | |
| 		private Oid _oid;
 | |
| 
 | |
| 		static byte[] Empty = new byte [0];
 | |
| 
 | |
| 		public PublicKey (Oid oid, AsnEncodedData parameters, AsnEncodedData keyValue)
 | |
| 		{
 | |
| 			if (oid == null)
 | |
| 				throw new ArgumentNullException ("oid");
 | |
| 			if (parameters == null)
 | |
| 				throw new ArgumentNullException ("parameters");
 | |
| 			if (keyValue == null)
 | |
| 				throw new ArgumentNullException ("keyValue");
 | |
| 
 | |
| 			_oid = new Oid (oid);
 | |
| 			_params = new AsnEncodedData (parameters);
 | |
| 			_keyValue = new AsnEncodedData (keyValue);
 | |
| 		}
 | |
| 
 | |
| 		internal PublicKey (MSX.X509Certificate certificate)
 | |
| 		{
 | |
| 			// note: _key MUSTonly contains the public part of the key
 | |
| 			bool export_required = true;
 | |
| 
 | |
| 			if (certificate.KeyAlgorithm == rsaOid) {
 | |
| 				// shortcut export/import in the case the private key isn't available
 | |
| 				RSACryptoServiceProvider rcsp = (certificate.RSA as RSACryptoServiceProvider);
 | |
| 				if ((rcsp != null) && rcsp.PublicOnly) {
 | |
| 					_key = certificate.RSA;
 | |
| 					export_required = false;
 | |
| 				} else 
 | |
| 				{
 | |
| 					RSAManaged rsam = (certificate.RSA as RSAManaged);
 | |
| 					if ((rsam != null) && rsam.PublicOnly) {
 | |
| 						_key = certificate.RSA;
 | |
| 						export_required = false;
 | |
| 					}
 | |
| 				}
 | |
| 
 | |
| 				if (export_required) {
 | |
| 					RSAParameters rsap = certificate.RSA.ExportParameters (false);
 | |
| 					_key = RSA.Create ();
 | |
| 					(_key as RSA).ImportParameters (rsap);
 | |
| 				}
 | |
| 			} else {
 | |
| 				// shortcut export/import in the case the private key isn't available
 | |
| 				DSACryptoServiceProvider dcsp = (certificate.DSA as DSACryptoServiceProvider);
 | |
| 				if ((dcsp != null) && dcsp.PublicOnly) {
 | |
| 					_key = certificate.DSA;
 | |
| 					export_required = false;
 | |
| 				}
 | |
| 				// note: DSAManaged isn't available in Mono.Security due to a bug in Fx 1.x
 | |
| 
 | |
| 				if (export_required) {
 | |
| 					DSAParameters rsap = certificate.DSA.ExportParameters (false);
 | |
| 					_key = DSA.Create ();
 | |
| 					(_key as DSA).ImportParameters (rsap);
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			_oid = new Oid (certificate.KeyAlgorithm);
 | |
| 			_keyValue = new AsnEncodedData (_oid, certificate.PublicKey);
 | |
| 			_params = new AsnEncodedData (_oid, certificate.KeyAlgorithmParameters ?? Empty);
 | |
| 		}
 | |
| 
 | |
| 		// properties
 | |
| 
 | |
| 		public AsnEncodedData EncodedKeyValue {
 | |
| 			get { return _keyValue; }
 | |
| 		}
 | |
| 
 | |
| 		public AsnEncodedData EncodedParameters {
 | |
| 			get { return _params; }
 | |
| 		}
 | |
| 
 | |
| 		public AsymmetricAlgorithm Key {
 | |
| 			get {
 | |
| 				switch (_oid.Value) {
 | |
| 				case rsaOid:
 | |
| 					return DecodeRSA (_keyValue.RawData);
 | |
| 				case dsaOid:
 | |
| 					return DecodeDSA (_keyValue.RawData, _params.RawData);
 | |
| 				default:
 | |
| 					string msg = Locale.GetText ("Cannot decode public key from unknown OID '{0}'.", _oid.Value);
 | |
| 					throw new NotSupportedException (msg);
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		public Oid Oid {
 | |
| 			get { return _oid; }
 | |
| 		}
 | |
| 
 | |
| 		// private stuff
 | |
| 
 | |
| 		static private byte[] GetUnsignedBigInteger (byte[] integer) 
 | |
| 		{
 | |
| 			if (integer [0] != 0x00)
 | |
| 				return integer;
 | |
| 
 | |
| 			// this first byte is added so we're sure it's an unsigned integer
 | |
| 			// however we can't feed it into RSAParameters or DSAParameters
 | |
| 			int length = integer.Length - 1;
 | |
| 			byte[] uinteger = new byte [length];
 | |
| 			Buffer.BlockCopy (integer, 1, uinteger, 0, length);
 | |
| 			return uinteger;
 | |
| 		}
 | |
| 
 | |
| 		static internal DSA DecodeDSA (byte[] rawPublicKey, byte[] rawParameters)
 | |
| 		{
 | |
| 			DSAParameters dsaParams = new DSAParameters ();
 | |
| 			try {
 | |
| 				// for DSA rawPublicKey contains 1 ASN.1 integer - Y
 | |
| 				ASN1 pubkey = new ASN1 (rawPublicKey);
 | |
| 				if (pubkey.Tag != 0x02)
 | |
| 					throw new CryptographicException (Locale.GetText ("Missing DSA Y integer."));
 | |
| 				dsaParams.Y = GetUnsignedBigInteger (pubkey.Value);
 | |
| 
 | |
| 				ASN1 param = new ASN1 (rawParameters);
 | |
| 				if ((param == null) || (param.Tag != 0x30) || (param.Count < 3))
 | |
| 					throw new CryptographicException (Locale.GetText ("Missing DSA parameters."));
 | |
| 				if ((param [0].Tag != 0x02) || (param [1].Tag != 0x02) || (param [2].Tag != 0x02))
 | |
| 					throw new CryptographicException (Locale.GetText ("Invalid DSA parameters."));
 | |
| 
 | |
| 				dsaParams.P = GetUnsignedBigInteger (param [0].Value);
 | |
| 				dsaParams.Q = GetUnsignedBigInteger (param [1].Value);
 | |
| 				dsaParams.G = GetUnsignedBigInteger (param [2].Value);
 | |
| 			}
 | |
| 			catch (Exception e) {
 | |
| 				string msg = Locale.GetText ("Error decoding the ASN.1 structure.");
 | |
| 				throw new CryptographicException (msg, e);
 | |
| 			}
 | |
| 
 | |
| 			DSA dsa = (DSA) new DSACryptoServiceProvider (dsaParams.Y.Length << 3);
 | |
| 			dsa.ImportParameters (dsaParams);
 | |
| 			return dsa;
 | |
| 		}
 | |
| 
 | |
| 		static internal RSA DecodeRSA (byte[] rawPublicKey)
 | |
| 		{
 | |
| 			RSAParameters rsaParams = new RSAParameters ();
 | |
| 			try {
 | |
| 				// for RSA rawPublicKey contains 2 ASN.1 integers
 | |
| 				// the modulus and the public exponent
 | |
| 				ASN1 pubkey = new ASN1 (rawPublicKey);
 | |
| 				if (pubkey.Count == 0)
 | |
| 					throw new CryptographicException (Locale.GetText ("Missing RSA modulus and exponent."));
 | |
| 				ASN1 modulus = pubkey [0];
 | |
| 				if ((modulus == null) || (modulus.Tag != 0x02))
 | |
| 					throw new CryptographicException (Locale.GetText ("Missing RSA modulus."));
 | |
| 				ASN1 exponent = pubkey [1];
 | |
| 				if (exponent.Tag != 0x02)
 | |
| 					throw new CryptographicException (Locale.GetText ("Missing RSA public exponent."));
 | |
| 
 | |
| 				rsaParams.Modulus = GetUnsignedBigInteger (modulus.Value);
 | |
| 				rsaParams.Exponent = exponent.Value;
 | |
| 			}
 | |
| 			catch (Exception e) {
 | |
| 				string msg = Locale.GetText ("Error decoding the ASN.1 structure.");
 | |
| 				throw new CryptographicException (msg, e);
 | |
| 			}
 | |
| 
 | |
| 			int keySize = (rsaParams.Modulus.Length << 3);
 | |
| 			RSA rsa = (RSA) new RSACryptoServiceProvider (keySize);
 | |
| 			rsa.ImportParameters (rsaParams);
 | |
| 			return rsa;
 | |
| 		}
 | |
| #else
 | |
| 		private PublicKey ()
 | |
| 		{
 | |
| 		}
 | |
| 
 | |
| 
 | |
| 		public AsymmetricAlgorithm Key {
 | |
| 			get {
 | |
| 				return null;
 | |
| 			}
 | |
| 		}
 | |
| #endif
 | |
| 	}
 | |
| }
 |