summary refs log tree commit diff
path: root/crypto/src/security
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2013-06-28 15:26:06 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2013-06-28 15:26:06 +0700
commit44288db4414158ac9b98a507b15e81d0d3c66ca6 (patch)
treeaa5ef88948ebb68ed6c8df81eb5da889641a9b50 /crypto/src/security
parentSet up text/binary handling for existing file types (diff)
downloadBouncyCastle.NET-ed25519-44288db4414158ac9b98a507b15e81d0d3c66ca6.tar.xz
Initial import of old CVS repository
Diffstat (limited to 'crypto/src/security')
-rw-r--r--crypto/src/security/AgreementUtilities.cs105
-rw-r--r--crypto/src/security/CipherUtilities.cs739
-rw-r--r--crypto/src/security/DigestUtilities.cs202
-rw-r--r--crypto/src/security/DotNetUtilities.cs222
-rw-r--r--crypto/src/security/GeneralSecurityException.cs29
-rw-r--r--crypto/src/security/GeneratorUtilities.cs349
-rw-r--r--crypto/src/security/InvalidKeyException.cs14
-rw-r--r--crypto/src/security/InvalidParameterException.cs14
-rw-r--r--crypto/src/security/KeyException.cs14
-rw-r--r--crypto/src/security/MacUtilities.cs243
-rw-r--r--crypto/src/security/NoSuchAlgorithmException.cs15
-rw-r--r--crypto/src/security/ParameterUtilities.cs327
-rw-r--r--crypto/src/security/PbeUtilities.cs663
-rw-r--r--crypto/src/security/PrivateKeyFactory.cs221
-rw-r--r--crypto/src/security/PublicKeyFactory.cs253
-rw-r--r--crypto/src/security/SecureRandom.cs228
-rw-r--r--crypto/src/security/SecurityUtilityException.cs36
-rw-r--r--crypto/src/security/SignatureException.cs14
-rw-r--r--crypto/src/security/SignerUtilities.cs549
-rw-r--r--crypto/src/security/WrapperUtilities.cs153
-rw-r--r--crypto/src/security/cert/CertificateEncodingException.cs14
-rw-r--r--crypto/src/security/cert/CertificateException.cs14
-rw-r--r--crypto/src/security/cert/CertificateExpiredException.cs14
-rw-r--r--crypto/src/security/cert/CertificateNotYetValidException.cs14
-rw-r--r--crypto/src/security/cert/CertificateParsingException.cs14
-rw-r--r--crypto/src/security/cert/CrlException.cs14
26 files changed, 4474 insertions, 0 deletions
diff --git a/crypto/src/security/AgreementUtilities.cs b/crypto/src/security/AgreementUtilities.cs
new file mode 100644
index 000000000..4c61ac354
--- /dev/null
+++ b/crypto/src/security/AgreementUtilities.cs
@@ -0,0 +1,105 @@
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Agreement;
+using Org.BouncyCastle.Crypto.Agreement.Kdf;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Security
+{
+	/// <remarks>
+	///  Utility class for creating IBasicAgreement objects from their names/Oids
+	/// </remarks>
+	public sealed class AgreementUtilities
+	{
+		private AgreementUtilities()
+		{
+		}
+
+		private static readonly IDictionary algorithms = Platform.CreateHashtable();
+        //private static readonly IDictionary oids = Platform.CreateHashtable();
+
+		static AgreementUtilities()
+		{
+			//algorithms[X9ObjectIdentifiers.DHSinglePassCofactorDHSha1KdfScheme.Id] = ?;
+			algorithms[X9ObjectIdentifiers.DHSinglePassStdDHSha1KdfScheme.Id] = "ECDHWITHSHA1KDF";
+			algorithms[X9ObjectIdentifiers.MqvSinglePassSha1KdfScheme.Id] = "ECMQVWITHSHA1KDF";
+		}
+
+		public static IBasicAgreement GetBasicAgreement(
+			DerObjectIdentifier oid)
+		{
+			return GetBasicAgreement(oid.Id);
+		}
+
+		public static IBasicAgreement GetBasicAgreement(
+			string algorithm)
+		{
+			string upper = Platform.ToUpperInvariant(algorithm);
+			string mechanism = (string) algorithms[upper];
+
+			if (mechanism == null)
+			{
+				mechanism = upper;
+			}
+
+			if (mechanism == "DH" || mechanism == "DIFFIEHELLMAN")
+				return new DHBasicAgreement();
+
+			if (mechanism == "ECDH")
+				return new ECDHBasicAgreement();
+
+			if (mechanism == "ECDHC")
+				return new ECDHCBasicAgreement();
+
+			if (mechanism == "ECMQV")
+				return new ECMqvBasicAgreement();
+
+			throw new SecurityUtilityException("Basic Agreement " + algorithm + " not recognised.");
+		}
+
+		public static IBasicAgreement GetBasicAgreementWithKdf(
+			DerObjectIdentifier oid,
+			string				wrapAlgorithm)
+		{
+			return GetBasicAgreementWithKdf(oid.Id, wrapAlgorithm);
+		}
+
+		public static IBasicAgreement GetBasicAgreementWithKdf(
+			string agreeAlgorithm,
+			string wrapAlgorithm)
+		{
+			string upper = Platform.ToUpperInvariant(agreeAlgorithm);
+			string mechanism = (string) algorithms[upper];
+
+			if (mechanism == null)
+			{
+				mechanism = upper;
+			}
+
+			// 'DHWITHSHA1KDF' retained for backward compatibility
+			if (mechanism == "DHWITHSHA1KDF" || mechanism == "ECDHWITHSHA1KDF")
+				return new ECDHWithKdfBasicAgreement(
+					wrapAlgorithm,
+					new ECDHKekGenerator(
+						new Sha1Digest()));
+
+			if (mechanism == "ECMQVWITHSHA1KDF")
+				return new ECMqvWithKdfBasicAgreement(
+					wrapAlgorithm,
+					new ECDHKekGenerator(
+						new Sha1Digest()));
+
+			throw new SecurityUtilityException("Basic Agreement (with KDF) " + agreeAlgorithm + " not recognised.");
+		}
+
+		public static string GetAlgorithmName(
+			DerObjectIdentifier oid)
+		{
+			return (string) algorithms[oid.Id];
+		}
+	}
+}
diff --git a/crypto/src/security/CipherUtilities.cs b/crypto/src/security/CipherUtilities.cs
new file mode 100644
index 000000000..cda769535
--- /dev/null
+++ b/crypto/src/security/CipherUtilities.cs
@@ -0,0 +1,739 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.Kisa;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Ntt;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Agreement;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Encodings;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Macs;
+using Org.BouncyCastle.Crypto.Modes;
+using Org.BouncyCastle.Crypto.Paddings;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Security
+{
+    /// <remarks>
+    ///  Cipher Utility class contains methods that can not be specifically grouped into other classes.
+    /// </remarks>
+    public sealed class CipherUtilities
+    {
+        private enum CipherAlgorithm {
+            AES,
+            ARC4,
+            BLOWFISH,
+            CAMELLIA,
+            CAST5,
+            CAST6,
+            DES,
+            DESEDE,
+            ELGAMAL,
+            GOST28147,
+            HC128,
+            HC256,
+            IDEA,
+            NOEKEON,
+            PBEWITHSHAAND128BITRC4,
+            PBEWITHSHAAND40BITRC4,
+            RC2,
+            RC5,
+            RC5_64,
+            RC6,
+            RIJNDAEL,
+            RSA,
+            SALSA20,
+            SEED,
+            SERPENT,
+            SKIPJACK,
+            TEA,
+            TWOFISH,
+            VMPC,
+            VMPC_KSA3,
+            XTEA,
+        };
+        
+        private enum CipherMode { ECB, NONE, CBC, CCM, CFB, CTR, CTS, EAX, GCM, GOFB, OCB, OFB, OPENPGPCFB, SIC };
+        private enum CipherPadding
+        {
+            NOPADDING,
+            RAW,
+            ISO10126PADDING,
+            ISO10126D2PADDING,
+            ISO10126_2PADDING,
+            ISO7816_4PADDING,
+            ISO9797_1PADDING,
+            ISO9796_1,
+            ISO9796_1PADDING,
+            OAEP,
+            OAEPPADDING,
+            OAEPWITHMD5ANDMGF1PADDING,
+            OAEPWITHSHA1ANDMGF1PADDING,
+            OAEPWITHSHA_1ANDMGF1PADDING,
+            OAEPWITHSHA224ANDMGF1PADDING,
+            OAEPWITHSHA_224ANDMGF1PADDING,
+            OAEPWITHSHA256ANDMGF1PADDING,
+            OAEPWITHSHA_256ANDMGF1PADDING,
+            OAEPWITHSHA384ANDMGF1PADDING,
+            OAEPWITHSHA_384ANDMGF1PADDING,
+            OAEPWITHSHA512ANDMGF1PADDING,
+            OAEPWITHSHA_512ANDMGF1PADDING,
+            PKCS1,
+            PKCS1PADDING,
+            PKCS5,
+            PKCS5PADDING,
+            PKCS7,
+            PKCS7PADDING,
+            TBCPADDING,
+            WITHCTS,
+            X923PADDING,
+            ZEROBYTEPADDING,
+        };
+
+        private static readonly IDictionary algorithms = Platform.CreateHashtable();
+        private static readonly IDictionary oids = Platform.CreateHashtable();
+
+        static CipherUtilities()
+        {
+            // Signal to obfuscation tools not to change enum constants
+            ((CipherAlgorithm)Enums.GetArbitraryValue(typeof(CipherAlgorithm))).ToString();
+            ((CipherMode)Enums.GetArbitraryValue(typeof(CipherMode))).ToString();
+            ((CipherPadding)Enums.GetArbitraryValue(typeof(CipherPadding))).ToString();
+
+            // TODO Flesh out the list of aliases
+
+            algorithms[NistObjectIdentifiers.IdAes128Ecb.Id] = "AES/ECB/PKCS7PADDING";
+            algorithms[NistObjectIdentifiers.IdAes192Ecb.Id] = "AES/ECB/PKCS7PADDING";
+            algorithms[NistObjectIdentifiers.IdAes256Ecb.Id] = "AES/ECB/PKCS7PADDING";
+            algorithms["AES//PKCS7"] = "AES/ECB/PKCS7PADDING";
+            algorithms["AES//PKCS7PADDING"] = "AES/ECB/PKCS7PADDING";
+            algorithms["AES//PKCS5"] = "AES/ECB/PKCS7PADDING";
+            algorithms["AES//PKCS5PADDING"] = "AES/ECB/PKCS7PADDING";
+
+            algorithms[NistObjectIdentifiers.IdAes128Cbc.Id] = "AES/CBC/PKCS7PADDING";
+            algorithms[NistObjectIdentifiers.IdAes192Cbc.Id] = "AES/CBC/PKCS7PADDING";
+            algorithms[NistObjectIdentifiers.IdAes256Cbc.Id] = "AES/CBC/PKCS7PADDING";
+
+            algorithms[NistObjectIdentifiers.IdAes128Ofb.Id] = "AES/OFB/NOPADDING";
+            algorithms[NistObjectIdentifiers.IdAes192Ofb.Id] = "AES/OFB/NOPADDING";
+            algorithms[NistObjectIdentifiers.IdAes256Ofb.Id] = "AES/OFB/NOPADDING";
+
+            algorithms[NistObjectIdentifiers.IdAes128Cfb.Id] = "AES/CFB/NOPADDING";
+            algorithms[NistObjectIdentifiers.IdAes192Cfb.Id] = "AES/CFB/NOPADDING";
+            algorithms[NistObjectIdentifiers.IdAes256Cfb.Id] = "AES/CFB/NOPADDING";
+
+            algorithms["RSA/ECB/PKCS1"] = "RSA//PKCS1PADDING";
+            algorithms["RSA/ECB/PKCS1PADDING"] = "RSA//PKCS1PADDING";
+            algorithms[PkcsObjectIdentifiers.RsaEncryption.Id] = "RSA//PKCS1PADDING";
+            algorithms[PkcsObjectIdentifiers.IdRsaesOaep.Id] = "RSA//OAEPPADDING";
+
+            algorithms[OiwObjectIdentifiers.DesCbc.Id] = "DES/CBC";
+            algorithms[OiwObjectIdentifiers.DesCfb.Id] = "DES/CFB";
+            algorithms[OiwObjectIdentifiers.DesEcb.Id] = "DES/ECB";
+            algorithms[OiwObjectIdentifiers.DesOfb.Id] = "DES/OFB";
+            algorithms[OiwObjectIdentifiers.DesEde.Id] = "DESEDE";
+            algorithms["TDEA"] = "DESEDE";
+            algorithms[PkcsObjectIdentifiers.DesEde3Cbc.Id] = "DESEDE/CBC";
+            algorithms[PkcsObjectIdentifiers.RC2Cbc.Id] = "RC2/CBC";
+            algorithms["1.3.6.1.4.1.188.7.1.1.2"] = "IDEA/CBC";
+            algorithms["1.2.840.113533.7.66.10"] = "CAST5/CBC";
+
+            algorithms["RC4"] = "ARC4";
+            algorithms["ARCFOUR"] = "ARC4";
+            algorithms["1.2.840.113549.3.4"] = "ARC4";
+
+
+
+            algorithms["PBEWITHSHA1AND128BITRC4"] = "PBEWITHSHAAND128BITRC4";
+            algorithms[PkcsObjectIdentifiers.PbeWithShaAnd128BitRC4.Id] = "PBEWITHSHAAND128BITRC4";
+            algorithms["PBEWITHSHA1AND40BITRC4"] = "PBEWITHSHAAND40BITRC4";
+            algorithms[PkcsObjectIdentifiers.PbeWithShaAnd40BitRC4.Id] = "PBEWITHSHAAND40BITRC4";
+
+            algorithms["PBEWITHSHA1ANDDES"] = "PBEWITHSHA1ANDDES-CBC";
+            algorithms[PkcsObjectIdentifiers.PbeWithSha1AndDesCbc.Id] = "PBEWITHSHA1ANDDES-CBC";
+            algorithms["PBEWITHSHA1ANDRC2"] = "PBEWITHSHA1ANDRC2-CBC";
+            algorithms[PkcsObjectIdentifiers.PbeWithSha1AndRC2Cbc.Id] = "PBEWITHSHA1ANDRC2-CBC";
+
+            algorithms["PBEWITHSHA1AND3-KEYTRIPLEDES-CBC"] = "PBEWITHSHAAND3-KEYTRIPLEDES-CBC";
+            algorithms["PBEWITHSHAAND3KEYTRIPLEDES"] = "PBEWITHSHAAND3-KEYTRIPLEDES-CBC";
+            algorithms[PkcsObjectIdentifiers.PbeWithShaAnd3KeyTripleDesCbc.Id] = "PBEWITHSHAAND3-KEYTRIPLEDES-CBC";
+            algorithms["PBEWITHSHA1ANDDESEDE"] = "PBEWITHSHAAND3-KEYTRIPLEDES-CBC";
+
+            algorithms["PBEWITHSHA1AND2-KEYTRIPLEDES-CBC"] = "PBEWITHSHAAND2-KEYTRIPLEDES-CBC";
+            algorithms[PkcsObjectIdentifiers.PbeWithShaAnd2KeyTripleDesCbc.Id] = "PBEWITHSHAAND2-KEYTRIPLEDES-CBC";
+
+            algorithms["PBEWITHSHA1AND128BITRC2-CBC"] = "PBEWITHSHAAND128BITRC2-CBC";
+            algorithms[PkcsObjectIdentifiers.PbeWithShaAnd128BitRC2Cbc.Id] = "PBEWITHSHAAND128BITRC2-CBC";
+
+            algorithms["PBEWITHSHA1AND40BITRC2-CBC"] = "PBEWITHSHAAND40BITRC2-CBC";
+            algorithms[PkcsObjectIdentifiers.PbewithShaAnd40BitRC2Cbc.Id] = "PBEWITHSHAAND40BITRC2-CBC";
+
+            algorithms["PBEWITHSHA1AND128BITAES-CBC-BC"] = "PBEWITHSHAAND128BITAES-CBC-BC";
+            algorithms["PBEWITHSHA-1AND128BITAES-CBC-BC"] = "PBEWITHSHAAND128BITAES-CBC-BC";
+
+            algorithms["PBEWITHSHA1AND192BITAES-CBC-BC"] = "PBEWITHSHAAND192BITAES-CBC-BC";
+            algorithms["PBEWITHSHA-1AND192BITAES-CBC-BC"] = "PBEWITHSHAAND192BITAES-CBC-BC";
+
+            algorithms["PBEWITHSHA1AND256BITAES-CBC-BC"] = "PBEWITHSHAAND256BITAES-CBC-BC";
+            algorithms["PBEWITHSHA-1AND256BITAES-CBC-BC"] = "PBEWITHSHAAND256BITAES-CBC-BC";
+
+            algorithms["PBEWITHSHA-256AND128BITAES-CBC-BC"] = "PBEWITHSHA256AND128BITAES-CBC-BC";
+            algorithms["PBEWITHSHA-256AND192BITAES-CBC-BC"] = "PBEWITHSHA256AND192BITAES-CBC-BC";
+            algorithms["PBEWITHSHA-256AND256BITAES-CBC-BC"] = "PBEWITHSHA256AND256BITAES-CBC-BC";
+
+
+            algorithms["GOST"] = "GOST28147";
+            algorithms["GOST-28147"] = "GOST28147";
+            algorithms[CryptoProObjectIdentifiers.GostR28147Cbc.Id] = "GOST28147/CBC/PKCS7PADDING";
+
+            algorithms["RC5-32"] = "RC5";
+
+            algorithms[NttObjectIdentifiers.IdCamellia128Cbc.Id] = "CAMELLIA/CBC/PKCS7PADDING";
+            algorithms[NttObjectIdentifiers.IdCamellia192Cbc.Id] = "CAMELLIA/CBC/PKCS7PADDING";
+            algorithms[NttObjectIdentifiers.IdCamellia256Cbc.Id] = "CAMELLIA/CBC/PKCS7PADDING";
+
+            algorithms[KisaObjectIdentifiers.IdSeedCbc.Id] = "SEED/CBC/PKCS7PADDING";
+
+            algorithms["1.3.6.1.4.1.3029.1.2"] = "BLOWFISH/CBC";
+        }
+
+        private CipherUtilities()
+        {
+        }
+
+        /// <summary>
+        /// Returns a ObjectIdentifier for a give encoding.
+        /// </summary>
+        /// <param name="mechanism">A string representation of the encoding.</param>
+        /// <returns>A DerObjectIdentifier, null if the Oid is not available.</returns>
+        // TODO Don't really want to support this
+        public static DerObjectIdentifier GetObjectIdentifier(
+            string mechanism)
+        {
+            if (mechanism == null)
+                throw new ArgumentNullException("mechanism");
+
+            mechanism = Platform.ToUpperInvariant(mechanism);
+            string aliased = (string) algorithms[mechanism];
+
+            if (aliased != null)
+                mechanism = aliased;
+
+            return (DerObjectIdentifier) oids[mechanism];
+        }
+
+        public static ICollection Algorithms
+        {
+            get { return oids.Keys; }
+        }
+
+        public static IBufferedCipher GetCipher(
+            DerObjectIdentifier oid)
+        {
+            return GetCipher(oid.Id);
+        }
+
+        public static IBufferedCipher GetCipher(
+            string algorithm)
+        {
+            if (algorithm == null)
+                throw new ArgumentNullException("algorithm");
+
+            algorithm = Platform.ToUpperInvariant(algorithm);
+
+            {
+                string aliased = (string) algorithms[algorithm];
+
+                if (aliased != null)
+                    algorithm = aliased;
+            }
+
+            IBasicAgreement iesAgreement = null;
+            if (algorithm == "IES")
+            {
+                iesAgreement = new DHBasicAgreement();
+            }
+            else if (algorithm == "ECIES")
+            {
+                iesAgreement = new ECDHBasicAgreement();
+            }
+
+            if (iesAgreement != null)
+            {
+                return new BufferedIesCipher(
+                    new IesEngine(
+                    iesAgreement,
+                    new Kdf2BytesGenerator(
+                    new Sha1Digest()),
+                    new HMac(
+                    new Sha1Digest())));
+            }
+
+
+
+            if (algorithm.StartsWith("PBE"))
+            {
+                if (algorithm.EndsWith("-CBC"))
+                {
+                    if (algorithm == "PBEWITHSHA1ANDDES-CBC")
+                    {
+                        return new PaddedBufferedBlockCipher(
+                            new CbcBlockCipher(new DesEngine()));
+                    }
+                    else if (algorithm == "PBEWITHSHA1ANDRC2-CBC")
+                    {
+                        return new PaddedBufferedBlockCipher(
+                            new CbcBlockCipher(new RC2Engine()));
+                    }
+                    else if (Strings.IsOneOf(algorithm,
+                        "PBEWITHSHAAND2-KEYTRIPLEDES-CBC", "PBEWITHSHAAND3-KEYTRIPLEDES-CBC"))
+                    {
+                        return new PaddedBufferedBlockCipher(
+                            new CbcBlockCipher(new DesEdeEngine()));
+                    }
+                    else if (Strings.IsOneOf(algorithm,
+                        "PBEWITHSHAAND128BITRC2-CBC", "PBEWITHSHAAND40BITRC2-CBC"))
+                    {
+                        return new PaddedBufferedBlockCipher(
+                            new CbcBlockCipher(new RC2Engine()));
+                    }
+                }
+                else if (algorithm.EndsWith("-BC") || algorithm.EndsWith("-OPENSSL"))
+                {
+                    if (Strings.IsOneOf(algorithm,
+                        "PBEWITHSHAAND128BITAES-CBC-BC",
+                        "PBEWITHSHAAND192BITAES-CBC-BC",
+                        "PBEWITHSHAAND256BITAES-CBC-BC",
+                        "PBEWITHSHA256AND128BITAES-CBC-BC",
+                        "PBEWITHSHA256AND192BITAES-CBC-BC",
+                        "PBEWITHSHA256AND256BITAES-CBC-BC",
+                        "PBEWITHMD5AND128BITAES-CBC-OPENSSL",
+                        "PBEWITHMD5AND192BITAES-CBC-OPENSSL",
+                        "PBEWITHMD5AND256BITAES-CBC-OPENSSL"))
+                    {
+                        return new PaddedBufferedBlockCipher(
+                            new CbcBlockCipher(new AesFastEngine()));
+                    }
+                }
+            }
+
+
+
+            string[] parts = algorithm.Split('/');
+
+            IBlockCipher blockCipher = null;
+            IAsymmetricBlockCipher asymBlockCipher = null;
+            IStreamCipher streamCipher = null;
+
+            string algorithmName = parts[0];
+
+            {
+                string aliased = (string)algorithms[algorithmName];
+
+                if (aliased != null)
+                    algorithmName = aliased;
+            }
+
+            CipherAlgorithm cipherAlgorithm;
+            try
+            {
+                cipherAlgorithm = (CipherAlgorithm)Enums.GetEnumValue(typeof(CipherAlgorithm), algorithmName);
+            }
+            catch (ArgumentException)
+            {
+                throw new SecurityUtilityException("Cipher " + algorithm + " not recognised.");
+            }
+
+            switch (cipherAlgorithm)
+            {
+                case CipherAlgorithm.AES:
+                    blockCipher = new AesFastEngine();
+                    break;
+                case CipherAlgorithm.ARC4:
+                    streamCipher = new RC4Engine();
+                    break;
+                case CipherAlgorithm.BLOWFISH:
+                    blockCipher = new BlowfishEngine();
+                    break;
+                case CipherAlgorithm.CAMELLIA:
+                    blockCipher = new CamelliaEngine();
+                    break;
+                case CipherAlgorithm.CAST5:
+                    blockCipher = new Cast5Engine();
+                    break;
+                case CipherAlgorithm.CAST6:
+                    blockCipher = new Cast6Engine();
+                    break;
+                case CipherAlgorithm.DES:
+                    blockCipher = new DesEngine();
+                    break;
+                case CipherAlgorithm.DESEDE:
+                    blockCipher = new DesEdeEngine();
+                    break;
+                case CipherAlgorithm.ELGAMAL:
+                    asymBlockCipher = new ElGamalEngine();
+                    break;
+                case CipherAlgorithm.GOST28147:
+                    blockCipher = new Gost28147Engine();
+                    break;
+                case CipherAlgorithm.HC128:
+                    streamCipher = new HC128Engine();
+                    break;
+                case CipherAlgorithm.HC256:
+                    streamCipher = new HC256Engine();
+                    break;
+#if INCLUDE_IDEA
+                case CipherAlgorithm.IDEA:
+                    blockCipher = new IdeaEngine();
+                    break;
+#endif
+                case CipherAlgorithm.NOEKEON:
+                    blockCipher = new NoekeonEngine();
+                    break;
+                case CipherAlgorithm.PBEWITHSHAAND128BITRC4:
+                case CipherAlgorithm.PBEWITHSHAAND40BITRC4:
+                    streamCipher = new RC4Engine();
+                    break;
+                case CipherAlgorithm.RC2:
+                    blockCipher = new RC2Engine();
+                    break;
+                case CipherAlgorithm.RC5:
+                    blockCipher = new RC532Engine();
+                    break;
+                case CipherAlgorithm.RC5_64:
+                    blockCipher = new RC564Engine();
+                    break;
+                case CipherAlgorithm.RC6:
+                    blockCipher = new RC6Engine();
+                    break;
+                case CipherAlgorithm.RIJNDAEL:
+                    blockCipher = new RijndaelEngine();
+                    break;
+                case CipherAlgorithm.RSA:
+                    asymBlockCipher = new RsaBlindedEngine();
+                    break;
+                case CipherAlgorithm.SALSA20:
+                    streamCipher = new Salsa20Engine();
+                    break;
+                case CipherAlgorithm.SEED:
+                    blockCipher = new SeedEngine();
+                    break;
+                case CipherAlgorithm.SERPENT:
+                    blockCipher = new SerpentEngine();
+                    break;
+                case CipherAlgorithm.SKIPJACK:
+                    blockCipher = new SkipjackEngine();
+                    break;
+                case CipherAlgorithm.TEA:
+                    blockCipher = new TeaEngine();
+                    break;
+                case CipherAlgorithm.TWOFISH:
+                    blockCipher = new TwofishEngine();
+                    break;
+                case CipherAlgorithm.VMPC:
+                    streamCipher = new VmpcEngine();
+                    break;
+                case CipherAlgorithm.VMPC_KSA3:
+                    streamCipher = new VmpcKsa3Engine();
+                    break;
+                case CipherAlgorithm.XTEA:
+                    blockCipher = new XteaEngine();
+                    break;
+                default:
+                    throw new SecurityUtilityException("Cipher " + algorithm + " not recognised.");
+            }
+
+            if (streamCipher != null)
+            {
+                if (parts.Length > 1)
+                    throw new ArgumentException("Modes and paddings not used for stream ciphers");
+
+                return new BufferedStreamCipher(streamCipher);
+            }
+
+
+            bool cts = false;
+            bool padded = true;
+            IBlockCipherPadding padding = null;
+            IAeadBlockCipher aeadBlockCipher = null;
+
+            if (parts.Length > 2)
+            {
+                if (streamCipher != null)
+                    throw new ArgumentException("Paddings not used for stream ciphers");
+
+                string paddingName = parts[2];
+
+                CipherPadding cipherPadding;
+                if (paddingName == "")
+                {
+                    cipherPadding = CipherPadding.RAW;
+                }
+                else if (paddingName == "X9.23PADDING")
+                {
+                    cipherPadding = CipherPadding.X923PADDING;
+                }
+                else
+                {
+                    try
+                    {
+                        cipherPadding = (CipherPadding)Enums.GetEnumValue(typeof(CipherPadding), paddingName);
+                    }
+                    catch (ArgumentException)
+                    {
+                        throw new SecurityUtilityException("Cipher " + algorithm + " not recognised.");
+                    }
+                }
+
+                switch (cipherPadding)
+                {
+                    case CipherPadding.NOPADDING:
+                        padded = false;
+                        break;
+                    case CipherPadding.RAW:
+                        break;
+                    case CipherPadding.ISO10126PADDING:
+                    case CipherPadding.ISO10126D2PADDING:
+                    case CipherPadding.ISO10126_2PADDING:
+                        padding = new ISO10126d2Padding();
+                        break;
+                    case CipherPadding.ISO7816_4PADDING:
+                    case CipherPadding.ISO9797_1PADDING:
+                        padding = new ISO7816d4Padding();
+                        break;
+                    case CipherPadding.ISO9796_1:
+                    case CipherPadding.ISO9796_1PADDING:
+                        asymBlockCipher = new ISO9796d1Encoding(asymBlockCipher);
+                        break;
+                    case CipherPadding.OAEP:
+                    case CipherPadding.OAEPPADDING:
+                        asymBlockCipher = new OaepEncoding(asymBlockCipher);
+                        break;
+                    case CipherPadding.OAEPWITHMD5ANDMGF1PADDING:
+                        asymBlockCipher = new OaepEncoding(asymBlockCipher, new MD5Digest());
+                        break;
+                    case CipherPadding.OAEPWITHSHA1ANDMGF1PADDING:
+                    case CipherPadding.OAEPWITHSHA_1ANDMGF1PADDING:
+                        asymBlockCipher = new OaepEncoding(asymBlockCipher, new Sha1Digest());
+                        break;
+                    case CipherPadding.OAEPWITHSHA224ANDMGF1PADDING:
+                    case CipherPadding.OAEPWITHSHA_224ANDMGF1PADDING:
+                        asymBlockCipher = new OaepEncoding(asymBlockCipher, new Sha224Digest());
+                        break;
+                    case CipherPadding.OAEPWITHSHA256ANDMGF1PADDING:
+                    case CipherPadding.OAEPWITHSHA_256ANDMGF1PADDING:
+                        asymBlockCipher = new OaepEncoding(asymBlockCipher, new Sha256Digest());
+                        break;
+                    case CipherPadding.OAEPWITHSHA384ANDMGF1PADDING:
+                    case CipherPadding.OAEPWITHSHA_384ANDMGF1PADDING:
+                        asymBlockCipher = new OaepEncoding(asymBlockCipher, new Sha384Digest());
+                        break;
+                    case CipherPadding.OAEPWITHSHA512ANDMGF1PADDING:
+                    case CipherPadding.OAEPWITHSHA_512ANDMGF1PADDING:
+                        asymBlockCipher = new OaepEncoding(asymBlockCipher, new Sha512Digest());
+                        break;
+                    case CipherPadding.PKCS1:
+                    case CipherPadding.PKCS1PADDING:
+                        asymBlockCipher = new Pkcs1Encoding(asymBlockCipher);
+                        break;
+                    case CipherPadding.PKCS5:
+                    case CipherPadding.PKCS5PADDING:
+                    case CipherPadding.PKCS7:
+                    case CipherPadding.PKCS7PADDING:
+                        padding = new Pkcs7Padding();
+                        break;
+                    case CipherPadding.TBCPADDING:
+                        padding = new TbcPadding();
+                        break;
+                    case CipherPadding.WITHCTS:
+                        cts = true;
+                        break;
+                    case CipherPadding.X923PADDING:
+                        padding = new X923Padding();
+                        break;
+                    case CipherPadding.ZEROBYTEPADDING:
+                        padding = new ZeroBytePadding();
+                        break;
+                    default:
+                        throw new SecurityUtilityException("Cipher " + algorithm + " not recognised.");
+                }
+            }
+
+            string mode = "";
+            if (parts.Length > 1)
+            {
+                mode = parts[1];
+
+                int di = GetDigitIndex(mode);
+                string modeName = di >= 0 ? mode.Substring(0, di) : mode;
+
+                try
+                {
+                    CipherMode cipherMode = modeName == ""
+                        ? CipherMode.NONE
+                        : (CipherMode)Enums.GetEnumValue(typeof(CipherMode), modeName);
+
+                    switch (cipherMode)
+                    {
+                        case CipherMode.ECB:
+                        case CipherMode.NONE:
+                            break;
+                        case CipherMode.CBC:
+                            blockCipher = new CbcBlockCipher(blockCipher);
+                            break;
+                        case CipherMode.CCM:
+                            aeadBlockCipher = new CcmBlockCipher(blockCipher);
+                            break;
+                        case CipherMode.CFB:
+                        {
+                            int bits = (di < 0)
+                                ?	8 * blockCipher.GetBlockSize()
+                                :	int.Parse(mode.Substring(di));
+    
+                            blockCipher = new CfbBlockCipher(blockCipher, bits);
+                            break;
+                        }
+                        case CipherMode.CTR:
+                            blockCipher = new SicBlockCipher(blockCipher);
+                            break;
+                        case CipherMode.CTS:
+                            cts = true;
+                            blockCipher = new CbcBlockCipher(blockCipher);
+                            break;
+                        case CipherMode.EAX:
+                            aeadBlockCipher = new EaxBlockCipher(blockCipher);
+                            break;
+                        case CipherMode.GCM:
+                            aeadBlockCipher = new GcmBlockCipher(blockCipher);
+                            break;
+                        case CipherMode.GOFB:
+                            blockCipher = new GOfbBlockCipher(blockCipher);
+                            break;
+                        case CipherMode.OCB:
+                            aeadBlockCipher = new OcbBlockCipher(blockCipher, CreateBlockCipher(cipherAlgorithm));
+                            break;
+                        case CipherMode.OFB:
+                        {
+                            int bits = (di < 0)
+                                ?	8 * blockCipher.GetBlockSize()
+                                :	int.Parse(mode.Substring(di));
+    
+                            blockCipher = new OfbBlockCipher(blockCipher, bits);
+                            break;
+                        }
+                        case CipherMode.OPENPGPCFB:
+                            blockCipher = new OpenPgpCfbBlockCipher(blockCipher);
+                            break;
+                        case CipherMode.SIC:
+                            if (blockCipher.GetBlockSize() < 16)
+                            {
+                                throw new ArgumentException("Warning: SIC-Mode can become a twotime-pad if the blocksize of the cipher is too small. Use a cipher with a block size of at least 128 bits (e.g. AES)");
+                            }
+                            blockCipher = new SicBlockCipher(blockCipher);
+                            break;
+                        default:
+                            throw new SecurityUtilityException("Cipher " + algorithm + " not recognised.");
+                    }
+                }
+                catch (ArgumentException)
+                {
+                    throw new SecurityUtilityException("Cipher " + algorithm + " not recognised.");
+                }
+            }
+
+            if (aeadBlockCipher != null)
+            {
+                if (cts)
+                    throw new SecurityUtilityException("CTS mode not valid for AEAD ciphers.");
+                if (padded && parts.Length > 2 && parts[2] != "")
+                    throw new SecurityUtilityException("Bad padding specified for AEAD cipher.");
+
+                return new BufferedAeadBlockCipher(aeadBlockCipher);
+            }
+
+            if (blockCipher != null)
+            {
+                if (cts)
+                {
+                    return new CtsBlockCipher(blockCipher);
+                }
+
+                if (padding != null)
+                {
+                    return new PaddedBufferedBlockCipher(blockCipher, padding);
+                }
+
+                if (!padded || blockCipher.IsPartialBlockOkay)
+                {
+                    return new BufferedBlockCipher(blockCipher);
+                }
+
+                return new PaddedBufferedBlockCipher(blockCipher);
+            }
+
+            if (asymBlockCipher != null)
+            {
+                return new BufferedAsymmetricBlockCipher(asymBlockCipher);
+            }
+
+            throw new SecurityUtilityException("Cipher " + algorithm + " not recognised.");
+        }
+
+        public static string GetAlgorithmName(
+            DerObjectIdentifier oid)
+        {
+            return (string) algorithms[oid.Id];
+        }
+
+        private static int GetDigitIndex(
+            string s)
+        {
+            for (int i = 0; i < s.Length; ++i)
+            {
+                if (char.IsDigit(s[i]))
+                    return i;
+            }
+
+            return -1;
+        }
+
+        private static IBlockCipher CreateBlockCipher(CipherAlgorithm cipherAlgorithm)
+        {
+            switch (cipherAlgorithm)
+            {
+                case CipherAlgorithm.AES: return new AesFastEngine();
+                case CipherAlgorithm.BLOWFISH: return new BlowfishEngine();
+                case CipherAlgorithm.CAMELLIA: return new CamelliaEngine();
+                case CipherAlgorithm.CAST5: return new Cast5Engine();
+                case CipherAlgorithm.CAST6: return new Cast6Engine();
+                case CipherAlgorithm.DES: return new DesEngine();
+                case CipherAlgorithm.DESEDE: return new DesEdeEngine();
+                case CipherAlgorithm.GOST28147: return new Gost28147Engine();
+#if INCLUDE_IDEA
+                case CipherAlgorithm.IDEA: return new IdeaEngine();
+#endif
+                case CipherAlgorithm.NOEKEON: return new NoekeonEngine();
+                case CipherAlgorithm.RC2: return new RC2Engine();
+                case CipherAlgorithm.RC5: return new RC532Engine();
+                case CipherAlgorithm.RC5_64: return new RC564Engine();
+                case CipherAlgorithm.RC6: return new RC6Engine();
+                case CipherAlgorithm.RIJNDAEL: return new RijndaelEngine();
+                case CipherAlgorithm.SEED: return new SeedEngine();
+                case CipherAlgorithm.SERPENT: return new SerpentEngine();
+                case CipherAlgorithm.SKIPJACK: return new SkipjackEngine();
+                case CipherAlgorithm.TEA: return new TeaEngine();
+                case CipherAlgorithm.TWOFISH: return new TwofishEngine();
+                case CipherAlgorithm.XTEA: return new XteaEngine();
+                default:
+                    throw new SecurityUtilityException("Cipher " + cipherAlgorithm + " not recognised or not a block cipher");
+            }
+        }
+    }
+}
diff --git a/crypto/src/security/DigestUtilities.cs b/crypto/src/security/DigestUtilities.cs
new file mode 100644
index 000000000..ec3f63940
--- /dev/null
+++ b/crypto/src/security/DigestUtilities.cs
@@ -0,0 +1,202 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.TeleTrust;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Security
+{
+    /// <remarks>
+    ///  Utility class for creating IDigest objects from their names/Oids
+    /// </remarks>
+    public sealed class DigestUtilities
+    {
+        private enum DigestAlgorithm {
+            GOST3411,
+            MD2, MD4, MD5,
+            RIPEMD128, RIPEMD160, RIPEMD256, RIPEMD320,
+            SHA_1, SHA_224, SHA_256, SHA_384, SHA_512,
+            SHA_512_224, SHA_512_256,
+            SHA3_224, SHA3_256, SHA3_384, SHA3_512,
+            TIGER,
+            WHIRLPOOL,
+        };
+
+        private DigestUtilities()
+        {
+        }
+
+        private static readonly IDictionary algorithms = Platform.CreateHashtable();
+        private static readonly IDictionary oids = Platform.CreateHashtable();
+
+        static DigestUtilities()
+        {
+            // Signal to obfuscation tools not to change enum constants
+            ((DigestAlgorithm)Enums.GetArbitraryValue(typeof(DigestAlgorithm))).ToString();
+
+            algorithms[PkcsObjectIdentifiers.MD2.Id] = "MD2";
+            algorithms[PkcsObjectIdentifiers.MD4.Id] = "MD4";
+            algorithms[PkcsObjectIdentifiers.MD5.Id] = "MD5";
+
+            algorithms["SHA1"] = "SHA-1";
+            algorithms[OiwObjectIdentifiers.IdSha1.Id] = "SHA-1";
+            algorithms["SHA224"] = "SHA-224";
+            algorithms[NistObjectIdentifiers.IdSha224.Id] = "SHA-224";
+            algorithms["SHA256"] = "SHA-256";
+            algorithms[NistObjectIdentifiers.IdSha256.Id] = "SHA-256";
+            algorithms["SHA384"] = "SHA-384";
+            algorithms[NistObjectIdentifiers.IdSha384.Id] = "SHA-384";
+            algorithms["SHA512"] = "SHA-512";
+            algorithms[NistObjectIdentifiers.IdSha512.Id] = "SHA-512";
+            algorithms["SHA512/224"] = "SHA-512/224";
+            algorithms[NistObjectIdentifiers.IdSha512_224.Id] = "SHA-512/224";
+            algorithms["SHA512/256"] = "SHA-512/256";
+            algorithms[NistObjectIdentifiers.IdSha512_256.Id] = "SHA-512/256";
+
+            algorithms["RIPEMD-128"] = "RIPEMD128";
+            algorithms[TeleTrusTObjectIdentifiers.RipeMD128.Id] = "RIPEMD128";
+            algorithms["RIPEMD-160"] = "RIPEMD160";
+            algorithms[TeleTrusTObjectIdentifiers.RipeMD160.Id] = "RIPEMD160";
+            algorithms["RIPEMD-256"] = "RIPEMD256";
+            algorithms[TeleTrusTObjectIdentifiers.RipeMD256.Id] = "RIPEMD256";
+            algorithms["RIPEMD-320"] = "RIPEMD320";
+//			algorithms[TeleTrusTObjectIdentifiers.RipeMD320.Id] = "RIPEMD320";
+
+            algorithms[CryptoProObjectIdentifiers.GostR3411.Id] = "GOST3411";
+
+
+
+            oids["MD2"] = PkcsObjectIdentifiers.MD2;
+            oids["MD4"] = PkcsObjectIdentifiers.MD4;
+            oids["MD5"] = PkcsObjectIdentifiers.MD5;
+            oids["SHA-1"] = OiwObjectIdentifiers.IdSha1;
+            oids["SHA-224"] = NistObjectIdentifiers.IdSha224;
+            oids["SHA-256"] = NistObjectIdentifiers.IdSha256;
+            oids["SHA-384"] = NistObjectIdentifiers.IdSha384;
+            oids["SHA-512"] = NistObjectIdentifiers.IdSha512;
+            oids["SHA-512/224"] = NistObjectIdentifiers.IdSha512_224;
+            oids["SHA-512/256"] = NistObjectIdentifiers.IdSha512_256;
+            oids["RIPEMD128"] = TeleTrusTObjectIdentifiers.RipeMD128;
+            oids["RIPEMD160"] = TeleTrusTObjectIdentifiers.RipeMD160;
+            oids["RIPEMD256"] = TeleTrusTObjectIdentifiers.RipeMD256;
+            oids["GOST3411"] = CryptoProObjectIdentifiers.GostR3411;
+        }
+
+        /// <summary>
+        /// Returns a ObjectIdentifier for a given digest mechanism.
+        /// </summary>
+        /// <param name="mechanism">A string representation of the digest meanism.</param>
+        /// <returns>A DerObjectIdentifier, null if the Oid is not available.</returns>
+
+        public static DerObjectIdentifier GetObjectIdentifier(
+            string mechanism)
+        {
+            if (mechanism == null)
+                throw new System.ArgumentNullException("mechanism");
+
+            mechanism = Platform.ToUpperInvariant(mechanism);
+            string aliased = (string) algorithms[mechanism];
+
+            if (aliased != null)
+                mechanism = aliased;
+
+            return (DerObjectIdentifier) oids[mechanism];
+        }
+
+        public static ICollection Algorithms
+        {
+            get { return oids.Keys; }
+        }
+
+        public static IDigest GetDigest(
+            DerObjectIdentifier id)
+        {
+            return GetDigest(id.Id);
+        }
+
+        public static IDigest GetDigest(
+            string algorithm)
+        {
+            string upper = Platform.ToUpperInvariant(algorithm);
+            string mechanism = (string) algorithms[upper];
+
+            if (mechanism == null)
+            {
+                mechanism = upper;
+            }
+
+            try
+            {
+                DigestAlgorithm digestAlgorithm = (DigestAlgorithm)Enums.GetEnumValue(
+                    typeof(DigestAlgorithm), mechanism);
+
+                switch (digestAlgorithm)
+                {
+                    case DigestAlgorithm.GOST3411:      return new Gost3411Digest();
+                    case DigestAlgorithm.MD2:		    return new MD2Digest();
+                    case DigestAlgorithm.MD4:		    return new MD4Digest();
+                    case DigestAlgorithm.MD5:		    return new MD5Digest();
+                    case DigestAlgorithm.RIPEMD128:	    return new RipeMD128Digest();
+                    case DigestAlgorithm.RIPEMD160:	    return new RipeMD160Digest();
+                    case DigestAlgorithm.RIPEMD256:	    return new RipeMD256Digest();
+                    case DigestAlgorithm.RIPEMD320:	    return new RipeMD320Digest();
+                    case DigestAlgorithm.SHA_1:		    return new Sha1Digest();
+                    case DigestAlgorithm.SHA_224:	    return new Sha224Digest();
+                    case DigestAlgorithm.SHA_256:	    return new Sha256Digest();
+                    case DigestAlgorithm.SHA_384:	    return new Sha384Digest();
+                    case DigestAlgorithm.SHA_512:	    return new Sha512Digest();
+                    case DigestAlgorithm.SHA_512_224:   return new Sha512tDigest(224);
+                    case DigestAlgorithm.SHA_512_256:   return new Sha512tDigest(256);
+                    case DigestAlgorithm.SHA3_224:      return new Sha3Digest(224);
+                    case DigestAlgorithm.SHA3_256:      return new Sha3Digest(256);
+                    case DigestAlgorithm.SHA3_384:      return new Sha3Digest(384);
+                    case DigestAlgorithm.SHA3_512:      return new Sha3Digest(512);
+                    case DigestAlgorithm.TIGER:         return new TigerDigest();
+                    case DigestAlgorithm.WHIRLPOOL:     return new WhirlpoolDigest();
+                }
+            }
+            catch (ArgumentException)
+            {
+            }
+
+            throw new SecurityUtilityException("Digest " + mechanism + " not recognised.");
+        }
+
+        public static string GetAlgorithmName(
+            DerObjectIdentifier oid)
+        {
+            return (string) algorithms[oid.Id];
+        }
+
+        public static byte[] CalculateDigest(string algorithm, byte[] input)
+        {
+            IDigest digest = GetDigest(algorithm);
+            digest.BlockUpdate(input, 0, input.Length);
+            return DoFinal(digest);
+        }
+
+        public static byte[] DoFinal(
+            IDigest digest)
+        {
+            byte[] b = new byte[digest.GetDigestSize()];
+            digest.DoFinal(b, 0);
+            return b;
+        }
+
+        public static byte[] DoFinal(
+            IDigest	digest,
+            byte[]	input)
+        {
+            digest.BlockUpdate(input, 0, input.Length);
+            return DoFinal(digest);
+        }
+    }
+}
diff --git a/crypto/src/security/DotNetUtilities.cs b/crypto/src/security/DotNetUtilities.cs
new file mode 100644
index 000000000..036c0d519
--- /dev/null
+++ b/crypto/src/security/DotNetUtilities.cs
@@ -0,0 +1,222 @@
+#if !(NETCF_1_0 || SILVERLIGHT)
+
+using System;
+using System.Security.Cryptography;
+using SystemX509 = System.Security.Cryptography.X509Certificates;
+
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Security
+{
+	/// <summary>
+	/// A class containing methods to interface the BouncyCastle world to the .NET Crypto world.
+	/// </summary>
+	public sealed class DotNetUtilities
+	{
+		private DotNetUtilities()
+		{
+		}
+
+		/// <summary>
+		/// Create an System.Security.Cryptography.X509Certificate from an X509Certificate Structure.
+		/// </summary>
+		/// <param name="x509Struct"></param>
+		/// <returns>A System.Security.Cryptography.X509Certificate.</returns>
+		public static SystemX509.X509Certificate ToX509Certificate(
+			X509CertificateStructure x509Struct)
+		{
+			return new SystemX509.X509Certificate(x509Struct.GetDerEncoded());
+		}
+
+		public static SystemX509.X509Certificate ToX509Certificate(
+			X509Certificate x509Cert)
+		{
+			return new SystemX509.X509Certificate(x509Cert.GetEncoded());
+		}
+
+		public static X509Certificate FromX509Certificate(
+			SystemX509.X509Certificate x509Cert)
+		{
+			return new X509CertificateParser().ReadCertificate(x509Cert.GetRawCertData());
+		}
+
+		public static AsymmetricCipherKeyPair GetDsaKeyPair(
+			DSA dsa)
+		{
+			return GetDsaKeyPair(dsa.ExportParameters(true));
+		}
+
+		public static AsymmetricCipherKeyPair GetDsaKeyPair(
+			DSAParameters dp)
+		{
+			DsaValidationParameters validationParameters = (dp.Seed != null)
+				?	new DsaValidationParameters(dp.Seed, dp.Counter)
+				:	null;
+
+			DsaParameters parameters = new DsaParameters(
+				new BigInteger(1, dp.P),
+				new BigInteger(1, dp.Q),
+				new BigInteger(1, dp.G),
+				validationParameters);
+
+			DsaPublicKeyParameters pubKey = new DsaPublicKeyParameters(
+				new BigInteger(1, dp.Y),
+				parameters);
+
+			DsaPrivateKeyParameters privKey = new DsaPrivateKeyParameters(
+				new BigInteger(1, dp.X),
+				parameters);
+
+			return new AsymmetricCipherKeyPair(pubKey, privKey);
+		}
+
+		public static DsaPublicKeyParameters GetDsaPublicKey(
+			DSA dsa)
+		{
+			return GetDsaPublicKey(dsa.ExportParameters(false));
+		}
+
+		public static DsaPublicKeyParameters GetDsaPublicKey(
+			DSAParameters dp)
+		{
+			DsaValidationParameters validationParameters = (dp.Seed != null)
+				?	new DsaValidationParameters(dp.Seed, dp.Counter)
+				:	null;
+
+			DsaParameters parameters = new DsaParameters(
+				new BigInteger(1, dp.P),
+				new BigInteger(1, dp.Q),
+				new BigInteger(1, dp.G),
+				validationParameters);
+
+			return new DsaPublicKeyParameters(
+				new BigInteger(1, dp.Y),
+				parameters);
+		}
+
+		public static AsymmetricCipherKeyPair GetRsaKeyPair(
+			RSA rsa)
+		{
+			return GetRsaKeyPair(rsa.ExportParameters(true));
+		}
+
+		public static AsymmetricCipherKeyPair GetRsaKeyPair(
+			RSAParameters rp)
+		{
+			BigInteger modulus = new BigInteger(1, rp.Modulus);
+			BigInteger pubExp = new BigInteger(1, rp.Exponent);
+
+			RsaKeyParameters pubKey = new RsaKeyParameters(
+				false,
+				modulus,
+				pubExp);
+
+			RsaPrivateCrtKeyParameters privKey = new RsaPrivateCrtKeyParameters(
+				modulus,
+				pubExp,
+				new BigInteger(1, rp.D),
+				new BigInteger(1, rp.P),
+				new BigInteger(1, rp.Q),
+				new BigInteger(1, rp.DP),
+				new BigInteger(1, rp.DQ),
+				new BigInteger(1, rp.InverseQ));
+
+			return new AsymmetricCipherKeyPair(pubKey, privKey);
+		}
+
+		public static RsaKeyParameters GetRsaPublicKey(
+			RSA rsa)
+		{
+			return GetRsaPublicKey(rsa.ExportParameters(false));
+		}
+
+		public static RsaKeyParameters GetRsaPublicKey(
+			RSAParameters rp)
+		{
+			return new RsaKeyParameters(
+				false,
+				new BigInteger(1, rp.Modulus),
+				new BigInteger(1, rp.Exponent));
+		}
+
+		public static AsymmetricCipherKeyPair GetKeyPair(AsymmetricAlgorithm privateKey)
+		{
+			if (privateKey is DSA)
+			{
+				return GetDsaKeyPair((DSA)privateKey);
+			}
+
+			if (privateKey is RSA)
+			{
+				return GetRsaKeyPair((RSA)privateKey);
+			}
+
+			throw new ArgumentException("Unsupported algorithm specified", "privateKey");
+		}
+
+		public static RSA ToRSA(RsaKeyParameters rsaKey)
+		{
+			RSAParameters rp = ToRSAParameters(rsaKey);
+			RSACryptoServiceProvider rsaCsp = new RSACryptoServiceProvider();
+			// TODO This call appears to not work for private keys (when no CRT info)
+			rsaCsp.ImportParameters(rp);
+			return rsaCsp;
+		}
+
+		public static RSA ToRSA(RsaPrivateCrtKeyParameters privKey)
+		{
+			RSAParameters rp = ToRSAParameters(privKey);
+			RSACryptoServiceProvider rsaCsp = new RSACryptoServiceProvider();
+			rsaCsp.ImportParameters(rp);
+			return rsaCsp;
+		}
+
+		public static RSAParameters ToRSAParameters(RsaKeyParameters rsaKey)
+		{
+			RSAParameters rp = new RSAParameters();
+			rp.Modulus = rsaKey.Modulus.ToByteArrayUnsigned();
+			if (rsaKey.IsPrivate)
+				rp.D = ConvertRSAParametersField(rsaKey.Exponent, rp.Modulus.Length);
+			else
+				rp.Exponent = rsaKey.Exponent.ToByteArrayUnsigned();
+			return rp;
+		}
+
+		public static RSAParameters ToRSAParameters(RsaPrivateCrtKeyParameters privKey)
+		{
+			RSAParameters rp = new RSAParameters();
+			rp.Modulus = privKey.Modulus.ToByteArrayUnsigned();
+			rp.Exponent = privKey.PublicExponent.ToByteArrayUnsigned();
+			rp.P = privKey.P.ToByteArrayUnsigned();
+			rp.Q = privKey.Q.ToByteArrayUnsigned();
+			rp.D = ConvertRSAParametersField(privKey.Exponent, rp.Modulus.Length);
+			rp.DP = ConvertRSAParametersField(privKey.DP, rp.P.Length);
+			rp.DQ = ConvertRSAParametersField(privKey.DQ, rp.Q.Length);
+			rp.InverseQ = ConvertRSAParametersField(privKey.QInv, rp.Q.Length);
+			return rp;
+		}
+
+		// TODO Move functionality to more general class
+		private static byte[] ConvertRSAParametersField(BigInteger n, int size)
+		{
+			byte[] bs = n.ToByteArrayUnsigned();
+
+			if (bs.Length == size)
+				return bs;
+
+			if (bs.Length > size)
+				throw new ArgumentException("Specified size too small", "size");
+
+			byte[] padded = new byte[size];
+			Array.Copy(bs, 0, padded, size - bs.Length, bs.Length);
+			return padded;
+		}
+	}
+}
+
+#endif
diff --git a/crypto/src/security/GeneralSecurityException.cs b/crypto/src/security/GeneralSecurityException.cs
new file mode 100644
index 000000000..2c3f2a555
--- /dev/null
+++ b/crypto/src/security/GeneralSecurityException.cs
@@ -0,0 +1,29 @@
+using System;
+
+namespace Org.BouncyCastle.Security
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class GeneralSecurityException
+		: Exception
+	{
+		public GeneralSecurityException()
+			: base()
+		{
+		}
+
+		public GeneralSecurityException(
+			string message)
+			: base(message)
+		{
+		}
+
+		public GeneralSecurityException(
+			string		message,
+			Exception	exception)
+			: base(message, exception)
+		{
+		}
+	}
+}
diff --git a/crypto/src/security/GeneratorUtilities.cs b/crypto/src/security/GeneratorUtilities.cs
new file mode 100644
index 000000000..45fbc9425
--- /dev/null
+++ b/crypto/src/security/GeneratorUtilities.cs
@@ -0,0 +1,349 @@
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.Iana;
+using Org.BouncyCastle.Asn1.Kisa;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Ntt;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Security
+{
+    public sealed class GeneratorUtilities
+    {
+        private GeneratorUtilities()
+        {
+        }
+
+        private static readonly IDictionary kgAlgorithms = Platform.CreateHashtable();
+        private static readonly IDictionary kpgAlgorithms = Platform.CreateHashtable();
+        private static readonly IDictionary defaultKeySizes = Platform.CreateHashtable();
+
+        static GeneratorUtilities()
+        {
+            //
+            // key generators.
+            //
+            AddKgAlgorithm("AES",
+                "AESWRAP");
+            AddKgAlgorithm("AES128",
+                "2.16.840.1.101.3.4.2",
+                NistObjectIdentifiers.IdAes128Cbc,
+                NistObjectIdentifiers.IdAes128Cfb,
+                NistObjectIdentifiers.IdAes128Ecb,
+                NistObjectIdentifiers.IdAes128Ofb,
+                NistObjectIdentifiers.IdAes128Wrap);
+            AddKgAlgorithm("AES192",
+                "2.16.840.1.101.3.4.22",
+                NistObjectIdentifiers.IdAes192Cbc,
+                NistObjectIdentifiers.IdAes192Cfb,
+                NistObjectIdentifiers.IdAes192Ecb,
+                NistObjectIdentifiers.IdAes192Ofb,
+                NistObjectIdentifiers.IdAes192Wrap);
+            AddKgAlgorithm("AES256",
+                "2.16.840.1.101.3.4.42",
+                NistObjectIdentifiers.IdAes256Cbc,
+                NistObjectIdentifiers.IdAes256Cfb,
+                NistObjectIdentifiers.IdAes256Ecb,
+                NistObjectIdentifiers.IdAes256Ofb,
+                NistObjectIdentifiers.IdAes256Wrap);
+            AddKgAlgorithm("BLOWFISH",
+                "1.3.6.1.4.1.3029.1.2");
+            AddKgAlgorithm("CAMELLIA",
+                "CAMELLIAWRAP");
+            AddKgAlgorithm("CAMELLIA128",
+                NttObjectIdentifiers.IdCamellia128Cbc,
+                NttObjectIdentifiers.IdCamellia128Wrap);
+            AddKgAlgorithm("CAMELLIA192",
+                NttObjectIdentifiers.IdCamellia192Cbc,
+                NttObjectIdentifiers.IdCamellia192Wrap);
+            AddKgAlgorithm("CAMELLIA256",
+                NttObjectIdentifiers.IdCamellia256Cbc,
+                NttObjectIdentifiers.IdCamellia256Wrap);
+            AddKgAlgorithm("CAST5",
+                "1.2.840.113533.7.66.10");
+            AddKgAlgorithm("CAST6");
+            AddKgAlgorithm("DES",
+                OiwObjectIdentifiers.DesCbc,
+                OiwObjectIdentifiers.DesCfb,
+                OiwObjectIdentifiers.DesEcb,
+                OiwObjectIdentifiers.DesOfb);
+            AddKgAlgorithm("DESEDE",
+                "DESEDEWRAP",
+                "TDEA",
+                OiwObjectIdentifiers.DesEde);
+            AddKgAlgorithm("DESEDE3",
+                PkcsObjectIdentifiers.DesEde3Cbc,
+                PkcsObjectIdentifiers.IdAlgCms3DesWrap);
+            AddKgAlgorithm("GOST28147",
+                "GOST",
+                "GOST-28147",
+                CryptoProObjectIdentifiers.GostR28147Cbc);
+            AddKgAlgorithm("HC128");
+            AddKgAlgorithm("HC256");
+            AddKgAlgorithm("IDEA",
+                "1.3.6.1.4.1.188.7.1.1.2");
+            AddKgAlgorithm("NOEKEON");
+            AddKgAlgorithm("RC2",
+                PkcsObjectIdentifiers.RC2Cbc,
+                PkcsObjectIdentifiers.IdAlgCmsRC2Wrap);
+            AddKgAlgorithm("RC4",
+                "ARC4",
+                "1.2.840.113549.3.4");
+            AddKgAlgorithm("RC5",
+                "RC5-32");
+            AddKgAlgorithm("RC5-64");
+            AddKgAlgorithm("RC6");
+            AddKgAlgorithm("RIJNDAEL");
+            AddKgAlgorithm("SALSA20");
+            AddKgAlgorithm("SEED",
+                KisaObjectIdentifiers.IdNpkiAppCmsSeedWrap,
+                KisaObjectIdentifiers.IdSeedCbc);
+            AddKgAlgorithm("SERPENT");
+            AddKgAlgorithm("SKIPJACK");
+            AddKgAlgorithm("TEA");
+            AddKgAlgorithm("TWOFISH");
+            AddKgAlgorithm("VMPC");
+            AddKgAlgorithm("VMPC-KSA3");
+            AddKgAlgorithm("XTEA");
+
+            //
+            // HMac key generators
+            //
+            AddHMacKeyGenerator("MD2");
+            AddHMacKeyGenerator("MD4");
+            AddHMacKeyGenerator("MD5",
+                IanaObjectIdentifiers.HmacMD5);
+            AddHMacKeyGenerator("SHA1",
+                PkcsObjectIdentifiers.IdHmacWithSha1,
+                IanaObjectIdentifiers.HmacSha1);
+            AddHMacKeyGenerator("SHA224",
+                PkcsObjectIdentifiers.IdHmacWithSha224);
+            AddHMacKeyGenerator("SHA256",
+                PkcsObjectIdentifiers.IdHmacWithSha256);
+            AddHMacKeyGenerator("SHA384",
+                PkcsObjectIdentifiers.IdHmacWithSha384);
+            AddHMacKeyGenerator("SHA512",
+                PkcsObjectIdentifiers.IdHmacWithSha512);
+            AddHMacKeyGenerator("SHA512/224");
+            AddHMacKeyGenerator("SHA512/256");
+            AddHMacKeyGenerator("SHA3-224");
+            AddHMacKeyGenerator("SHA3-256");
+            AddHMacKeyGenerator("SHA3-384");
+            AddHMacKeyGenerator("SHA3-512");
+            AddHMacKeyGenerator("RIPEMD128");
+            AddHMacKeyGenerator("RIPEMD160",
+                IanaObjectIdentifiers.HmacRipeMD160);
+            AddHMacKeyGenerator("TIGER",
+                IanaObjectIdentifiers.HmacTiger);
+
+
+
+            //
+            // key pair generators.
+            //
+            AddKpgAlgorithm("DH",
+                "DIFFIEHELLMAN");
+            AddKpgAlgorithm("DSA");
+            AddKpgAlgorithm("EC",
+                // TODO Should this be an alias for ECDH?
+                X9ObjectIdentifiers.DHSinglePassStdDHSha1KdfScheme);
+            AddKpgAlgorithm("ECDH",
+                "ECIES");
+            AddKpgAlgorithm("ECDHC");
+            AddKpgAlgorithm("ECMQV",
+                X9ObjectIdentifiers.MqvSinglePassSha1KdfScheme);
+            AddKpgAlgorithm("ECDSA");
+            AddKpgAlgorithm("ECGOST3410",
+                "ECGOST-3410",
+                "GOST-3410-2001");
+            AddKpgAlgorithm("ELGAMAL");
+            AddKpgAlgorithm("GOST3410",
+                "GOST-3410",
+                "GOST-3410-94");
+            AddKpgAlgorithm("RSA",
+                "1.2.840.113549.1.1.1");
+
+            AddDefaultKeySizeEntries(64, "DES");
+            AddDefaultKeySizeEntries(80, "SKIPJACK");
+            AddDefaultKeySizeEntries(128, "AES128", "BLOWFISH", "CAMELLIA128", "CAST5", "DESEDE",
+                "HC128", "HMACMD2", "HMACMD4", "HMACMD5", "HMACRIPEMD128", "IDEA", "NOEKEON",
+                "RC2", "RC4", "RC5", "SALSA20", "SEED", "TEA", "XTEA", "VMPC", "VMPC-KSA3");
+            AddDefaultKeySizeEntries(160, "HMACRIPEMD160", "HMACSHA1");
+            AddDefaultKeySizeEntries(192, "AES", "AES192", "CAMELLIA192", "DESEDE3", "HMACTIGER",
+                "RIJNDAEL", "SERPENT");
+            AddDefaultKeySizeEntries(224, "HMACSHA224");
+            AddDefaultKeySizeEntries(256, "AES256", "CAMELLIA", "CAMELLIA256", "CAST6", "GOST28147",
+                "HC256", "HMACSHA256", "RC5-64", "RC6", "TWOFISH");
+            AddDefaultKeySizeEntries(384, "HMACSHA384");
+            AddDefaultKeySizeEntries(512, "HMACSHA512");
+            AddDefaultKeySizeEntries(224, "HMACSHA512/224");
+            AddDefaultKeySizeEntries(256, "HMACSHA512/256");
+        }
+
+        private static void AddDefaultKeySizeEntries(int size, params string[] algorithms)
+        {
+            foreach (string algorithm in algorithms)
+            {
+                defaultKeySizes.Add(algorithm, size);
+            }
+        }
+
+        private static void AddKgAlgorithm(
+            string			canonicalName,
+            params object[] aliases)
+        {
+            kgAlgorithms[canonicalName] = canonicalName;
+
+            foreach (object alias in aliases)
+            {
+                kgAlgorithms[alias.ToString()] = canonicalName;
+            }
+        }
+
+        private static void AddKpgAlgorithm(
+            string			canonicalName,
+            params object[] aliases)
+        {
+            kpgAlgorithms[canonicalName] = canonicalName;
+
+            foreach (object alias in aliases)
+            {
+                kpgAlgorithms[alias.ToString()] = canonicalName;
+            }
+        }
+
+        private static void AddHMacKeyGenerator(
+            string			algorithm,
+            params object[]	aliases)
+        {
+            string mainName = "HMAC" + algorithm;
+
+            kgAlgorithms[mainName] = mainName;
+            kgAlgorithms["HMAC-" + algorithm] = mainName;
+            kgAlgorithms["HMAC/" + algorithm] = mainName;
+
+            foreach (object alias in aliases)
+            {
+                kgAlgorithms[alias.ToString()] = mainName;
+            }
+        }
+
+        // TODO Consider making this public
+        internal static string GetCanonicalKeyGeneratorAlgorithm(
+            string algorithm)
+        {
+            return (string) kgAlgorithms[Platform.ToUpperInvariant(algorithm)];
+        }
+
+        // TODO Consider making this public
+        internal static string GetCanonicalKeyPairGeneratorAlgorithm(
+            string algorithm)
+        {
+            return (string)kpgAlgorithms[Platform.ToUpperInvariant(algorithm)];
+        }
+
+        public static CipherKeyGenerator GetKeyGenerator(
+            DerObjectIdentifier oid)
+        {
+            return GetKeyGenerator(oid.Id);
+        }
+
+        public static CipherKeyGenerator GetKeyGenerator(
+            string algorithm)
+        {
+            string canonicalName = GetCanonicalKeyGeneratorAlgorithm(algorithm);
+
+            if (canonicalName == null)
+                throw new SecurityUtilityException("KeyGenerator " + algorithm + " not recognised.");
+
+            int defaultKeySize = FindDefaultKeySize(canonicalName);
+            if (defaultKeySize == -1)
+                throw new SecurityUtilityException("KeyGenerator " + algorithm
+                    + " (" + canonicalName + ") not supported.");
+
+            if (canonicalName == "DES")
+                return new DesKeyGenerator(defaultKeySize);
+
+            if (canonicalName == "DESEDE" || canonicalName == "DESEDE3")
+                return new DesEdeKeyGenerator(defaultKeySize);
+
+            return new CipherKeyGenerator(defaultKeySize);
+        }
+
+        public static IAsymmetricCipherKeyPairGenerator GetKeyPairGenerator(
+            DerObjectIdentifier oid)
+        {
+            return GetKeyPairGenerator(oid.Id);
+        }
+
+        public static IAsymmetricCipherKeyPairGenerator GetKeyPairGenerator(
+            string algorithm)
+        {
+            string canonicalName = GetCanonicalKeyPairGeneratorAlgorithm(algorithm);
+
+            if (canonicalName == null)
+                throw new SecurityUtilityException("KeyPairGenerator " + algorithm + " not recognised.");
+
+            if (canonicalName == "DH")
+                return new DHKeyPairGenerator();
+
+            if (canonicalName == "DSA")
+                return new DsaKeyPairGenerator();
+
+            // "EC", "ECDH", "ECDHC", "ECDSA", "ECGOST3410", "ECMQV"
+            if (canonicalName.StartsWith("EC"))
+                return new ECKeyPairGenerator(canonicalName);
+
+            if (canonicalName == "ELGAMAL")
+                return new ElGamalKeyPairGenerator();
+
+            if (canonicalName == "GOST3410")
+                return new Gost3410KeyPairGenerator();
+
+            if (canonicalName == "RSA")
+                return new RsaKeyPairGenerator();
+
+            throw new SecurityUtilityException("KeyPairGenerator " + algorithm
+                + " (" + canonicalName + ") not supported.");
+        }
+
+        internal static int GetDefaultKeySize(
+            DerObjectIdentifier oid)
+        {
+            return GetDefaultKeySize(oid.Id);
+        }
+
+        internal static int GetDefaultKeySize(
+            string algorithm)
+        {
+            string canonicalName = GetCanonicalKeyGeneratorAlgorithm(algorithm);
+
+            if (canonicalName == null)
+                throw new SecurityUtilityException("KeyGenerator " + algorithm + " not recognised.");
+
+            int defaultKeySize = FindDefaultKeySize(canonicalName);
+            if (defaultKeySize == -1)
+                throw new SecurityUtilityException("KeyGenerator " + algorithm
+                    + " (" + canonicalName + ") not supported.");
+
+            return defaultKeySize;
+        }
+
+        private static int FindDefaultKeySize(
+            string canonicalName)
+        {
+            if (!defaultKeySizes.Contains(canonicalName))
+                return -1;
+
+            return (int)defaultKeySizes[canonicalName];
+        }
+    }
+}
diff --git a/crypto/src/security/InvalidKeyException.cs b/crypto/src/security/InvalidKeyException.cs
new file mode 100644
index 000000000..4d4488ef2
--- /dev/null
+++ b/crypto/src/security/InvalidKeyException.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Org.BouncyCastle.Security
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class InvalidKeyException : KeyException
+	{
+		public InvalidKeyException() : base() { }
+		public InvalidKeyException(string message) : base(message) { }
+		public InvalidKeyException(string message, Exception exception) : base(message, exception) { }
+	}
+}
diff --git a/crypto/src/security/InvalidParameterException.cs b/crypto/src/security/InvalidParameterException.cs
new file mode 100644
index 000000000..57a912d03
--- /dev/null
+++ b/crypto/src/security/InvalidParameterException.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Org.BouncyCastle.Security
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class InvalidParameterException : KeyException
+	{
+		public InvalidParameterException() : base() { }
+		public InvalidParameterException(string message) : base(message) { }
+		public InvalidParameterException(string message, Exception exception) : base(message, exception) { }
+	}
+}
diff --git a/crypto/src/security/KeyException.cs b/crypto/src/security/KeyException.cs
new file mode 100644
index 000000000..9304c1c4d
--- /dev/null
+++ b/crypto/src/security/KeyException.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Org.BouncyCastle.Security
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class KeyException : GeneralSecurityException
+	{
+		public KeyException() : base() { }
+		public KeyException(string message) : base(message) { }
+		public KeyException(string message, Exception exception) : base(message, exception) { }
+	}
+}
diff --git a/crypto/src/security/MacUtilities.cs b/crypto/src/security/MacUtilities.cs
new file mode 100644
index 000000000..49162fb57
--- /dev/null
+++ b/crypto/src/security/MacUtilities.cs
@@ -0,0 +1,243 @@
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Iana;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Macs;
+using Org.BouncyCastle.Crypto.Paddings;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Security
+{
+    /// <remarks>
+    ///  Utility class for creating HMac object from their names/Oids
+    /// </remarks>
+    public sealed class MacUtilities
+    {
+        private MacUtilities()
+        {
+        }
+
+        private static readonly IDictionary algorithms = Platform.CreateHashtable();
+        //private static readonly IDictionary oids = Platform.CreateHashtable();
+
+        static MacUtilities()
+        {
+            algorithms[IanaObjectIdentifiers.HmacMD5.Id] = "HMAC-MD5";
+            algorithms[IanaObjectIdentifiers.HmacRipeMD160.Id] = "HMAC-RIPEMD160";
+            algorithms[IanaObjectIdentifiers.HmacSha1.Id] = "HMAC-SHA1";
+            algorithms[IanaObjectIdentifiers.HmacTiger.Id] = "HMAC-TIGER";
+
+            algorithms[PkcsObjectIdentifiers.IdHmacWithSha1.Id] = "HMAC-SHA1";
+            algorithms[PkcsObjectIdentifiers.IdHmacWithSha224.Id] = "HMAC-SHA224";
+            algorithms[PkcsObjectIdentifiers.IdHmacWithSha256.Id] = "HMAC-SHA256";
+            algorithms[PkcsObjectIdentifiers.IdHmacWithSha384.Id] = "HMAC-SHA384";
+            algorithms[PkcsObjectIdentifiers.IdHmacWithSha512.Id] = "HMAC-SHA512";
+
+            // TODO AESMAC?
+
+            algorithms["DES"] = "DESMAC";
+            algorithms["DES/CFB8"] = "DESMAC/CFB8";
+            algorithms["DES64"] = "DESMAC64";
+            algorithms["DESEDE"] = "DESEDEMAC";
+            algorithms[PkcsObjectIdentifiers.DesEde3Cbc.Id] = "DESEDEMAC";
+            algorithms["DESEDE/CFB8"] = "DESEDEMAC/CFB8";
+            algorithms["DESISO9797MAC"] = "DESWITHISO9797";
+            algorithms["DESEDE64"] = "DESEDEMAC64";
+
+            algorithms["DESEDE64WITHISO7816-4PADDING"] = "DESEDEMAC64WITHISO7816-4PADDING";
+            algorithms["DESEDEISO9797ALG1MACWITHISO7816-4PADDING"] = "DESEDEMAC64WITHISO7816-4PADDING";
+            algorithms["DESEDEISO9797ALG1WITHISO7816-4PADDING"] = "DESEDEMAC64WITHISO7816-4PADDING";
+
+            algorithms["ISO9797ALG3"] = "ISO9797ALG3MAC";
+            algorithms["ISO9797ALG3MACWITHISO7816-4PADDING"] = "ISO9797ALG3WITHISO7816-4PADDING";
+
+            algorithms["SKIPJACK"] = "SKIPJACKMAC";
+            algorithms["SKIPJACK/CFB8"] = "SKIPJACKMAC/CFB8";
+            algorithms["IDEA"] = "IDEAMAC";
+            algorithms["IDEA/CFB8"] = "IDEAMAC/CFB8";
+            algorithms["RC2"] = "RC2MAC";
+            algorithms["RC2/CFB8"] = "RC2MAC/CFB8";
+            algorithms["RC5"] = "RC5MAC";
+            algorithms["RC5/CFB8"] = "RC5MAC/CFB8";
+            algorithms["GOST28147"] = "GOST28147MAC";
+            algorithms["VMPC"] = "VMPCMAC";
+            algorithms["VMPC-MAC"] = "VMPCMAC";
+            algorithms["SIPHASH"] = "SIPHASH-2-4";
+
+            algorithms["PBEWITHHMACSHA"] = "PBEWITHHMACSHA1";
+            algorithms["1.3.14.3.2.26"] = "PBEWITHHMACSHA1";
+        }
+
+//		/// <summary>
+//		/// Returns a ObjectIdentifier for a given digest mechanism.
+//		/// </summary>
+//		/// <param name="mechanism">A string representation of the digest meanism.</param>
+//		/// <returns>A DerObjectIdentifier, null if the Oid is not available.</returns>
+//		public static DerObjectIdentifier GetObjectIdentifier(
+//			string mechanism)
+//		{
+//			mechanism = (string) algorithms[Platform.ToUpperInvariant(mechanism)];
+//
+//			if (mechanism != null)
+//			{
+//				return (DerObjectIdentifier)oids[mechanism];
+//			}
+//
+//			return null;
+//		}
+
+//		public static ICollection Algorithms
+//		{
+//			get { return oids.Keys; }
+//		}
+
+        public static IMac GetMac(
+            DerObjectIdentifier id)
+        {
+            return GetMac(id.Id);
+        }
+
+        public static IMac GetMac(
+            string algorithm)
+        {
+            string upper = Platform.ToUpperInvariant(algorithm);
+
+            string mechanism = (string) algorithms[upper];
+
+            if (mechanism == null)
+            {
+                mechanism = upper;
+            }
+
+            if (mechanism.StartsWith("PBEWITH"))
+            {
+                mechanism = mechanism.Substring("PBEWITH".Length);
+            }
+
+            if (mechanism.StartsWith("HMAC"))
+            {
+                string digestName;
+                if (mechanism.StartsWith("HMAC-") || mechanism.StartsWith("HMAC/"))
+                {
+                    digestName = mechanism.Substring(5);
+                }
+                else
+                {
+                    digestName = mechanism.Substring(4);
+                }
+
+                return new HMac(DigestUtilities.GetDigest(digestName));
+            }
+
+            if (mechanism == "AESCMAC")
+            {
+                return new CMac(new AesFastEngine());
+            }
+            if (mechanism == "DESMAC")
+            {
+                return new CbcBlockCipherMac(new DesEngine());
+            }
+            if (mechanism == "DESMAC/CFB8")
+            {
+                return new CfbBlockCipherMac(new DesEngine());
+            }
+            if (mechanism == "DESMAC64")
+            {
+                return new CbcBlockCipherMac(new DesEngine(), 64);
+            }
+            if (mechanism == "DESEDECMAC")
+            {
+                return new CMac(new DesEdeEngine());
+            }
+            if (mechanism == "DESEDEMAC")
+            {
+                return new CbcBlockCipherMac(new DesEdeEngine());
+            }
+            if (mechanism == "DESEDEMAC/CFB8")
+            {
+                return new CfbBlockCipherMac(new DesEdeEngine());
+            }
+            if (mechanism == "DESEDEMAC64")
+            {
+                return new CbcBlockCipherMac(new DesEdeEngine(), 64);
+            }
+            if (mechanism == "DESEDEMAC64WITHISO7816-4PADDING")
+            {
+                return new CbcBlockCipherMac(new DesEdeEngine(), 64, new ISO7816d4Padding());
+            }
+            if (mechanism == "DESWITHISO9797"
+                || mechanism == "ISO9797ALG3MAC")
+            {
+                return new ISO9797Alg3Mac(new DesEngine());
+            }
+            if (mechanism == "ISO9797ALG3WITHISO7816-4PADDING")
+            {
+                return new ISO9797Alg3Mac(new DesEngine(), new ISO7816d4Padding());
+            }
+            if (mechanism == "SKIPJACKMAC")
+            {
+                return new CbcBlockCipherMac(new SkipjackEngine());
+            }
+            if (mechanism == "SKIPJACKMAC/CFB8")
+            {
+                return new CfbBlockCipherMac(new SkipjackEngine());
+            }
+#if INCLUDE_IDEA
+            if (mechanism == "IDEAMAC")
+            {
+                return new CbcBlockCipherMac(new IdeaEngine());
+            }
+            if (mechanism == "IDEAMAC/CFB8")
+            {
+                return new CfbBlockCipherMac(new IdeaEngine());
+            }
+#endif
+            if (mechanism == "RC2MAC")
+            {
+                return new CbcBlockCipherMac(new RC2Engine());
+            }
+            if (mechanism == "RC2MAC/CFB8")
+            {
+                return new CfbBlockCipherMac(new RC2Engine());
+            }
+            if (mechanism == "RC5MAC")
+            {
+                return new CbcBlockCipherMac(new RC532Engine());
+            }
+            if (mechanism == "RC5MAC/CFB8")
+            {
+                return new CfbBlockCipherMac(new RC532Engine());
+            }
+            if (mechanism == "GOST28147MAC")
+            {
+                return new Gost28147Mac();
+            }
+            if (mechanism == "VMPCMAC")
+            {
+                return new VmpcMac();
+            }
+            if (mechanism == "SIPHASH-2-4")
+            {
+                return new SipHash();
+            }
+            throw new SecurityUtilityException("Mac " + mechanism + " not recognised.");
+        }
+
+        public static string GetAlgorithmName(
+            DerObjectIdentifier oid)
+        {
+            return (string) algorithms[oid.Id];
+        }
+
+        public static byte[] DoFinal(
+            IMac mac)
+        {
+            byte[] b = new byte[mac.GetMacSize()];
+            mac.DoFinal(b, 0);
+            return b;
+        }
+    }
+}
diff --git a/crypto/src/security/NoSuchAlgorithmException.cs b/crypto/src/security/NoSuchAlgorithmException.cs
new file mode 100644
index 000000000..d120c5f77
--- /dev/null
+++ b/crypto/src/security/NoSuchAlgorithmException.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace Org.BouncyCastle.Security
+{
+	[Obsolete("Never thrown")]
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class NoSuchAlgorithmException : GeneralSecurityException
+	{
+		public NoSuchAlgorithmException() : base() {}
+		public NoSuchAlgorithmException(string message) : base(message) {}
+		public NoSuchAlgorithmException(string message, Exception exception) : base(message, exception) {}
+	}
+}
diff --git a/crypto/src/security/ParameterUtilities.cs b/crypto/src/security/ParameterUtilities.cs
new file mode 100644
index 000000000..bf448edff
--- /dev/null
+++ b/crypto/src/security/ParameterUtilities.cs
@@ -0,0 +1,327 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.Kisa;
+using Org.BouncyCastle.Asn1.Misc;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Ntt;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Security
+{
+    public sealed class ParameterUtilities
+    {
+        private ParameterUtilities()
+        {
+        }
+
+        private static readonly IDictionary algorithms = Platform.CreateHashtable();
+        private static readonly IDictionary basicIVSizes = Platform.CreateHashtable();
+
+        static ParameterUtilities()
+        {
+            AddAlgorithm("AES",
+                "AESWRAP");
+            AddAlgorithm("AES128",
+                "2.16.840.1.101.3.4.2",
+                NistObjectIdentifiers.IdAes128Cbc,
+                NistObjectIdentifiers.IdAes128Cfb,
+                NistObjectIdentifiers.IdAes128Ecb,
+                NistObjectIdentifiers.IdAes128Ofb,
+                NistObjectIdentifiers.IdAes128Wrap);
+            AddAlgorithm("AES192",
+                "2.16.840.1.101.3.4.22",
+                NistObjectIdentifiers.IdAes192Cbc,
+                NistObjectIdentifiers.IdAes192Cfb,
+                NistObjectIdentifiers.IdAes192Ecb,
+                NistObjectIdentifiers.IdAes192Ofb,
+                NistObjectIdentifiers.IdAes192Wrap);
+            AddAlgorithm("AES256",
+                "2.16.840.1.101.3.4.42",
+                NistObjectIdentifiers.IdAes256Cbc,
+                NistObjectIdentifiers.IdAes256Cfb,
+                NistObjectIdentifiers.IdAes256Ecb,
+                NistObjectIdentifiers.IdAes256Ofb,
+                NistObjectIdentifiers.IdAes256Wrap);
+            AddAlgorithm("BLOWFISH",
+                "1.3.6.1.4.1.3029.1.2");
+            AddAlgorithm("CAMELLIA",
+                "CAMELLIAWRAP");
+            AddAlgorithm("CAMELLIA128",
+                NttObjectIdentifiers.IdCamellia128Cbc,
+                NttObjectIdentifiers.IdCamellia128Wrap);
+            AddAlgorithm("CAMELLIA192",
+                NttObjectIdentifiers.IdCamellia192Cbc,
+                NttObjectIdentifiers.IdCamellia192Wrap);
+            AddAlgorithm("CAMELLIA256",
+                NttObjectIdentifiers.IdCamellia256Cbc,
+                NttObjectIdentifiers.IdCamellia256Wrap);
+            AddAlgorithm("CAST5",
+                "1.2.840.113533.7.66.10");
+            AddAlgorithm("CAST6");
+            AddAlgorithm("DES",
+                OiwObjectIdentifiers.DesCbc,
+                OiwObjectIdentifiers.DesCfb,
+                OiwObjectIdentifiers.DesEcb,
+                OiwObjectIdentifiers.DesOfb);
+            AddAlgorithm("DESEDE",
+                "DESEDEWRAP",
+                "TDEA",
+                OiwObjectIdentifiers.DesEde,
+                PkcsObjectIdentifiers.IdAlgCms3DesWrap);
+            AddAlgorithm("DESEDE3",
+                PkcsObjectIdentifiers.DesEde3Cbc);
+            AddAlgorithm("GOST28147",
+                "GOST",
+                "GOST-28147",
+                CryptoProObjectIdentifiers.GostR28147Cbc);
+            AddAlgorithm("HC128");
+            AddAlgorithm("HC256");
+#if INCLUDE_IDEA
+            AddAlgorithm("IDEA",
+                "1.3.6.1.4.1.188.7.1.1.2");
+#endif
+            AddAlgorithm("NOEKEON");
+            AddAlgorithm("RC2",
+                PkcsObjectIdentifiers.RC2Cbc,
+                PkcsObjectIdentifiers.IdAlgCmsRC2Wrap);
+            AddAlgorithm("RC4",
+                "ARC4",
+                "1.2.840.113549.3.4");
+            AddAlgorithm("RC5",
+                "RC5-32");
+            AddAlgorithm("RC5-64");
+            AddAlgorithm("RC6");
+            AddAlgorithm("RIJNDAEL");
+            AddAlgorithm("SALSA20");
+            AddAlgorithm("SEED",
+                KisaObjectIdentifiers.IdNpkiAppCmsSeedWrap,
+                KisaObjectIdentifiers.IdSeedCbc);
+            AddAlgorithm("SERPENT");
+            AddAlgorithm("SKIPJACK");
+            AddAlgorithm("TEA");
+            AddAlgorithm("TWOFISH");
+            AddAlgorithm("VMPC");
+            AddAlgorithm("VMPC-KSA3");
+            AddAlgorithm("XTEA");
+
+            AddBasicIVSizeEntries(8, "BLOWFISH", "DES", "DESEDE", "DESEDE3");
+            AddBasicIVSizeEntries(16, "AES", "AES128", "AES192", "AES256",
+                "CAMELLIA", "CAMELLIA128", "CAMELLIA192", "CAMELLIA256", "NOEKEON", "SEED");
+
+            // TODO These algorithms support an IV
+            // but JCE doesn't seem to provide an AlgorithmParametersGenerator for them
+            // "RIJNDAEL", "SKIPJACK", "TWOFISH"
+        }
+
+        private static void AddAlgorithm(
+            string			canonicalName,
+            params object[]	aliases)
+        {
+            algorithms[canonicalName] = canonicalName;
+
+            foreach (object alias in aliases)
+            {
+                algorithms[alias.ToString()] = canonicalName;
+            }
+        }
+
+        private static void AddBasicIVSizeEntries(int size, params string[] algorithms)
+        {
+            foreach (string algorithm in algorithms)
+            {
+                basicIVSizes.Add(algorithm, size);
+            }
+        }
+
+        public static string GetCanonicalAlgorithmName(
+            string algorithm)
+        {
+            return (string) algorithms[Platform.ToUpperInvariant(algorithm)];
+        }
+
+        public static KeyParameter CreateKeyParameter(
+            DerObjectIdentifier algOid,
+            byte[]				keyBytes)
+        {
+            return CreateKeyParameter(algOid.Id, keyBytes, 0, keyBytes.Length);
+        }
+
+        public static KeyParameter CreateKeyParameter(
+            string	algorithm,
+            byte[]	keyBytes)
+        {
+            return CreateKeyParameter(algorithm, keyBytes, 0, keyBytes.Length);
+        }
+
+        public static KeyParameter CreateKeyParameter(
+            DerObjectIdentifier algOid,
+            byte[]				keyBytes,
+            int					offset,
+            int					length)
+        {
+            return CreateKeyParameter(algOid.Id, keyBytes, offset, length);
+        }
+
+        public static KeyParameter CreateKeyParameter(
+            string	algorithm,
+            byte[]	keyBytes,
+            int		offset,
+            int		length)
+        {
+            if (algorithm == null)
+                throw new ArgumentNullException("algorithm");
+
+            string canonical = GetCanonicalAlgorithmName(algorithm);
+
+            if (canonical == null)
+                throw new SecurityUtilityException("Algorithm " + algorithm + " not recognised.");
+
+            if (canonical == "DES")
+                return new DesParameters(keyBytes, offset, length);
+
+            if (canonical == "DESEDE" || canonical =="DESEDE3")
+                return new DesEdeParameters(keyBytes, offset, length);
+
+            if (canonical == "RC2")
+                return new RC2Parameters(keyBytes, offset, length);
+
+            return new KeyParameter(keyBytes, offset, length);
+        }
+
+        public static ICipherParameters GetCipherParameters(
+            DerObjectIdentifier	algOid,
+            ICipherParameters	key,
+            Asn1Object			asn1Params)
+        {
+            return GetCipherParameters(algOid.Id, key, asn1Params);
+        }
+
+        public static ICipherParameters GetCipherParameters(
+            string				algorithm,
+            ICipherParameters	key,
+            Asn1Object			asn1Params)
+        {
+            if (algorithm == null)
+                throw new ArgumentNullException("algorithm");
+
+            string canonical = GetCanonicalAlgorithmName(algorithm);
+
+            if (canonical == null)
+                throw new SecurityUtilityException("Algorithm " + algorithm + " not recognised.");
+
+            byte[] iv = null;
+
+            try
+            {
+                // TODO These algorithms support an IV
+                // but JCE doesn't seem to provide an AlgorithmParametersGenerator for them
+                // "RIJNDAEL", "SKIPJACK", "TWOFISH"
+
+                int basicIVKeySize = FindBasicIVSize(canonical);
+                if (basicIVKeySize != -1
+                    || canonical == "RIJNDAEL" || canonical == "SKIPJACK" || canonical == "TWOFISH")
+                {
+                    iv = ((Asn1OctetString) asn1Params).GetOctets();
+                }
+                else if (canonical == "CAST5")
+                {
+                    iv = Cast5CbcParameters.GetInstance(asn1Params).GetIV();
+                }
+#if INCLUDE_IDEA
+                else if (canonical == "IDEA")
+                {
+                    iv = IdeaCbcPar.GetInstance(asn1Params).GetIV();
+                }
+#endif
+                else if (canonical == "RC2")
+                {
+                    iv = RC2CbcParameter.GetInstance(asn1Params).GetIV();
+                }
+            }
+            catch (Exception e)
+            {
+                throw new ArgumentException("Could not process ASN.1 parameters", e);
+            }
+
+            if (iv != null)
+            {
+                return new ParametersWithIV(key, iv);
+            }
+
+            throw new SecurityUtilityException("Algorithm " + algorithm + " not recognised.");
+        }
+
+        public static Asn1Encodable GenerateParameters(
+            DerObjectIdentifier algID,
+            SecureRandom		random)
+        {
+            return GenerateParameters(algID.Id, random);
+        }
+
+        public static Asn1Encodable GenerateParameters(
+            string			algorithm,
+            SecureRandom	random)
+        {
+            if (algorithm == null)
+                throw new ArgumentNullException("algorithm");
+
+            string canonical = GetCanonicalAlgorithmName(algorithm);
+
+            if (canonical == null)
+                throw new SecurityUtilityException("Algorithm " + algorithm + " not recognised.");
+
+            // TODO These algorithms support an IV
+            // but JCE doesn't seem to provide an AlgorithmParametersGenerator for them
+            // "RIJNDAEL", "SKIPJACK", "TWOFISH"
+
+            int basicIVKeySize = FindBasicIVSize(canonical);
+            if (basicIVKeySize != -1)
+                return CreateIVOctetString(random, basicIVKeySize);
+
+            if (canonical == "CAST5")
+                return new Cast5CbcParameters(CreateIV(random, 8), 128);
+
+#if INCLUDE_IDEA
+            if (canonical == "IDEA")
+                return new IdeaCbcPar(CreateIV(random, 8));
+#endif
+
+            if (canonical == "RC2")
+                return new RC2CbcParameter(CreateIV(random, 8));
+
+            throw new SecurityUtilityException("Algorithm " + algorithm + " not recognised.");
+        }
+
+        private static Asn1OctetString CreateIVOctetString(
+            SecureRandom	random,
+            int				ivLength)
+        {
+            return new DerOctetString(CreateIV(random, ivLength));
+        }
+
+        private static byte[] CreateIV(
+            SecureRandom	random,
+            int				ivLength)
+        {
+            byte[] iv = new byte[ivLength];
+            random.NextBytes(iv);
+            return iv;
+        }
+
+        private static int FindBasicIVSize(
+            string canonicalName)
+        {
+            if (!basicIVSizes.Contains(canonicalName))
+                return -1;
+
+            return (int)basicIVSizes[canonicalName];
+        }
+    }
+}
diff --git a/crypto/src/security/PbeUtilities.cs b/crypto/src/security/PbeUtilities.cs
new file mode 100644
index 000000000..56d68ba0a
--- /dev/null
+++ b/crypto/src/security/PbeUtilities.cs
@@ -0,0 +1,663 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.BC;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.TeleTrust;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Macs;
+using Org.BouncyCastle.Crypto.Modes;
+using Org.BouncyCastle.Crypto.Paddings;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Security
+{
+    /// <summary>
+    ///
+    /// </summary>
+    public sealed class PbeUtilities
+    {
+        private PbeUtilities()
+        {
+        }
+
+        const string Pkcs5S1 = "Pkcs5S1";
+        const string Pkcs5S2 = "Pkcs5S2";
+        const string Pkcs12 = "Pkcs12";
+        const string OpenSsl = "OpenSsl";
+
+        private static readonly IDictionary algorithms = Platform.CreateHashtable();
+        private static readonly IDictionary algorithmType = Platform.CreateHashtable();
+        private static readonly IDictionary oids = Platform.CreateHashtable();
+
+        static PbeUtilities()
+        {
+            algorithms["PKCS5SCHEME1"] = "Pkcs5scheme1";
+            algorithms["PKCS5SCHEME2"] = "Pkcs5scheme2";
+            algorithms[PkcsObjectIdentifiers.IdPbeS2.Id] = "Pkcs5scheme2";
+//			algorithms[PkcsObjectIdentifiers.IdPbkdf2.Id] = "Pkcs5scheme2";
+
+            // FIXME Add support for these? (see Pkcs8Generator)
+//			algorithms[PkcsObjectIdentifiers.DesEde3Cbc.Id] = "Pkcs5scheme2";
+//			algorithms[NistObjectIdentifiers.IdAes128Cbc.Id] = "Pkcs5scheme2";
+//			algorithms[NistObjectIdentifiers.IdAes192Cbc.Id] = "Pkcs5scheme2";
+//			algorithms[NistObjectIdentifiers.IdAes256Cbc.Id] = "Pkcs5scheme2";
+
+            algorithms["PBEWITHMD2ANDDES-CBC"] = "PBEwithMD2andDES-CBC";
+            algorithms[PkcsObjectIdentifiers.PbeWithMD2AndDesCbc.Id] = "PBEwithMD2andDES-CBC";
+            algorithms["PBEWITHMD2ANDRC2-CBC"] = "PBEwithMD2andRC2-CBC";
+            algorithms[PkcsObjectIdentifiers.PbeWithMD2AndRC2Cbc.Id] = "PBEwithMD2andRC2-CBC";
+            algorithms["PBEWITHMD5ANDDES-CBC"] = "PBEwithMD5andDES-CBC";
+            algorithms[PkcsObjectIdentifiers.PbeWithMD5AndDesCbc.Id] = "PBEwithMD5andDES-CBC";
+            algorithms["PBEWITHMD5ANDRC2-CBC"] = "PBEwithMD5andRC2-CBC";
+            algorithms[PkcsObjectIdentifiers.PbeWithMD5AndRC2Cbc.Id] = "PBEwithMD5andRC2-CBC";
+            algorithms["PBEWITHSHA1ANDDES"] = "PBEwithSHA-1andDES-CBC";
+            algorithms["PBEWITHSHA-1ANDDES"] = "PBEwithSHA-1andDES-CBC";
+            algorithms["PBEWITHSHA1ANDDES-CBC"] = "PBEwithSHA-1andDES-CBC";
+            algorithms["PBEWITHSHA-1ANDDES-CBC"] = "PBEwithSHA-1andDES-CBC";
+            algorithms[PkcsObjectIdentifiers.PbeWithSha1AndDesCbc.Id] = "PBEwithSHA-1andDES-CBC";
+            algorithms["PBEWITHSHA1ANDRC2"] = "PBEwithSHA-1andRC2-CBC";
+            algorithms["PBEWITHSHA-1ANDRC2"] = "PBEwithSHA-1andRC2-CBC";
+            algorithms["PBEWITHSHA1ANDRC2-CBC"] = "PBEwithSHA-1andRC2-CBC";
+            algorithms["PBEWITHSHA-1ANDRC2-CBC"] = "PBEwithSHA-1andRC2-CBC";
+            algorithms[PkcsObjectIdentifiers.PbeWithSha1AndRC2Cbc.Id] = "PBEwithSHA-1andRC2-CBC";
+            algorithms["PKCS12"] = "Pkcs12";
+            algorithms[BCObjectIdentifiers.bc_pbe_sha1_pkcs12_aes128_cbc.Id] = "PBEwithSHA-1and128bitAES-CBC-BC";
+            algorithms[BCObjectIdentifiers.bc_pbe_sha1_pkcs12_aes192_cbc.Id] = "PBEwithSHA-1and192bitAES-CBC-BC";
+            algorithms[BCObjectIdentifiers.bc_pbe_sha1_pkcs12_aes256_cbc.Id] = "PBEwithSHA-1and256bitAES-CBC-BC";
+            algorithms[BCObjectIdentifiers.bc_pbe_sha256_pkcs12_aes128_cbc.Id] = "PBEwithSHA-256and128bitAES-CBC-BC";
+            algorithms[BCObjectIdentifiers.bc_pbe_sha256_pkcs12_aes192_cbc.Id] = "PBEwithSHA-256and192bitAES-CBC-BC";
+            algorithms[BCObjectIdentifiers.bc_pbe_sha256_pkcs12_aes256_cbc.Id] = "PBEwithSHA-256and256bitAES-CBC-BC";
+            algorithms["PBEWITHSHAAND128BITRC4"] = "PBEwithSHA-1and128bitRC4";
+            algorithms["PBEWITHSHA1AND128BITRC4"] = "PBEwithSHA-1and128bitRC4";
+            algorithms["PBEWITHSHA-1AND128BITRC4"] = "PBEwithSHA-1and128bitRC4";
+            algorithms[PkcsObjectIdentifiers.PbeWithShaAnd128BitRC4.Id] = "PBEwithSHA-1and128bitRC4";
+            algorithms["PBEWITHSHAAND40BITRC4"] = "PBEwithSHA-1and40bitRC4";
+            algorithms["PBEWITHSHA1AND40BITRC4"] = "PBEwithSHA-1and40bitRC4";
+            algorithms["PBEWITHSHA-1AND40BITRC4"] = "PBEwithSHA-1and40bitRC4";
+            algorithms[PkcsObjectIdentifiers.PbeWithShaAnd40BitRC4.Id] = "PBEwithSHA-1and40bitRC4";
+            algorithms["PBEWITHSHAAND3-KEYDESEDE-CBC"] = "PBEwithSHA-1and3-keyDESEDE-CBC";
+            algorithms["PBEWITHSHAAND3-KEYTRIPLEDES-CBC"] = "PBEwithSHA-1and3-keyDESEDE-CBC";
+            algorithms["PBEWITHSHA1AND3-KEYDESEDE-CBC"] = "PBEwithSHA-1and3-keyDESEDE-CBC";
+            algorithms["PBEWITHSHA1AND3-KEYTRIPLEDES-CBC"] = "PBEwithSHA-1and3-keyDESEDE-CBC";
+            algorithms["PBEWITHSHA-1AND3-KEYDESEDE-CBC"] = "PBEwithSHA-1and3-keyDESEDE-CBC";
+            algorithms["PBEWITHSHA-1AND3-KEYTRIPLEDES-CBC"] = "PBEwithSHA-1and3-keyDESEDE-CBC";
+            algorithms[PkcsObjectIdentifiers.PbeWithShaAnd3KeyTripleDesCbc.Id] = "PBEwithSHA-1and3-keyDESEDE-CBC";
+            algorithms["PBEWITHSHAAND2-KEYDESEDE-CBC"] = "PBEwithSHA-1and2-keyDESEDE-CBC";
+            algorithms["PBEWITHSHAAND2-KEYTRIPLEDES-CBC"] = "PBEwithSHA-1and2-keyDESEDE-CBC";
+            algorithms["PBEWITHSHA1AND2-KEYDESEDE-CBC"] = "PBEwithSHA-1and2-keyDESEDE-CBC";
+            algorithms["PBEWITHSHA1AND2-KEYTRIPLEDES-CBC"] = "PBEwithSHA-1and2-keyDESEDE-CBC";
+            algorithms["PBEWITHSHA-1AND2-KEYDESEDE-CBC"] = "PBEwithSHA-1and2-keyDESEDE-CBC";
+            algorithms["PBEWITHSHA-1AND2-KEYTRIPLEDES-CBC"] = "PBEwithSHA-1and2-keyDESEDE-CBC";
+            algorithms[PkcsObjectIdentifiers.PbeWithShaAnd2KeyTripleDesCbc.Id] = "PBEwithSHA-1and2-keyDESEDE-CBC";
+            algorithms["PBEWITHSHAAND128BITRC2-CBC"] = "PBEwithSHA-1and128bitRC2-CBC";
+            algorithms["PBEWITHSHA1AND128BITRC2-CBC"] = "PBEwithSHA-1and128bitRC2-CBC";
+            algorithms["PBEWITHSHA-1AND128BITRC2-CBC"] = "PBEwithSHA-1and128bitRC2-CBC";
+            algorithms[PkcsObjectIdentifiers.PbeWithShaAnd128BitRC2Cbc.Id] = "PBEwithSHA-1and128bitRC2-CBC";
+            algorithms["PBEWITHSHAAND40BITRC2-CBC"] = "PBEwithSHA-1and40bitRC2-CBC";
+            algorithms["PBEWITHSHA1AND40BITRC2-CBC"] = "PBEwithSHA-1and40bitRC2-CBC";
+            algorithms["PBEWITHSHA-1AND40BITRC2-CBC"] = "PBEwithSHA-1and40bitRC2-CBC";
+            algorithms[PkcsObjectIdentifiers.PbewithShaAnd40BitRC2Cbc.Id] = "PBEwithSHA-1and40bitRC2-CBC";
+            algorithms["PBEWITHSHAAND128BITAES-CBC-BC"] = "PBEwithSHA-1and128bitAES-CBC-BC";
+            algorithms["PBEWITHSHA1AND128BITAES-CBC-BC"] = "PBEwithSHA-1and128bitAES-CBC-BC";
+            algorithms["PBEWITHSHA-1AND128BITAES-CBC-BC"] = "PBEwithSHA-1and128bitAES-CBC-BC";
+            algorithms["PBEWITHSHAAND192BITAES-CBC-BC"] = "PBEwithSHA-1and192bitAES-CBC-BC";
+            algorithms["PBEWITHSHA1AND192BITAES-CBC-BC"] = "PBEwithSHA-1and192bitAES-CBC-BC";
+            algorithms["PBEWITHSHA-1AND192BITAES-CBC-BC"] = "PBEwithSHA-1and192bitAES-CBC-BC";
+            algorithms["PBEWITHSHAAND256BITAES-CBC-BC"] = "PBEwithSHA-1and256bitAES-CBC-BC";
+            algorithms["PBEWITHSHA1AND256BITAES-CBC-BC"] = "PBEwithSHA-1and256bitAES-CBC-BC";
+            algorithms["PBEWITHSHA-1AND256BITAES-CBC-BC"] = "PBEwithSHA-1and256bitAES-CBC-BC";
+            algorithms["PBEWITHSHA256AND128BITAES-CBC-BC"] = "PBEwithSHA-256and128bitAES-CBC-BC";
+            algorithms["PBEWITHSHA-256AND128BITAES-CBC-BC"] = "PBEwithSHA-256and128bitAES-CBC-BC";
+            algorithms["PBEWITHSHA256AND192BITAES-CBC-BC"] = "PBEwithSHA-256and192bitAES-CBC-BC";
+            algorithms["PBEWITHSHA-256AND192BITAES-CBC-BC"] = "PBEwithSHA-256and192bitAES-CBC-BC";
+            algorithms["PBEWITHSHA256AND256BITAES-CBC-BC"] = "PBEwithSHA-256and256bitAES-CBC-BC";
+            algorithms["PBEWITHSHA-256AND256BITAES-CBC-BC"] = "PBEwithSHA-256and256bitAES-CBC-BC";
+            algorithms["PBEWITHSHAANDIDEA"] = "PBEwithSHA-1andIDEA-CBC";
+            algorithms["PBEWITHSHAANDIDEA-CBC"] = "PBEwithSHA-1andIDEA-CBC";
+            algorithms["PBEWITHSHAANDTWOFISH"] = "PBEwithSHA-1andTWOFISH-CBC";
+            algorithms["PBEWITHSHAANDTWOFISH-CBC"] = "PBEwithSHA-1andTWOFISH-CBC";
+            algorithms["PBEWITHHMACSHA1"] = "PBEwithHmacSHA-1";
+            algorithms["PBEWITHHMACSHA-1"] = "PBEwithHmacSHA-1";
+            algorithms[OiwObjectIdentifiers.IdSha1.Id] = "PBEwithHmacSHA-1";
+            algorithms["PBEWITHHMACSHA224"] = "PBEwithHmacSHA-224";
+            algorithms["PBEWITHHMACSHA-224"] = "PBEwithHmacSHA-224";
+            algorithms[NistObjectIdentifiers.IdSha224.Id] = "PBEwithHmacSHA-224";
+            algorithms["PBEWITHHMACSHA256"] = "PBEwithHmacSHA-256";
+            algorithms["PBEWITHHMACSHA-256"] = "PBEwithHmacSHA-256";
+            algorithms[NistObjectIdentifiers.IdSha256.Id] = "PBEwithHmacSHA-256";
+            algorithms["PBEWITHHMACRIPEMD128"] = "PBEwithHmacRipeMD128";
+            algorithms[TeleTrusTObjectIdentifiers.RipeMD128.Id] = "PBEwithHmacRipeMD128";
+            algorithms["PBEWITHHMACRIPEMD160"] = "PBEwithHmacRipeMD160";
+            algorithms[TeleTrusTObjectIdentifiers.RipeMD160.Id] = "PBEwithHmacRipeMD160";
+            algorithms["PBEWITHHMACRIPEMD256"] = "PBEwithHmacRipeMD256";
+            algorithms[TeleTrusTObjectIdentifiers.RipeMD256.Id] = "PBEwithHmacRipeMD256";
+            algorithms["PBEWITHHMACTIGER"] = "PBEwithHmacTiger";
+
+            algorithms["PBEWITHMD5AND128BITAES-CBC-OPENSSL"] = "PBEwithMD5and128bitAES-CBC-OpenSSL";
+            algorithms["PBEWITHMD5AND192BITAES-CBC-OPENSSL"] = "PBEwithMD5and192bitAES-CBC-OpenSSL";
+            algorithms["PBEWITHMD5AND256BITAES-CBC-OPENSSL"] = "PBEwithMD5and256bitAES-CBC-OpenSSL";
+
+            algorithmType["Pkcs5scheme1"] = Pkcs5S1;
+            algorithmType["Pkcs5scheme2"] = Pkcs5S2;
+            algorithmType["PBEwithMD2andDES-CBC"] = Pkcs5S1;
+            algorithmType["PBEwithMD2andRC2-CBC"] = Pkcs5S1;
+            algorithmType["PBEwithMD5andDES-CBC"] = Pkcs5S1;
+            algorithmType["PBEwithMD5andRC2-CBC"] = Pkcs5S1;
+            algorithmType["PBEwithSHA-1andDES-CBC"] = Pkcs5S1;
+            algorithmType["PBEwithSHA-1andRC2-CBC"] = Pkcs5S1;
+            algorithmType["Pkcs12"] = Pkcs12;
+            algorithmType["PBEwithSHA-1and128bitRC4"] = Pkcs12;
+            algorithmType["PBEwithSHA-1and40bitRC4"] = Pkcs12;
+            algorithmType["PBEwithSHA-1and3-keyDESEDE-CBC"] = Pkcs12;
+            algorithmType["PBEwithSHA-1and2-keyDESEDE-CBC"] = Pkcs12;
+            algorithmType["PBEwithSHA-1and128bitRC2-CBC"] = Pkcs12;
+            algorithmType["PBEwithSHA-1and40bitRC2-CBC"] = Pkcs12;
+            algorithmType["PBEwithSHA-1and128bitAES-CBC-BC"] = Pkcs12;
+            algorithmType["PBEwithSHA-1and192bitAES-CBC-BC"] = Pkcs12;
+            algorithmType["PBEwithSHA-1and256bitAES-CBC-BC"] = Pkcs12;
+            algorithmType["PBEwithSHA-256and128bitAES-CBC-BC"] = Pkcs12;
+            algorithmType["PBEwithSHA-256and192bitAES-CBC-BC"] = Pkcs12;
+            algorithmType["PBEwithSHA-256and256bitAES-CBC-BC"] = Pkcs12;
+            algorithmType["PBEwithSHA-1andIDEA-CBC"] = Pkcs12;
+            algorithmType["PBEwithSHA-1andTWOFISH-CBC"] = Pkcs12;
+            algorithmType["PBEwithHmacSHA-1"] = Pkcs12;
+            algorithmType["PBEwithHmacSHA-224"] = Pkcs12;
+            algorithmType["PBEwithHmacSHA-256"] = Pkcs12;
+            algorithmType["PBEwithHmacRipeMD128"] = Pkcs12;
+            algorithmType["PBEwithHmacRipeMD160"] = Pkcs12;
+            algorithmType["PBEwithHmacRipeMD256"] = Pkcs12;
+            algorithmType["PBEwithHmacTiger"] = Pkcs12;
+
+            algorithmType["PBEwithMD5and128bitAES-CBC-OpenSSL"] = OpenSsl;
+            algorithmType["PBEwithMD5and192bitAES-CBC-OpenSSL"] = OpenSsl;
+            algorithmType["PBEwithMD5and256bitAES-CBC-OpenSSL"] = OpenSsl;
+
+            oids["PBEwithMD2andDES-CBC"] = PkcsObjectIdentifiers.PbeWithMD2AndDesCbc;
+            oids["PBEwithMD2andRC2-CBC"] = PkcsObjectIdentifiers.PbeWithMD2AndRC2Cbc;
+            oids["PBEwithMD5andDES-CBC"] = PkcsObjectIdentifiers.PbeWithMD5AndDesCbc;
+            oids["PBEwithMD5andRC2-CBC"] = PkcsObjectIdentifiers.PbeWithMD5AndRC2Cbc;
+            oids["PBEwithSHA-1andDES-CBC"] = PkcsObjectIdentifiers.PbeWithSha1AndDesCbc;
+            oids["PBEwithSHA-1andRC2-CBC"] = PkcsObjectIdentifiers.PbeWithSha1AndRC2Cbc;
+            oids["PBEwithSHA-1and128bitRC4"] = PkcsObjectIdentifiers.PbeWithShaAnd128BitRC4;
+            oids["PBEwithSHA-1and40bitRC4"] = PkcsObjectIdentifiers.PbeWithShaAnd40BitRC4;
+            oids["PBEwithSHA-1and3-keyDESEDE-CBC"] = PkcsObjectIdentifiers.PbeWithShaAnd3KeyTripleDesCbc;
+            oids["PBEwithSHA-1and2-keyDESEDE-CBC"] = PkcsObjectIdentifiers.PbeWithShaAnd2KeyTripleDesCbc;
+            oids["PBEwithSHA-1and128bitRC2-CBC"] = PkcsObjectIdentifiers.PbeWithShaAnd128BitRC2Cbc;
+            oids["PBEwithSHA-1and40bitRC2-CBC"] = PkcsObjectIdentifiers.PbewithShaAnd40BitRC2Cbc;
+            oids["PBEwithHmacSHA-1"] = OiwObjectIdentifiers.IdSha1;
+            oids["PBEwithHmacSHA-224"] = NistObjectIdentifiers.IdSha224;
+            oids["PBEwithHmacSHA-256"] = NistObjectIdentifiers.IdSha256;
+            oids["PBEwithHmacRipeMD128"] = TeleTrusTObjectIdentifiers.RipeMD128;
+            oids["PBEwithHmacRipeMD160"] = TeleTrusTObjectIdentifiers.RipeMD160;
+            oids["PBEwithHmacRipeMD256"] = TeleTrusTObjectIdentifiers.RipeMD256;
+            oids["Pkcs5scheme2"] = PkcsObjectIdentifiers.IdPbeS2;
+        }
+
+        static PbeParametersGenerator MakePbeGenerator(
+            string	type,
+            IDigest	digest,
+            byte[]	key,
+            byte[]	salt,
+            int		iterationCount)
+        {
+            PbeParametersGenerator generator;
+
+            if (type.Equals(Pkcs5S1))
+            {
+                generator = new Pkcs5S1ParametersGenerator(digest);
+            }
+            else if (type.Equals(Pkcs5S2))
+            {
+                generator = new Pkcs5S2ParametersGenerator();
+            }
+            else if (type.Equals(Pkcs12))
+            {
+                generator = new Pkcs12ParametersGenerator(digest);
+            }
+            else if (type.Equals(OpenSsl))
+            {
+                generator = new OpenSslPbeParametersGenerator();
+            }
+            else
+            {
+                throw new ArgumentException("Unknown PBE type: " + type, "type");
+            }
+
+            generator.Init(key, salt, iterationCount);
+            return generator;
+        }
+
+        /// <summary>
+        /// Returns a ObjectIdentifier for a give encoding.
+        /// </summary>
+        /// <param name="mechanism">A string representation of the encoding.</param>
+        /// <returns>A DerObjectIdentifier, null if the Oid is not available.</returns>
+        public static DerObjectIdentifier GetObjectIdentifier(
+            string mechanism)
+        {
+            mechanism = (string) algorithms[Platform.ToUpperInvariant(mechanism)];
+            if (mechanism != null)
+            {
+                return (DerObjectIdentifier)oids[mechanism];
+            }
+            return null;
+        }
+
+        public static ICollection Algorithms
+        {
+            get { return oids.Keys; }
+        }
+
+        public static bool IsPkcs12(
+            string algorithm)
+        {
+            string mechanism = (string)algorithms[Platform.ToUpperInvariant(algorithm)];
+
+            return mechanism != null && Pkcs12.Equals(algorithmType[mechanism]);
+        }
+
+        public static bool IsPkcs5Scheme1(
+            string algorithm)
+        {
+            string mechanism = (string)algorithms[Platform.ToUpperInvariant(algorithm)];
+
+            return mechanism != null && Pkcs5S1.Equals(algorithmType[mechanism]);
+        }
+
+        public static bool IsPkcs5Scheme2(
+            string algorithm)
+        {
+            string mechanism = (string)algorithms[Platform.ToUpperInvariant(algorithm)];
+
+            return mechanism != null && Pkcs5S2.Equals(algorithmType[mechanism]);
+        }
+
+        public static bool IsOpenSsl(
+            string algorithm)
+        {
+            string mechanism = (string)algorithms[Platform.ToUpperInvariant(algorithm)];
+
+            return mechanism != null && OpenSsl.Equals(algorithmType[mechanism]);
+        }
+
+        public static bool IsPbeAlgorithm(
+            string algorithm)
+        {
+            string mechanism = (string)algorithms[Platform.ToUpperInvariant(algorithm)];
+
+            return mechanism != null && algorithmType[mechanism] != null;
+        }
+
+        public static Asn1Encodable GenerateAlgorithmParameters(
+            DerObjectIdentifier algorithmOid,
+            byte[]              salt,
+            int                 iterationCount)
+        {
+            return GenerateAlgorithmParameters(algorithmOid.Id, salt, iterationCount);
+        }
+
+        public static Asn1Encodable GenerateAlgorithmParameters(
+            string  algorithm,
+            byte[]  salt,
+            int     iterationCount)
+        {
+            if (IsPkcs12(algorithm))
+            {
+                return new Pkcs12PbeParams(salt, iterationCount);
+            }
+            else if (IsPkcs5Scheme2(algorithm))
+            {
+                return new Pbkdf2Params(salt, iterationCount);
+            }
+            else
+            {
+                return new PbeParameter(salt, iterationCount);
+            }
+        }
+
+        public static ICipherParameters GenerateCipherParameters(
+            DerObjectIdentifier algorithmOid,
+            char[]              password,
+            Asn1Encodable       pbeParameters)
+        {
+            return GenerateCipherParameters(algorithmOid.Id, password, false, pbeParameters);
+        }
+
+        public static ICipherParameters GenerateCipherParameters(
+            DerObjectIdentifier algorithmOid,
+            char[]              password,
+            bool				wrongPkcs12Zero,
+            Asn1Encodable       pbeParameters)
+        {
+            return GenerateCipherParameters(algorithmOid.Id, password, wrongPkcs12Zero, pbeParameters);
+        }
+
+        public static ICipherParameters GenerateCipherParameters(
+            AlgorithmIdentifier algID,
+            char[]              password)
+        {
+            return GenerateCipherParameters(algID.ObjectID.Id, password, false, algID.Parameters);
+        }
+
+        public static ICipherParameters GenerateCipherParameters(
+            AlgorithmIdentifier algID,
+            char[]              password,
+            bool				wrongPkcs12Zero)
+        {
+            return GenerateCipherParameters(algID.ObjectID.Id, password, wrongPkcs12Zero, algID.Parameters);
+        }
+
+        public static ICipherParameters GenerateCipherParameters(
+            string          algorithm,
+            char[]          password,
+            Asn1Encodable   pbeParameters)
+        {
+            return GenerateCipherParameters(algorithm, password, false, pbeParameters);
+        }
+
+        public static ICipherParameters GenerateCipherParameters(
+            string          algorithm,
+            char[]          password,
+            bool			wrongPkcs12Zero,
+            Asn1Encodable   pbeParameters)
+        {
+            string mechanism = (string)algorithms[Platform.ToUpperInvariant(algorithm)];
+
+            byte[] keyBytes = null;
+            byte[] salt = null;
+            int iterationCount = 0;
+
+            if (IsPkcs12(mechanism))
+            {
+                Pkcs12PbeParams pbeParams = Pkcs12PbeParams.GetInstance(pbeParameters);
+                salt = pbeParams.GetIV();
+                iterationCount = pbeParams.Iterations.IntValue;
+                keyBytes = PbeParametersGenerator.Pkcs12PasswordToBytes(password, wrongPkcs12Zero);
+            }
+            else if (IsPkcs5Scheme2(mechanism))
+            {
+                // See below
+            }
+            else
+            {
+                PbeParameter pbeParams = PbeParameter.GetInstance(pbeParameters);
+                salt = pbeParams.GetSalt();
+                iterationCount = pbeParams.IterationCount.IntValue;
+                keyBytes = PbeParametersGenerator.Pkcs5PasswordToBytes(password);
+            }
+
+            ICipherParameters parameters = null;
+
+            if (IsPkcs5Scheme2(mechanism))
+            {
+                PbeS2Parameters s2p = PbeS2Parameters.GetInstance(pbeParameters.ToAsn1Object());
+                AlgorithmIdentifier encScheme = s2p.EncryptionScheme;
+                DerObjectIdentifier encOid = encScheme.ObjectID;
+                Asn1Object encParams = encScheme.Parameters.ToAsn1Object();
+
+                // TODO What about s2p.KeyDerivationFunc.ObjectID?
+                Pbkdf2Params pbeParams = Pbkdf2Params.GetInstance(s2p.KeyDerivationFunc.Parameters.ToAsn1Object());
+
+                byte[] iv;
+                if (encOid.Equals(PkcsObjectIdentifiers.RC2Cbc)) // PKCS5.B.2.3
+                {
+                    RC2CbcParameter rc2Params = RC2CbcParameter.GetInstance(encParams);
+                    iv = rc2Params.GetIV();
+                }
+                else
+                {
+                    iv = Asn1OctetString.GetInstance(encParams).GetOctets();
+                }
+
+                salt = pbeParams.GetSalt();
+                iterationCount = pbeParams.IterationCount.IntValue;
+                keyBytes = PbeParametersGenerator.Pkcs5PasswordToBytes(password);
+
+                int keyLength = pbeParams.KeyLength != null
+                    ?	pbeParams.KeyLength.IntValue * 8
+                    :	GeneratorUtilities.GetDefaultKeySize(encOid);
+
+                PbeParametersGenerator gen = MakePbeGenerator(
+                    (string)algorithmType[mechanism], null, keyBytes, salt, iterationCount);
+
+                parameters = gen.GenerateDerivedParameters(encOid.Id, keyLength);
+
+                if (iv != null)
+                {
+                    // FIXME? OpenSSL weirdness with IV of zeros (for ECB keys?)
+                    if (Arrays.AreEqual(iv, new byte[iv.Length]))
+                    {
+                        //Console.Error.Write("***** IV all 0 (length " + iv.Length + ") *****");
+                    }
+                    else
+                    {
+                        parameters = new ParametersWithIV(parameters, iv);
+                    }
+                }
+            }
+            else if (mechanism.StartsWith("PBEwithSHA-1"))
+            {
+                PbeParametersGenerator generator = MakePbeGenerator(
+                    (string) algorithmType[mechanism], new Sha1Digest(), keyBytes, salt, iterationCount);
+
+                if (mechanism.Equals("PBEwithSHA-1and128bitAES-CBC-BC"))
+                {
+                    parameters = generator.GenerateDerivedParameters("AES", 128, 128);
+                }
+                else if (mechanism.Equals("PBEwithSHA-1and192bitAES-CBC-BC"))
+                {
+                    parameters = generator.GenerateDerivedParameters("AES", 192, 128);
+                }
+                else if (mechanism.Equals("PBEwithSHA-1and256bitAES-CBC-BC"))
+                {
+                    parameters = generator.GenerateDerivedParameters("AES", 256, 128);
+                }
+                else if (mechanism.Equals("PBEwithSHA-1and128bitRC4"))
+                {
+                    parameters = generator.GenerateDerivedParameters("RC4", 128);
+                }
+                else if (mechanism.Equals("PBEwithSHA-1and40bitRC4"))
+                {
+                    parameters = generator.GenerateDerivedParameters("RC4", 40);
+                }
+                else if (mechanism.Equals("PBEwithSHA-1and3-keyDESEDE-CBC"))
+                {
+                    parameters = generator.GenerateDerivedParameters("DESEDE", 192, 64);
+                }
+                else if (mechanism.Equals("PBEwithSHA-1and2-keyDESEDE-CBC"))
+                {
+                    parameters = generator.GenerateDerivedParameters("DESEDE", 128, 64);
+                }
+                else if (mechanism.Equals("PBEwithSHA-1and128bitRC2-CBC"))
+                {
+                    parameters = generator.GenerateDerivedParameters("RC2", 128, 64);
+                }
+                else if (mechanism.Equals("PBEwithSHA-1and40bitRC2-CBC"))
+                {
+                    parameters = generator.GenerateDerivedParameters("RC2", 40, 64);
+                }
+                else if (mechanism.Equals("PBEwithSHA-1andDES-CBC"))
+                {
+                    parameters = generator.GenerateDerivedParameters("DES", 64, 64);
+                }
+                else if (mechanism.Equals("PBEwithSHA-1andRC2-CBC"))
+                {
+                    parameters = generator.GenerateDerivedParameters("RC2", 64, 64);
+                }
+            }
+            else if (mechanism.StartsWith("PBEwithSHA-256"))
+            {
+                PbeParametersGenerator generator = MakePbeGenerator(
+                    (string) algorithmType[mechanism], new Sha256Digest(), keyBytes, salt, iterationCount);
+
+                if (mechanism.Equals("PBEwithSHA-256and128bitAES-CBC-BC"))
+                {
+                    parameters = generator.GenerateDerivedParameters("AES", 128, 128);
+                }
+                else if (mechanism.Equals("PBEwithSHA-256and192bitAES-CBC-BC"))
+                {
+                    parameters = generator.GenerateDerivedParameters("AES", 192, 128);
+                }
+                else if (mechanism.Equals("PBEwithSHA-256and256bitAES-CBC-BC"))
+                {
+                    parameters = generator.GenerateDerivedParameters("AES", 256, 128);
+                }
+            }
+            else if (mechanism.StartsWith("PBEwithMD5"))
+            {
+                PbeParametersGenerator generator = MakePbeGenerator(
+                    (string)algorithmType[mechanism], new MD5Digest(), keyBytes, salt, iterationCount);
+
+                if (mechanism.Equals("PBEwithMD5andDES-CBC"))
+                {
+                    parameters = generator.GenerateDerivedParameters("DES", 64, 64);
+                }
+                else if (mechanism.Equals("PBEwithMD5andRC2-CBC"))
+                {
+                    parameters = generator.GenerateDerivedParameters("RC2", 64, 64);
+                }
+                else if (mechanism.Equals("PBEwithMD5and128bitAES-CBC-OpenSSL"))
+                {
+                    parameters = generator.GenerateDerivedParameters("AES", 128, 128);
+                }
+                else if (mechanism.Equals("PBEwithMD5and192bitAES-CBC-OpenSSL"))
+                {
+                    parameters = generator.GenerateDerivedParameters("AES", 192, 128);
+                }
+                else if (mechanism.Equals("PBEwithMD5and256bitAES-CBC-OpenSSL"))
+                {
+                    parameters = generator.GenerateDerivedParameters("AES", 256, 128);
+                }
+            }
+            else if (mechanism.StartsWith("PBEwithMD2"))
+            {
+                PbeParametersGenerator generator = MakePbeGenerator(
+                    (string)algorithmType[mechanism], new MD2Digest(), keyBytes, salt, iterationCount);
+                if (mechanism.Equals("PBEwithMD2andDES-CBC"))
+                {
+                    parameters = generator.GenerateDerivedParameters("DES", 64, 64);
+                }
+                else if (mechanism.Equals("PBEwithMD2andRC2-CBC"))
+                {
+                    parameters = generator.GenerateDerivedParameters("RC2", 64, 64);
+                }
+            }
+            else if (mechanism.StartsWith("PBEwithHmac"))
+            {
+                string digestName = mechanism.Substring("PBEwithHmac".Length);
+                IDigest digest = DigestUtilities.GetDigest(digestName);
+
+                PbeParametersGenerator generator = MakePbeGenerator(
+                    (string) algorithmType[mechanism], digest, keyBytes, salt, iterationCount);
+
+                int bitLen = digest.GetDigestSize() * 8;
+                parameters = generator.GenerateDerivedMacParameters(bitLen);
+            }
+
+            Array.Clear(keyBytes, 0, keyBytes.Length);
+
+            return FixDesParity(mechanism, parameters);
+        }
+
+        public static object CreateEngine(
+            DerObjectIdentifier algorithmOid)
+        {
+            return CreateEngine(algorithmOid.Id);
+        }
+
+        public static object CreateEngine(
+            AlgorithmIdentifier algID)
+        {
+            string algorithm = algID.ObjectID.Id;
+
+            if (IsPkcs5Scheme2(algorithm))
+            {
+                PbeS2Parameters s2p = PbeS2Parameters.GetInstance(algID.Parameters.ToAsn1Object());
+                AlgorithmIdentifier encScheme = s2p.EncryptionScheme;
+                return CipherUtilities.GetCipher(encScheme.ObjectID);
+            }
+
+            return CreateEngine(algorithm);
+        }
+
+        public static object CreateEngine(
+            string algorithm)
+        {
+            string mechanism = (string)algorithms[Platform.ToUpperInvariant(algorithm)];
+
+            if (mechanism.StartsWith("PBEwithHmac"))
+            {
+                string digestName = mechanism.Substring("PBEwithHmac".Length);
+
+                return MacUtilities.GetMac("HMAC/" + digestName);
+            }
+
+            if (mechanism.StartsWith("PBEwithMD2")
+                ||	mechanism.StartsWith("PBEwithMD5")
+                ||	mechanism.StartsWith("PBEwithSHA-1")
+                ||	mechanism.StartsWith("PBEwithSHA-256"))
+            {
+                if (mechanism.EndsWith("AES-CBC-BC") || mechanism.EndsWith("AES-CBC-OPENSSL"))
+                {
+                    return CipherUtilities.GetCipher("AES/CBC");
+                }
+
+                if (mechanism.EndsWith("DES-CBC"))
+                {
+                    return CipherUtilities.GetCipher("DES/CBC");
+                }
+
+                if (mechanism.EndsWith("DESEDE-CBC"))
+                {
+                    return CipherUtilities.GetCipher("DESEDE/CBC");
+                }
+
+                if (mechanism.EndsWith("RC2-CBC"))
+                {
+                    return CipherUtilities.GetCipher("RC2/CBC");
+                }
+
+                if (mechanism.EndsWith("RC4"))
+                {
+                    return CipherUtilities.GetCipher("RC4");
+                }
+            }
+
+            return null;
+        }
+
+        public static string GetEncodingName(
+            DerObjectIdentifier oid)
+        {
+            return (string) algorithms[oid.Id];
+        }
+
+        private static ICipherParameters FixDesParity(string mechanism, ICipherParameters parameters)
+        {
+            if (!mechanism.EndsWith("DES-CBC") & !mechanism.EndsWith("DESEDE-CBC"))
+            {
+                return parameters;
+            }
+
+            if (parameters is ParametersWithIV)
+            {
+                ParametersWithIV ivParams = (ParametersWithIV)parameters;
+                return new ParametersWithIV(FixDesParity(mechanism, ivParams.Parameters), ivParams.GetIV());
+            }
+
+            KeyParameter kParam = (KeyParameter)parameters;
+            byte[] keyBytes = kParam.GetKey();
+            DesParameters.SetOddParity(keyBytes);
+            return new KeyParameter(keyBytes);
+        }
+    }
+}
diff --git a/crypto/src/security/PrivateKeyFactory.cs b/crypto/src/security/PrivateKeyFactory.cs
new file mode 100644
index 000000000..5ebebd55a
--- /dev/null
+++ b/crypto/src/security/PrivateKeyFactory.cs
@@ -0,0 +1,221 @@
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.Sec;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Pkcs;
+
+namespace Org.BouncyCastle.Security
+{
+    public sealed class PrivateKeyFactory
+    {
+        private PrivateKeyFactory()
+        {
+        }
+
+		public static AsymmetricKeyParameter CreateKey(
+			byte[] privateKeyInfoData)
+		{
+			return CreateKey(
+				PrivateKeyInfo.GetInstance(
+					Asn1Object.FromByteArray(privateKeyInfoData)));
+		}
+
+		public static AsymmetricKeyParameter CreateKey(
+			Stream inStr)
+		{
+			return CreateKey(
+				PrivateKeyInfo.GetInstance(
+					Asn1Object.FromStream(inStr)));
+		}
+
+		public static AsymmetricKeyParameter CreateKey(
+			PrivateKeyInfo keyInfo)
+        {
+            AlgorithmIdentifier algID = keyInfo.AlgorithmID;
+			DerObjectIdentifier algOid = algID.ObjectID;
+
+			// TODO See RSAUtil.isRsaOid in Java build
+			if (algOid.Equals(PkcsObjectIdentifiers.RsaEncryption)
+				|| algOid.Equals(X509ObjectIdentifiers.IdEARsa)
+				|| algOid.Equals(PkcsObjectIdentifiers.IdRsassaPss)
+				|| algOid.Equals(PkcsObjectIdentifiers.IdRsaesOaep))
+			{
+				RsaPrivateKeyStructure keyStructure = new RsaPrivateKeyStructure(
+					Asn1Sequence.GetInstance(keyInfo.PrivateKey));
+
+				return new RsaPrivateCrtKeyParameters(
+					keyStructure.Modulus,
+					keyStructure.PublicExponent,
+					keyStructure.PrivateExponent,
+					keyStructure.Prime1,
+					keyStructure.Prime2,
+					keyStructure.Exponent1,
+					keyStructure.Exponent2,
+					keyStructure.Coefficient);
+			}
+			// TODO?
+//			else if (algOid.Equals(X9ObjectIdentifiers.DHPublicNumber))
+			else if (algOid.Equals(PkcsObjectIdentifiers.DhKeyAgreement))
+			{
+				DHParameter para = new DHParameter(
+					Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object()));
+				DerInteger derX = (DerInteger)keyInfo.PrivateKey;
+
+				BigInteger lVal = para.L;
+				int l = lVal == null ? 0 : lVal.IntValue;
+				DHParameters dhParams = new DHParameters(para.P, para.G, null, l);
+
+				return new DHPrivateKeyParameters(derX.Value, dhParams, algOid);
+			}
+			else if (algOid.Equals(OiwObjectIdentifiers.ElGamalAlgorithm))
+			{
+				ElGamalParameter  para = new ElGamalParameter(
+					Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object()));
+				DerInteger derX = (DerInteger)keyInfo.PrivateKey;
+
+				return new ElGamalPrivateKeyParameters(
+					derX.Value,
+					new ElGamalParameters(para.P, para.G));
+			}
+			else if (algOid.Equals(X9ObjectIdentifiers.IdDsa))
+			{
+				DerInteger derX = (DerInteger) keyInfo.PrivateKey;
+				Asn1Encodable ae = algID.Parameters;
+
+				DsaParameters parameters = null;
+				if (ae != null)
+				{
+					DsaParameter para = DsaParameter.GetInstance(ae.ToAsn1Object());
+					parameters = new DsaParameters(para.P, para.Q, para.G);
+				}
+
+				return new DsaPrivateKeyParameters(derX.Value, parameters);
+			}
+			else if (algOid.Equals(X9ObjectIdentifiers.IdECPublicKey))
+			{
+				X962Parameters para = new X962Parameters(algID.Parameters.ToAsn1Object());
+
+				X9ECParameters x9;
+				if (para.IsNamedCurve)
+				{
+                    x9 = ECKeyPairGenerator.FindECCurveByOid((DerObjectIdentifier)para.Parameters);
+				}
+				else
+				{
+                    x9 = new X9ECParameters((Asn1Sequence)para.Parameters);
+				}
+
+                ECPrivateKeyStructure ec = new ECPrivateKeyStructure(
+                    Asn1Sequence.GetInstance(keyInfo.PrivateKey));
+                BigInteger d = ec.GetKey();
+
+                if (para.IsNamedCurve)
+                {
+                    return new ECPrivateKeyParameters("EC", d, (DerObjectIdentifier)para.Parameters);
+                }
+
+                ECDomainParameters dParams = new ECDomainParameters(x9.Curve, x9.G, x9.N, x9.H,  x9.GetSeed());
+				return new ECPrivateKeyParameters(d, dParams);
+			}
+			else if (algOid.Equals(CryptoProObjectIdentifiers.GostR3410x2001))
+			{
+				Gost3410PublicKeyAlgParameters gostParams = new Gost3410PublicKeyAlgParameters(
+					Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object()));
+
+				ECPrivateKeyStructure ec = new ECPrivateKeyStructure(
+					Asn1Sequence.GetInstance(keyInfo.PrivateKey));
+
+				ECDomainParameters ecP = ECGost3410NamedCurves.GetByOid(gostParams.PublicKeyParamSet);
+
+				if (ecP == null)
+					return null;
+
+				return new ECPrivateKeyParameters("ECGOST3410", ec.GetKey(), gostParams.PublicKeyParamSet);
+			}
+			else if (algOid.Equals(CryptoProObjectIdentifiers.GostR3410x94))
+			{
+				Gost3410PublicKeyAlgParameters gostParams = new Gost3410PublicKeyAlgParameters(
+					Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object()));
+
+				DerOctetString derX = (DerOctetString) keyInfo.PrivateKey;
+				byte[] keyEnc = derX.GetOctets();
+				byte[] keyBytes = new byte[keyEnc.Length];
+
+				for (int i = 0; i != keyEnc.Length; i++)
+				{
+					keyBytes[i] = keyEnc[keyEnc.Length - 1 - i]; // was little endian
+				}
+
+				BigInteger x = new BigInteger(1, keyBytes);
+
+				return new Gost3410PrivateKeyParameters(x, gostParams.PublicKeyParamSet);
+			}
+			else
+			{
+				throw new SecurityUtilityException("algorithm identifier in key not recognised");
+			}
+        }
+
+		public static AsymmetricKeyParameter DecryptKey(
+			char[]					passPhrase,
+			EncryptedPrivateKeyInfo	encInfo)
+		{
+			return CreateKey(PrivateKeyInfoFactory.CreatePrivateKeyInfo(passPhrase, encInfo));
+		}
+
+		public static AsymmetricKeyParameter DecryptKey(
+			char[]	passPhrase,
+			byte[]	encryptedPrivateKeyInfoData)
+		{
+			return DecryptKey(passPhrase, Asn1Object.FromByteArray(encryptedPrivateKeyInfoData));
+		}
+
+		public static AsymmetricKeyParameter DecryptKey(
+			char[]	passPhrase,
+			Stream	encryptedPrivateKeyInfoStream)
+		{
+			return DecryptKey(passPhrase, Asn1Object.FromStream(encryptedPrivateKeyInfoStream));
+		}
+
+		private static AsymmetricKeyParameter DecryptKey(
+			char[]		passPhrase,
+			Asn1Object	asn1Object)
+		{
+			return DecryptKey(passPhrase, EncryptedPrivateKeyInfo.GetInstance(asn1Object));
+		}
+
+        public static byte[] EncryptKey(
+            DerObjectIdentifier		algorithm,
+            char[]					passPhrase,
+            byte[]					salt,
+            int						iterationCount,
+            AsymmetricKeyParameter	key)
+        {
+			return EncryptedPrivateKeyInfoFactory.CreateEncryptedPrivateKeyInfo(
+				algorithm, passPhrase, salt, iterationCount, key).GetEncoded();
+        }
+
+		public static byte[] EncryptKey(
+			string					algorithm,
+            char[]					passPhrase,
+            byte[]					salt,
+            int						iterationCount,
+            AsymmetricKeyParameter	key)
+        {
+			return EncryptedPrivateKeyInfoFactory.CreateEncryptedPrivateKeyInfo(
+				algorithm, passPhrase, salt, iterationCount, key).GetEncoded();
+        }
+	}
+}
diff --git a/crypto/src/security/PublicKeyFactory.cs b/crypto/src/security/PublicKeyFactory.cs
new file mode 100644
index 000000000..c15e24a41
--- /dev/null
+++ b/crypto/src/security/PublicKeyFactory.cs
@@ -0,0 +1,253 @@
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.Sec;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+
+namespace Org.BouncyCastle.Security
+{
+    public sealed class PublicKeyFactory
+    {
+        private PublicKeyFactory()
+        {
+        }
+
+		public static AsymmetricKeyParameter CreateKey(
+			byte[] keyInfoData)
+		{
+			return CreateKey(
+				SubjectPublicKeyInfo.GetInstance(
+					Asn1Object.FromByteArray(keyInfoData)));
+		}
+
+		public static AsymmetricKeyParameter CreateKey(
+			Stream inStr)
+		{
+			return CreateKey(
+				SubjectPublicKeyInfo.GetInstance(
+					Asn1Object.FromStream(inStr)));
+		}
+
+		public static AsymmetricKeyParameter CreateKey(
+			SubjectPublicKeyInfo keyInfo)
+        {
+            AlgorithmIdentifier algID = keyInfo.AlgorithmID;
+			DerObjectIdentifier algOid = algID.ObjectID;
+
+			// TODO See RSAUtil.isRsaOid in Java build
+			if (algOid.Equals(PkcsObjectIdentifiers.RsaEncryption)
+				|| algOid.Equals(X509ObjectIdentifiers.IdEARsa)
+				|| algOid.Equals(PkcsObjectIdentifiers.IdRsassaPss)
+				|| algOid.Equals(PkcsObjectIdentifiers.IdRsaesOaep))
+			{
+				RsaPublicKeyStructure pubKey = RsaPublicKeyStructure.GetInstance(
+					keyInfo.GetPublicKey());
+
+				return new RsaKeyParameters(false, pubKey.Modulus, pubKey.PublicExponent);
+			}
+			else if (algOid.Equals(X9ObjectIdentifiers.DHPublicNumber))
+			{
+				Asn1Sequence seq = Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object());
+
+				DHPublicKey dhPublicKey = DHPublicKey.GetInstance(keyInfo.GetPublicKey());
+
+				BigInteger y = dhPublicKey.Y.Value;
+
+				if (IsPkcsDHParam(seq))
+					return ReadPkcsDHParam(algOid, y, seq);
+
+				DHDomainParameters dhParams = DHDomainParameters.GetInstance(seq);
+
+				BigInteger p = dhParams.P.Value;
+				BigInteger g = dhParams.G.Value;
+				BigInteger q = dhParams.Q.Value;
+
+				BigInteger j = null;
+				if (dhParams.J != null)
+				{
+					j = dhParams.J.Value;
+				}
+
+				DHValidationParameters validation = null;
+				DHValidationParms dhValidationParms = dhParams.ValidationParms;
+				if (dhValidationParms != null)
+				{
+					byte[] seed = dhValidationParms.Seed.GetBytes();
+					BigInteger pgenCounter = dhValidationParms.PgenCounter.Value;
+
+					// TODO Check pgenCounter size?
+
+					validation = new DHValidationParameters(seed, pgenCounter.IntValue);
+				}
+
+				return new DHPublicKeyParameters(y, new DHParameters(p, g, q, j, validation));
+			}
+			else if (algOid.Equals(PkcsObjectIdentifiers.DhKeyAgreement))
+			{
+				Asn1Sequence seq = Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object());
+
+				DerInteger derY = (DerInteger) keyInfo.GetPublicKey();
+
+				return ReadPkcsDHParam(algOid, derY.Value, seq);
+			}
+			else if (algOid.Equals(OiwObjectIdentifiers.ElGamalAlgorithm))
+			{
+				ElGamalParameter para = new ElGamalParameter(
+					Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object()));
+				DerInteger derY = (DerInteger) keyInfo.GetPublicKey();
+
+				return new ElGamalPublicKeyParameters(
+					derY.Value,
+					new ElGamalParameters(para.P, para.G));
+			}
+			else if (algOid.Equals(X9ObjectIdentifiers.IdDsa)
+				|| algOid.Equals(OiwObjectIdentifiers.DsaWithSha1))
+			{
+				DerInteger derY = (DerInteger) keyInfo.GetPublicKey();
+				Asn1Encodable ae = algID.Parameters;
+
+				DsaParameters parameters = null;
+				if (ae != null)
+				{
+					DsaParameter para = DsaParameter.GetInstance(ae.ToAsn1Object());
+					parameters = new DsaParameters(para.P, para.Q, para.G);
+				}
+
+				return new DsaPublicKeyParameters(derY.Value, parameters);
+			}
+			else if (algOid.Equals(X9ObjectIdentifiers.IdECPublicKey))
+			{
+				X962Parameters para = new X962Parameters(algID.Parameters.ToAsn1Object());
+
+                X9ECParameters x9;
+				if (para.IsNamedCurve)
+				{
+					x9 = ECKeyPairGenerator.FindECCurveByOid((DerObjectIdentifier)para.Parameters);
+				}
+				else
+				{
+					x9 = new X9ECParameters((Asn1Sequence)para.Parameters);
+				}
+
+                Asn1OctetString key = new DerOctetString(keyInfo.PublicKeyData.GetBytes());
+                X9ECPoint derQ = new X9ECPoint(x9.Curve, key);
+                ECPoint q = derQ.Point;
+
+                if (para.IsNamedCurve)
+                {
+                    return new ECPublicKeyParameters("EC", q, (DerObjectIdentifier)para.Parameters);
+                }
+
+                ECDomainParameters dParams = new ECDomainParameters(x9.Curve, x9.G, x9.N, x9.H, x9.GetSeed());
+				return new ECPublicKeyParameters(q, dParams);
+			}
+			else if (algOid.Equals(CryptoProObjectIdentifiers.GostR3410x2001))
+			{
+				Gost3410PublicKeyAlgParameters gostParams = new Gost3410PublicKeyAlgParameters(
+					(Asn1Sequence) algID.Parameters);
+
+				Asn1OctetString key;
+				try
+				{
+					key = (Asn1OctetString) keyInfo.GetPublicKey();
+				}
+				catch (IOException)
+				{
+					throw new ArgumentException("invalid info structure in GOST3410 public key");
+				}
+
+				byte[] keyEnc = key.GetOctets();
+				byte[] x = new byte[32];
+				byte[] y = new byte[32];
+
+				for (int i = 0; i != y.Length; i++)
+				{
+					x[i] = keyEnc[32 - 1 - i];
+				}
+
+				for (int i = 0; i != x.Length; i++)
+				{
+					y[i] = keyEnc[64 - 1 - i];
+				}
+
+				ECDomainParameters ecP = ECGost3410NamedCurves.GetByOid(gostParams.PublicKeyParamSet);
+
+				if (ecP == null)
+					return null;
+
+				ECPoint q = ecP.Curve.CreatePoint(new BigInteger(1, x), new BigInteger(1, y), false);
+
+				return new ECPublicKeyParameters("ECGOST3410", q, gostParams.PublicKeyParamSet);
+			}
+			else if (algOid.Equals(CryptoProObjectIdentifiers.GostR3410x94))
+			{
+				Gost3410PublicKeyAlgParameters algParams = new Gost3410PublicKeyAlgParameters(
+					(Asn1Sequence) algID.Parameters);
+
+				DerOctetString derY;
+				try
+				{
+					derY = (DerOctetString) keyInfo.GetPublicKey();
+				}
+				catch (IOException)
+				{
+					throw new ArgumentException("invalid info structure in GOST3410 public key");
+				}
+
+				byte[] keyEnc = derY.GetOctets();
+				byte[] keyBytes = new byte[keyEnc.Length];
+
+				for (int i = 0; i != keyEnc.Length; i++)
+				{
+					keyBytes[i] = keyEnc[keyEnc.Length - 1 - i]; // was little endian
+				}
+
+				BigInteger y = new BigInteger(1, keyBytes);
+
+				return new Gost3410PublicKeyParameters(y, algParams.PublicKeyParamSet);
+			}
+            else
+            {
+                throw new SecurityUtilityException("algorithm identifier in key not recognised: " + algOid);
+            }
+        }
+
+		private static bool IsPkcsDHParam(Asn1Sequence seq)
+		{
+			if (seq.Count == 2)
+				return true;
+
+			if (seq.Count > 3)
+				return false;
+
+			DerInteger l = DerInteger.GetInstance(seq[2]);
+			DerInteger p = DerInteger.GetInstance(seq[0]);
+
+			return l.Value.CompareTo(BigInteger.ValueOf(p.Value.BitLength)) <= 0;
+		}
+
+		private static DHPublicKeyParameters ReadPkcsDHParam(DerObjectIdentifier algOid,
+			BigInteger y, Asn1Sequence seq)
+		{
+			DHParameter para = new DHParameter(seq);
+
+			BigInteger lVal = para.L;
+			int l = lVal == null ? 0 : lVal.IntValue;
+			DHParameters dhParams = new DHParameters(para.P, para.G, null, l);
+
+			return new DHPublicKeyParameters(y, dhParams, algOid);
+		}
+	}
+}
diff --git a/crypto/src/security/SecureRandom.cs b/crypto/src/security/SecureRandom.cs
new file mode 100644
index 000000000..ac9d98158
--- /dev/null
+++ b/crypto/src/security/SecureRandom.cs
@@ -0,0 +1,228 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Prng;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Security
+{
+    public class SecureRandom
+		: Random
+    {
+		// Note: all objects of this class should be deriving their random data from
+		// a single generator appropriate to the digest being used.
+		private static readonly IRandomGenerator sha1Generator = new DigestRandomGenerator(new Sha1Digest());
+		private static readonly IRandomGenerator sha256Generator = new DigestRandomGenerator(new Sha256Digest());
+
+		private static readonly SecureRandom[] master = { null };
+		private static SecureRandom Master
+		{
+			get
+			{
+				if (master[0] == null)
+				{
+					IRandomGenerator gen = sha256Generator;
+					gen = new ReversedWindowGenerator(gen, 32);
+					SecureRandom sr = master[0] = new SecureRandom(gen);
+
+					sr.SetSeed(DateTime.Now.Ticks);
+					sr.SetSeed(new ThreadedSeedGenerator().GenerateSeed(24, true));
+					sr.GenerateSeed(1 + sr.Next(32));
+				}
+
+				return master[0];
+			}
+		}
+
+		public static SecureRandom GetInstance(
+			string algorithm)
+		{
+			// TODO Compared to JDK, we don't auto-seed if the client forgets - problem?
+
+			// TODO Support all digests more generally, by stripping PRNG and calling DigestUtilities?
+			string drgName = Platform.ToUpperInvariant(algorithm);
+
+			IRandomGenerator drg = null;
+			if (drgName == "SHA1PRNG")
+			{
+				drg = sha1Generator;
+			}
+			else if (drgName == "SHA256PRNG")
+			{
+				drg = sha256Generator;
+			}
+
+			if (drg != null)
+			{
+				return new SecureRandom(drg);
+			}
+
+			throw new ArgumentException("Unrecognised PRNG algorithm: " + algorithm, "algorithm");
+		}
+
+		public static byte[] GetSeed(
+			int length)
+		{
+			return Master.GenerateSeed(length);
+		}
+
+		protected IRandomGenerator generator;
+
+		public SecureRandom()
+			: this(sha1Generator)
+        {
+			SetSeed(GetSeed(8));
+		}
+
+		public SecureRandom(
+			byte[] inSeed)
+			: this(sha1Generator)
+        {
+			SetSeed(inSeed);
+        }
+
+		/// <summary>Use the specified instance of IRandomGenerator as random source.</summary>
+		/// <remarks>
+		/// This constructor performs no seeding of either the <c>IRandomGenerator</c> or the
+		/// constructed <c>SecureRandom</c>. It is the responsibility of the client to provide
+		/// proper seed material as necessary/appropriate for the given <c>IRandomGenerator</c>
+		/// implementation.
+		/// </remarks>
+		/// <param name="generator">The source to generate all random bytes from.</param>
+		public SecureRandom(
+			IRandomGenerator generator)
+			: base(0)
+		{
+			this.generator = generator;
+		}
+
+		public virtual byte[] GenerateSeed(
+			int length)
+		{
+			SetSeed(DateTime.Now.Ticks);
+
+			byte[] rv = new byte[length];
+			NextBytes(rv);
+			return rv;
+		}
+
+		public virtual void SetSeed(
+			byte[] inSeed)
+        {
+			generator.AddSeedMaterial(inSeed);
+        }
+
+        public virtual void SetSeed(
+			long seed)
+        {
+			generator.AddSeedMaterial(seed);
+		}
+
+		public override int Next()
+		{
+			for (;;)
+			{
+				int i = NextInt() & int.MaxValue;
+
+				if (i != int.MaxValue)
+					return i;
+			}
+		}
+
+		public override int Next(
+			int maxValue)
+		{
+			if (maxValue < 2)
+			{
+				if (maxValue < 0)
+					throw new ArgumentOutOfRangeException("maxValue", "cannot be negative");
+
+				return 0;
+			}
+
+			// Test whether maxValue is a power of 2
+			if ((maxValue & -maxValue) == maxValue)
+			{
+				int val = NextInt() & int.MaxValue;
+				long lr = ((long) maxValue * (long) val) >> 31;
+				return (int) lr;
+			}
+
+			int bits, result;
+			do
+			{
+				bits = NextInt() & int.MaxValue;
+				result = bits % maxValue;
+			}
+			while (bits - result + (maxValue - 1) < 0); // Ignore results near overflow
+
+			return result;
+		}
+
+		public override int Next(
+			int	minValue,
+			int	maxValue)
+		{
+			if (maxValue <= minValue)
+			{
+				if (maxValue == minValue)
+					return minValue;
+
+				throw new ArgumentException("maxValue cannot be less than minValue");
+			}
+
+			int diff = maxValue - minValue;
+			if (diff > 0)
+				return minValue + Next(diff);
+
+			for (;;)
+			{
+				int i = NextInt();
+
+				if (i >= minValue && i < maxValue)
+					return i;
+			}
+		}
+
+		public override void NextBytes(
+			byte[] buffer)
+        {
+			generator.NextBytes(buffer);
+        }
+
+		public virtual void NextBytes(
+			byte[]	buffer,
+			int		start,
+			int		length)
+		{
+			generator.NextBytes(buffer, start, length);
+		}
+
+		private static readonly double DoubleScale = System.Math.Pow(2.0, 64.0);
+
+		public override double NextDouble()
+		{
+			return Convert.ToDouble((ulong) NextLong()) / DoubleScale;
+		}
+
+		public virtual int NextInt()
+        {
+			byte[] intBytes = new byte[4];
+            NextBytes(intBytes);
+
+			int result = 0;
+            for (int i = 0; i < 4; i++)
+            {
+                result = (result << 8) + (intBytes[i] & 0xff);
+            }
+
+			return result;
+        }
+
+		public virtual long NextLong()
+		{
+			return ((long)(uint) NextInt() << 32) | (long)(uint) NextInt();
+		}
+    }
+}
diff --git a/crypto/src/security/SecurityUtilityException.cs b/crypto/src/security/SecurityUtilityException.cs
new file mode 100644
index 000000000..02a3e806e
--- /dev/null
+++ b/crypto/src/security/SecurityUtilityException.cs
@@ -0,0 +1,36 @@
+using System;
+
+namespace Org.BouncyCastle.Security
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class SecurityUtilityException
+		: Exception
+    {
+        /**
+        * base constructor.
+        */
+        public SecurityUtilityException()
+        {
+        }
+
+		/**
+         * create a SecurityUtilityException with the given message.
+         *
+         * @param message the message to be carried with the exception.
+         */
+        public SecurityUtilityException(
+            string message)
+			: base(message)
+        {
+        }
+
+		public SecurityUtilityException(
+            string		message,
+            Exception	exception)
+			: base(message, exception)
+        {
+        }
+    }
+}
diff --git a/crypto/src/security/SignatureException.cs b/crypto/src/security/SignatureException.cs
new file mode 100644
index 000000000..cea3c59cd
--- /dev/null
+++ b/crypto/src/security/SignatureException.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Org.BouncyCastle.Security
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class SignatureException : GeneralSecurityException
+	{
+		public SignatureException() : base() { }
+		public SignatureException(string message) : base(message) { }
+		public SignatureException(string message, Exception exception) : base(message, exception) { }
+	}
+}
diff --git a/crypto/src/security/SignerUtilities.cs b/crypto/src/security/SignerUtilities.cs
new file mode 100644
index 000000000..136361532
--- /dev/null
+++ b/crypto/src/security/SignerUtilities.cs
@@ -0,0 +1,549 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.TeleTrust;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Signers;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Security
+{
+    /// <summary>
+    ///  Signer Utility class contains methods that can not be specifically grouped into other classes.
+    /// </summary>
+    public sealed class SignerUtilities
+    {
+		private SignerUtilities()
+		{
+		}
+
+		internal static readonly IDictionary algorithms = Platform.CreateHashtable();
+        internal static readonly IDictionary oids = Platform.CreateHashtable();
+
+		static SignerUtilities()
+        {
+			algorithms["MD2WITHRSA"] = "MD2withRSA";
+            algorithms["MD2WITHRSAENCRYPTION"] = "MD2withRSA";
+            algorithms[PkcsObjectIdentifiers.MD2WithRsaEncryption.Id] = "MD2withRSA";
+
+            algorithms["MD4WITHRSA"] = "MD4withRSA";
+            algorithms["MD4WITHRSAENCRYPTION"] = "MD4withRSA";
+            algorithms[PkcsObjectIdentifiers.MD4WithRsaEncryption.Id] = "MD4withRSA";
+
+            algorithms["MD5WITHRSA"] = "MD5withRSA";
+            algorithms["MD5WITHRSAENCRYPTION"] = "MD5withRSA";
+            algorithms[PkcsObjectIdentifiers.MD5WithRsaEncryption.Id] = "MD5withRSA";
+
+            algorithms["SHA1WITHRSA"] = "SHA-1withRSA";
+            algorithms["SHA1WITHRSAENCRYPTION"] = "SHA-1withRSA";
+            algorithms[PkcsObjectIdentifiers.Sha1WithRsaEncryption.Id] = "SHA-1withRSA";
+            algorithms["SHA-1WITHRSA"] = "SHA-1withRSA";
+
+            algorithms["SHA224WITHRSA"] = "SHA-224withRSA";
+            algorithms["SHA224WITHRSAENCRYPTION"] = "SHA-224withRSA";
+            algorithms[PkcsObjectIdentifiers.Sha224WithRsaEncryption.Id] = "SHA-224withRSA";
+            algorithms["SHA-224WITHRSA"] = "SHA-224withRSA";
+
+            algorithms["SHA256WITHRSA"] = "SHA-256withRSA";
+            algorithms["SHA256WITHRSAENCRYPTION"] = "SHA-256withRSA";
+            algorithms[PkcsObjectIdentifiers.Sha256WithRsaEncryption.Id] = "SHA-256withRSA";
+            algorithms["SHA-256WITHRSA"] = "SHA-256withRSA";
+
+            algorithms["SHA384WITHRSA"] = "SHA-384withRSA";
+            algorithms["SHA384WITHRSAENCRYPTION"] = "SHA-384withRSA";
+            algorithms[PkcsObjectIdentifiers.Sha384WithRsaEncryption.Id] = "SHA-384withRSA";
+            algorithms["SHA-384WITHRSA"] = "SHA-384withRSA";
+
+            algorithms["SHA512WITHRSA"] = "SHA-512withRSA";
+            algorithms["SHA512WITHRSAENCRYPTION"] = "SHA-512withRSA";
+            algorithms[PkcsObjectIdentifiers.Sha512WithRsaEncryption.Id] = "SHA-512withRSA";
+            algorithms["SHA-512WITHRSA"] = "SHA-512withRSA";
+
+			algorithms["PSSWITHRSA"] = "PSSwithRSA";
+			algorithms["RSASSA-PSS"] = "PSSwithRSA";
+			algorithms[PkcsObjectIdentifiers.IdRsassaPss.Id] = "PSSwithRSA";
+			algorithms["RSAPSS"] = "PSSwithRSA";
+
+			algorithms["SHA1WITHRSAANDMGF1"] = "SHA-1withRSAandMGF1";
+			algorithms["SHA-1WITHRSAANDMGF1"] = "SHA-1withRSAandMGF1";
+			algorithms["SHA1WITHRSA/PSS"] = "SHA-1withRSAandMGF1";
+			algorithms["SHA-1WITHRSA/PSS"] = "SHA-1withRSAandMGF1";
+
+			algorithms["SHA224WITHRSAANDMGF1"] = "SHA-224withRSAandMGF1";
+			algorithms["SHA-224WITHRSAANDMGF1"] = "SHA-224withRSAandMGF1";
+			algorithms["SHA224WITHRSA/PSS"] = "SHA-224withRSAandMGF1";
+			algorithms["SHA-224WITHRSA/PSS"] = "SHA-224withRSAandMGF1";
+
+			algorithms["SHA256WITHRSAANDMGF1"] = "SHA-256withRSAandMGF1";
+            algorithms["SHA-256WITHRSAANDMGF1"] = "SHA-256withRSAandMGF1";
+			algorithms["SHA256WITHRSA/PSS"] = "SHA-256withRSAandMGF1";
+			algorithms["SHA-256WITHRSA/PSS"] = "SHA-256withRSAandMGF1";
+
+            algorithms["SHA384WITHRSAANDMGF1"] = "SHA-384withRSAandMGF1";
+            algorithms["SHA-384WITHRSAANDMGF1"] = "SHA-384withRSAandMGF1";
+			algorithms["SHA384WITHRSA/PSS"] = "SHA-384withRSAandMGF1";
+			algorithms["SHA-384WITHRSA/PSS"] = "SHA-384withRSAandMGF1";
+
+            algorithms["SHA512WITHRSAANDMGF1"] = "SHA-512withRSAandMGF1";
+            algorithms["SHA-512WITHRSAANDMGF1"] = "SHA-512withRSAandMGF1";
+			algorithms["SHA512WITHRSA/PSS"] = "SHA-512withRSAandMGF1";
+			algorithms["SHA-512WITHRSA/PSS"] = "SHA-512withRSAandMGF1";
+
+			algorithms["RIPEMD128WITHRSA"] = "RIPEMD128withRSA";
+            algorithms["RIPEMD128WITHRSAENCRYPTION"] = "RIPEMD128withRSA";
+            algorithms[TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128.Id] = "RIPEMD128withRSA";
+
+			algorithms["RIPEMD160WITHRSA"] = "RIPEMD160withRSA";
+            algorithms["RIPEMD160WITHRSAENCRYPTION"] = "RIPEMD160withRSA";
+            algorithms[TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160.Id] = "RIPEMD160withRSA";
+
+            algorithms["RIPEMD256WITHRSA"] = "RIPEMD256withRSA";
+            algorithms["RIPEMD256WITHRSAENCRYPTION"] = "RIPEMD256withRSA";
+            algorithms[TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256.Id] = "RIPEMD256withRSA";
+
+			algorithms["NONEWITHRSA"] = "RSA";
+			algorithms["RSAWITHNONE"] = "RSA";
+			algorithms["RAWRSA"] = "RSA";
+
+			algorithms["RAWRSAPSS"] = "RAWRSASSA-PSS";
+			algorithms["NONEWITHRSAPSS"] = "RAWRSASSA-PSS";
+			algorithms["NONEWITHRSASSA-PSS"] = "RAWRSASSA-PSS";
+
+			algorithms["NONEWITHDSA"] = "NONEwithDSA";
+			algorithms["DSAWITHNONE"] = "NONEwithDSA";
+			algorithms["RAWDSA"] = "NONEwithDSA";
+
+			algorithms["DSA"] = "SHA-1withDSA";
+			algorithms["DSAWITHSHA1"] = "SHA-1withDSA";
+			algorithms["DSAWITHSHA-1"] = "SHA-1withDSA";
+			algorithms["SHA/DSA"] = "SHA-1withDSA";
+			algorithms["SHA1/DSA"] = "SHA-1withDSA";
+			algorithms["SHA-1/DSA"] = "SHA-1withDSA";
+			algorithms["SHA1WITHDSA"] = "SHA-1withDSA";
+            algorithms["SHA-1WITHDSA"] = "SHA-1withDSA";
+            algorithms[X9ObjectIdentifiers.IdDsaWithSha1.Id] = "SHA-1withDSA";
+
+			algorithms["DSAWITHSHA224"] = "SHA-224withDSA";
+			algorithms["DSAWITHSHA-224"] = "SHA-224withDSA";
+			algorithms["SHA224/DSA"] = "SHA-224withDSA";
+			algorithms["SHA-224/DSA"] = "SHA-224withDSA";
+			algorithms["SHA224WITHDSA"] = "SHA-224withDSA";
+			algorithms["SHA-224WITHDSA"] = "SHA-224withDSA";
+			algorithms[NistObjectIdentifiers.DsaWithSha224.Id] = "SHA-224withDSA";
+
+			algorithms["DSAWITHSHA256"] = "SHA-256withDSA";
+			algorithms["DSAWITHSHA-256"] = "SHA-256withDSA";
+			algorithms["SHA256/DSA"] = "SHA-256withDSA";
+			algorithms["SHA-256/DSA"] = "SHA-256withDSA";
+			algorithms["SHA256WITHDSA"] = "SHA-256withDSA";
+			algorithms["SHA-256WITHDSA"] = "SHA-256withDSA";
+			algorithms[NistObjectIdentifiers.DsaWithSha256.Id] = "SHA-256withDSA";
+
+			algorithms["DSAWITHSHA384"] = "SHA-384withDSA";
+			algorithms["DSAWITHSHA-384"] = "SHA-384withDSA";
+			algorithms["SHA384/DSA"] = "SHA-384withDSA";
+			algorithms["SHA-384/DSA"] = "SHA-384withDSA";
+			algorithms["SHA384WITHDSA"] = "SHA-384withDSA";
+			algorithms["SHA-384WITHDSA"] = "SHA-384withDSA";
+			algorithms[NistObjectIdentifiers.DsaWithSha384.Id] = "SHA-384withDSA";
+
+			algorithms["DSAWITHSHA512"] = "SHA-512withDSA";
+			algorithms["DSAWITHSHA-512"] = "SHA-512withDSA";
+			algorithms["SHA512/DSA"] = "SHA-512withDSA";
+			algorithms["SHA-512/DSA"] = "SHA-512withDSA";
+			algorithms["SHA512WITHDSA"] = "SHA-512withDSA";
+			algorithms["SHA-512WITHDSA"] = "SHA-512withDSA";
+			algorithms[NistObjectIdentifiers.DsaWithSha512.Id] = "SHA-512withDSA";
+
+			algorithms["NONEWITHECDSA"] = "NONEwithECDSA";
+			algorithms["ECDSAWITHNONE"] = "NONEwithECDSA";
+
+			algorithms["ECDSA"] = "SHA-1withECDSA";
+			algorithms["SHA1/ECDSA"] = "SHA-1withECDSA";
+			algorithms["SHA-1/ECDSA"] = "SHA-1withECDSA";
+			algorithms["ECDSAWITHSHA1"] = "SHA-1withECDSA";
+			algorithms["ECDSAWITHSHA-1"] = "SHA-1withECDSA";
+			algorithms["SHA1WITHECDSA"] = "SHA-1withECDSA";
+            algorithms["SHA-1WITHECDSA"] = "SHA-1withECDSA";
+			algorithms[X9ObjectIdentifiers.ECDsaWithSha1.Id] = "SHA-1withECDSA";
+			algorithms[TeleTrusTObjectIdentifiers.ECSignWithSha1.Id] = "SHA-1withECDSA";
+
+			algorithms["SHA224/ECDSA"] = "SHA-224withECDSA";
+			algorithms["SHA-224/ECDSA"] = "SHA-224withECDSA";
+			algorithms["ECDSAWITHSHA224"] = "SHA-224withECDSA";
+			algorithms["ECDSAWITHSHA-224"] = "SHA-224withECDSA";
+			algorithms["SHA224WITHECDSA"] = "SHA-224withECDSA";
+			algorithms["SHA-224WITHECDSA"] = "SHA-224withECDSA";
+			algorithms[X9ObjectIdentifiers.ECDsaWithSha224.Id] = "SHA-224withECDSA";
+
+			algorithms["SHA256/ECDSA"] = "SHA-256withECDSA";
+			algorithms["SHA-256/ECDSA"] = "SHA-256withECDSA";
+			algorithms["ECDSAWITHSHA256"] = "SHA-256withECDSA";
+			algorithms["ECDSAWITHSHA-256"] = "SHA-256withECDSA";
+			algorithms["SHA256WITHECDSA"] = "SHA-256withECDSA";
+			algorithms["SHA-256WITHECDSA"] = "SHA-256withECDSA";
+			algorithms[X9ObjectIdentifiers.ECDsaWithSha256.Id] = "SHA-256withECDSA";
+
+			algorithms["SHA384/ECDSA"] = "SHA-384withECDSA";
+			algorithms["SHA-384/ECDSA"] = "SHA-384withECDSA";
+			algorithms["ECDSAWITHSHA384"] = "SHA-384withECDSA";
+			algorithms["ECDSAWITHSHA-384"] = "SHA-384withECDSA";
+			algorithms["SHA384WITHECDSA"] = "SHA-384withECDSA";
+			algorithms["SHA-384WITHECDSA"] = "SHA-384withECDSA";
+			algorithms[X9ObjectIdentifiers.ECDsaWithSha384.Id] = "SHA-384withECDSA";
+
+			algorithms["SHA512/ECDSA"] = "SHA-512withECDSA";
+			algorithms["SHA-512/ECDSA"] = "SHA-512withECDSA";
+			algorithms["ECDSAWITHSHA512"] = "SHA-512withECDSA";
+			algorithms["ECDSAWITHSHA-512"] = "SHA-512withECDSA";
+			algorithms["SHA512WITHECDSA"] = "SHA-512withECDSA";
+			algorithms["SHA-512WITHECDSA"] = "SHA-512withECDSA";
+			algorithms[X9ObjectIdentifiers.ECDsaWithSha512.Id] = "SHA-512withECDSA";
+
+			algorithms["RIPEMD160/ECDSA"] = "RIPEMD160withECDSA";
+			algorithms["SHA-512/ECDSA"] = "RIPEMD160withECDSA";
+			algorithms["ECDSAWITHRIPEMD160"] = "RIPEMD160withECDSA";
+			algorithms["ECDSAWITHRIPEMD160"] = "RIPEMD160withECDSA";
+			algorithms["RIPEMD160WITHECDSA"] = "RIPEMD160withECDSA";
+			algorithms["RIPEMD160WITHECDSA"] = "RIPEMD160withECDSA";
+			algorithms[TeleTrusTObjectIdentifiers.ECSignWithRipeMD160.Id] = "RIPEMD160withECDSA";
+
+			algorithms["GOST-3410"] = "GOST3410";
+			algorithms["GOST-3410-94"] = "GOST3410";
+			algorithms["GOST3411WITHGOST3410"] = "GOST3410";
+			algorithms[CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94.Id] = "GOST3410";
+
+			algorithms["ECGOST-3410"] = "ECGOST3410";
+			algorithms["ECGOST-3410-2001"] = "ECGOST3410";
+			algorithms["GOST3411WITHECGOST3410"] = "ECGOST3410";
+			algorithms[CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001.Id] = "ECGOST3410";
+
+
+
+			oids["MD2withRSA"] = PkcsObjectIdentifiers.MD2WithRsaEncryption;
+            oids["MD4withRSA"] = PkcsObjectIdentifiers.MD4WithRsaEncryption;
+            oids["MD5withRSA"] = PkcsObjectIdentifiers.MD5WithRsaEncryption;
+
+            oids["SHA-1withRSA"] = PkcsObjectIdentifiers.Sha1WithRsaEncryption;
+            oids["SHA-224withRSA"] = PkcsObjectIdentifiers.Sha224WithRsaEncryption;
+            oids["SHA-256withRSA"] = PkcsObjectIdentifiers.Sha256WithRsaEncryption;
+            oids["SHA-384withRSA"] = PkcsObjectIdentifiers.Sha384WithRsaEncryption;
+            oids["SHA-512withRSA"] = PkcsObjectIdentifiers.Sha512WithRsaEncryption;
+
+			oids["PSSwithRSA"] = PkcsObjectIdentifiers.IdRsassaPss;
+			oids["SHA-1withRSAandMGF1"] = PkcsObjectIdentifiers.IdRsassaPss;
+			oids["SHA-224withRSAandMGF1"] = PkcsObjectIdentifiers.IdRsassaPss;
+			oids["SHA-256withRSAandMGF1"] = PkcsObjectIdentifiers.IdRsassaPss;
+			oids["SHA-384withRSAandMGF1"] = PkcsObjectIdentifiers.IdRsassaPss;
+			oids["SHA-512withRSAandMGF1"] = PkcsObjectIdentifiers.IdRsassaPss;
+
+			oids["RIPEMD128withRSA"] = TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128;
+			oids["RIPEMD160withRSA"] = TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160;
+			oids["RIPEMD256withRSA"] = TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256;
+
+			oids["SHA-1withDSA"] = X9ObjectIdentifiers.IdDsaWithSha1;
+
+			oids["SHA-1withECDSA"] = X9ObjectIdentifiers.ECDsaWithSha1;
+			oids["SHA-224withECDSA"] = X9ObjectIdentifiers.ECDsaWithSha224;
+			oids["SHA-256withECDSA"] = X9ObjectIdentifiers.ECDsaWithSha256;
+			oids["SHA-384withECDSA"] = X9ObjectIdentifiers.ECDsaWithSha384;
+			oids["SHA-512withECDSA"] = X9ObjectIdentifiers.ECDsaWithSha512;
+
+			oids["GOST3410"] = CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94;
+			oids["ECGOST3410"] = CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001;
+		}
+
+		/// <summary>
+        /// Returns a ObjectIdentifier for a give encoding.
+        /// </summary>
+        /// <param name="mechanism">A string representation of the encoding.</param>
+        /// <returns>A DerObjectIdentifier, null if the Oid is not available.</returns>
+		// TODO Don't really want to support this
+        public static DerObjectIdentifier GetObjectIdentifier(
+			string mechanism)
+        {
+			if (mechanism == null)
+				throw new ArgumentNullException("mechanism");
+
+			mechanism = Platform.ToUpperInvariant(mechanism);
+			string aliased = (string) algorithms[mechanism];
+
+			if (aliased != null)
+				mechanism = aliased;
+
+			return (DerObjectIdentifier) oids[mechanism];
+		}
+
+		public static ICollection Algorithms
+        {
+            get { return oids.Keys; }
+        }
+
+		public static Asn1Encodable GetDefaultX509Parameters(
+			DerObjectIdentifier id)
+		{
+			return GetDefaultX509Parameters(id.Id);
+		}
+
+		public static Asn1Encodable GetDefaultX509Parameters(
+			string algorithm)
+		{
+			if (algorithm == null)
+				throw new ArgumentNullException("algorithm");
+
+			algorithm = Platform.ToUpperInvariant(algorithm);
+
+			string mechanism = (string) algorithms[algorithm];
+
+			if (mechanism == null)
+				mechanism = algorithm;
+
+			if (mechanism == "PSSwithRSA")
+			{
+				// TODO The Sha1Digest here is a default. In JCE version, the actual digest
+				// to be used can be overridden by subsequent parameter settings.
+				return GetPssX509Parameters("SHA-1");
+			}
+
+			if (mechanism.EndsWith("withRSAandMGF1"))
+			{
+				string digestName = mechanism.Substring(0, mechanism.Length - "withRSAandMGF1".Length);
+				return GetPssX509Parameters(digestName);
+			}
+
+			return DerNull.Instance;
+		}
+
+		private static Asn1Encodable GetPssX509Parameters(
+			string	digestName)
+		{
+			AlgorithmIdentifier hashAlgorithm = new AlgorithmIdentifier(
+				DigestUtilities.GetObjectIdentifier(digestName), DerNull.Instance);
+
+			// TODO Is it possible for the MGF hash alg to be different from the PSS one?
+			AlgorithmIdentifier maskGenAlgorithm = new AlgorithmIdentifier(
+				PkcsObjectIdentifiers.IdMgf1, hashAlgorithm);
+
+			int saltLen = DigestUtilities.GetDigest(digestName).GetDigestSize();
+			return new RsassaPssParameters(hashAlgorithm, maskGenAlgorithm,
+				new DerInteger(saltLen), new DerInteger(1));
+		}
+
+		public static ISigner GetSigner(
+			DerObjectIdentifier id)
+        {
+            return GetSigner(id.Id);
+        }
+
+		public static ISigner GetSigner(
+			string algorithm)
+        {
+			if (algorithm == null)
+				throw new ArgumentNullException("algorithm");
+
+            algorithm = Platform.ToUpperInvariant(algorithm);
+
+			string mechanism = (string) algorithms[algorithm];
+
+			if (mechanism == null)
+				mechanism = algorithm;
+
+			if (mechanism.Equals("RSA"))
+			{
+				return (new RsaDigestSigner(new NullDigest()));
+			}
+			if (mechanism.Equals("MD2withRSA"))
+            {
+                return (new RsaDigestSigner(new MD2Digest()));
+            }
+            if (mechanism.Equals("MD4withRSA"))
+            {
+                return (new RsaDigestSigner(new MD4Digest()));
+            }
+            if (mechanism.Equals("MD5withRSA"))
+            {
+                return (new RsaDigestSigner(new MD5Digest()));
+            }
+            if (mechanism.Equals("SHA-1withRSA"))
+            {
+                return (new RsaDigestSigner(new Sha1Digest()));
+            }
+            if (mechanism.Equals("SHA-224withRSA"))
+            {
+                return (new RsaDigestSigner(new Sha224Digest()));
+            }
+            if (mechanism.Equals("SHA-256withRSA"))
+            {
+                return (new RsaDigestSigner(new Sha256Digest()));
+            }
+            if (mechanism.Equals("SHA-384withRSA"))
+            {
+                return (new RsaDigestSigner(new Sha384Digest()));
+            }
+            if (mechanism.Equals("SHA-512withRSA"))
+            {
+                return (new RsaDigestSigner(new Sha512Digest()));
+            }
+			if (mechanism.Equals("RIPEMD128withRSA"))
+            {
+                return (new RsaDigestSigner(new RipeMD128Digest()));
+            }
+            if (mechanism.Equals("RIPEMD160withRSA"))
+            {
+                return (new RsaDigestSigner(new RipeMD160Digest()));
+            }
+            if (mechanism.Equals("RIPEMD256withRSA"))
+            {
+                return (new RsaDigestSigner(new RipeMD256Digest()));
+            }
+
+			if (mechanism.Equals("RAWRSASSA-PSS"))
+			{
+				// TODO Add support for other parameter settings
+				return PssSigner.CreateRawSigner(new RsaBlindedEngine(), new Sha1Digest());
+			}
+			if (mechanism.Equals("PSSwithRSA"))
+			{
+				// TODO The Sha1Digest here is a default. In JCE version, the actual digest
+				// to be used can be overridden by subsequent parameter settings.
+				return (new PssSigner(new RsaBlindedEngine(), new Sha1Digest()));
+			}
+			if (mechanism.Equals("SHA-1withRSAandMGF1"))
+			{
+				return (new PssSigner(new RsaBlindedEngine(), new Sha1Digest()));
+			}
+			if (mechanism.Equals("SHA-224withRSAandMGF1"))
+			{
+				return (new PssSigner(new RsaBlindedEngine(), new Sha224Digest()));
+			}
+			if (mechanism.Equals("SHA-256withRSAandMGF1"))
+			{
+				return (new PssSigner(new RsaBlindedEngine(), new Sha256Digest()));
+			}
+			if (mechanism.Equals("SHA-384withRSAandMGF1"))
+			{
+				return (new PssSigner(new RsaBlindedEngine(), new Sha384Digest()));
+			}
+			if (mechanism.Equals("SHA-512withRSAandMGF1"))
+			{
+				return (new PssSigner(new RsaBlindedEngine(), new Sha512Digest()));
+			}
+
+			if (mechanism.Equals("NONEwithDSA"))
+			{
+				return (new DsaDigestSigner(new DsaSigner(), new NullDigest()));
+			}
+			if (mechanism.Equals("SHA-1withDSA"))
+            {
+                return (new DsaDigestSigner(new DsaSigner(), new Sha1Digest()));
+            }
+			if (mechanism.Equals("SHA-224withDSA"))
+			{
+				return (new DsaDigestSigner(new DsaSigner(), new Sha224Digest()));
+			}
+			if (mechanism.Equals("SHA-256withDSA"))
+			{
+				return (new DsaDigestSigner(new DsaSigner(), new Sha256Digest()));
+			}
+			if (mechanism.Equals("SHA-384withDSA"))
+			{
+				return (new DsaDigestSigner(new DsaSigner(), new Sha384Digest()));
+			}
+			if (mechanism.Equals("SHA-512withDSA"))
+			{
+				return (new DsaDigestSigner(new DsaSigner(), new Sha512Digest()));
+			}
+
+			if (mechanism.Equals("NONEwithECDSA"))
+			{
+				return (new DsaDigestSigner(new ECDsaSigner(), new NullDigest()));
+			}
+			if (mechanism.Equals("SHA-1withECDSA"))
+            {
+                return (new DsaDigestSigner(new ECDsaSigner(), new Sha1Digest()));
+            }
+			if (mechanism.Equals("SHA-224withECDSA"))
+			{
+				return (new DsaDigestSigner(new ECDsaSigner(), new Sha224Digest()));
+			}
+			if (mechanism.Equals("SHA-256withECDSA"))
+			{
+				return (new DsaDigestSigner(new ECDsaSigner(), new Sha256Digest()));
+			}
+			if (mechanism.Equals("SHA-384withECDSA"))
+			{
+				return (new DsaDigestSigner(new ECDsaSigner(), new Sha384Digest()));
+			}
+			if (mechanism.Equals("SHA-512withECDSA"))
+			{
+				return (new DsaDigestSigner(new ECDsaSigner(), new Sha512Digest()));
+			}
+
+			if (mechanism.Equals("RIPEMD160withECDSA"))
+			{
+				return (new DsaDigestSigner(new ECDsaSigner(), new RipeMD160Digest()));
+			}
+
+			if (mechanism.Equals("SHA1WITHECNR"))
+			{
+				return (new DsaDigestSigner(new ECNRSigner(), new Sha1Digest()));
+			}
+			if (mechanism.Equals("SHA224WITHECNR"))
+			{
+				return (new DsaDigestSigner(new ECNRSigner(), new Sha224Digest()));
+			}
+			if (mechanism.Equals("SHA256WITHECNR"))
+			{
+				return (new DsaDigestSigner(new ECNRSigner(), new Sha256Digest()));
+			}
+			if (mechanism.Equals("SHA384WITHECNR"))
+			{
+				return (new DsaDigestSigner(new ECNRSigner(), new Sha384Digest()));
+			}
+			if (mechanism.Equals("SHA512WITHECNR"))
+			{
+				return (new DsaDigestSigner(new ECNRSigner(), new Sha512Digest()));
+			}
+
+			if (mechanism.Equals("GOST3410"))
+			{
+				return new Gost3410DigestSigner(new Gost3410Signer(), new Gost3411Digest());
+			}
+			if (mechanism.Equals("ECGOST3410"))
+			{
+				return new Gost3410DigestSigner(new ECGost3410Signer(), new Gost3411Digest());
+			}
+
+			if (mechanism.Equals("SHA1WITHRSA/ISO9796-2"))
+			{
+				return new Iso9796d2Signer(new RsaBlindedEngine(), new Sha1Digest(), true);
+			}
+			if (mechanism.Equals("MD5WITHRSA/ISO9796-2"))
+			{
+				return new Iso9796d2Signer(new RsaBlindedEngine(), new MD5Digest(), true);
+			}
+			if (mechanism.Equals("RIPEMD160WITHRSA/ISO9796-2"))
+			{
+				return new Iso9796d2Signer(new RsaBlindedEngine(), new RipeMD160Digest(), true);
+			}
+
+			throw new SecurityUtilityException("Signer " + algorithm + " not recognised.");
+        }
+
+        public static string GetEncodingName(
+			DerObjectIdentifier oid)
+        {
+            return (string) algorithms[oid.Id];
+        }
+    }
+}
diff --git a/crypto/src/security/WrapperUtilities.cs b/crypto/src/security/WrapperUtilities.cs
new file mode 100644
index 000000000..ce31ea519
--- /dev/null
+++ b/crypto/src/security/WrapperUtilities.cs
@@ -0,0 +1,153 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Kisa;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Ntt;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Security
+{
+    /// <remarks>
+    ///  Utility class for creating IWrapper objects from their names/Oids
+    /// </remarks>
+    public sealed class WrapperUtilities
+    {
+        private enum WrapAlgorithm { AESWRAP, CAMELLIAWRAP, DESEDEWRAP, RC2WRAP, SEEDWRAP,
+            DESEDERFC3211WRAP, AESRFC3211WRAP, CAMELLIARFC3211WRAP };
+
+        private WrapperUtilities()
+        {
+        }
+
+        private static readonly IDictionary algorithms = Platform.CreateHashtable();
+        //private static readonly IDictionary oids = Platform.CreateHashtable();
+
+        static WrapperUtilities()
+        {
+            // Signal to obfuscation tools not to change enum constants
+            ((WrapAlgorithm)Enums.GetArbitraryValue(typeof(WrapAlgorithm))).ToString();
+
+            algorithms[NistObjectIdentifiers.IdAes128Wrap.Id] = "AESWRAP";
+            algorithms[NistObjectIdentifiers.IdAes192Wrap.Id] = "AESWRAP";
+            algorithms[NistObjectIdentifiers.IdAes256Wrap.Id] = "AESWRAP";
+
+            algorithms[NttObjectIdentifiers.IdCamellia128Wrap.Id] = "CAMELLIAWRAP";
+            algorithms[NttObjectIdentifiers.IdCamellia192Wrap.Id] = "CAMELLIAWRAP";
+            algorithms[NttObjectIdentifiers.IdCamellia256Wrap.Id] = "CAMELLIAWRAP";
+
+            algorithms[PkcsObjectIdentifiers.IdAlgCms3DesWrap.Id] = "DESEDEWRAP";
+            algorithms["TDEAWRAP"] = "DESEDEWRAP";
+
+            algorithms[PkcsObjectIdentifiers.IdAlgCmsRC2Wrap.Id] = "RC2WRAP";
+
+            algorithms[KisaObjectIdentifiers.IdNpkiAppCmsSeedWrap.Id] = "SEEDWRAP";
+        }
+
+        public static IWrapper GetWrapper(
+            DerObjectIdentifier oid)
+        {
+            return GetWrapper(oid.Id);
+        }
+
+        public static IWrapper GetWrapper(
+            string algorithm)
+        {
+            string upper = Platform.ToUpperInvariant(algorithm);
+            string mechanism = (string)algorithms[upper];
+
+            if (mechanism == null)
+            {
+                mechanism = upper;
+            }
+
+            try
+            {
+                WrapAlgorithm wrapAlgorithm = (WrapAlgorithm)Enums.GetEnumValue(
+                    typeof(WrapAlgorithm), mechanism);
+
+                switch (wrapAlgorithm)
+                {
+                    case WrapAlgorithm.AESWRAP:				return new AesWrapEngine();
+                    case WrapAlgorithm.CAMELLIAWRAP:		return new CamelliaWrapEngine();
+                    case WrapAlgorithm.DESEDEWRAP:			return new DesEdeWrapEngine();
+                    case WrapAlgorithm.RC2WRAP:				return new RC2WrapEngine();
+                    case WrapAlgorithm.SEEDWRAP:			return new SeedWrapEngine();
+                    case WrapAlgorithm.DESEDERFC3211WRAP:	return new Rfc3211WrapEngine(new DesEdeEngine());
+                    case WrapAlgorithm.AESRFC3211WRAP:		return new Rfc3211WrapEngine(new AesFastEngine());
+                    case WrapAlgorithm.CAMELLIARFC3211WRAP:	return new Rfc3211WrapEngine(new CamelliaEngine());
+                }
+            }
+            catch (ArgumentException)
+            {
+            }
+
+            // Create an IBufferedCipher and use it as IWrapper (via BufferedCipherWrapper)
+            IBufferedCipher blockCipher = CipherUtilities.GetCipher(algorithm);
+
+            if (blockCipher != null)
+                return new BufferedCipherWrapper(blockCipher);
+
+            throw new SecurityUtilityException("Wrapper " + algorithm + " not recognised.");
+        }
+
+        public static string GetAlgorithmName(
+            DerObjectIdentifier oid)
+        {
+            return (string) algorithms[oid.Id];
+        }
+
+        private class BufferedCipherWrapper
+            : IWrapper
+        {
+            private readonly IBufferedCipher cipher;
+            private bool forWrapping;
+
+            public BufferedCipherWrapper(
+                IBufferedCipher cipher)
+            {
+                this.cipher = cipher;
+            }
+
+            public string AlgorithmName
+            {
+                get { return cipher.AlgorithmName; }
+            }
+
+            public void Init(
+                bool				forWrapping,
+                ICipherParameters	parameters)
+            {
+                this.forWrapping = forWrapping;
+
+                cipher.Init(forWrapping, parameters);
+            }
+
+            public byte[] Wrap(
+                byte[]	input,
+                int		inOff,
+                int		length)
+            {
+                if (!forWrapping)
+                    throw new InvalidOperationException("Not initialised for wrapping");
+
+                return cipher.DoFinal(input, inOff, length);
+            }
+
+            public byte[] Unwrap(
+                byte[]	input,
+                int		inOff,
+                int		length)
+            {
+                if (forWrapping)
+                    throw new InvalidOperationException("Not initialised for unwrapping");
+
+                return cipher.DoFinal(input, inOff, length);
+            }
+        }
+    }
+}
diff --git a/crypto/src/security/cert/CertificateEncodingException.cs b/crypto/src/security/cert/CertificateEncodingException.cs
new file mode 100644
index 000000000..a2909b0d5
--- /dev/null
+++ b/crypto/src/security/cert/CertificateEncodingException.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Org.BouncyCastle.Security.Certificates
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class CertificateEncodingException : CertificateException
+	{
+		public CertificateEncodingException() : base() { }
+		public CertificateEncodingException(string msg) : base(msg) { }
+		public CertificateEncodingException(string msg, Exception e) : base(msg, e) { }
+	}
+}
diff --git a/crypto/src/security/cert/CertificateException.cs b/crypto/src/security/cert/CertificateException.cs
new file mode 100644
index 000000000..441c598e4
--- /dev/null
+++ b/crypto/src/security/cert/CertificateException.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Org.BouncyCastle.Security.Certificates
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class CertificateException : GeneralSecurityException
+	{
+		public CertificateException() : base() { }
+		public CertificateException(string message) : base(message) { }
+		public CertificateException(string message, Exception exception) : base(message, exception) { }
+	}
+}
diff --git a/crypto/src/security/cert/CertificateExpiredException.cs b/crypto/src/security/cert/CertificateExpiredException.cs
new file mode 100644
index 000000000..c893c07ee
--- /dev/null
+++ b/crypto/src/security/cert/CertificateExpiredException.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Org.BouncyCastle.Security.Certificates
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class CertificateExpiredException : CertificateException
+	{
+		public CertificateExpiredException() : base() { }
+		public CertificateExpiredException(string message) : base(message) { }
+		public CertificateExpiredException(string message, Exception exception) : base(message, exception) { }
+	}
+}
diff --git a/crypto/src/security/cert/CertificateNotYetValidException.cs b/crypto/src/security/cert/CertificateNotYetValidException.cs
new file mode 100644
index 000000000..a0081ce23
--- /dev/null
+++ b/crypto/src/security/cert/CertificateNotYetValidException.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Org.BouncyCastle.Security.Certificates
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class CertificateNotYetValidException : CertificateException
+	{
+		public CertificateNotYetValidException() : base() { }
+		public CertificateNotYetValidException(string message) : base(message) { }
+		public CertificateNotYetValidException(string message, Exception exception) : base(message, exception) { }
+	}
+}
diff --git a/crypto/src/security/cert/CertificateParsingException.cs b/crypto/src/security/cert/CertificateParsingException.cs
new file mode 100644
index 000000000..8d8ed1e92
--- /dev/null
+++ b/crypto/src/security/cert/CertificateParsingException.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Org.BouncyCastle.Security.Certificates
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class CertificateParsingException : CertificateException
+	{
+		public CertificateParsingException() : base() { }
+		public CertificateParsingException(string message) : base(message) { }
+		public CertificateParsingException(string message, Exception exception) : base(message, exception) { }
+	}
+}
diff --git a/crypto/src/security/cert/CrlException.cs b/crypto/src/security/cert/CrlException.cs
new file mode 100644
index 000000000..0df007b1e
--- /dev/null
+++ b/crypto/src/security/cert/CrlException.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Org.BouncyCastle.Security.Certificates
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class CrlException : GeneralSecurityException
+	{
+		public CrlException() : base() { }
+		public CrlException(string msg) : base(msg) {}
+		public CrlException(string msg, Exception e) : base(msg, e) {}
+	}
+}