| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933 | 
							- //
 
- // PKCS12.cs: PKCS 12 - Personal Information Exchange Syntax
 
- //
 
- // Author:
 
- //	Sebastien Pouliot  <sebastien@xamarin.com>
 
- //
 
- // (C) 2003 Motus Technologies Inc. (http://www.motus.com)
 
- // Copyright (C) 2004,2005,2006 Novell Inc. (http://www.novell.com)
 
- // Copyright 2013 Xamarin Inc. (http://www.xamarin.com)
 
- //
 
- // Key derivation translated from Bouncy Castle JCE (http://www.bouncycastle.org/)
 
- // See bouncycastle.txt for license.
 
- //
 
- // 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.Collections;
 
- using System.IO;
 
- using System.Security.Cryptography;
 
- using System.Text;
 
- namespace MediaBrowser.Server.Mono.Security {
 
-     public class PKCS5 {
 
- 		public const string pbeWithMD2AndDESCBC = "1.2.840.113549.1.5.1";
 
- 		public const string pbeWithMD5AndDESCBC = "1.2.840.113549.1.5.3";
 
- 		public const string pbeWithMD2AndRC2CBC = "1.2.840.113549.1.5.4";
 
- 		public const string pbeWithMD5AndRC2CBC = "1.2.840.113549.1.5.6";
 
- 		public const string pbeWithSHA1AndDESCBC = "1.2.840.113549.1.5.10";
 
- 		public const string pbeWithSHA1AndRC2CBC = "1.2.840.113549.1.5.11";
 
- 		public PKCS5 () {}
 
- 	}
 
-     public class PKCS9 {
 
- 		public const string friendlyName = "1.2.840.113549.1.9.20";
 
- 		public const string localKeyId = "1.2.840.113549.1.9.21";
 
- 		public PKCS9 () {}
 
- 	}
 
- 	internal class SafeBag {
 
- 		private string _bagOID;
 
- 		private ASN1 _asn1;
 
- 		public SafeBag(string bagOID, ASN1 asn1) {
 
- 			_bagOID = bagOID;
 
- 			_asn1 = asn1;
 
- 		}
 
- 		public string BagOID {
 
- 			get { return _bagOID; }
 
- 		}
 
- 		public ASN1 ASN1 {
 
- 			get { return _asn1; }
 
- 		}
 
- 	}
 
-     public class PKCS12 : ICloneable {
 
- 		public const string pbeWithSHAAnd128BitRC4 = "1.2.840.113549.1.12.1.1";
 
- 		public const string pbeWithSHAAnd40BitRC4 = "1.2.840.113549.1.12.1.2";
 
- 		public const string pbeWithSHAAnd3KeyTripleDESCBC = "1.2.840.113549.1.12.1.3";
 
- 		public const string pbeWithSHAAnd2KeyTripleDESCBC = "1.2.840.113549.1.12.1.4";
 
- 		public const string pbeWithSHAAnd128BitRC2CBC = "1.2.840.113549.1.12.1.5";
 
- 		public const string pbeWithSHAAnd40BitRC2CBC = "1.2.840.113549.1.12.1.6";
 
- 		// bags
 
- 		public const string keyBag  = "1.2.840.113549.1.12.10.1.1";
 
- 		public const string pkcs8ShroudedKeyBag  = "1.2.840.113549.1.12.10.1.2";
 
- 		public const string certBag  = "1.2.840.113549.1.12.10.1.3";
 
- 		public const string crlBag  = "1.2.840.113549.1.12.10.1.4";
 
- 		public const string secretBag  = "1.2.840.113549.1.12.10.1.5";
 
- 		public const string safeContentsBag  = "1.2.840.113549.1.12.10.1.6";
 
- 		// types
 
- 		public const string x509Certificate = "1.2.840.113549.1.9.22.1";
 
-  		public const string sdsiCertificate = "1.2.840.113549.1.9.22.2";
 
- 		public const string x509Crl = "1.2.840.113549.1.9.23.1";
 
- 		// Adapted from BouncyCastle PKCS12ParametersGenerator.java
 
- 		public class DeriveBytes {
 
- 			public enum Purpose {
 
- 				Key,
 
- 				IV,
 
- 				MAC
 
- 			}
 
- 			static private byte[] keyDiversifier = { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 };
 
- 			static private byte[] ivDiversifier  = { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2 };
 
- 			static private byte[] macDiversifier = { 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3 };
 
- 			private string _hashName;
 
- 			private int _iterations;
 
- 			private byte[] _password;
 
- 			private byte[] _salt;
 
- 			public DeriveBytes () {}
 
- 			public string HashName {
 
- 				get { return _hashName; } 
 
- 				set { _hashName = value; }
 
- 			}
 
- 			public int IterationCount {
 
- 				get { return _iterations; }
 
- 				set { _iterations = value; }
 
- 			}
 
- 			public byte[] Password {
 
- 				get { return (byte[]) _password.Clone (); }
 
- 				set { 
 
- 					if (value == null)
 
- 						_password = new byte [0];
 
- 					else
 
- 						_password = (byte[]) value.Clone ();
 
- 				}
 
- 			}
 
- 			public byte[] Salt {
 
- 				get { return (byte[]) _salt.Clone ();  }
 
- 				set {
 
- 					if (value != null)
 
- 						_salt = (byte[]) value.Clone ();
 
- 					else
 
- 						_salt = null;
 
- 				}
 
- 			}
 
- 			private void Adjust (byte[] a, int aOff, byte[] b) 
 
- 			{
 
- 				int x = (b[b.Length - 1] & 0xff) + (a [aOff + b.Length - 1] & 0xff) + 1;
 
- 				a [aOff + b.Length - 1] = (byte) x;
 
- 				x >>= 8;
 
- 				for (int i = b.Length - 2; i >= 0; i--) {
 
- 					x += (b [i] & 0xff) + (a [aOff + i] & 0xff);
 
- 					a [aOff + i] = (byte) x;
 
- 					x >>= 8;
 
- 				}
 
- 			}
 
- 			private byte[] Derive (byte[] diversifier, int n) 
 
- 			{
 
- 				HashAlgorithm digest = PKCS1.CreateFromName (_hashName);
 
- 				int u = (digest.HashSize >> 3); // div 8
 
- 				int v = 64;
 
- 				byte[] dKey = new byte [n];
 
- 				byte[] S;
 
- 				if ((_salt != null) && (_salt.Length != 0)) {
 
- 					S = new byte[v * ((_salt.Length + v - 1) / v)];
 
- 					for (int i = 0; i != S.Length; i++) {
 
- 						S[i] = _salt[i % _salt.Length];
 
- 					}
 
- 				}
 
- 				else {
 
- 					S = new byte[0];
 
- 				}
 
- 				byte[] P;
 
- 				if ((_password != null) && (_password.Length != 0)) {
 
- 					P = new byte[v * ((_password.Length + v - 1) / v)];
 
- 					for (int i = 0; i != P.Length; i++) {
 
- 						P[i] = _password[i % _password.Length];
 
- 					}
 
- 				}
 
- 				else {
 
- 					P = new byte[0];
 
- 				}
 
- 				byte[] I = new byte [S.Length + P.Length];
 
- 				Buffer.BlockCopy (S, 0, I, 0, S.Length);
 
- 				Buffer.BlockCopy (P, 0, I, S.Length, P.Length);
 
- 				byte[]  B = new byte[v];
 
- 				int     c = (n + u - 1) / u;
 
- 				for (int i = 1; i <= c; i++) {
 
- 					digest.TransformBlock (diversifier, 0, diversifier.Length, diversifier, 0);
 
- 					digest.TransformFinalBlock (I, 0, I.Length);
 
- 					byte[] A = digest.Hash;
 
- 					digest.Initialize ();
 
- 					for (int j = 1; j != _iterations; j++) {
 
- 						A = digest.ComputeHash (A, 0, A.Length);
 
- 					}
 
- 					for (int j = 0; j != B.Length; j++) {
 
- 						B [j] = A [j % A.Length];
 
- 					}
 
- 					for (int j = 0; j != I.Length / v; j++) {
 
- 						Adjust (I, j * v, B);
 
- 					}
 
- 					if (i == c) {
 
- 						Buffer.BlockCopy(A, 0, dKey, (i - 1) * u, dKey.Length - ((i - 1) * u));
 
- 					}
 
- 					else {
 
- 						Buffer.BlockCopy(A, 0, dKey, (i - 1) * u, A.Length);
 
- 					}
 
- 				}
 
- 				return dKey;
 
- 			}
 
- 			public byte[] DeriveKey (int size) 
 
- 			{
 
- 				return Derive (keyDiversifier, size);
 
- 			}
 
- 			public byte[] DeriveIV (int size) 
 
- 			{
 
- 				return Derive (ivDiversifier, size);
 
- 			}
 
- 			public byte[] DeriveMAC (int size) 
 
- 			{
 
- 				return Derive (macDiversifier, size);
 
- 			}
 
- 		}
 
- 		const int recommendedIterationCount = 2000;
 
- 		//private int _version;
 
- 		private byte[] _password;
 
- 		private ArrayList _keyBags;
 
- 		private ArrayList _secretBags;
 
- 		private X509CertificateCollection _certs;
 
- 		private bool _keyBagsChanged;
 
- 		private bool _secretBagsChanged;
 
- 		private bool _certsChanged;
 
- 		private int _iterations;
 
- 		private ArrayList _safeBags;
 
- 		private RandomNumberGenerator _rng;
 
- 		// constructors
 
- 		public PKCS12 () 
 
- 		{
 
- 			_iterations = recommendedIterationCount;
 
- 			_keyBags = new ArrayList ();
 
- 			_secretBags = new ArrayList ();
 
- 			_certs = new X509CertificateCollection ();
 
- 			_keyBagsChanged = false;
 
- 			_secretBagsChanged = false;
 
- 			_certsChanged = false;
 
- 			_safeBags = new ArrayList ();
 
- 		}
 
- 		public PKCS12 (byte[] data)
 
- 			: this ()
 
- 		{
 
- 			Password = null;
 
- 			Decode (data);
 
- 		}
 
- 		/*
 
- 		 * PFX ::= SEQUENCE {
 
- 		 *	version INTEGER {v3(3)}(v3,...),
 
- 		 *	authSafe ContentInfo,
 
- 		 *	macData MacData OPTIONAL
 
- 		 * }
 
- 		 * 
 
- 		 * MacData ::= SEQUENCE {
 
- 		 *	mac DigestInfo,
 
- 		 *	macSalt OCTET STRING,
 
- 		 *	iterations INTEGER DEFAULT 1
 
- 		 *	-- Note: The default is for historical reasons and its use is deprecated. A higher
 
- 		 *	-- value, like 1024 is recommended.
 
- 		 * }
 
- 		 * 
 
- 		 * SafeContents ::= SEQUENCE OF SafeBag
 
- 		 * 
 
- 		 * SafeBag ::= SEQUENCE {
 
- 		 *	bagId BAG-TYPE.&id ({PKCS12BagSet}),
 
- 		 *	bagValue [0] EXPLICIT BAG-TYPE.&Type({PKCS12BagSet}{@bagId}),
 
- 		 *	bagAttributes SET OF PKCS12Attribute OPTIONAL
 
- 		 * }
 
- 		 */
 
- 		public PKCS12 (byte[] data, string password)
 
- 			: this ()
 
- 		{
 
- 			Password = password;
 
- 			Decode (data);
 
- 		}
 
- 		public PKCS12 (byte[] data, byte[] password)
 
- 			: this ()
 
- 		{
 
- 			_password = password;
 
- 			Decode (data);
 
- 		}
 
- 		private void Decode (byte[] data)
 
- 		{
 
- 			ASN1 pfx = new ASN1 (data);
 
- 			if (pfx.Tag != 0x30)
 
- 				throw new ArgumentException ("invalid data");
 
- 			
 
- 			ASN1 version = pfx [0];
 
- 			if (version.Tag != 0x02)
 
- 				throw new ArgumentException ("invalid PFX version");
 
- 			//_version = version.Value [0];
 
- 			PKCS7.ContentInfo authSafe = new PKCS7.ContentInfo (pfx [1]);
 
- 			if (authSafe.ContentType != PKCS7.Oid.data)
 
- 				throw new ArgumentException ("invalid authenticated safe");
 
- 			// now that we know it's a PKCS#12 file, check the (optional) MAC
 
- 			// before decoding anything else in the file
 
- 			if (pfx.Count > 2) {
 
- 				ASN1 macData = pfx [2];
 
- 				if (macData.Tag != 0x30)
 
- 					throw new ArgumentException ("invalid MAC");
 
- 				
 
- 				ASN1 mac = macData [0];
 
- 				if (mac.Tag != 0x30)
 
- 					throw new ArgumentException ("invalid MAC");
 
- 				ASN1 macAlgorithm = mac [0];
 
- 				string macOid = ASN1Convert.ToOid (macAlgorithm [0]);
 
- 				if (macOid != "1.3.14.3.2.26")
 
- 					throw new ArgumentException ("unsupported HMAC");
 
- 				byte[] macValue = mac [1].Value;
 
- 				ASN1 macSalt = macData [1];
 
- 				if (macSalt.Tag != 0x04)
 
- 					throw new ArgumentException ("missing MAC salt");
 
- 				_iterations = 1; // default value
 
- 				if (macData.Count > 2) {
 
- 					ASN1 iters = macData [2];
 
- 					if (iters.Tag != 0x02)
 
- 						throw new ArgumentException ("invalid MAC iteration");
 
- 					_iterations = ASN1Convert.ToInt32 (iters);
 
- 				}
 
- 				byte[] authSafeData = authSafe.Content [0].Value;
 
- 				byte[] calculatedMac = MAC (_password, macSalt.Value, _iterations, authSafeData);
 
- 				if (!Compare (macValue, calculatedMac)) {
 
- 					byte[] nullPassword = {0, 0};
 
- 					calculatedMac = MAC(nullPassword, macSalt.Value, _iterations, authSafeData);
 
- 					if (!Compare (macValue, calculatedMac))
 
- 						throw new CryptographicException ("Invalid MAC - file may have been tampe red!");
 
- 					_password = nullPassword;
 
- 				}
 
- 			}
 
- 			// we now returns to our original presentation - PFX
 
- 			ASN1 authenticatedSafe = new ASN1 (authSafe.Content [0].Value);
 
- 			for (int i=0; i < authenticatedSafe.Count; i++) {
 
- 				PKCS7.ContentInfo ci = new PKCS7.ContentInfo (authenticatedSafe [i]);
 
- 				switch (ci.ContentType) {
 
- 					case PKCS7.Oid.data:
 
- 						// unencrypted (by PKCS#12)
 
- 						ASN1 safeContents = new ASN1 (ci.Content [0].Value);
 
- 						for (int j=0; j < safeContents.Count; j++) {
 
- 							ASN1 safeBag = safeContents [j];
 
- 							ReadSafeBag (safeBag);
 
- 						}
 
- 						break;
 
- 					case PKCS7.Oid.encryptedData:
 
- 						// password encrypted
 
- 						PKCS7.EncryptedData ed = new PKCS7.EncryptedData (ci.Content [0]);
 
- 						ASN1 decrypted = new ASN1 (Decrypt (ed));
 
- 						for (int j=0; j < decrypted.Count; j++) {
 
- 							ASN1 safeBag = decrypted [j];
 
- 							ReadSafeBag (safeBag);
 
- 						}
 
- 						break;
 
- 					case PKCS7.Oid.envelopedData:
 
- 						// public key encrypted
 
- 						throw new NotImplementedException ("public key encrypted");
 
- 					default:
 
- 						throw new ArgumentException ("unknown authenticatedSafe");
 
- 				}
 
- 			}
 
- 		}
 
- 		~PKCS12 () 
 
- 		{
 
- 			if (_password != null) {
 
- 				Array.Clear (_password, 0, _password.Length);
 
- 			}
 
- 			_password = null;
 
- 		}
 
- 		// properties
 
- 		public string Password {
 
- 			set {
 
- 				// Clear old password.
 
- 				if (_password != null)
 
- 					Array.Clear (_password, 0, _password.Length);
 
- 				_password = null;
 
- 				if (value != null) {
 
- 					if (value.Length > 0) {
 
- 						int size = value.Length;
 
- 						int nul = 0;
 
- 						if (size < MaximumPasswordLength) {
 
- 							// if not present, add space for a NULL (0x00) character
 
- 							if (value[size - 1] != 0x00)
 
- 								nul = 1;
 
- 						} else {
 
- 							size = MaximumPasswordLength;
 
- 						}
 
- 						_password = new byte[(size + nul) << 1]; // double for unicode
 
- 						Encoding.BigEndianUnicode.GetBytes (value, 0, size, _password, 0);
 
- 					} else {
 
- 						// double-byte (Unicode) NULL (0x00) - see bug #79617
 
- 						_password = new byte[2];
 
- 					}
 
- 				}
 
- 			}
 
- 		}
 
- 		public int IterationCount {
 
- 			get { return _iterations; }
 
- 			set { _iterations = value; }
 
- 		}
 
- 		public ArrayList Keys {
 
- 			get {
 
- 				if (_keyBagsChanged) {
 
- 					_keyBags.Clear ();
 
- 					foreach (SafeBag sb in _safeBags) {
 
- 						if (sb.BagOID.Equals (keyBag)) {
 
- 							ASN1 safeBag = sb.ASN1;
 
- 							ASN1 bagValue = safeBag [1];
 
- 							PKCS8.PrivateKeyInfo pki = new PKCS8.PrivateKeyInfo (bagValue.Value);
 
- 							byte[] privateKey = pki.PrivateKey;
 
- 							switch (privateKey [0]) {
 
- 							case 0x02:
 
- 								DSAParameters p = new DSAParameters (); // FIXME
 
- 								_keyBags.Add (PKCS8.PrivateKeyInfo.DecodeDSA (privateKey, p));
 
- 								break;
 
- 							case 0x30:
 
- 								_keyBags.Add (PKCS8.PrivateKeyInfo.DecodeRSA (privateKey));
 
- 								break;
 
- 							default:
 
- 								break;
 
- 							}
 
- 							Array.Clear (privateKey, 0, privateKey.Length);
 
- 						} else if (sb.BagOID.Equals (pkcs8ShroudedKeyBag)) {
 
- 							ASN1 safeBag = sb.ASN1;
 
- 							ASN1 bagValue = safeBag [1];
 
- 							PKCS8.EncryptedPrivateKeyInfo epki = new PKCS8.EncryptedPrivateKeyInfo (bagValue.Value);
 
- 							byte[] decrypted = Decrypt (epki.Algorithm, epki.Salt, epki.IterationCount, epki.EncryptedData);
 
- 							PKCS8.PrivateKeyInfo pki = new PKCS8.PrivateKeyInfo (decrypted);
 
- 							byte[] privateKey = pki.PrivateKey;
 
- 							switch (privateKey [0]) {
 
- 							case 0x02:
 
- 								DSAParameters p = new DSAParameters (); // FIXME
 
- 								_keyBags.Add (PKCS8.PrivateKeyInfo.DecodeDSA (privateKey, p));
 
- 								break;
 
- 							case 0x30:
 
- 								_keyBags.Add (PKCS8.PrivateKeyInfo.DecodeRSA (privateKey));
 
- 								break;
 
- 							default:
 
- 								break;
 
- 							}
 
- 							Array.Clear (privateKey, 0, privateKey.Length);
 
- 							Array.Clear (decrypted, 0, decrypted.Length);
 
- 						}
 
- 					}
 
- 					_keyBagsChanged = false;
 
- 				}
 
- 				return ArrayList.ReadOnly(_keyBags);
 
- 			}
 
- 		}
 
- 		public ArrayList Secrets {
 
- 			get {
 
- 				if (_secretBagsChanged) {
 
- 					_secretBags.Clear ();
 
- 					foreach (SafeBag sb in _safeBags) {
 
- 						if (sb.BagOID.Equals (secretBag)) {
 
- 							ASN1 safeBag = sb.ASN1;
 
- 							ASN1 bagValue = safeBag [1];
 
- 							byte[] secret = bagValue.Value;
 
- 							_secretBags.Add(secret);
 
- 						}
 
- 					}
 
- 					_secretBagsChanged = false;
 
- 				}
 
- 				return ArrayList.ReadOnly(_secretBags);
 
- 			}
 
- 		}
 
- 		public X509CertificateCollection Certificates {
 
- 			get {
 
- 				if (_certsChanged) {
 
- 					_certs.Clear ();
 
- 					foreach (SafeBag sb in _safeBags) {
 
- 						if (sb.BagOID.Equals (certBag)) {
 
- 							ASN1 safeBag = sb.ASN1;
 
- 							ASN1 bagValue = safeBag [1];
 
- 							PKCS7.ContentInfo cert = new PKCS7.ContentInfo (bagValue.Value);
 
- 							_certs.Add (new X509Certificate (cert.Content [0].Value));
 
- 						}
 
- 					}
 
- 					_certsChanged = false;
 
- 				}
 
- 				return _certs;
 
- 			}
 
- 		}
 
- 		internal RandomNumberGenerator RNG {
 
- 			get {
 
- 				if (_rng == null)
 
- 					_rng = RandomNumberGenerator.Create ();
 
- 				return _rng;
 
- 			}
 
- 		}
 
- 		// private methods
 
- 		private bool Compare (byte[] expected, byte[] actual) 
 
- 		{
 
- 			bool compare = false;
 
- 			if (expected.Length == actual.Length) {
 
- 				for (int i=0; i < expected.Length; i++) {
 
- 					if (expected [i] != actual [i])
 
- 						return false;
 
- 				}
 
- 				compare = true;
 
- 			}
 
- 			return compare;
 
- 		}
 
- 		private SymmetricAlgorithm GetSymmetricAlgorithm (string algorithmOid, byte[] salt, int iterationCount)
 
- 		{
 
- 			string algorithm = null;
 
- 			int keyLength = 8;	// 64 bits (default)
 
- 			int ivLength = 8;	// 64 bits (default)
 
- 			PKCS12.DeriveBytes pd = new PKCS12.DeriveBytes ();
 
- 			pd.Password = _password; 
 
- 			pd.Salt = salt;
 
- 			pd.IterationCount = iterationCount;
 
- 			switch (algorithmOid) {
 
- 				case PKCS5.pbeWithMD2AndDESCBC:			// no unit test available
 
- 					pd.HashName = "MD2";
 
- 					algorithm = "DES";
 
- 					break;
 
- 				case PKCS5.pbeWithMD5AndDESCBC:			// no unit test available
 
- 					pd.HashName = "MD5";
 
- 					algorithm = "DES";
 
- 					break;
 
- 				case PKCS5.pbeWithMD2AndRC2CBC:			// no unit test available
 
- 					// TODO - RC2-CBC-Parameter (PKCS5)
 
- 					// if missing default to 32 bits !!!
 
- 					pd.HashName = "MD2";
 
- 					algorithm = "RC2";
 
- 					keyLength = 4;		// default
 
- 					break;
 
- 				case PKCS5.pbeWithMD5AndRC2CBC:			// no unit test available
 
- 					// TODO - RC2-CBC-Parameter (PKCS5)
 
- 					// if missing default to 32 bits !!!
 
- 					pd.HashName = "MD5";
 
- 					algorithm = "RC2";
 
- 					keyLength = 4;		// default
 
- 					break;
 
- 				case PKCS5.pbeWithSHA1AndDESCBC: 		// no unit test available
 
- 					pd.HashName = "SHA1";
 
- 					algorithm = "DES";
 
- 					break;
 
- 				case PKCS5.pbeWithSHA1AndRC2CBC:		// no unit test available
 
- 					// TODO - RC2-CBC-Parameter (PKCS5)
 
- 					// if missing default to 32 bits !!!
 
- 					pd.HashName = "SHA1";
 
- 					algorithm = "RC2";
 
- 					keyLength = 4;		// default
 
- 					break;
 
- 				case PKCS12.pbeWithSHAAnd128BitRC4: 		// no unit test available
 
- 					pd.HashName = "SHA1";
 
- 					algorithm = "RC4";
 
- 					keyLength = 16;
 
- 					ivLength = 0;		// N/A
 
- 					break;
 
- 				case PKCS12.pbeWithSHAAnd40BitRC4: 		// no unit test available
 
- 					pd.HashName = "SHA1";
 
- 					algorithm = "RC4";
 
- 					keyLength = 5;
 
- 					ivLength = 0;		// N/A
 
- 					break;
 
- 				case PKCS12.pbeWithSHAAnd3KeyTripleDESCBC: 
 
- 					pd.HashName = "SHA1";
 
- 					algorithm = "TripleDES";
 
- 					keyLength = 24;
 
- 					break;
 
- 				case PKCS12.pbeWithSHAAnd2KeyTripleDESCBC:	// no unit test available
 
- 					pd.HashName = "SHA1";
 
- 					algorithm = "TripleDES";
 
- 					keyLength = 16;
 
- 					break;
 
- 				case PKCS12.pbeWithSHAAnd128BitRC2CBC: 		// no unit test available
 
- 					pd.HashName = "SHA1";
 
- 					algorithm = "RC2";
 
- 					keyLength = 16;
 
- 					break;
 
- 				case PKCS12.pbeWithSHAAnd40BitRC2CBC: 
 
- 					pd.HashName = "SHA1";
 
- 					algorithm = "RC2";
 
- 					keyLength = 5;
 
- 					break;
 
- 				default:
 
- 					throw new NotSupportedException ("unknown oid " + algorithm);
 
- 			}
 
- 			SymmetricAlgorithm sa = null;
 
-             sa = SymmetricAlgorithm.Create(algorithm);
 
-             sa.Key = pd.DeriveKey (keyLength);
 
- 			// IV required only for block ciphers (not stream ciphers)
 
- 			if (ivLength > 0) {
 
- 				sa.IV = pd.DeriveIV (ivLength);
 
- 				sa.Mode = CipherMode.CBC;
 
- 			}
 
- 			return sa;
 
- 		}
 
- 		public byte[] Decrypt (string algorithmOid, byte[] salt, int iterationCount, byte[] encryptedData) 
 
- 		{
 
- 			SymmetricAlgorithm sa = null;
 
- 			byte[] result = null;
 
- 			try {
 
- 				sa = GetSymmetricAlgorithm (algorithmOid, salt, iterationCount);
 
- 				ICryptoTransform ct = sa.CreateDecryptor ();
 
- 				result = ct.TransformFinalBlock (encryptedData, 0, encryptedData.Length);
 
- 			}
 
- 			finally {
 
- 				if (sa != null)
 
- 					sa.Clear ();
 
- 			}
 
- 			return result;
 
- 		}
 
- 		public byte[] Decrypt (PKCS7.EncryptedData ed)
 
- 		{
 
- 			return Decrypt (ed.EncryptionAlgorithm.ContentType, 
 
- 				ed.EncryptionAlgorithm.Content [0].Value, 
 
- 				ASN1Convert.ToInt32 (ed.EncryptionAlgorithm.Content [1]),
 
- 				ed.EncryptedContent);
 
- 		}
 
- 		public byte[] Encrypt (string algorithmOid, byte[] salt, int iterationCount, byte[] data) 
 
- 		{
 
- 			byte[] result = null;
 
- 			using (SymmetricAlgorithm sa = GetSymmetricAlgorithm (algorithmOid, salt, iterationCount)) {
 
- 				ICryptoTransform ct = sa.CreateEncryptor ();
 
- 				result = ct.TransformFinalBlock (data, 0, data.Length);
 
- 			}
 
- 			return result;
 
- 		}
 
- 		private DSAParameters GetExistingParameters (out bool found)
 
- 		{
 
- 			foreach (X509Certificate cert in Certificates) {
 
- 				// FIXME: that won't work if parts of the parameters are missing
 
- 				if (cert.KeyAlgorithmParameters != null) {
 
- 					DSA dsa = cert.DSA;
 
- 					if (dsa != null) {
 
- 						found = true;
 
- 						return dsa.ExportParameters (false);
 
- 					}
 
- 				}
 
- 			}
 
- 			found = false;
 
- 			return new DSAParameters ();
 
- 		}
 
- 		private void AddPrivateKey (PKCS8.PrivateKeyInfo pki) 
 
- 		{
 
- 			byte[] privateKey = pki.PrivateKey;
 
- 			switch (privateKey [0]) {
 
- 				case 0x02:
 
- 					bool found;
 
- 					DSAParameters p = GetExistingParameters (out found);
 
- 					if (found) {
 
- 						_keyBags.Add (PKCS8.PrivateKeyInfo.DecodeDSA (privateKey, p));
 
- 					}
 
- 					break;
 
- 				case 0x30:
 
- 					_keyBags.Add (PKCS8.PrivateKeyInfo.DecodeRSA (privateKey));
 
- 					break;
 
- 				default:
 
- 					Array.Clear (privateKey, 0, privateKey.Length);
 
- 					throw new CryptographicException ("Unknown private key format");
 
- 			}
 
- 			Array.Clear (privateKey, 0, privateKey.Length);
 
- 		}
 
- 		private void ReadSafeBag (ASN1 safeBag) 
 
- 		{
 
- 			if (safeBag.Tag != 0x30)
 
- 				throw new ArgumentException ("invalid safeBag");
 
- 			ASN1 bagId = safeBag [0];
 
- 			if (bagId.Tag != 0x06)
 
- 				throw new ArgumentException ("invalid safeBag id");
 
- 			ASN1 bagValue = safeBag [1];
 
- 			string oid = ASN1Convert.ToOid (bagId);
 
- 			switch (oid) {
 
- 				case keyBag:
 
- 					// NEED UNIT TEST
 
- 					AddPrivateKey (new PKCS8.PrivateKeyInfo (bagValue.Value));
 
- 					break;
 
- 				case pkcs8ShroudedKeyBag:
 
- 					PKCS8.EncryptedPrivateKeyInfo epki = new PKCS8.EncryptedPrivateKeyInfo (bagValue.Value);
 
- 					byte[] decrypted = Decrypt (epki.Algorithm, epki.Salt, epki.IterationCount, epki.EncryptedData);
 
- 					AddPrivateKey (new PKCS8.PrivateKeyInfo (decrypted));
 
- 					Array.Clear (decrypted, 0, decrypted.Length);
 
- 					break;
 
- 				case certBag:
 
- 					PKCS7.ContentInfo cert = new PKCS7.ContentInfo (bagValue.Value);
 
- 					if (cert.ContentType != x509Certificate)
 
- 						throw new NotSupportedException ("unsupport certificate type");
 
- 					X509Certificate x509 = new X509Certificate (cert.Content [0].Value);
 
- 					_certs.Add (x509);
 
- 					break;
 
- 				case crlBag:
 
- 					// TODO
 
- 					break;
 
- 				case secretBag: 
 
- 					byte[] secret = bagValue.Value;
 
- 					_secretBags.Add(secret);
 
- 					break;
 
- 				case safeContentsBag:
 
- 					// TODO - ? recurse ?
 
- 					break;
 
- 				default:
 
- 					throw new ArgumentException ("unknown safeBag oid");
 
- 			}
 
- 			if (safeBag.Count > 2) {
 
- 				ASN1 bagAttributes = safeBag [2];
 
- 				if (bagAttributes.Tag != 0x31)
 
- 					throw new ArgumentException ("invalid safeBag attributes id");
 
- 				for (int i = 0; i < bagAttributes.Count; i++) {
 
- 					ASN1 pkcs12Attribute = bagAttributes[i];
 
- 						
 
- 					if (pkcs12Attribute.Tag != 0x30)
 
- 						throw new ArgumentException ("invalid PKCS12 attributes id");
 
- 					ASN1 attrId = pkcs12Attribute [0];
 
- 					if (attrId.Tag != 0x06)
 
- 						throw new ArgumentException ("invalid attribute id");
 
- 						
 
- 					string attrOid = ASN1Convert.ToOid (attrId);
 
- 					ASN1 attrValues = pkcs12Attribute[1];
 
- 					for (int j = 0; j < attrValues.Count; j++) {
 
- 						ASN1 attrValue = attrValues[j];
 
- 						switch (attrOid) {
 
- 						case PKCS9.friendlyName:
 
- 							if (attrValue.Tag != 0x1e)
 
- 								throw new ArgumentException ("invalid attribute value id");
 
- 							break;
 
- 						case PKCS9.localKeyId:
 
- 							if (attrValue.Tag != 0x04)
 
- 								throw new ArgumentException ("invalid attribute value id");
 
- 							break;
 
- 						default:
 
- 							// Unknown OID -- don't check Tag
 
- 							break;
 
- 						}
 
- 					}
 
- 				}
 
- 			}
 
- 			_safeBags.Add (new SafeBag(oid, safeBag));
 
- 		}
 
- 		private ASN1 Pkcs8ShroudedKeyBagSafeBag (AsymmetricAlgorithm aa, IDictionary attributes) 
 
- 		{
 
- 			PKCS8.PrivateKeyInfo pki = new PKCS8.PrivateKeyInfo ();
 
- 			if (aa is RSA) {
 
- 				pki.Algorithm = "1.2.840.113549.1.1.1";
 
- 				pki.PrivateKey = PKCS8.PrivateKeyInfo.Encode ((RSA)aa);
 
- 			}
 
- 			else if (aa is DSA) {
 
- 				pki.Algorithm = null;
 
- 				pki.PrivateKey = PKCS8.PrivateKeyInfo.Encode ((DSA)aa);
 
- 			}
 
- 			else
 
- 				throw new CryptographicException ("Unknown asymmetric algorithm {0}", aa.ToString ());
 
- 			PKCS8.EncryptedPrivateKeyInfo epki = new PKCS8.EncryptedPrivateKeyInfo ();
 
- 			epki.Algorithm = pbeWithSHAAnd3KeyTripleDESCBC;
 
- 			epki.IterationCount = _iterations;
 
- 			epki.EncryptedData = Encrypt (pbeWithSHAAnd3KeyTripleDESCBC, epki.Salt, _iterations, pki.GetBytes ());
 
- 			ASN1 safeBag = new ASN1 (0x30);
 
- 			safeBag.Add (ASN1Convert.FromOid (pkcs8ShroudedKeyBag));
 
- 			ASN1 bagValue = new ASN1 (0xA0);
 
- 			bagValue.Add (new ASN1 (epki.GetBytes ()));
 
- 			safeBag.Add (bagValue);
 
- 			if (attributes != null) {
 
- 				ASN1 bagAttributes = new ASN1 (0x31);
 
- 				IDictionaryEnumerator de = attributes.GetEnumerator ();
 
- 				while (de.MoveNext ()) {
 
- 					string oid = (string)de.Key;
 
- 					switch (oid) {
 
- 					case PKCS9.friendlyName:
 
- 						ArrayList names = (ArrayList)de.Value;
 
- 						if (names.Count > 0) {
 
- 							ASN1 pkcs12Attribute = new ASN1 (0x30);
 
- 							pkcs12Attribute.Add (ASN1Convert.FromOid (PKCS9.friendlyName));
 
- 							ASN1 attrValues = new ASN1 (0x31);
 
- 							foreach (byte[] name in names) {
 
- 								ASN1 attrValue = new ASN1 (0x1e);
 
- 								attrValue.Value = name;
 
- 								attrValues.Add (attrValue);
 
- 							}
 
- 							pkcs12Attribute.Add (attrValues);
 
- 							bagAttributes.Add (pkcs12Attribute);
 
- 						}
 
- 						break;
 
- 					case PKCS9.localKeyId:
 
- 						ArrayList keys = (ArrayList)de.Value;
 
- 						if (keys.Count > 0) {
 
- 							ASN1 pkcs12Attribute = new ASN1 (0x30);
 
- 							pkcs12Attribute.Add (ASN1Convert.FromOid (PKCS9.localKeyId));
 
- 							ASN1 attrValues = new ASN1 (0x31);
 
- 							foreach (byte[] key in keys) {
 
- 								ASN1 attrValue = new ASN1 (0x04);
 
- 								attrValue.Value = key;
 
- 								attrValues.Add (attrValue);
 
- 							}
 
- 							pkcs12Attribute.Add (attrValues);
 
- 							bagAttributes.Add (pkcs12Attribute);
 
- 						}
 
- 						break;
 
- 					default:
 
- 						break;
 
- 					}
 
- 				}
 
- 				if (bagAttributes.Count > 0) {
 
- 					safeBag.Add (bagAttributes);
 
- 				}
 
- 			}
 
- 			return safeBag;
 
- 		}
 
- 		private ASN1 KeyBagSafeBag (AsymmetricAlgorithm aa, IDictionary attributes) 
 
- 		{
 
- 			PKCS8.PrivateKeyInfo pki = new PKCS8.PrivateKeyInfo ();
 
- 			if (aa is RSA) {
 
- 				pki.Algorithm = "1.2.840.113549.1.1.1";
 
- 				pki.PrivateKey = PKCS8.PrivateKeyInfo.Encode ((RSA)aa);
 
- 			}
 
- 			else if (aa is DSA) {
 
- 				pki.Algorithm = null;
 
- 				pki.PrivateKey = PKCS8.PrivateKeyInfo.Encode ((DSA)aa);
 
- 			}
 
- 			else
 
- 				throw new CryptographicException ("Unknown asymmetric algorithm {0}", aa.ToString ());
 
- 			ASN1 safeBag = new ASN1 (0x30);
 
- 			safeBag.Add (ASN1Convert.FromOid (keyBag));
 
- 			ASN1 bagValue = new ASN1 (0xA0);
 
- 			bagValue.Add (new ASN1 (pki.GetBytes ()));
 
- 			safeBag.Add (bagValue);
 
- 			if (attributes != null) {
 
- 				ASN1 bagAttributes = new ASN1 (0x31);
 
- 				IDictionaryEnumerator de = attributes.GetEnumerator ();
 
- 				while (de.MoveNext ()) {
 
- 					string oid = (string)de.Key;
 
- 					switch (oid) {
 
- 					case PKCS9.friendlyName:
 
- 						ArrayList names = (ArrayList)de.Value;
 
- 						if (names.Count > 0) {
 
- 							ASN1 pkcs12Attribute = new ASN1 (0x30);
 
- 							pkcs12Attribute.Add (ASN1Convert.FromOid (PKCS9.friendlyName));
 
- 							ASN1 attrValues = new ASN1 (0x31);
 
- 							foreach (byte[] name in names) {
 
- 								ASN1 attrValue = new ASN1 (0x1e);
 
- 								attrValue.Value = name;
 
- 								attrValues.Add (attrValue);
 
- 							}
 
- 							pkcs12Attribute.Add (attrValues);
 
- 							bagAttributes.Add (pkcs12Attribute);
 
- 						}
 
- 						break;
 
- 					case PKCS9.localKeyId:
 
- 						ArrayList keys = (ArrayList)de.Value;
 
- 						if (keys.Count > 0) {
 
- 							ASN1 pkcs12Attribute = new ASN1 (0x30);
 
- 							pkcs12Attribute.Add (ASN1Convert.FromOid (PKCS9.localKeyId));
 
- 							ASN1 attrValues = new ASN1 (0x31);
 
- 							foreach (byte[] key in keys) {
 
- 								ASN1 attrValue = new ASN1 (0x04);
 
- 								attrValue.Value = key;
 
- 								attrValues.Add (attrValue);
 
- 							}
 
- 							pkcs12Attribute.Add (attrValues);
 
- 							bagAttributes.Add (pkcs12Attribute);
 
- 						}
 
- 						break;
 
- 					default:
 
- 						break;
 
- 					}
 
- 				}
 
- 				if (bagAttributes.Count > 0) {
 
- 					safeBag.Add (bagAttributes);
 
- 				}
 
- 			}
 
- 			return safeBag;
 
- 		}
 
- 		private ASN1 SecretBagSafeBag (byte[] secret, IDictionary attributes) 
 
- 		{
 
- 			ASN1 safeBag = new ASN1 (0x30);
 
- 			safeBag.Add (ASN1Convert.FromOid (secretBag));
 
- 			ASN1 bagValue = new ASN1 (0x80, secret);
 
- 			safeBag.Add (bagValue);
 
- 			if (attributes != null) {
 
- 				ASN1 bagAttributes = new ASN1 (0x31);
 
- 				IDictionaryEnumerator de = attributes.GetEnumerator ();
 
- 				while (de.MoveNext ()) {
 
- 					string oid = (string)de.Key;
 
- 					switch (oid) {
 
- 					case PKCS9.friendlyName:
 
- 						ArrayList names = (ArrayList)de.Value;
 
- 						if (names.Count > 0) {
 
- 							ASN1 pkcs12Attribute = new ASN1 (0x30);
 
- 							pkcs12Attribute.Add (ASN1Convert.FromOid (PKCS9.friendlyName));
 
- 							ASN1 attrValues = new ASN1 (0x31);
 
- 							foreach (byte[] name in names) {
 
- 								ASN1 attrValue = new ASN1 (0x1e);
 
- 								attrValue.Value = name;
 
- 								attrValues.Add (attrValue);
 
- 							}
 
- 							pkcs12Attribute.Add (attrValues);
 
- 							bagAttributes.Add (pkcs12Attribute);
 
- 						}
 
- 						break;
 
- 					case PKCS9.localKeyId:
 
- 						ArrayList keys = (ArrayList)de.Value;
 
- 						if (keys.Count > 0) {
 
- 							ASN1 pkcs12Attribute = new ASN1 (0x30);
 
- 							pkcs12Attribute.Add (ASN1Convert.FromOid (PKCS9.localKeyId));
 
- 							ASN1 attrValues = new ASN1 (0x31);
 
- 							foreach (byte[] key in keys) {
 
- 								ASN1 attrValue = new ASN1 (0x04);
 
- 								attrValue.Value = key;
 
- 								attrValues.Add (attrValue);
 
- 							}
 
- 							pkcs12Attribute.Add (attrValues);
 
- 							bagAttributes.Add (pkcs12Attribute);
 
- 						}
 
- 						break;
 
- 					default:
 
- 						break;
 
- 					}
 
- 				}
 
- 				if (bagAttributes.Count > 0) {
 
- 					safeBag.Add (bagAttributes);
 
- 				}
 
- 			}
 
- 			return safeBag;
 
- 		}
 
- 		private ASN1 CertificateSafeBag (X509Certificate x509, IDictionary attributes) 
 
- 		{
 
- 			ASN1 encapsulatedCertificate = new ASN1 (0x04, x509.RawData);
 
- 			PKCS7.ContentInfo ci = new PKCS7.ContentInfo ();
 
- 			ci.ContentType = x509Certificate;
 
- 			ci.Content.Add (encapsulatedCertificate);
 
- 			ASN1 bagValue = new ASN1 (0xA0);
 
- 			bagValue.Add (ci.ASN1);
 
- 			ASN1 safeBag = new ASN1 (0x30);
 
- 			safeBag.Add (ASN1Convert.FromOid (certBag));
 
- 			safeBag.Add (bagValue);
 
- 			if (attributes != null) {
 
- 				ASN1 bagAttributes = new ASN1 (0x31);
 
- 				IDictionaryEnumerator de = attributes.GetEnumerator ();
 
- 				while (de.MoveNext ()) {
 
- 					string oid = (string)de.Key;
 
- 					switch (oid) {
 
- 					case PKCS9.friendlyName:
 
- 						ArrayList names = (ArrayList)de.Value;
 
- 						if (names.Count > 0) {
 
- 							ASN1 pkcs12Attribute = new ASN1 (0x30);
 
- 							pkcs12Attribute.Add (ASN1Convert.FromOid (PKCS9.friendlyName));
 
- 							ASN1 attrValues = new ASN1 (0x31);
 
- 							foreach (byte[] name in names) {
 
- 								ASN1 attrValue = new ASN1 (0x1e);
 
- 								attrValue.Value = name;
 
- 								attrValues.Add (attrValue);
 
- 							}
 
- 							pkcs12Attribute.Add (attrValues);
 
- 							bagAttributes.Add (pkcs12Attribute);
 
- 						}
 
- 						break;
 
- 					case PKCS9.localKeyId:
 
- 						ArrayList keys = (ArrayList)de.Value;
 
- 						if (keys.Count > 0) {
 
- 							ASN1 pkcs12Attribute = new ASN1 (0x30);
 
- 							pkcs12Attribute.Add (ASN1Convert.FromOid (PKCS9.localKeyId));
 
- 							ASN1 attrValues = new ASN1 (0x31);
 
- 							foreach (byte[] key in keys) {
 
- 								ASN1 attrValue = new ASN1 (0x04);
 
- 								attrValue.Value = key;
 
- 								attrValues.Add (attrValue);
 
- 							}
 
- 							pkcs12Attribute.Add (attrValues);
 
- 							bagAttributes.Add (pkcs12Attribute);
 
- 						}
 
- 						break;
 
- 					default:
 
- 						break;
 
- 					}
 
- 				}
 
- 				if (bagAttributes.Count > 0) {
 
- 					safeBag.Add (bagAttributes);
 
- 				}
 
- 			}
 
- 			return safeBag;
 
- 		}
 
- 		private byte[] MAC (byte[] password, byte[] salt, int iterations, byte[] data) 
 
- 		{
 
- 			PKCS12.DeriveBytes pd = new PKCS12.DeriveBytes ();
 
- 			pd.HashName = "SHA1";
 
- 			pd.Password = password;
 
- 			pd.Salt = salt;
 
- 			pd.IterationCount = iterations;
 
- 			HMACSHA1 hmac = (HMACSHA1) HMACSHA1.Create ();
 
- 			hmac.Key = pd.DeriveMAC (20);
 
- 			return hmac.ComputeHash (data, 0, data.Length);
 
- 		}
 
- 		/*
 
- 		 * SafeContents ::= SEQUENCE OF SafeBag
 
- 		 * 
 
- 		 * SafeBag ::= SEQUENCE {
 
- 		 *	bagId BAG-TYPE.&id ({PKCS12BagSet}),
 
- 		 *	bagValue [0] EXPLICIT BAG-TYPE.&Type({PKCS12BagSet}{@bagId}),
 
- 		 *	bagAttributes SET OF PKCS12Attribute OPTIONAL
 
- 		 * }
 
- 		 */
 
- 		public byte[] GetBytes () 
 
- 		{
 
- 			// TODO (incomplete)
 
- 			ASN1 safeBagSequence = new ASN1 (0x30);
 
- 			// Sync Safe Bag list since X509CertificateCollection may be updated
 
- 			ArrayList scs = new ArrayList ();
 
- 			foreach (SafeBag sb in _safeBags) {
 
- 				if (sb.BagOID.Equals (certBag)) {
 
- 					ASN1 safeBag = sb.ASN1;
 
- 					ASN1 bagValue = safeBag [1];
 
- 					PKCS7.ContentInfo cert = new PKCS7.ContentInfo (bagValue.Value);
 
- 					scs.Add (new X509Certificate (cert.Content [0].Value));
 
- 				}
 
- 			}
 
- 			ArrayList addcerts = new ArrayList ();
 
- 			ArrayList removecerts = new ArrayList ();
 
- 			foreach (X509Certificate c in Certificates) {
 
- 				bool found = false;
 
- 				foreach (X509Certificate lc in scs) {
 
- 					if (Compare (c.RawData, lc.RawData)) {
 
- 						found = true;
 
- 					}
 
- 				}
 
- 				if (!found) {
 
- 					addcerts.Add (c);
 
- 				}
 
- 			}
 
- 			foreach (X509Certificate c in scs) {
 
- 				bool found = false;
 
- 				foreach (X509Certificate lc in Certificates) {
 
- 					if (Compare (c.RawData, lc.RawData)) {
 
- 						found = true;
 
- 					}
 
- 				}
 
- 				if (!found) {
 
- 					removecerts.Add (c);
 
- 				}
 
- 			}
 
- 			foreach (X509Certificate c in removecerts) {
 
- 				RemoveCertificate (c);
 
- 			}
 
- 			foreach (X509Certificate c in addcerts) {
 
- 				AddCertificate (c);
 
- 			}
 
- 			// Sync done
 
- 			if (_safeBags.Count > 0) {
 
- 				ASN1 certsSafeBag = new ASN1 (0x30);
 
- 				foreach (SafeBag sb in _safeBags) {
 
- 					if (sb.BagOID.Equals (certBag)) {
 
- 						certsSafeBag.Add (sb.ASN1);
 
- 					}
 
- 				}
 
- 				if (certsSafeBag.Count > 0) {
 
- 					PKCS7.ContentInfo contentInfo = EncryptedContentInfo (certsSafeBag, pbeWithSHAAnd3KeyTripleDESCBC);
 
- 					safeBagSequence.Add (contentInfo.ASN1);
 
- 				}
 
- 			}
 
- 			if (_safeBags.Count > 0) {
 
- 				ASN1 safeContents = new ASN1 (0x30);
 
- 				foreach (SafeBag sb in _safeBags) {
 
- 					if (sb.BagOID.Equals (keyBag) ||
 
- 					    sb.BagOID.Equals (pkcs8ShroudedKeyBag)) {
 
- 						safeContents.Add (sb.ASN1);
 
- 					}
 
- 				}
 
- 				if (safeContents.Count > 0) {
 
- 					ASN1 content = new ASN1 (0xA0);
 
- 					content.Add (new ASN1 (0x04, safeContents.GetBytes ()));
 
- 				
 
- 					PKCS7.ContentInfo keyBag = new PKCS7.ContentInfo (PKCS7.Oid.data);
 
- 					keyBag.Content = content;
 
- 					safeBagSequence.Add (keyBag.ASN1);
 
- 				}
 
- 			}
 
- 			// Doing SecretBags separately in case we want to change their encryption independently.
 
- 			if (_safeBags.Count > 0) {
 
- 				ASN1 secretsSafeBag = new ASN1 (0x30);
 
- 				foreach (SafeBag sb in _safeBags) {
 
- 					if (sb.BagOID.Equals (secretBag)) {
 
- 						secretsSafeBag.Add (sb.ASN1);
 
- 					}
 
- 				}
 
- 				if (secretsSafeBag.Count > 0) {
 
- 					PKCS7.ContentInfo contentInfo = EncryptedContentInfo (secretsSafeBag, pbeWithSHAAnd3KeyTripleDESCBC);
 
- 					safeBagSequence.Add (contentInfo.ASN1);
 
- 				}
 
- 			}
 
- 			ASN1 encapsulates = new ASN1 (0x04, safeBagSequence.GetBytes ());
 
- 			ASN1 ci = new ASN1 (0xA0);
 
- 			ci.Add (encapsulates);
 
- 			PKCS7.ContentInfo authSafe = new PKCS7.ContentInfo (PKCS7.Oid.data);
 
- 			authSafe.Content = ci;
 
- 			
 
- 			ASN1 macData = new ASN1 (0x30);
 
- 			if (_password != null) {
 
- 				// only for password based encryption
 
- 				byte[] salt = new byte [20];
 
- 				RNG.GetBytes (salt);
 
- 				byte[] macValue = MAC (_password, salt, _iterations, authSafe.Content [0].Value);
 
- 				ASN1 oidSeq = new ASN1 (0x30);
 
- 				oidSeq.Add (ASN1Convert.FromOid ("1.3.14.3.2.26"));	// SHA1
 
- 				oidSeq.Add (new ASN1 (0x05));
 
- 				ASN1 mac = new ASN1 (0x30);
 
- 				mac.Add (oidSeq);
 
- 				mac.Add (new ASN1 (0x04, macValue));
 
- 				macData.Add (mac);
 
- 				macData.Add (new ASN1 (0x04, salt));
 
- 				macData.Add (ASN1Convert.FromInt32 (_iterations));
 
- 			}
 
- 			
 
- 			ASN1 version = new ASN1 (0x02, new byte [1] { 0x03 });
 
- 			
 
- 			ASN1 pfx = new ASN1 (0x30);
 
- 			pfx.Add (version);
 
- 			pfx.Add (authSafe.ASN1);
 
- 			if (macData.Count > 0) {
 
- 				// only for password based encryption
 
- 				pfx.Add (macData);
 
- 			}
 
- 			return pfx.GetBytes ();
 
- 		}
 
- 		// Creates an encrypted PKCS#7 ContentInfo with safeBags as its SafeContents.  Used in GetBytes(), above.
 
- 		private PKCS7.ContentInfo EncryptedContentInfo(ASN1 safeBags, string algorithmOid)
 
- 		{
 
- 			byte[] salt = new byte [8];
 
- 			RNG.GetBytes (salt);
 
- 			ASN1 seqParams = new ASN1 (0x30);
 
- 			seqParams.Add (new ASN1 (0x04, salt));
 
- 			seqParams.Add (ASN1Convert.FromInt32 (_iterations));
 
- 			ASN1 seqPbe = new ASN1 (0x30);
 
- 			seqPbe.Add (ASN1Convert.FromOid (algorithmOid));
 
- 			seqPbe.Add (seqParams);
 
- 			byte[] encrypted = Encrypt (algorithmOid, salt, _iterations, safeBags.GetBytes ());
 
- 			ASN1 encryptedContent = new ASN1 (0x80, encrypted);
 
- 			ASN1 seq = new ASN1 (0x30);
 
- 			seq.Add (ASN1Convert.FromOid (PKCS7.Oid.data));
 
- 			seq.Add (seqPbe);
 
- 			seq.Add (encryptedContent);
 
- 			ASN1 version = new ASN1 (0x02, new byte [1] { 0x00 });
 
- 			ASN1 encData = new ASN1 (0x30);
 
- 			encData.Add (version);
 
- 			encData.Add (seq);
 
- 			ASN1 finalContent = new ASN1 (0xA0);
 
- 			finalContent.Add (encData);
 
- 			PKCS7.ContentInfo bag = new PKCS7.ContentInfo (PKCS7.Oid.encryptedData);
 
- 			bag.Content = finalContent;
 
- 			return bag;
 
- 		}
 
- 		public void AddCertificate (X509Certificate cert)
 
- 		{
 
- 			AddCertificate (cert, null);
 
- 		}
 
- 		public void AddCertificate (X509Certificate cert, IDictionary attributes)
 
- 		{
 
- 			bool found = false;
 
- 			for (int i = 0; !found && i < _safeBags.Count; i++) {
 
- 				SafeBag sb = (SafeBag)_safeBags [i];
 
- 				if (sb.BagOID.Equals (certBag)) {
 
- 					ASN1 safeBag = sb.ASN1;
 
- 					ASN1 bagValue = safeBag [1];
 
- 					PKCS7.ContentInfo crt = new PKCS7.ContentInfo (bagValue.Value);
 
- 					X509Certificate c = new X509Certificate (crt.Content [0].Value);
 
- 					if (Compare (cert.RawData, c.RawData)) {
 
- 						found = true;
 
- 					}
 
- 				}
 
- 			}
 
- 			if (!found) {
 
- 				_safeBags.Add (new SafeBag (certBag, CertificateSafeBag (cert, attributes)));
 
- 				_certsChanged = true;
 
- 			}
 
- 		}
 
- 		public void RemoveCertificate (X509Certificate cert)
 
- 		{
 
- 			RemoveCertificate (cert, null);
 
- 		}
 
- 		public void RemoveCertificate (X509Certificate cert, IDictionary attrs)
 
- 		{
 
- 			int certIndex = -1;
 
- 			for (int i = 0; certIndex == -1 && i < _safeBags.Count; i++) {
 
- 				SafeBag sb = (SafeBag)_safeBags [i];
 
- 				if (sb.BagOID.Equals (certBag)) {
 
- 					ASN1 safeBag = sb.ASN1;
 
- 					ASN1 bagValue = safeBag [1];
 
- 					PKCS7.ContentInfo crt = new PKCS7.ContentInfo (bagValue.Value);
 
- 					X509Certificate c = new X509Certificate (crt.Content [0].Value);
 
- 					if (Compare (cert.RawData, c.RawData)) {
 
- 						if (attrs != null) {
 
- 							if (safeBag.Count == 3) {
 
- 								ASN1 bagAttributes = safeBag [2];
 
- 								int bagAttributesFound = 0;
 
- 								for (int j = 0; j < bagAttributes.Count; j++) {
 
- 									ASN1 pkcs12Attribute = bagAttributes [j];
 
- 									ASN1 attrId = pkcs12Attribute [0];
 
- 									string ao = ASN1Convert.ToOid (attrId);
 
- 									ArrayList dattrValues = (ArrayList)attrs [ao];
 
- 									if (dattrValues != null) {
 
- 										ASN1 attrValues = pkcs12Attribute [1];
 
- 										if (dattrValues.Count == attrValues.Count) {
 
- 											int attrValuesFound = 0;
 
- 											for (int k = 0; k < attrValues.Count; k++) {
 
- 												ASN1 attrValue = attrValues [k];
 
- 												byte[] value = (byte[])dattrValues [k];
 
- 									
 
- 												if (Compare (value, attrValue.Value)) {
 
- 													attrValuesFound += 1;
 
- 												}
 
- 											}
 
- 											if (attrValuesFound == attrValues.Count) {
 
- 												bagAttributesFound += 1;
 
- 											}
 
- 										}
 
- 									}
 
- 								}
 
- 								if (bagAttributesFound == bagAttributes.Count) {
 
- 									certIndex = i;
 
- 								}
 
- 							}
 
- 						} else {
 
- 							certIndex = i;
 
- 						}
 
- 					}
 
- 				}
 
- 			}
 
- 			if (certIndex != -1) {
 
- 				_safeBags.RemoveAt (certIndex);
 
- 				_certsChanged = true;
 
- 			}
 
- 		}
 
- 		private bool CompareAsymmetricAlgorithm (AsymmetricAlgorithm a1, AsymmetricAlgorithm a2)
 
- 		{
 
- 			// fast path
 
- 			if (a1.KeySize != a2.KeySize)
 
- 				return false;
 
- 			// compare public keys - if they match we can assume the private match too
 
- 			return (a1.ToXmlString (false) == a2.ToXmlString (false));
 
- 		}
 
- 		public void AddPkcs8ShroudedKeyBag (AsymmetricAlgorithm aa)
 
- 		{
 
- 			AddPkcs8ShroudedKeyBag (aa, null);
 
- 		}
 
- 		public void AddPkcs8ShroudedKeyBag (AsymmetricAlgorithm aa, IDictionary attributes)
 
- 		{
 
- 			bool found = false;
 
- 			for (int i = 0; !found && i < _safeBags.Count; i++) {
 
- 				SafeBag sb = (SafeBag)_safeBags [i];
 
- 				if (sb.BagOID.Equals (pkcs8ShroudedKeyBag)) {
 
- 					ASN1 bagValue = sb.ASN1 [1];
 
- 					PKCS8.EncryptedPrivateKeyInfo epki = new PKCS8.EncryptedPrivateKeyInfo (bagValue.Value);
 
- 					byte[] decrypted = Decrypt (epki.Algorithm, epki.Salt, epki.IterationCount, epki.EncryptedData);
 
- 					PKCS8.PrivateKeyInfo pki = new PKCS8.PrivateKeyInfo (decrypted);
 
- 					byte[] privateKey = pki.PrivateKey;
 
- 					AsymmetricAlgorithm saa = null;
 
- 					switch (privateKey [0]) {
 
- 					case 0x02:
 
- 						DSAParameters p = new DSAParameters (); // FIXME
 
- 						saa = PKCS8.PrivateKeyInfo.DecodeDSA (privateKey, p);
 
- 						break;
 
- 					case 0x30:
 
- 						saa = PKCS8.PrivateKeyInfo.DecodeRSA (privateKey);
 
- 						break;
 
- 					default:
 
- 						Array.Clear (decrypted, 0, decrypted.Length);
 
- 						Array.Clear (privateKey, 0, privateKey.Length);
 
- 						throw new CryptographicException ("Unknown private key format");
 
- 					}
 
- 					Array.Clear (decrypted, 0, decrypted.Length);
 
- 					Array.Clear (privateKey, 0, privateKey.Length);
 
- 					if (CompareAsymmetricAlgorithm (aa , saa)) {
 
- 						found = true;
 
- 					}
 
- 				}
 
- 			}
 
- 			if (!found) {
 
- 				_safeBags.Add (new SafeBag (pkcs8ShroudedKeyBag, Pkcs8ShroudedKeyBagSafeBag (aa, attributes)));
 
- 				_keyBagsChanged = true;
 
- 			}
 
- 		}
 
- 		public void RemovePkcs8ShroudedKeyBag (AsymmetricAlgorithm aa)
 
- 		{
 
- 			int aaIndex = -1;
 
- 			for (int i = 0; aaIndex == -1 && i < _safeBags.Count; i++) {
 
- 				SafeBag sb = (SafeBag)_safeBags [i];
 
- 				if (sb.BagOID.Equals (pkcs8ShroudedKeyBag)) {
 
- 					ASN1 bagValue = sb.ASN1 [1];
 
- 					PKCS8.EncryptedPrivateKeyInfo epki = new PKCS8.EncryptedPrivateKeyInfo (bagValue.Value);
 
- 					byte[] decrypted = Decrypt (epki.Algorithm, epki.Salt, epki.IterationCount, epki.EncryptedData);
 
- 					PKCS8.PrivateKeyInfo pki = new PKCS8.PrivateKeyInfo (decrypted);
 
- 					byte[] privateKey = pki.PrivateKey;
 
- 					AsymmetricAlgorithm saa = null;
 
- 					switch (privateKey [0]) {
 
- 					case 0x02:
 
- 						DSAParameters p = new DSAParameters (); // FIXME
 
- 						saa = PKCS8.PrivateKeyInfo.DecodeDSA (privateKey, p);
 
- 						break;
 
- 					case 0x30:
 
- 						saa = PKCS8.PrivateKeyInfo.DecodeRSA (privateKey);
 
- 						break;
 
- 					default:
 
- 						Array.Clear (decrypted, 0, decrypted.Length);
 
- 						Array.Clear (privateKey, 0, privateKey.Length);
 
- 						throw new CryptographicException ("Unknown private key format");
 
- 					}
 
- 					Array.Clear (decrypted, 0, decrypted.Length);
 
- 					Array.Clear (privateKey, 0, privateKey.Length);
 
- 					if (CompareAsymmetricAlgorithm (aa, saa)) {
 
- 						aaIndex = i;
 
- 					}
 
- 				}
 
- 			}
 
- 			if (aaIndex != -1) {
 
- 				_safeBags.RemoveAt (aaIndex);
 
- 				_keyBagsChanged = true;
 
- 			}
 
- 		}
 
- 		public void AddKeyBag (AsymmetricAlgorithm aa)
 
- 		{
 
- 			AddKeyBag (aa, null);
 
- 		}
 
- 		public void AddKeyBag (AsymmetricAlgorithm aa, IDictionary attributes)
 
- 		{
 
- 			bool found = false;
 
- 			for (int i = 0; !found && i < _safeBags.Count; i++) {
 
- 				SafeBag sb = (SafeBag)_safeBags [i];
 
- 				if (sb.BagOID.Equals (keyBag)) {
 
- 					ASN1 bagValue = sb.ASN1 [1];
 
- 					PKCS8.PrivateKeyInfo pki = new PKCS8.PrivateKeyInfo (bagValue.Value);
 
- 					byte[] privateKey = pki.PrivateKey;
 
- 					AsymmetricAlgorithm saa = null;
 
- 					switch (privateKey [0]) {
 
- 					case 0x02:
 
- 						DSAParameters p = new DSAParameters (); // FIXME
 
- 						saa = PKCS8.PrivateKeyInfo.DecodeDSA (privateKey, p);
 
- 						break;
 
- 					case 0x30:
 
- 						saa = PKCS8.PrivateKeyInfo.DecodeRSA (privateKey);
 
- 						break;
 
- 					default:
 
- 						Array.Clear (privateKey, 0, privateKey.Length);
 
- 						throw new CryptographicException ("Unknown private key format");
 
- 					}
 
- 					Array.Clear (privateKey, 0, privateKey.Length);
 
- 					if (CompareAsymmetricAlgorithm (aa, saa)) {
 
- 						found = true;
 
- 					}
 
- 				}
 
- 			}
 
- 			if (!found) {
 
- 				_safeBags.Add (new SafeBag (keyBag, KeyBagSafeBag (aa, attributes)));
 
- 				_keyBagsChanged = true;
 
- 			}
 
- 		}
 
- 		public void RemoveKeyBag (AsymmetricAlgorithm aa)
 
- 		{
 
- 			int aaIndex = -1;
 
- 			for (int i = 0; aaIndex == -1 && i < _safeBags.Count; i++) {
 
- 				SafeBag sb = (SafeBag)_safeBags [i];
 
- 				if (sb.BagOID.Equals (keyBag)) {
 
- 					ASN1 bagValue = sb.ASN1 [1];
 
- 					PKCS8.PrivateKeyInfo pki = new PKCS8.PrivateKeyInfo (bagValue.Value);
 
- 					byte[] privateKey = pki.PrivateKey;
 
- 					AsymmetricAlgorithm saa = null;
 
- 					switch (privateKey [0]) {
 
- 					case 0x02:
 
- 						DSAParameters p = new DSAParameters (); // FIXME
 
- 						saa = PKCS8.PrivateKeyInfo.DecodeDSA (privateKey, p);
 
- 						break;
 
- 					case 0x30:
 
- 						saa = PKCS8.PrivateKeyInfo.DecodeRSA (privateKey);
 
- 						break;
 
- 					default:
 
- 						Array.Clear (privateKey, 0, privateKey.Length);
 
- 						throw new CryptographicException ("Unknown private key format");
 
- 					}
 
- 					Array.Clear (privateKey, 0, privateKey.Length);
 
- 					if (CompareAsymmetricAlgorithm (aa, saa)) {
 
- 						aaIndex = i;
 
- 					}
 
- 				}
 
- 			}
 
- 			if (aaIndex != -1) {
 
- 				_safeBags.RemoveAt (aaIndex);
 
- 				_keyBagsChanged = true;
 
- 			}
 
- 		}
 
- 		public void AddSecretBag (byte[] secret)
 
- 		{
 
- 			AddSecretBag (secret, null);
 
- 		}
 
- 		public void AddSecretBag (byte[] secret, IDictionary attributes)
 
- 		{
 
- 			bool found = false;
 
- 			for (int i = 0; !found && i < _safeBags.Count; i++) {
 
- 				SafeBag sb = (SafeBag)_safeBags [i];
 
- 				if (sb.BagOID.Equals (secretBag)) {
 
- 					ASN1 bagValue = sb.ASN1 [1];
 
- 					byte[] ssecret = bagValue.Value;
 
- 					if (Compare (secret, ssecret)) {
 
- 						found = true;
 
- 					}
 
- 				}
 
- 			}
 
- 			if (!found) {
 
- 				_safeBags.Add (new SafeBag (secretBag, SecretBagSafeBag (secret, attributes)));
 
- 				_secretBagsChanged = true;
 
- 			}
 
- 		}
 
- 		public void RemoveSecretBag (byte[] secret)
 
- 		{
 
- 			int sIndex = -1;
 
- 			for (int i = 0; sIndex == -1 && i < _safeBags.Count; i++) {
 
- 				SafeBag sb = (SafeBag)_safeBags [i];
 
- 				if (sb.BagOID.Equals (secretBag)) {
 
- 					ASN1 bagValue = sb.ASN1 [1];
 
- 					byte[] ssecret = bagValue.Value;
 
- 					if (Compare (secret, ssecret)) {
 
- 						sIndex = i;
 
- 					}
 
- 				}
 
- 			}
 
- 			if (sIndex != -1) {
 
- 				_safeBags.RemoveAt (sIndex);
 
- 				_secretBagsChanged = true;
 
- 			}
 
- 		}
 
- 		public AsymmetricAlgorithm GetAsymmetricAlgorithm (IDictionary attrs)
 
- 		{
 
- 			foreach (SafeBag sb in _safeBags) {
 
- 				if (sb.BagOID.Equals (keyBag) || sb.BagOID.Equals (pkcs8ShroudedKeyBag)) {
 
- 					ASN1 safeBag = sb.ASN1;
 
- 					if (safeBag.Count == 3) {
 
- 						ASN1 bagAttributes = safeBag [2];
 
- 						int bagAttributesFound = 0;
 
- 						for (int i = 0; i < bagAttributes.Count; i++) {
 
- 							ASN1 pkcs12Attribute = bagAttributes [i];
 
- 							ASN1 attrId = pkcs12Attribute [0];
 
- 							string ao = ASN1Convert.ToOid (attrId);
 
- 							ArrayList dattrValues = (ArrayList)attrs [ao];
 
- 							if (dattrValues != null) {
 
- 								ASN1 attrValues = pkcs12Attribute [1];
 
- 								if (dattrValues.Count == attrValues.Count) {
 
- 									int attrValuesFound = 0;
 
- 									for (int j = 0; j < attrValues.Count; j++) {
 
- 										ASN1 attrValue = attrValues [j];
 
- 										byte[] value = (byte[])dattrValues [j];
 
- 									
 
- 										if (Compare (value, attrValue.Value)) {
 
- 											attrValuesFound += 1;
 
- 										}
 
- 									}
 
- 									if (attrValuesFound == attrValues.Count) {
 
- 										bagAttributesFound += 1;
 
- 									}
 
- 								}
 
- 							}
 
- 						}
 
- 						if (bagAttributesFound == bagAttributes.Count) {
 
- 							ASN1 bagValue = safeBag [1];
 
- 							AsymmetricAlgorithm aa = null;
 
- 							if (sb.BagOID.Equals (keyBag)) {
 
- 								PKCS8.PrivateKeyInfo pki = new PKCS8.PrivateKeyInfo (bagValue.Value);
 
- 								byte[] privateKey = pki.PrivateKey;
 
- 								switch (privateKey [0]) {
 
- 								case 0x02:
 
- 									DSAParameters p = new DSAParameters (); // FIXME
 
- 									aa = PKCS8.PrivateKeyInfo.DecodeDSA (privateKey, p);
 
- 									break;
 
- 								case 0x30:
 
- 									aa = PKCS8.PrivateKeyInfo.DecodeRSA (privateKey);
 
- 									break;
 
- 								default:
 
- 									break;
 
- 								}
 
- 								Array.Clear (privateKey, 0, privateKey.Length);
 
- 							} else if (sb.BagOID.Equals (pkcs8ShroudedKeyBag)) {
 
- 								PKCS8.EncryptedPrivateKeyInfo epki = new PKCS8.EncryptedPrivateKeyInfo (bagValue.Value);
 
- 								byte[] decrypted = Decrypt (epki.Algorithm, epki.Salt, epki.IterationCount, epki.EncryptedData);
 
- 								PKCS8.PrivateKeyInfo pki = new PKCS8.PrivateKeyInfo (decrypted);
 
- 								byte[] privateKey = pki.PrivateKey;
 
- 								switch (privateKey [0]) {
 
- 								case 0x02:
 
- 									DSAParameters p = new DSAParameters (); // FIXME
 
- 									aa = PKCS8.PrivateKeyInfo.DecodeDSA (privateKey, p);
 
- 									break;
 
- 								case 0x30:
 
- 									aa = PKCS8.PrivateKeyInfo.DecodeRSA (privateKey);
 
- 									break;
 
- 								default:
 
- 									break;
 
- 								}
 
- 								Array.Clear (privateKey, 0, privateKey.Length);
 
- 								Array.Clear (decrypted, 0, decrypted.Length);
 
- 							}
 
- 							return aa;
 
- 						}
 
- 					}
 
- 				}
 
- 			}
 
- 			return null;
 
- 		}
 
- 		public byte[] GetSecret (IDictionary attrs)
 
- 		{
 
- 			foreach (SafeBag sb in _safeBags) {
 
- 				if (sb.BagOID.Equals (secretBag)) {
 
- 					ASN1 safeBag = sb.ASN1;
 
- 					if (safeBag.Count == 3) {
 
- 						ASN1 bagAttributes = safeBag [2];
 
- 						int bagAttributesFound = 0;
 
- 						for (int i = 0; i < bagAttributes.Count; i++) {
 
- 							ASN1 pkcs12Attribute = bagAttributes [i];
 
- 							ASN1 attrId = pkcs12Attribute [0];
 
- 							string ao = ASN1Convert.ToOid (attrId);
 
- 							ArrayList dattrValues = (ArrayList)attrs [ao];
 
- 							if (dattrValues != null) {
 
- 								ASN1 attrValues = pkcs12Attribute [1];
 
- 								if (dattrValues.Count == attrValues.Count) {
 
- 									int attrValuesFound = 0;
 
- 									for (int j = 0; j < attrValues.Count; j++) {
 
- 										ASN1 attrValue = attrValues [j];
 
- 										byte[] value = (byte[])dattrValues [j];
 
- 									
 
- 										if (Compare (value, attrValue.Value)) {
 
- 											attrValuesFound += 1;
 
- 										}
 
- 									}
 
- 									if (attrValuesFound == attrValues.Count) {
 
- 										bagAttributesFound += 1;
 
- 									}
 
- 								}
 
- 							}
 
- 						}
 
- 						if (bagAttributesFound == bagAttributes.Count) {
 
- 							ASN1 bagValue = safeBag [1];
 
- 							return bagValue.Value;
 
- 						}
 
- 					}
 
- 				}
 
- 			}
 
- 			return null;
 
- 		}
 
- 		public X509Certificate GetCertificate (IDictionary attrs)
 
- 		{
 
- 			foreach (SafeBag sb in _safeBags) {
 
- 				if (sb.BagOID.Equals (certBag)) {
 
- 					ASN1 safeBag = sb.ASN1;
 
- 					if (safeBag.Count == 3) {
 
- 						ASN1 bagAttributes = safeBag [2];
 
- 						int bagAttributesFound = 0;
 
- 						for (int i = 0; i < bagAttributes.Count; i++) {
 
- 							ASN1 pkcs12Attribute = bagAttributes [i];
 
- 							ASN1 attrId = pkcs12Attribute [0];
 
- 							string ao = ASN1Convert.ToOid (attrId);
 
- 							ArrayList dattrValues = (ArrayList)attrs [ao];
 
- 							if (dattrValues != null) {
 
- 								ASN1 attrValues = pkcs12Attribute [1];
 
- 								
 
- 								if (dattrValues.Count == attrValues.Count) {
 
- 									int attrValuesFound = 0;
 
- 									for (int j = 0; j < attrValues.Count; j++) {
 
- 										ASN1 attrValue = attrValues [j];
 
- 										byte[] value = (byte[])dattrValues [j];
 
- 									
 
- 										if (Compare (value, attrValue.Value)) {
 
- 											attrValuesFound += 1;
 
- 										}
 
- 									}
 
- 									if (attrValuesFound == attrValues.Count) {
 
- 										bagAttributesFound += 1;
 
- 									}
 
- 								}
 
- 							}
 
- 						}
 
- 						if (bagAttributesFound == bagAttributes.Count) {
 
- 							ASN1 bagValue = safeBag [1];
 
- 							PKCS7.ContentInfo crt = new PKCS7.ContentInfo (bagValue.Value);
 
- 							return new X509Certificate (crt.Content [0].Value);
 
- 						}
 
- 					}
 
- 				}
 
- 			}
 
- 			return null;
 
- 		}
 
- 		public IDictionary GetAttributes (AsymmetricAlgorithm aa)
 
- 		{
 
- 			IDictionary result = new Hashtable ();
 
- 			foreach (SafeBag sb in _safeBags) {
 
- 				if (sb.BagOID.Equals (keyBag) || sb.BagOID.Equals (pkcs8ShroudedKeyBag)) {
 
- 					ASN1 safeBag = sb.ASN1;
 
- 					ASN1 bagValue = safeBag [1];
 
- 					AsymmetricAlgorithm saa = null;
 
- 					if (sb.BagOID.Equals (keyBag)) {
 
- 						PKCS8.PrivateKeyInfo pki = new PKCS8.PrivateKeyInfo (bagValue.Value);
 
- 						byte[] privateKey = pki.PrivateKey;
 
- 						switch (privateKey [0]) {
 
- 						case 0x02:
 
- 							DSAParameters p = new DSAParameters (); // FIXME
 
- 							saa = PKCS8.PrivateKeyInfo.DecodeDSA (privateKey, p);
 
- 							break;
 
- 						case 0x30:
 
- 							saa = PKCS8.PrivateKeyInfo.DecodeRSA (privateKey);
 
- 							break;
 
- 						default:
 
- 							break;
 
- 						}
 
- 						Array.Clear (privateKey, 0, privateKey.Length);
 
- 					} else if (sb.BagOID.Equals (pkcs8ShroudedKeyBag)) {
 
- 						PKCS8.EncryptedPrivateKeyInfo epki = new PKCS8.EncryptedPrivateKeyInfo (bagValue.Value);
 
- 						byte[] decrypted = Decrypt (epki.Algorithm, epki.Salt, epki.IterationCount, epki.EncryptedData);
 
- 						PKCS8.PrivateKeyInfo pki = new PKCS8.PrivateKeyInfo (decrypted);
 
- 						byte[] privateKey = pki.PrivateKey;
 
- 						switch (privateKey [0]) {
 
- 						case 0x02:
 
- 							DSAParameters p = new DSAParameters (); // FIXME
 
- 							saa = PKCS8.PrivateKeyInfo.DecodeDSA (privateKey, p);
 
- 							break;
 
- 						case 0x30:
 
- 							saa = PKCS8.PrivateKeyInfo.DecodeRSA (privateKey);
 
- 							break;
 
- 						default:
 
- 							break;
 
- 						}
 
- 						Array.Clear (privateKey, 0, privateKey.Length);
 
- 						Array.Clear (decrypted, 0, decrypted.Length);
 
- 					}
 
- 					if (saa != null && CompareAsymmetricAlgorithm (saa, aa)) {
 
- 						if (safeBag.Count == 3) {
 
- 							ASN1 bagAttributes = safeBag [2];
 
- 							
 
- 							for (int i = 0; i < bagAttributes.Count; i++) {
 
- 								ASN1 pkcs12Attribute = bagAttributes [i];
 
- 								ASN1 attrId = pkcs12Attribute [0];
 
- 								string aOid = ASN1Convert.ToOid (attrId);
 
- 								ArrayList aValues = new ArrayList ();
 
- 								ASN1 attrValues = pkcs12Attribute [1];
 
- 									
 
- 								for (int j = 0; j < attrValues.Count; j++) {
 
- 									ASN1 attrValue = attrValues [j];
 
- 									aValues.Add (attrValue.Value);
 
- 								}
 
- 								result.Add (aOid, aValues);
 
- 							}
 
- 						}
 
- 					}
 
- 				}
 
- 			}
 
- 			return result;
 
- 		}
 
- 		public IDictionary GetAttributes (X509Certificate cert)
 
- 		{
 
- 			IDictionary result = new Hashtable ();
 
- 			foreach (SafeBag sb in _safeBags) {
 
- 				if (sb.BagOID.Equals (certBag)) {
 
- 					ASN1 safeBag = sb.ASN1;
 
- 					ASN1 bagValue = safeBag [1];
 
- 					PKCS7.ContentInfo crt = new PKCS7.ContentInfo (bagValue.Value);
 
- 					X509Certificate xc = new X509Certificate (crt.Content [0].Value);
 
- 					if (Compare (cert.RawData, xc.RawData)) {
 
- 						if (safeBag.Count == 3) {
 
- 							ASN1 bagAttributes = safeBag [2];
 
- 							for (int i = 0; i < bagAttributes.Count; i++) {
 
- 								ASN1 pkcs12Attribute = bagAttributes [i];
 
- 								ASN1 attrId = pkcs12Attribute [0];
 
- 								string aOid = ASN1Convert.ToOid (attrId);
 
- 								ArrayList aValues = new ArrayList ();
 
- 								ASN1 attrValues = pkcs12Attribute [1];
 
- 									
 
- 								for (int j = 0; j < attrValues.Count; j++) {
 
- 									ASN1 attrValue = attrValues [j];
 
- 									aValues.Add (attrValue.Value);
 
- 								}
 
- 								result.Add (aOid, aValues);
 
- 							}
 
- 						}
 
- 					}
 
- 				}
 
- 			}
 
- 			return result;
 
- 		}
 
- 		public void SaveToFile (string filename)
 
- 		{
 
- 			if (filename == null)
 
- 				throw new ArgumentNullException ("filename");
 
- 			using (FileStream fs = File.Create (filename)) {
 
- 				byte[] data = GetBytes ();
 
- 				fs.Write (data, 0, data.Length);
 
- 			}
 
- 		}
 
- 		public object Clone ()
 
- 		{
 
- 			PKCS12 clone = null;
 
- 			if (_password != null) {
 
- 				clone = new PKCS12 (GetBytes (), Encoding.BigEndianUnicode.GetString (_password));
 
- 			} else {
 
- 				clone = new PKCS12 (GetBytes ());
 
- 			}
 
- 			clone.IterationCount = this.IterationCount;
 
- 			return clone;
 
- 		}
 
- 		// static
 
- 		public const int CryptoApiPasswordLimit = 32;
 
- 		
 
- 		static private int password_max_length = Int32.MaxValue;
 
- 		// static properties
 
- 		
 
- 		// MS CryptoAPI limits the password to a maximum of 31 characters
 
- 		// other implementations, like OpenSSL, have no such limitation.
 
- 		// Setting a maximum value will truncate the password length to 
 
- 		// ensure compatibility with MS's PFXImportCertStore API.
 
- 		static public int MaximumPasswordLength {
 
- 			get { return password_max_length; }
 
- 			set {
 
- 				if (value < CryptoApiPasswordLimit) {
 
- 					string msg = string.Format ("Maximum password length cannot be less than {0}.", CryptoApiPasswordLimit);
 
- 					throw new ArgumentOutOfRangeException (msg);
 
- 				}
 
- 				password_max_length = value;
 
- 			}
 
- 		}
 
- 	}
 
- }
 
 
  |