summary refs log tree commit diff
path: root/crypto
diff options
context:
space:
mode:
authorOren Novotny <oren@novotny.org>2019-01-25 16:18:07 -0500
committerOren Novotny <oren@novotny.org>2019-01-25 16:18:07 -0500
commitba3b6a80aebde476efacd352cdd2b20df0a1da3f (patch)
tree19071f7b74370235299e17ea1f55a7f6eaf9f8d4 /crypto
parentifdef's to support PORTABLE netstandard1/1.3 surface area (diff)
parentremoved unnecessary extra ECGOST3410 class (diff)
downloadBouncyCastle.NET-ed25519-ba3b6a80aebde476efacd352cdd2b20df0a1da3f.tar.xz
merge from master
Diffstat (limited to 'crypto')
-rw-r--r--crypto/Readme.html7
-rw-r--r--crypto/src/asn1/misc/MiscObjectIdentifiers.cs2
-rw-r--r--crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs3
-rw-r--r--crypto/src/cmp/RevocationDetails.cs39
-rw-r--r--crypto/src/cmp/RevocationDetailsBuilder.cs58
-rw-r--r--crypto/src/cms/CMSEnvelopedDataGenerator.cs71
-rw-r--r--crypto/src/cms/CMSEnvelopedGenerator.cs10
-rw-r--r--crypto/src/cms/CMSProcessableByteArray.cs17
-rw-r--r--crypto/src/cms/EnvelopedDataHelper.cs123
-rw-r--r--crypto/src/cms/KeyTransRecipientInfoGenerator.cs171
-rw-r--r--crypto/src/cms/KeyTransRecipientInformation.cs14
-rw-r--r--crypto/src/cms/RecipientInfoGenerator.cs2
-rw-r--r--crypto/src/crmf/CertificateRequestMessage.cs4
-rw-r--r--crypto/src/crmf/CertificateRequestMessageBuilder.cs9
-rw-r--r--crypto/src/crmf/EncryptedValueBuilder.cs1
-rw-r--r--crypto/src/crmf/PkiArchiveControlBuilder.cs58
-rw-r--r--crypto/src/crypto/SimpleBlockResult.cs51
-rw-r--r--crypto/src/crypto/digests/GOST3411_2012Digest.cs6
-rw-r--r--crypto/src/crypto/digests/GOST3411_2012_256Digest.cs8
-rw-r--r--crypto/src/crypto/digests/GOST3411_2012_512Digest.cs8
-rw-r--r--crypto/src/crypto/operators/Asn1CipherBuilder.cs100
-rw-r--r--crypto/src/crypto/operators/Asn1KeyWrapper.cs168
-rw-r--r--crypto/src/crypto/operators/Asn1Signature.cs4
-rw-r--r--crypto/src/crypto/operators/CmsContentEncryptorBuilder.cs64
-rw-r--r--crypto/src/crypto/operators/CmsKeyTransRecipientInfoGenerator.cs38
-rw-r--r--crypto/src/crypto/parameters/ECGOST3410Parameters.cs6
-rw-r--r--crypto/src/crypto/signers/ECGOST3410Signer.cs15
-rw-r--r--crypto/src/crypto/signers/EcGost3410_2012Signer.cs153
-rw-r--r--crypto/src/crypto/util/AlgorithmIdentifierFactory.cs105
-rw-r--r--crypto/src/crypto/util/CipherFactory.cs151
-rw-r--r--crypto/src/crypto/util/CipherKeyGeneratorFactory.cs101
-rw-r--r--crypto/src/pkcs/PrivateKeyInfoFactory.cs4
-rw-r--r--crypto/src/security/DigestUtilities.cs4
-rw-r--r--crypto/src/security/PrivateKeyFactory.cs12
-rw-r--r--crypto/src/security/PublicKeyFactory.cs4
-rw-r--r--crypto/src/x509/SubjectPublicKeyInfoFactory.cs4
-rw-r--r--crypto/test/src/crmf/test/CrmfTest.cs188
-rw-r--r--crypto/test/src/crypto/test/ECGOST3410_2012Test.cs64
-rw-r--r--crypto/test/src/crypto/test/EGOST3410_2012SignatureTest.cs18
-rw-r--r--crypto/test/src/crypto/test/GOST3411_2012_256DigestTest.cs6
-rw-r--r--crypto/test/src/crypto/test/GOST3411_2012_512DigestTest.cs6
41 files changed, 1565 insertions, 312 deletions
diff --git a/crypto/Readme.html b/crypto/Readme.html
index d63974c66..9491b7d98 100644
--- a/crypto/Readme.html
+++ b/crypto/Readme.html
@@ -296,6 +296,13 @@ We state, where EC MQV has not otherwise been disabled or removed:
 		<hr style="WIDTH: 100%; HEIGHT: 2px">
 		<h3><a class="mozTocH3" name="mozTocId3413"></a>Notes:</h3>
 
+        <h4><a class="mozTocH4" name="mozTocId85318"></a>Release 1.8.5, 2019</h4>
+        <h5>Additional Features and Functionality</h5>
+        <ul>
+        <li>Supported added for encoding and decoding of GOST3410-2012 keys</li>
+        <li>Basic support added for CMP (RFC 4210) and CRMF (RFC 4211), including the PKI archive control.</li>
+        </ul>
+
         <h4><a class="mozTocH4" name="mozTocId85318"></a>Release 1.8.4, Saturday October 27, 2018</h4>
 
         <h5>IMPORTANT</h5>
diff --git a/crypto/src/asn1/misc/MiscObjectIdentifiers.cs b/crypto/src/asn1/misc/MiscObjectIdentifiers.cs
index d344393dd..1ff19e737 100644
--- a/crypto/src/asn1/misc/MiscObjectIdentifiers.cs
+++ b/crypto/src/asn1/misc/MiscObjectIdentifiers.cs
@@ -50,6 +50,8 @@ namespace Org.BouncyCastle.Asn1.Misc
         public static readonly string				Entrust					= "1.2.840.113533.7";
         public static readonly DerObjectIdentifier EntrustVersionExtension = new DerObjectIdentifier(Entrust + ".65.0");
 
+        public static readonly DerObjectIdentifier cast5CBC = new DerObjectIdentifier(Entrust+ ".66.10");
+
         //
         // Ascom
         //
diff --git a/crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs b/crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs
index b1099ed5b..a991585f6 100644
--- a/crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs
+++ b/crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs
@@ -62,8 +62,9 @@ namespace Org.BouncyCastle.Asn1.Pkcs
 
 		public static readonly DerObjectIdentifier DesEde3Cbc	= new DerObjectIdentifier(EncryptionAlgorithm + ".7");
         public static readonly DerObjectIdentifier RC2Cbc		= new DerObjectIdentifier(EncryptionAlgorithm + ".2");
+        public static readonly DerObjectIdentifier rc4          = new DerObjectIdentifier(EncryptionAlgorithm + ".4");
 
-		//
+        //
         // object identifiers for digests
         //
         public const string DigestAlgorithm = "1.2.840.113549.2";
diff --git a/crypto/src/cmp/RevocationDetails.cs b/crypto/src/cmp/RevocationDetails.cs
new file mode 100644
index 000000000..6e1cb34c3
--- /dev/null
+++ b/crypto/src/cmp/RevocationDetails.cs
@@ -0,0 +1,39 @@
+using Org.BouncyCastle.Asn1.Cmp;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Cmp
+{
+    public class RevocationDetails
+    {
+        private RevDetails revDetails;
+
+        public RevocationDetails(RevDetails revDetails)
+        {
+            this.revDetails = revDetails;
+        }
+
+        public X509Name Subject
+        {
+            get { return revDetails.CertDetails.Subject; }
+        }
+
+        public X509Name Issuer
+        {
+            get { return revDetails.CertDetails.Issuer; }
+        }
+
+        public BigInteger SerialNumber
+        {
+            get
+            {
+                return revDetails.CertDetails.SerialNumber.Value; //   getCertDetails().getSerialNumber().getValue();
+            }
+        }
+
+        public RevDetails ToASN1Structure()
+        {
+            return revDetails;
+        }
+    }
+}
\ No newline at end of file
diff --git a/crypto/src/cmp/RevocationDetailsBuilder.cs b/crypto/src/cmp/RevocationDetailsBuilder.cs
new file mode 100644
index 000000000..464c0bb13
--- /dev/null
+++ b/crypto/src/cmp/RevocationDetailsBuilder.cs
@@ -0,0 +1,58 @@
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cmp;
+using Org.BouncyCastle.Asn1.Crmf;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Cmp
+{
+    public class RevocationDetailsBuilder
+    {
+        private readonly CertTemplateBuilder _templateBuilder = new CertTemplateBuilder();
+
+        public RevocationDetailsBuilder SetPublicKey(SubjectPublicKeyInfo publicKey)
+        {
+            if (publicKey != null)
+            {
+                _templateBuilder.SetPublicKey(publicKey);
+            }
+
+            return this;
+        }
+
+        public RevocationDetailsBuilder SetIssuer(X509Name issuer)
+        {
+            if (issuer != null)
+            {
+                _templateBuilder.SetIssuer(issuer);
+            }
+
+            return this;
+        }
+
+        public RevocationDetailsBuilder SetSerialNumber(BigInteger serialNumber)
+        {
+            if (serialNumber != null)
+            {
+                _templateBuilder.SetSerialNumber(new DerInteger(serialNumber));
+            }
+
+            return this;
+        }
+
+        public RevocationDetailsBuilder SetSubject(X509Name subject)
+        {
+            if (subject != null)
+            {
+                _templateBuilder.SetSubject(subject);
+            }
+
+            return this;
+        }
+
+        public RevocationDetails build()
+        {
+            return new RevocationDetails(new RevDetails(_templateBuilder.Build()));
+        }
+    }
+}
\ No newline at end of file
diff --git a/crypto/src/cms/CMSEnvelopedDataGenerator.cs b/crypto/src/cms/CMSEnvelopedDataGenerator.cs
index d260e998a..8ba41161e 100644
--- a/crypto/src/cms/CMSEnvelopedDataGenerator.cs
+++ b/crypto/src/cms/CMSEnvelopedDataGenerator.cs
@@ -144,7 +144,7 @@ namespace Org.BouncyCastle.Cms
             try
             {
 				CipherKeyGenerator keyGen = GeneratorUtilities.GetKeyGenerator(encryptionOid);
-
+               
 				keyGen.Init(new KeyGenerationParameters(rand, keyGen.DefaultStrength));
 
 				return Generate(content, encryptionOid, keyGen);
@@ -155,6 +155,75 @@ namespace Org.BouncyCastle.Cms
             }
         }
 
+
+        public CmsEnvelopedData Generate(CmsProcessable content, ICipherBuilderWithKey cipherBuilder)
+        {
+            AlgorithmIdentifier encAlgId = null;
+            KeyParameter encKey;
+            Asn1OctetString encContent;
+
+            try
+            {
+                encKey = (KeyParameter) cipherBuilder.Key;
+
+                MemoryStream collector = new MemoryStream();
+                Stream bOut = cipherBuilder.BuildCipher(collector).Stream;            
+                content.Write(bOut);  
+                Platform.Dispose(bOut);                            
+                encContent = new BerOctetString(collector.ToArray());
+            }
+            catch (SecurityUtilityException e)
+            {
+                throw new CmsException("couldn't create cipher.", e);
+            }
+            catch (InvalidKeyException e)
+            {
+                throw new CmsException("key invalid in message.", e);
+            }
+            catch (IOException e)
+            {
+                throw new CmsException("exception decoding algorithm parameters.", e);
+            }
+
+
+            Asn1EncodableVector recipientInfos = new Asn1EncodableVector();
+
+            foreach (RecipientInfoGenerator rig in recipientInfoGenerators)
+            {
+                try
+                {
+                    recipientInfos.Add(rig.Generate(encKey, rand));
+                }
+                catch (InvalidKeyException e)
+                {
+                    throw new CmsException("key inappropriate for algorithm.", e);
+                }
+                catch (GeneralSecurityException e)
+                {
+                    throw new CmsException("error making encrypted content.", e);
+                }
+            }
+
+            EncryptedContentInfo eci = new EncryptedContentInfo(
+                CmsObjectIdentifiers.Data,
+                (AlgorithmIdentifier) cipherBuilder.AlgorithmDetails,
+                encContent);
+
+            Asn1Set unprotectedAttrSet = null;
+            if (unprotectedAttributeGenerator != null)
+            {
+                Asn1.Cms.AttributeTable attrTable = unprotectedAttributeGenerator.GetAttributes(Platform.CreateHashtable());
+
+                unprotectedAttrSet = new BerSet(attrTable.ToAsn1EncodableVector());
+            }
+
+            ContentInfo contentInfo = new ContentInfo(
+                CmsObjectIdentifiers.EnvelopedData,
+                new EnvelopedData(null, new DerSet(recipientInfos), eci, unprotectedAttrSet));
+
+            return new CmsEnvelopedData(contentInfo);
+        }
+
 		/// <summary>Generate an enveloped object that contains an CMS Enveloped Data object.</summary>
         public CmsEnvelopedData Generate(
             CmsProcessable  content,
diff --git a/crypto/src/cms/CMSEnvelopedGenerator.cs b/crypto/src/cms/CMSEnvelopedGenerator.cs
index f92ae3824..ed7e1edee 100644
--- a/crypto/src/cms/CMSEnvelopedGenerator.cs
+++ b/crypto/src/cms/CMSEnvelopedGenerator.cs
@@ -263,6 +263,16 @@ namespace Org.BouncyCastle.Cms
 			recipientInfoGenerators.Add(karig);
 		}
 
+        /// <summary>
+        /// Add a generator to produce the recipient info required.
+        /// </summary>
+        /// <param name="recipientInfoGenerator">a generator of a recipient info object.</param>
+	    public void AddRecipientInfoGenerator(RecipientInfoGenerator recipientInfoGenerator)
+	    {
+	        recipientInfoGenerators.Add(recipientInfoGenerator);
+	    }
+
+
         protected internal virtual AlgorithmIdentifier GetAlgorithmIdentifier(
 			string					encryptionOid,
 			KeyParameter			encKey,
diff --git a/crypto/src/cms/CMSProcessableByteArray.cs b/crypto/src/cms/CMSProcessableByteArray.cs
index a6ab9b6a2..b09935dd8 100644
--- a/crypto/src/cms/CMSProcessableByteArray.cs
+++ b/crypto/src/cms/CMSProcessableByteArray.cs
@@ -1,5 +1,7 @@
 using System;
 using System.IO;
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
 
 namespace Org.BouncyCastle.Cms
 {
@@ -9,13 +11,26 @@ namespace Org.BouncyCastle.Cms
 	public class CmsProcessableByteArray
 		: CmsProcessable, CmsReadable
 	{
+	    private readonly DerObjectIdentifier type;
 		private readonly byte[] bytes;
 
         public CmsProcessableByteArray(byte[] bytes)
-		{
+        {
+            type = CmsObjectIdentifiers.Data;
 			this.bytes = bytes;
 		}
 
+	    public CmsProcessableByteArray(DerObjectIdentifier type, byte[] bytes)
+	    {
+	        this.bytes = bytes;
+	        this.type = type;
+	    }
+
+	    public DerObjectIdentifier Type
+	    {
+	        get { return type; }
+	    }
+
         public virtual Stream GetInputStream()
 		{
 			return new MemoryStream(bytes, false);
diff --git a/crypto/src/cms/EnvelopedDataHelper.cs b/crypto/src/cms/EnvelopedDataHelper.cs
new file mode 100644
index 000000000..fe5bc2a97
--- /dev/null
+++ b/crypto/src/cms/EnvelopedDataHelper.cs
@@ -0,0 +1,123 @@
+using System.Collections;
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Operators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Utilities;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Crypto.Utilites;
+
+namespace Org.BouncyCastle.Cms
+{
+    internal class EnvelopedDataHelper
+    {
+        private static readonly IDictionary BaseCipherNames = Platform.CreateHashtable();
+        private static readonly IDictionary MacAlgNames = Platform.CreateHashtable();
+
+        private static readonly IDictionary prfs = Platform.CreateHashtable();
+
+
+        public delegate IDigest DigestCreator();
+
+        static EnvelopedDataHelper()
+        {
+            prfs.Add(PkcsObjectIdentifiers.IdHmacWithSha1, new DigestProvider(delegate () { return new Sha1Digest(); }));
+            prfs.Add(PkcsObjectIdentifiers.IdHmacWithSha224, new DigestProvider(delegate () { return new Sha224Digest(); }));
+            prfs.Add(PkcsObjectIdentifiers.IdHmacWithSha256, new DigestProvider(delegate () { return new Sha256Digest(); }));
+            prfs.Add(PkcsObjectIdentifiers.IdHmacWithSha384, new DigestProvider(delegate () { return new Sha384Digest(); }));
+            prfs.Add(PkcsObjectIdentifiers.IdHmacWithSha512, new DigestProvider(delegate () { return new Sha512Digest(); }));
+
+
+            BaseCipherNames.Add(PkcsObjectIdentifiers.DesEde3Cbc, "DESEDE");
+            BaseCipherNames.Add(NistObjectIdentifiers.IdAes128Cbc, "AES");
+            BaseCipherNames.Add(NistObjectIdentifiers.IdAes192Cbc, "AES");
+            BaseCipherNames.Add(NistObjectIdentifiers.IdAes256Cbc, "AES");
+
+            MacAlgNames.Add(PkcsObjectIdentifiers.DesEde3Cbc, "DESEDEMac");
+            MacAlgNames.Add(NistObjectIdentifiers.IdAes128Cbc, "AESMac");
+            MacAlgNames.Add(NistObjectIdentifiers.IdAes192Cbc, "AESMac");
+            MacAlgNames.Add(NistObjectIdentifiers.IdAes256Cbc, "AESMac");
+            MacAlgNames.Add(PkcsObjectIdentifiers.RC2Cbc, "RC2Mac");
+        }
+
+        static IDigest GetPrf(AlgorithmIdentifier algID)
+        {
+            return ((DigestCreator)prfs[algID]).Invoke();
+        }
+
+
+        static IWrapper CreateRFC3211Wrapper(DerObjectIdentifier algorithm)
+
+        {
+            if (NistObjectIdentifiers.IdAes128Cbc.Equals(algorithm)
+        || NistObjectIdentifiers.IdAes192Cbc.Equals(algorithm)
+        || NistObjectIdentifiers.IdAes256Cbc.Equals(algorithm))
+            {
+                return new Rfc3211WrapEngine(new AesEngine());
+            }
+            else if (PkcsObjectIdentifiers.DesEde3Cbc.Equals(algorithm))
+            {
+                return new Rfc3211WrapEngine(new DesEdeEngine());
+            }
+            else if (OiwObjectIdentifiers.DesCbc.Equals(algorithm))
+            {
+                return new Rfc3211WrapEngine(new DesEngine());
+            }
+            else if (PkcsObjectIdentifiers.RC2Cbc.Equals(algorithm))
+            {
+                return new Rfc3211WrapEngine(new RC2Engine());
+            }
+            else
+            {
+                throw new CmsException("cannot recognise wrapper: " + algorithm);
+            }
+        }
+
+
+
+       public static object CreateContentCipher(bool forEncryption, ICipherParameters encKey,
+            AlgorithmIdentifier encryptionAlgID)
+
+        {
+            return CipherFactory.CreateContentCipher(forEncryption, encKey, encryptionAlgID);
+        }
+
+
+        public AlgorithmIdentifier GenerateEncryptionAlgID(DerObjectIdentifier encryptionOID, KeyParameter encKey, SecureRandom random)
+        {
+            return AlgorithmIdentifierFactory.GenerateEncryptionAlgID(encryptionOID, encKey.GetKey().Length * 8, random);
+        }
+
+       public  CipherKeyGenerator CreateKeyGenerator(DerObjectIdentifier algorithm, SecureRandom random)
+
+        {
+            return CipherKeyGeneratorFactory.CreateKeyGenerator(algorithm, random);
+        }
+
+
+    }
+
+    // This exists because we can't directly put a delegate in a map as it is
+    // not an object.
+    internal class DigestProvider
+    {
+        private readonly EnvelopedDataHelper.DigestCreator creator;
+
+        public DigestProvider(EnvelopedDataHelper.DigestCreator creator)
+        {
+            this.creator = creator;
+        }
+
+        public IDigest Create()
+        {
+            return creator.Invoke();
+        }
+    }
+}
diff --git a/crypto/src/cms/KeyTransRecipientInfoGenerator.cs b/crypto/src/cms/KeyTransRecipientInfoGenerator.cs
index a1d8fbfa8..23b06d3b3 100644
--- a/crypto/src/cms/KeyTransRecipientInfoGenerator.cs
+++ b/crypto/src/cms/KeyTransRecipientInfoGenerator.cs
@@ -11,77 +11,106 @@ using Org.BouncyCastle.X509;
 
 namespace Org.BouncyCastle.Cms
 {
-	internal class KeyTransRecipientInfoGenerator : RecipientInfoGenerator
-	{
-		private static readonly CmsEnvelopedHelper Helper = CmsEnvelopedHelper.Instance;
-
-		private TbsCertificateStructure	recipientTbsCert;
-		private AsymmetricKeyParameter	recipientPublicKey;
-		private Asn1OctetString			subjectKeyIdentifier;
-
-		// Derived fields
-		private SubjectPublicKeyInfo info;
-
-		internal KeyTransRecipientInfoGenerator()
-		{
-		}
-
-		internal X509Certificate RecipientCert
-		{
-			set
-			{
-				this.recipientTbsCert = CmsUtilities.GetTbsCertificateStructure(value);
-				this.recipientPublicKey = value.GetPublicKey();
-				this.info = recipientTbsCert.SubjectPublicKeyInfo;
-			}
-		}
-		
-		internal AsymmetricKeyParameter RecipientPublicKey
-		{
-			set
-			{
-				this.recipientPublicKey = value;
-
-				try
-				{
-					info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(
-						recipientPublicKey);
-				}
-				catch (IOException)
-				{
-					throw new ArgumentException("can't extract key algorithm from this key");
-				}
-			}
-		}
-		
-		internal Asn1OctetString SubjectKeyIdentifier
-		{
-			set { this.subjectKeyIdentifier = value; }
-		}
-
-		public RecipientInfo Generate(KeyParameter contentEncryptionKey, SecureRandom random)
-		{
-			byte[] keyBytes = contentEncryptionKey.GetKey();
-			AlgorithmIdentifier keyEncryptionAlgorithm = info.AlgorithmID;
+    public class KeyTransRecipientInfoGenerator : RecipientInfoGenerator
+    {
+        private static readonly CmsEnvelopedHelper Helper = CmsEnvelopedHelper.Instance;
+
+        private TbsCertificateStructure recipientTbsCert;
+        private AsymmetricKeyParameter recipientPublicKey;
+        private Asn1OctetString subjectKeyIdentifier;
+
+        // Derived fields
+        private SubjectPublicKeyInfo info;
+        private IssuerAndSerialNumber issuerAndSerialNumber;
+        private SecureRandom random;
+
+        internal KeyTransRecipientInfoGenerator()
+        {
+        }
+
+        protected KeyTransRecipientInfoGenerator(IssuerAndSerialNumber issuerAndSerialNumber)
+        {
+            this.issuerAndSerialNumber = issuerAndSerialNumber;
+        }
+
+        protected KeyTransRecipientInfoGenerator(byte[] subjectKeyIdentifier)
+        {
+            this.subjectKeyIdentifier = new DerOctetString(subjectKeyIdentifier);
+        }
+
+        internal X509Certificate RecipientCert
+        {
+            set
+            {
+                this.recipientTbsCert = CmsUtilities.GetTbsCertificateStructure(value);
+                this.recipientPublicKey = value.GetPublicKey();
+                this.info = recipientTbsCert.SubjectPublicKeyInfo;
+            }
+        }
+
+        internal AsymmetricKeyParameter RecipientPublicKey
+        {
+            set
+            {
+                this.recipientPublicKey = value;
+
+                try
+                {
+                    info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(
+                        recipientPublicKey);
+                }
+                catch (IOException)
+                {
+                    throw new ArgumentException("can't extract key algorithm from this key");
+                }
+            }
+        }
+
+        internal Asn1OctetString SubjectKeyIdentifier
+        {
+            set { this.subjectKeyIdentifier = value; }
+        }
+
+        public RecipientInfo Generate(KeyParameter contentEncryptionKey, SecureRandom random)
+        {
+            AlgorithmIdentifier keyEncryptionAlgorithm = this.AlgorithmDetails;
+
+            this.random = random;
+
+            byte[] encryptedKeyBytes = GenerateWrappedKey(contentEncryptionKey);
+
+            RecipientIdentifier recipId;
+            if (recipientTbsCert != null)
+            {
+                IssuerAndSerialNumber issuerAndSerial = new IssuerAndSerialNumber(
+                    recipientTbsCert.Issuer, recipientTbsCert.SerialNumber.Value);
+                recipId = new RecipientIdentifier(issuerAndSerial);
+            }
+            else
+            {
+                recipId = new RecipientIdentifier(subjectKeyIdentifier);
+            }
+
+            return new RecipientInfo(new KeyTransRecipientInfo(recipId, keyEncryptionAlgorithm,
+                new DerOctetString(encryptedKeyBytes)));
+        }
+
+        protected virtual AlgorithmIdentifier AlgorithmDetails
+        {
+            get
+            {
+                return info.AlgorithmID;
+            }
+        }
+
+        protected virtual byte[] GenerateWrappedKey(KeyParameter contentEncryptionKey)
+        {
+            byte[] keyBytes = contentEncryptionKey.GetKey();
+            AlgorithmIdentifier keyEncryptionAlgorithm = info.AlgorithmID;
 
             IWrapper keyWrapper = Helper.CreateWrapper(keyEncryptionAlgorithm.Algorithm.Id);
-			keyWrapper.Init(true, new ParametersWithRandom(recipientPublicKey, random));
-			byte[] encryptedKeyBytes = keyWrapper.Wrap(keyBytes, 0, keyBytes.Length);
-
-			RecipientIdentifier recipId;
-			if (recipientTbsCert != null)
-			{
-				IssuerAndSerialNumber issuerAndSerial = new IssuerAndSerialNumber(
-					recipientTbsCert.Issuer, recipientTbsCert.SerialNumber.Value);
-				recipId = new RecipientIdentifier(issuerAndSerial);
-			}
-			else
-			{
-				recipId = new RecipientIdentifier(subjectKeyIdentifier);
-			}
-
-			return new RecipientInfo(new KeyTransRecipientInfo(recipId, keyEncryptionAlgorithm,
-				new DerOctetString(encryptedKeyBytes)));
-		}
-	}
+            keyWrapper.Init(true, new ParametersWithRandom(recipientPublicKey, random));
+            return keyWrapper.Wrap(keyBytes, 0, keyBytes.Length);
+        }
+    }
 }
diff --git a/crypto/src/cms/KeyTransRecipientInformation.cs b/crypto/src/cms/KeyTransRecipientInformation.cs
index 3b1ea7b5e..7d2f072b5 100644
--- a/crypto/src/cms/KeyTransRecipientInformation.cs
+++ b/crypto/src/cms/KeyTransRecipientInformation.cs
@@ -55,12 +55,18 @@ namespace Org.BouncyCastle.Cms
         }
 
 		private string GetExchangeEncryptionAlgorithmName(
-			DerObjectIdentifier oid)
+			AlgorithmIdentifier algo)
 		{
-			if (Asn1Pkcs.PkcsObjectIdentifiers.RsaEncryption.Equals(oid))
+		    DerObjectIdentifier oid = algo.Algorithm;
+
+            if (Asn1Pkcs.PkcsObjectIdentifiers.RsaEncryption.Equals(oid))
 			{
 				return "RSA//PKCS1Padding";
-			}
+			} else if (Asn1Pkcs.PkcsObjectIdentifiers.IdRsaesOaep.Equals(oid))
+            {
+                 Asn1Pkcs.RsaesOaepParameters rsaParams = Asn1Pkcs.RsaesOaepParameters.GetInstance(algo.Parameters);                       
+                return "RSA//OAEPWITH"+DigestUtilities.GetAlgorithmName(rsaParams.HashAlgorithm.Algorithm)+"ANDMGF1Padding";
+            }
 
 			return oid.Id;
 		}
@@ -68,7 +74,7 @@ namespace Org.BouncyCastle.Cms
 		internal KeyParameter UnwrapKey(ICipherParameters key)
 		{
 			byte[] encryptedKey = info.EncryptedKey.GetOctets();
-            string keyExchangeAlgorithm = GetExchangeEncryptionAlgorithmName(keyEncAlg.Algorithm);
+            string keyExchangeAlgorithm = GetExchangeEncryptionAlgorithmName(keyEncAlg);
 
 			try
 			{
diff --git a/crypto/src/cms/RecipientInfoGenerator.cs b/crypto/src/cms/RecipientInfoGenerator.cs
index c41db6122..75f5dcc33 100644
--- a/crypto/src/cms/RecipientInfoGenerator.cs
+++ b/crypto/src/cms/RecipientInfoGenerator.cs
@@ -6,7 +6,7 @@ using Org.BouncyCastle.Security;
 
 namespace Org.BouncyCastle.Cms
 {
-	interface RecipientInfoGenerator
+	public interface RecipientInfoGenerator
 	{
 		/// <summary>
 		/// Generate a RecipientInfo object for the given key.
diff --git a/crypto/src/crmf/CertificateRequestMessage.cs b/crypto/src/crmf/CertificateRequestMessage.cs
index 087e8a933..5b5d37c9e 100644
--- a/crypto/src/crmf/CertificateRequestMessage.cs
+++ b/crypto/src/crmf/CertificateRequestMessage.cs
@@ -211,8 +211,8 @@ namespace Org.BouncyCastle.Crmf
               calculator.Stream.Write(b,0,b.Length);
             }
             else
-            {
-                byte[] b = certReqMsg.GetDerEncoded();
+            {              
+                byte[] b = certReqMsg.CertReq.GetDerEncoded();
                 calculator.Stream.Write(b,0,b.Length);
             }
 
diff --git a/crypto/src/crmf/CertificateRequestMessageBuilder.cs b/crypto/src/crmf/CertificateRequestMessageBuilder.cs
index 1c1eba320..04b210ec7 100644
--- a/crypto/src/crmf/CertificateRequestMessageBuilder.cs
+++ b/crypto/src/crmf/CertificateRequestMessageBuilder.cs
@@ -94,6 +94,12 @@ namespace Org.BouncyCastle.Crmf
             return this;
         }
 
+        public CertificateRequestMessageBuilder AddControl(IControl control)
+        {
+            _controls.Add(control);
+            return this;
+        }
+
         public CertificateRequestMessageBuilder SetProofOfPossessionSignKeySigner(ISignatureFactory popoSignatureFactory)
         {
             if (_popoPrivKey != null || _popRaVerified != null || _agreeMac != null)
@@ -101,7 +107,8 @@ namespace Org.BouncyCastle.Crmf
                 throw new InvalidOperationException("only one proof of possession is allowed.");
             }
 
-            this._popoType = ProofOfPossession.TYPE_KEY_ENCIPHERMENT;
+            this._popSigner = popoSignatureFactory;
+          
             return this;
         }
 
diff --git a/crypto/src/crmf/EncryptedValueBuilder.cs b/crypto/src/crmf/EncryptedValueBuilder.cs
index e8cf263f7..a7f581527 100644
--- a/crypto/src/crmf/EncryptedValueBuilder.cs
+++ b/crypto/src/crmf/EncryptedValueBuilder.cs
@@ -110,6 +110,7 @@ namespace Org.BouncyCastle.Crmf
             {
                 throw new CrmfException("cannot wrap key: " + e.Message, e);
             }
+
         }
 
         private EncryptedValue encryptData(byte[] data)
diff --git a/crypto/src/crmf/PkiArchiveControlBuilder.cs b/crypto/src/crmf/PkiArchiveControlBuilder.cs
new file mode 100644
index 000000000..2677e4e0d
--- /dev/null
+++ b/crypto/src/crmf/PkiArchiveControlBuilder.cs
@@ -0,0 +1,58 @@
+using System;
+using System.IO;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.Crmf;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Cms;
+using Org.BouncyCastle.Crypto;
+
+namespace Org.BouncyCastle.Crmf
+{
+    public class PkiArchiveControlBuilder
+    {
+        private CmsEnvelopedDataGenerator envGen;
+        private CmsProcessableByteArray keyContent;
+
+        /// <summary>
+        ///Basic constructor - specify the contents of the PKIArchiveControl structure.
+        /// </summary>
+        /// <param name="privateKeyInfo">the private key to be archived.</param>
+        /// <param name="generalName">the general name to be associated with the private key.</param>
+        ///
+        public PkiArchiveControlBuilder(PrivateKeyInfo privateKeyInfo, GeneralName generalName)
+        {
+            EncKeyWithID encKeyWithID = new EncKeyWithID(privateKeyInfo, generalName);
+
+            try
+            {
+                this.keyContent = new CmsProcessableByteArray(CrmfObjectIdentifiers.id_ct_encKeyWithID, encKeyWithID.GetEncoded());
+            }
+            catch (IOException e)
+            {
+                throw new InvalidOperationException("unable to encode key and general name info");
+            }
+
+            this.envGen = new CmsEnvelopedDataGenerator();
+        }
+
+        ///<summary>Add a recipient generator to this control.</summary>       
+        ///<param name="recipientGen"> recipient generator created for a specific recipient.</param>
+        ///<returns>this builder object.</returns>       
+        public PkiArchiveControlBuilder AddRecipientGenerator(RecipientInfoGenerator recipientGen)
+        {
+            envGen.AddRecipientInfoGenerator(recipientGen);
+            return this;
+        }
+       
+        /// <summary>Build the PKIArchiveControl using the passed in encryptor to encrypt its contents.</summary>
+        /// <param name="contentEncryptor">a suitable content encryptor.</param>
+        /// <returns>a PKIArchiveControl object.</returns>
+        public PkiArchiveControl Build(ICipherBuilderWithKey contentEncryptor)
+        {                                            
+            CmsEnvelopedData envContent = envGen.Generate(keyContent, contentEncryptor);
+            EnvelopedData envD = EnvelopedData.GetInstance(envContent.ContentInfo.Content);        
+            return new PkiArchiveControl(new PkiArchiveOptions(new EncryptedKey(envD)));
+        }
+    }
+}
\ No newline at end of file
diff --git a/crypto/src/crypto/SimpleBlockResult.cs b/crypto/src/crypto/SimpleBlockResult.cs
new file mode 100644
index 000000000..01a6c4e01
--- /dev/null
+++ b/crypto/src/crypto/SimpleBlockResult.cs
@@ -0,0 +1,51 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto
+{
+	/// <summary>
+	/// A simple block result object which just carries a byte array.
+	/// </summary>
+	public class SimpleBlockResult: IBlockResult
+	{
+        private readonly bool approvedOnlyMode;
+		private readonly byte[] result;
+
+        /// <summary>
+        /// Base constructor - a wrapper for the passed in byte array.
+        /// </summary>
+        /// <param name="result">The byte array to be wrapped.</param>
+		public SimpleBlockResult (byte[] result)
+		{
+			this.result = result;
+		}
+
+		/// <summary>
+		/// Return the number of bytes in the result
+		/// </summary>
+		/// <value>The length of the result in bytes.</value>
+		public int Length { get { return result.Length; } }
+
+		/// <summary>
+		/// Return the final result of the operation.
+		/// </summary>
+		/// <returns>A block of bytes, representing the result of an operation.</returns>
+		public byte[] Collect()
+		{
+            return result;
+		}
+
+		/// <summary>
+		/// Store the final result of the operation by copying it into the destination array.
+		/// </summary>
+		/// <returns>The number of bytes copied into destination.</returns>
+		/// <param name="destination">The byte array to copy the result into.</param>
+		/// <param name="offset">The offset into destination to start copying the result at.</param>
+		public int Collect(byte[] destination, int offset)
+		{
+            Array.Copy (result, 0, destination, offset, result.Length);
+
+			return result.Length;
+		}
+	}
+}
+
diff --git a/crypto/src/crypto/digests/GOST3411_2012Digest.cs b/crypto/src/crypto/digests/GOST3411_2012Digest.cs
index 439512924..68cb6c035 100644
--- a/crypto/src/crypto/digests/GOST3411_2012Digest.cs
+++ b/crypto/src/crypto/digests/GOST3411_2012Digest.cs
@@ -4,7 +4,7 @@ using Org.BouncyCastle.Utilities;
 
 namespace Org.BouncyCastle.Crypto.Digests
 {
-    public abstract class GOST3411_2012Digest:IDigest,IMemoable
+    public abstract class Gost3411_2012Digest:IDigest,IMemoable
     {
         private readonly byte[] IV = new byte[64];
         private readonly byte[] N = new byte[64];
@@ -19,7 +19,7 @@ namespace Org.BouncyCastle.Crypto.Digests
 
         private int bOff = 64;
 
-        protected GOST3411_2012Digest(byte[] IV)
+        protected Gost3411_2012Digest(byte[] IV)
         {
             System.Array.Copy(IV,this.IV,64);
             System.Array.Copy(IV, h, 64);
@@ -79,7 +79,7 @@ namespace Org.BouncyCastle.Crypto.Digests
 
         public void Reset(IMemoable other)
         {
-            GOST3411_2012Digest o = (GOST3411_2012Digest)other;
+            Gost3411_2012Digest o = (Gost3411_2012Digest)other;
 
             System.Array.Copy(o.IV, 0, this.IV, 0, 64);
             System.Array.Copy(o.N, 0, this.N, 0, 64);
diff --git a/crypto/src/crypto/digests/GOST3411_2012_256Digest.cs b/crypto/src/crypto/digests/GOST3411_2012_256Digest.cs
index 8686851e2..77cf6c50f 100644
--- a/crypto/src/crypto/digests/GOST3411_2012_256Digest.cs
+++ b/crypto/src/crypto/digests/GOST3411_2012_256Digest.cs
@@ -3,7 +3,7 @@ using Org.BouncyCastle.Utilities;
 
 namespace Org.BouncyCastle.Crypto.Digests
 {
-    public class GOST3411_2012_256Digest : GOST3411_2012Digest
+    public class Gost3411_2012_256Digest : Gost3411_2012Digest
     {
         private readonly static byte[] IV = {
             0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
@@ -21,12 +21,12 @@ namespace Org.BouncyCastle.Crypto.Digests
             get { return "GOST3411-2012-256"; }
         }
 
-        public GOST3411_2012_256Digest() : base(IV)
+        public Gost3411_2012_256Digest() : base(IV)
         {
 
         }
 
-        public GOST3411_2012_256Digest(GOST3411_2012_256Digest other) : base(IV)
+        public Gost3411_2012_256Digest(Gost3411_2012_256Digest other) : base(IV)
         {
             Reset(other);
         }
@@ -48,7 +48,7 @@ namespace Org.BouncyCastle.Crypto.Digests
 
         public override IMemoable Copy()
         {
-			return new GOST3411_2012_256Digest(this);
+			return new Gost3411_2012_256Digest(this);
         }
     }
 }
diff --git a/crypto/src/crypto/digests/GOST3411_2012_512Digest.cs b/crypto/src/crypto/digests/GOST3411_2012_512Digest.cs
index eb40aba1d..2b77e36a9 100644
--- a/crypto/src/crypto/digests/GOST3411_2012_512Digest.cs
+++ b/crypto/src/crypto/digests/GOST3411_2012_512Digest.cs
@@ -3,7 +3,7 @@ using Org.BouncyCastle.Utilities;
 
 namespace Org.BouncyCastle.Crypto.Digests
 {
-    public class GOST3411_2012_512Digest:GOST3411_2012Digest
+    public class Gost3411_2012_512Digest:Gost3411_2012Digest
     {
 		private readonly static byte[] IV = {
 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -21,11 +21,11 @@ namespace Org.BouncyCastle.Crypto.Digests
 			get { return "GOST3411-2012-512"; }
 		}
 
-        public GOST3411_2012_512Digest():base(IV)
+        public Gost3411_2012_512Digest():base(IV)
         {
         }
 
-		public GOST3411_2012_512Digest(GOST3411_2012_512Digest other) : base(IV)
+		public Gost3411_2012_512Digest(Gost3411_2012_512Digest other) : base(IV)
 		{
             Reset(other);
         }
@@ -37,7 +37,7 @@ namespace Org.BouncyCastle.Crypto.Digests
 
 		public override IMemoable Copy()
 		{
-			return new GOST3411_2012_512Digest(this);
+			return new Gost3411_2012_512Digest(this);
 		}
     }
 }
diff --git a/crypto/src/crypto/operators/Asn1CipherBuilder.cs b/crypto/src/crypto/operators/Asn1CipherBuilder.cs
new file mode 100644
index 000000000..adb4507a3
--- /dev/null
+++ b/crypto/src/crypto/operators/Asn1CipherBuilder.cs
@@ -0,0 +1,100 @@
+using System.Collections;
+using System.IO;
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Ntt;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Cms;
+using Org.BouncyCastle.Crypto.IO;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Crypto.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Operators
+{
+    public class Asn1CipherBuilderWithKey:ICipherBuilderWithKey
+    {
+
+        private readonly KeyParameter encKey;
+        private AlgorithmIdentifier algorithmIdentifier;
+       
+      
+        public Asn1CipherBuilderWithKey(DerObjectIdentifier encryptionOID, int keySize, SecureRandom random)
+        {
+            if (random == null)
+            {
+                random= new SecureRandom();
+            }
+            CipherKeyGenerator keyGen = CipherKeyGeneratorFactory.CreateKeyGenerator(encryptionOID, random);
+    
+            encKey = new KeyParameter(keyGen.GenerateKey());
+            algorithmIdentifier = AlgorithmIdentifierFactory.GenerateEncryptionAlgID(encryptionOID, encKey.GetKey().Length * 8, random);
+        }
+
+
+        public object AlgorithmDetails
+        {
+            get { return algorithmIdentifier; }
+        }
+        public int GetMaxOutputSize(int inputLen)
+        {
+            throw new System.NotImplementedException();
+        }
+
+        public ICipher BuildCipher(Stream stream)
+        {
+
+            object cipher = EnvelopedDataHelper.CreateContentCipher(true, encKey, algorithmIdentifier);
+
+            //
+            // BufferedBlockCipher
+            // IStreamCipher
+            //
+
+            if (cipher is IStreamCipher)
+            {
+                   cipher = new BufferedStreamCipher((IStreamCipher)cipher);                
+            }
+
+            if (stream == null)
+            {
+                stream = new MemoryStream();
+            }
+
+            return new BufferedCipherWrapper((IBufferedCipher)cipher,stream);
+        }
+
+        public ICipherParameters Key
+        {
+            get { return encKey; }
+        }
+    }
+
+    public class BufferedCipherWrapper : ICipher
+    {
+        private readonly IBufferedCipher bufferedCipher;
+        private readonly CipherStream stream;
+
+        public BufferedCipherWrapper(IBufferedCipher bufferedCipher, Stream source)
+        {
+            this.bufferedCipher = bufferedCipher;
+            stream = new CipherStream(source, bufferedCipher, bufferedCipher);
+        }
+
+        public int GetMaxOutputSize(int inputLen)
+        {
+            return bufferedCipher.GetOutputSize(inputLen);
+        }
+
+        public int GetUpdateOutputSize(int inputLen)
+        {
+            return bufferedCipher.GetUpdateOutputSize(inputLen);
+        }
+
+        public Stream Stream
+        {
+            get { return stream; }
+        }
+    }
+}
diff --git a/crypto/src/crypto/operators/Asn1KeyWrapper.cs b/crypto/src/crypto/operators/Asn1KeyWrapper.cs
new file mode 100644
index 000000000..ffce7f63a
--- /dev/null
+++ b/crypto/src/crypto/operators/Asn1KeyWrapper.cs
@@ -0,0 +1,168 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Encodings;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Operators
+{
+    public class Asn1KeyWrapper : IKeyWrapper
+    {
+        private string algorithm;
+        private IKeyWrapper wrapper;
+
+        public Asn1KeyWrapper(string algorithm, X509Certificate cert)
+        {
+            this.algorithm = algorithm;
+            wrapper = KeyWrapperUtil.WrapperForName(algorithm, cert.GetPublicKey());
+        }
+
+        public object AlgorithmDetails
+        {
+            get { return wrapper.AlgorithmDetails; }
+        }
+
+        public IBlockResult Wrap(byte[] keyData)
+        {
+            return wrapper.Wrap(keyData);
+        }
+    }
+
+    internal class KeyWrapperUtil
+    {
+        //
+        // Provider 
+        //
+        private static readonly IDictionary providerMap = Platform.CreateHashtable();
+
+        static KeyWrapperUtil()
+        {
+            providerMap["RSA/NONE/OAEPWITHSHA1ANDMGF1PADDING"] = new WrapperCreator(RsaOaepWrapper.Rsa_Sha1_Oaep);
+            providerMap["RSA/NONE/OAEPWITHSHA224ANDMGF1PADDING"] = new WrapperCreator(RsaOaepWrapper.Rsa_Sha224_Oaep);
+            providerMap["RSA/NONE/OAEPWITHSHA256ANDMGF1PADDING"] = new WrapperCreator(RsaOaepWrapper.Rsa_Sha256_Oaep);
+            providerMap["RSA/NONE/OAEPWITHSHA384ANDMGF1PADDING"] = new WrapperCreator(RsaOaepWrapper.Rsa_Sha384_Oaep);
+            providerMap["RSA/NONE/OAEPWITHSHA512ANDMGF1PADDING"] = new WrapperCreator(RsaOaepWrapper.Rsa_Sha512_Oaep);
+        }
+
+        public static IKeyWrapper WrapperForName(string algorithm, ICipherParameters parameters)
+        {
+            WrapperProvider provider = (WrapperProvider)providerMap[Strings.ToUpperCase(algorithm)];
+
+            if (provider == null)
+            {
+                throw new ArgumentException("could not resolve " + algorithm + " to a KeyWrapper");
+            }
+
+            return (IKeyWrapper)provider.createWrapper(true, parameters);
+        }
+
+        public static IKeyUnwrapper UnwrapperForName(string algorithm, ICipherParameters parameters)
+        {
+            WrapperProvider provider = (WrapperProvider)providerMap[Strings.ToUpperCase(algorithm)];
+            if (provider == null)
+            {
+                throw new ArgumentException("could not resolve " + algorithm + " to a KeyUnwrapper");
+            }
+
+            return (IKeyUnwrapper)provider.createWrapper(false, parameters);
+        }
+    }
+
+    internal delegate object WrapperCreatorDelegate(bool forWrapping, ICipherParameters parameters);
+
+    /// <summary>
+    /// Wraps delegate and implements the WrapperProvider Interface.
+    /// </summary>
+    internal class WrapperCreator : WrapperProvider
+    {
+        private readonly WrapperCreatorDelegate creator;
+
+        public WrapperCreator(WrapperCreatorDelegate creator)
+        {
+            this.creator = creator;
+        }
+
+        public object createWrapper(bool forWrapping, ICipherParameters parameters)
+        {
+            return this.creator.Invoke(forWrapping, parameters);
+        }
+    }
+
+    internal interface WrapperProvider
+    {
+        object createWrapper(bool forWrapping, ICipherParameters parameters);
+    }
+
+    internal class RsaOaepWrapper : IKeyWrapper, IKeyUnwrapper
+    {
+        internal static object Rsa_Sha1_Oaep(bool forWrapping, ICipherParameters parameters)
+        {
+            return new RsaOaepWrapper(forWrapping, parameters, OiwObjectIdentifiers.IdSha1);
+        }
+
+        internal static object Rsa_Sha224_Oaep(bool forWrapping, ICipherParameters parameters)
+        {
+            return new RsaOaepWrapper(forWrapping, parameters, NistObjectIdentifiers.IdSha224);
+        }
+
+        internal static object Rsa_Sha256_Oaep(bool forWrapping, ICipherParameters parameters)
+        {
+            return new RsaOaepWrapper(forWrapping, parameters, NistObjectIdentifiers.IdSha256);
+        }
+
+        internal static object Rsa_Sha384_Oaep(bool forWrapping, ICipherParameters parameters)
+        {
+            return new RsaOaepWrapper(forWrapping, parameters, NistObjectIdentifiers.IdSha384);
+        }
+
+        internal static object Rsa_Sha512_Oaep(bool forWrapping, ICipherParameters parameters)
+        {
+            return new RsaOaepWrapper(forWrapping, parameters, NistObjectIdentifiers.IdSha512);
+        }
+
+        private readonly AlgorithmIdentifier algId;
+        private readonly IAsymmetricBlockCipher engine;
+
+        public RsaOaepWrapper(bool forWrapping, ICipherParameters parameters, DerObjectIdentifier digestOid)
+        {
+            AlgorithmIdentifier digestAlgId = new AlgorithmIdentifier(digestOid, DerNull.Instance);
+
+            this.algId = new AlgorithmIdentifier(
+                PkcsObjectIdentifiers.IdRsaesOaep,
+                new RsaesOaepParameters(
+                    digestAlgId,
+                    new AlgorithmIdentifier(PkcsObjectIdentifiers.IdMgf1, digestAlgId),
+                    RsaesOaepParameters.DefaultPSourceAlgorithm));
+            this.engine = new OaepEncoding(new RsaBlindedEngine(), DigestUtilities.GetDigest(digestOid) );
+            this.engine.Init(forWrapping, parameters);
+        }
+
+        public object AlgorithmDetails
+        {
+            get
+            {
+                return algId;
+            }
+        }
+
+        public IBlockResult Unwrap(byte[] cipherText, int offset, int length)
+        {
+            return new SimpleBlockResult(engine.ProcessBlock(cipherText, offset, length));
+        }
+
+        public IBlockResult Wrap(byte[] keyData)
+        {
+            return new SimpleBlockResult(engine.ProcessBlock(keyData, 0, keyData.Length));
+        }
+    }
+}
diff --git a/crypto/src/crypto/operators/Asn1Signature.cs b/crypto/src/crypto/operators/Asn1Signature.cs
index 3962a4a15..66050789e 100644
--- a/crypto/src/crypto/operators/Asn1Signature.cs
+++ b/crypto/src/crypto/operators/Asn1Signature.cs
@@ -12,6 +12,7 @@ using Org.BouncyCastle.Asn1.X509;
 using Org.BouncyCastle.Asn1.X9;
 using Org.BouncyCastle.Crypto.IO;
 using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Signers;
 using Org.BouncyCastle.Security;
 using Org.BouncyCastle.Utilities;
 using Org.BouncyCastle.Utilities.Collections;
@@ -346,7 +347,8 @@ namespace Org.BouncyCastle.Crypto.Operators
 		}
 
         public IStreamCalculator CreateCalculator()
-        {
+        {       
+           
             ISigner verifier = SignerUtilities.InitSigner(X509Utilities.GetSignatureName(algID), false, publicKey, null);
 
             return new DefaultVerifierCalculator(verifier);
diff --git a/crypto/src/crypto/operators/CmsContentEncryptorBuilder.cs b/crypto/src/crypto/operators/CmsContentEncryptorBuilder.cs
new file mode 100644
index 000000000..da9e32f9e
--- /dev/null
+++ b/crypto/src/crypto/operators/CmsContentEncryptorBuilder.cs
@@ -0,0 +1,64 @@
+using System.Collections;
+using System.IO;
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Ntt;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Cms;
+using Org.BouncyCastle.Crypto.IO;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Operators;
+
+namespace Org.BouncyCastle.Operators
+{
+    public class CmsContentEncryptorBuilder
+    {
+        private static readonly IDictionary keySizes = Platform.CreateHashtable();
+
+        static CmsContentEncryptorBuilder()
+        {
+            keySizes[NistObjectIdentifiers.IdAes128Cbc] = 128;
+            keySizes[NistObjectIdentifiers.IdAes192Cbc] =192;
+            keySizes[NistObjectIdentifiers.IdAes256Cbc] =256;
+
+           
+            keySizes[NttObjectIdentifiers.IdCamellia128Cbc] =128;
+            keySizes[NttObjectIdentifiers.IdCamellia192Cbc] =192;
+            keySizes[NttObjectIdentifiers.IdCamellia256Cbc] =256;
+        }
+
+        private static int getKeySize(DerObjectIdentifier oid)
+        {
+            if (keySizes.Contains(oid))
+            {
+                return (int)keySizes[oid];
+            }
+
+            return -1;
+        }
+
+        private readonly DerObjectIdentifier encryptionOID;
+        private readonly int keySize;
+
+      
+        private EnvelopedDataHelper helper = new EnvelopedDataHelper();
+        private SecureRandom random;
+
+        public CmsContentEncryptorBuilder(DerObjectIdentifier encryptionOID):this(encryptionOID, getKeySize(encryptionOID)) { 
+        }
+
+        public CmsContentEncryptorBuilder(DerObjectIdentifier encryptionOID, int keySize)
+        {
+            this.encryptionOID = encryptionOID;
+            this.keySize = keySize;
+        }
+
+        public ICipherBuilderWithKey Build()
+        {
+            return new Asn1CipherBuilderWithKey(encryptionOID,keySize,random);
+        }
+    }
+}
diff --git a/crypto/src/crypto/operators/CmsKeyTransRecipientInfoGenerator.cs b/crypto/src/crypto/operators/CmsKeyTransRecipientInfoGenerator.cs
new file mode 100644
index 000000000..997231b6e
--- /dev/null
+++ b/crypto/src/crypto/operators/CmsKeyTransRecipientInfoGenerator.cs
@@ -0,0 +1,38 @@
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Cms;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Operators
+{
+    public class CmsKeyTransRecipientInfoGenerator: KeyTransRecipientInfoGenerator
+    {
+        private IKeyWrapper keyWrapper;
+
+        public CmsKeyTransRecipientInfoGenerator(X509Certificate recipCert, IKeyWrapper keyWrapper): base(new Asn1.Cms.IssuerAndSerialNumber(recipCert.IssuerDN, new DerInteger(recipCert.SerialNumber)))
+        {
+            this.keyWrapper = keyWrapper;
+            this.RecipientCert = recipCert;
+            this.RecipientPublicKey = recipCert.GetPublicKey();
+        }
+
+        public CmsKeyTransRecipientInfoGenerator(byte[] subjectKeyID, IKeyWrapper keyWrapper) : base(subjectKeyID)
+        {
+            this.keyWrapper = keyWrapper;
+        }
+
+        protected override AlgorithmIdentifier AlgorithmDetails
+        {
+            get
+            {
+                return (AlgorithmIdentifier)keyWrapper.AlgorithmDetails;
+            }
+        }
+
+        protected override byte[] GenerateWrappedKey(Crypto.Parameters.KeyParameter contentKey)
+        {
+            return keyWrapper.Wrap(contentKey.GetKey()).Collect();
+        }
+    }
+}
diff --git a/crypto/src/crypto/parameters/ECGOST3410Parameters.cs b/crypto/src/crypto/parameters/ECGOST3410Parameters.cs
index ede7433d6..a3aa1953c 100644
--- a/crypto/src/crypto/parameters/ECGOST3410Parameters.cs
+++ b/crypto/src/crypto/parameters/ECGOST3410Parameters.cs
@@ -4,7 +4,7 @@ using Org.BouncyCastle.Math.EC;
 
 namespace Org.BouncyCastle.Crypto.Parameters
 {
-    public class ECGOST3410Parameters : ECNamedDomainParameters
+    public class ECGost3410Parameters : ECNamedDomainParameters
     {
 
         private readonly DerObjectIdentifier _publicKeyParamSet;
@@ -26,7 +26,7 @@ namespace Org.BouncyCastle.Crypto.Parameters
             get { return _encryptionParamSet; }
         }
 
-        public ECGOST3410Parameters(
+        public ECGost3410Parameters(
             ECNamedDomainParameters dp,
             DerObjectIdentifier publicKeyParamSet,
             DerObjectIdentifier digestParamSet,
@@ -38,7 +38,7 @@ namespace Org.BouncyCastle.Crypto.Parameters
         }
 
 
-        public ECGOST3410Parameters(ECDomainParameters dp, DerObjectIdentifier publicKeyParamSet,
+        public ECGost3410Parameters(ECDomainParameters dp, DerObjectIdentifier publicKeyParamSet,
             DerObjectIdentifier digestParamSet,
             DerObjectIdentifier encryptionParamSet) : base(publicKeyParamSet, dp.Curve, dp.G, dp.N, dp.H, dp.GetSeed())
         {
diff --git a/crypto/src/crypto/signers/ECGOST3410Signer.cs b/crypto/src/crypto/signers/ECGOST3410Signer.cs
index 451cd3dd8..f08d16551 100644
--- a/crypto/src/crypto/signers/ECGOST3410Signer.cs
+++ b/crypto/src/crypto/signers/ECGOST3410Signer.cs
@@ -17,16 +17,19 @@ namespace Org.BouncyCastle.Crypto.Signers
     {
         private ECKeyParameters key;
         private SecureRandom random;
+        private bool forSigning;
 
         public virtual string AlgorithmName
         {
-            get { return "ECGOST3410"; }
+            get { return key.AlgorithmName; }
         }
 
         public virtual void Init(
             bool				forSigning,
             ICipherParameters	parameters)
         {
+            this.forSigning = forSigning;
+
             if (forSigning)
             {
                 if (parameters is ParametersWithRandom)
@@ -70,6 +73,11 @@ namespace Org.BouncyCastle.Crypto.Signers
         public virtual BigInteger[] GenerateSignature(
             byte[] message)
         {
+            if (!forSigning)
+            {
+                throw new InvalidOperationException("not initialized for signing");
+            }
+
             byte[] mRev = new byte[message.Length]; // conversion is little-endian
             for (int i = 0; i != mRev.Length; i++)
             {
@@ -120,6 +128,11 @@ namespace Org.BouncyCastle.Crypto.Signers
             BigInteger	r,
             BigInteger	s)
         {
+            if (forSigning)
+            {
+                throw new InvalidOperationException("not initialized for verification");
+            }
+
             byte[] mRev = new byte[message.Length]; // conversion is little-endian
             for (int i = 0; i != mRev.Length; i++)
             {
diff --git a/crypto/src/crypto/signers/EcGost3410_2012Signer.cs b/crypto/src/crypto/signers/EcGost3410_2012Signer.cs
deleted file mode 100644
index e7174ace6..000000000
--- a/crypto/src/crypto/signers/EcGost3410_2012Signer.cs
+++ /dev/null
@@ -1,153 +0,0 @@
-using Org.BouncyCastle.Math;
-using System;
-using System.IO;
-
-using Org.BouncyCastle.Crypto.Parameters;
-using Org.BouncyCastle.Math.EC;
-using Org.BouncyCastle.Math.EC.Multiplier;
-using Org.BouncyCastle.Security;
-using Org.BouncyCastle.Utilities;
-
-namespace Org.BouncyCastle.Crypto.Signers
-{
-    public class ECGOST3410_2012Signer : IDsaExt
-    {
-        private ECKeyParameters key;
-        private SecureRandom secureRandom;
-        private bool forSigning;
-
-        public BigInteger Order
-        {
-            get { return key.Parameters.N; }
-        }
-
-        public string AlgorithmName
-        {
-            get { return key.AlgorithmName; }
-        }
-
-        public virtual void Init(bool forSigning, ICipherParameters parameters)
-        {
-            this.forSigning = forSigning;
-            if (forSigning)
-            {
-                if (parameters is ParametersWithRandom)
-                {
-                    ParametersWithRandom rParam = (ParametersWithRandom)parameters;
-                    this.secureRandom = rParam.Random;
-                    this.key = (ECPrivateKeyParameters)rParam.Parameters;
-                }
-                else
-                {
-                    this.secureRandom = new SecureRandom();
-                    this.key = (ECPrivateKeyParameters)parameters;
-                }
-            }
-            else
-            {
-                this.key = (ECPublicKeyParameters)parameters;
-            }
-        } 
-
-        public BigInteger[] GenerateSignature(byte[] message)
-        {
-            if (!forSigning)
-            {
-                throw new InvalidOperationException("not initialized for signing");
-            }
-
-            byte[] mRev = new byte[message.Length]; // conversion is little-endian
-            for (int i = 0; i != mRev.Length; i++)
-            {
-                mRev[i] = message[mRev.Length - 1 - i];
-            }
-            BigInteger e = new BigInteger(1, mRev);
-
-            ECDomainParameters ec = key.Parameters;
-            BigInteger n = ec.N;
-            BigInteger d = ((ECPrivateKeyParameters)key).D;
-
-            BigInteger r, s;
-
-            ECMultiplier basePointMultiplier = CreateBasePointMultiplier();
-
-            do // generate s
-            {
-                BigInteger k;
-                do // generate r
-                {
-                    do
-                    {
-                        k = BigIntegers.CreateRandomBigInteger(n.BitLength, secureRandom);
-                    }
-                    while (k.Equals(BigInteger.Zero)); //  ECConstants.ZERO));
-
-                    ECPoint p = basePointMultiplier.Multiply(ec.G, k).Normalize();
-
-                    r = p.AffineXCoord.ToBigInteger().Mod(n);
-                }
-                while (r.Equals(BigInteger.Zero)); //  ECConstants.ZERO));
-
-                s = (k.Multiply(e)).Add(d.Multiply(r)).Mod(n);
-            }
-            while (s.Equals(BigInteger.Zero)); //   ECConstants.ZERO));
-
-            return new BigInteger[] { r, s };
-        }
-
-
-        public bool VerifySignature(byte[] message, BigInteger r, BigInteger s)
-        {
-            if (forSigning)
-            {
-                throw new InvalidOperationException("not initialized for verification");
-            }
-
-
-            byte[] mRev = new byte[message.Length]; // conversion is little-endian
-            for (int i = 0; i != mRev.Length; i++)
-            {
-                mRev[i] = message[mRev.Length - 1 - i];
-            }
-            BigInteger e = new BigInteger(1, mRev);
-            BigInteger n = key.Parameters.N;
-
-            // r in the range [1,n-1]
-            if (r.CompareTo(BigInteger.One) < 0 || r.CompareTo(n) >= 0)
-            {
-                return false;
-            }
-
-            // s in the range [1,n-1]
-            if (s.CompareTo(BigInteger.One) < 0 || s.CompareTo(n) >= 0)
-            {
-                return false;
-            }
-
-            BigInteger v = e.ModInverse(n);
-
-            BigInteger z1 = s.Multiply(v).Mod(n);
-            BigInteger z2 = (n.Subtract(r)).Multiply(v).Mod(n);
-
-            ECPoint G = key.Parameters.G; // P
-            ECPoint Q = ((ECPublicKeyParameters)key).Q;
-
-            ECPoint point = ECAlgorithms.SumOfTwoMultiplies(G, z1, Q, z2).Normalize();
-
-            // components must be bogus.
-            if (point.IsInfinity)
-            {
-                return false;
-            }
-
-            BigInteger R = point.AffineXCoord.ToBigInteger().Mod(n);
-
-            return R.Equals(r);
-        }
-
-        protected virtual ECMultiplier CreateBasePointMultiplier()
-        {
-            return new FixedPointCombMultiplier();
-        }
-    }
-}
\ No newline at end of file
diff --git a/crypto/src/crypto/util/AlgorithmIdentifierFactory.cs b/crypto/src/crypto/util/AlgorithmIdentifierFactory.cs
new file mode 100644
index 000000000..20eac84ce
--- /dev/null
+++ b/crypto/src/crypto/util/AlgorithmIdentifierFactory.cs
@@ -0,0 +1,105 @@
+using System;
+using Org.BouncyCastle.Asn1;
+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.Asn1.X509;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Utilities
+{
+    public class AlgorithmIdentifierFactory
+    {
+        public static readonly DerObjectIdentifier IDEA_CBC = new DerObjectIdentifier("1.3.6.1.4.1.188.7.1.1.2");
+        public static readonly DerObjectIdentifier CAST5_CBC = new DerObjectIdentifier("1.2.840.113533.7.66.10");
+
+        private static readonly short[] rc2Table = {
+            0xbd, 0x56, 0xea, 0xf2, 0xa2, 0xf1, 0xac, 0x2a, 0xb0, 0x93, 0xd1, 0x9c, 0x1b, 0x33, 0xfd, 0xd0,
+            0x30, 0x04, 0xb6, 0xdc, 0x7d, 0xdf, 0x32, 0x4b, 0xf7, 0xcb, 0x45, 0x9b, 0x31, 0xbb, 0x21, 0x5a,
+            0x41, 0x9f, 0xe1, 0xd9, 0x4a, 0x4d, 0x9e, 0xda, 0xa0, 0x68, 0x2c, 0xc3, 0x27, 0x5f, 0x80, 0x36,
+            0x3e, 0xee, 0xfb, 0x95, 0x1a, 0xfe, 0xce, 0xa8, 0x34, 0xa9, 0x13, 0xf0, 0xa6, 0x3f, 0xd8, 0x0c,
+            0x78, 0x24, 0xaf, 0x23, 0x52, 0xc1, 0x67, 0x17, 0xf5, 0x66, 0x90, 0xe7, 0xe8, 0x07, 0xb8, 0x60,
+            0x48, 0xe6, 0x1e, 0x53, 0xf3, 0x92, 0xa4, 0x72, 0x8c, 0x08, 0x15, 0x6e, 0x86, 0x00, 0x84, 0xfa,
+            0xf4, 0x7f, 0x8a, 0x42, 0x19, 0xf6, 0xdb, 0xcd, 0x14, 0x8d, 0x50, 0x12, 0xba, 0x3c, 0x06, 0x4e,
+            0xec, 0xb3, 0x35, 0x11, 0xa1, 0x88, 0x8e, 0x2b, 0x94, 0x99, 0xb7, 0x71, 0x74, 0xd3, 0xe4, 0xbf,
+            0x3a, 0xde, 0x96, 0x0e, 0xbc, 0x0a, 0xed, 0x77, 0xfc, 0x37, 0x6b, 0x03, 0x79, 0x89, 0x62, 0xc6,
+            0xd7, 0xc0, 0xd2, 0x7c, 0x6a, 0x8b, 0x22, 0xa3, 0x5b, 0x05, 0x5d, 0x02, 0x75, 0xd5, 0x61, 0xe3,
+            0x18, 0x8f, 0x55, 0x51, 0xad, 0x1f, 0x0b, 0x5e, 0x85, 0xe5, 0xc2, 0x57, 0x63, 0xca, 0x3d, 0x6c,
+            0xb4, 0xc5, 0xcc, 0x70, 0xb2, 0x91, 0x59, 0x0d, 0x47, 0x20, 0xc8, 0x4f, 0x58, 0xe0, 0x01, 0xe2,
+            0x16, 0x38, 0xc4, 0x6f, 0x3b, 0x0f, 0x65, 0x46, 0xbe, 0x7e, 0x2d, 0x7b, 0x82, 0xf9, 0x40, 0xb5,
+            0x1d, 0x73, 0xf8, 0xeb, 0x26, 0xc7, 0x87, 0x97, 0x25, 0x54, 0xb1, 0x28, 0xaa, 0x98, 0x9d, 0xa5,
+            0x64, 0x6d, 0x7a, 0xd4, 0x10, 0x81, 0x44, 0xef, 0x49, 0xd6, 0xae, 0x2e, 0xdd, 0x76, 0x5c, 0x2f,
+            0xa7, 0x1c, 0xc9, 0x09, 0x69, 0x9a, 0x83, 0xcf, 0x29, 0x39, 0xb9, 0xe9, 0x4c, 0xff, 0x43, 0xab
+        };
+
+
+        /**
+    * Create an AlgorithmIdentifier for the passed in encryption algorithm.
+    *
+    * @param encryptionOID OID for the encryption algorithm
+    * @param keySize key size in bits (-1 if unknown)
+    * @param random SecureRandom to use for parameter generation.
+    * @return a full AlgorithmIdentifier including parameters
+    * @throws IllegalArgumentException if encryptionOID cannot be matched
+    */
+        public static AlgorithmIdentifier GenerateEncryptionAlgID(DerObjectIdentifier encryptionOID, int keySize, SecureRandom random)
+
+        {
+            if (encryptionOID.Equals(NistObjectIdentifiers.IdAes128Cbc)
+                    || encryptionOID.Equals(NistObjectIdentifiers.IdAes192Cbc)
+                    || encryptionOID.Equals(NistObjectIdentifiers.IdAes256Cbc)
+                    || encryptionOID.Equals(NttObjectIdentifiers.IdCamellia128Cbc)
+                    || encryptionOID.Equals(NttObjectIdentifiers.IdCamellia192Cbc)
+                    || encryptionOID.Equals(NttObjectIdentifiers.IdCamellia256Cbc)
+                    || encryptionOID.Equals(KisaObjectIdentifiers.IdSeedCbc))
+            {
+                byte[] iv = new byte[16];
+
+                random.NextBytes(iv);
+
+                return new AlgorithmIdentifier(encryptionOID, new DerOctetString(iv));
+            }
+            else if (encryptionOID.Equals(PkcsObjectIdentifiers.DesEde3Cbc)
+                    || encryptionOID.Equals(IDEA_CBC)
+                    || encryptionOID.Equals(OiwObjectIdentifiers.DesCbc))
+            {
+                byte[] iv = new byte[8];
+
+                random.NextBytes(iv);
+
+                return new AlgorithmIdentifier(encryptionOID, new DerOctetString(iv));
+            }
+            else if (encryptionOID.Equals(CAST5_CBC))
+            {
+                byte[] iv = new byte[8];
+
+                random.NextBytes(iv);
+
+                Cast5CbcParameters cbcParams = new Cast5CbcParameters(iv, keySize);
+
+                return new AlgorithmIdentifier(encryptionOID, cbcParams);
+            }
+            else if (encryptionOID.Equals(PkcsObjectIdentifiers.rc4))
+            {
+                return new AlgorithmIdentifier(encryptionOID, DerNull.Instance);
+            }
+            else if (encryptionOID.Equals(PkcsObjectIdentifiers.RC2Cbc))
+            {
+                byte[] iv = new byte[8];
+
+                random.NextBytes(iv);
+
+                RC2CbcParameter cbcParams = new RC2CbcParameter(rc2Table[128], iv);
+
+                return new AlgorithmIdentifier(encryptionOID, cbcParams);
+            }
+            else
+            {
+                throw new InvalidOperationException("unable to match algorithm");
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/crypto/src/crypto/util/CipherFactory.cs b/crypto/src/crypto/util/CipherFactory.cs
new file mode 100644
index 000000000..0a4010b42
--- /dev/null
+++ b/crypto/src/crypto/util/CipherFactory.cs
@@ -0,0 +1,151 @@
+using System;
+using Org.BouncyCastle.Asn1;
+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.Asn1.X509;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Modes;
+using Org.BouncyCastle.Crypto.Paddings;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Utilites
+{
+    public class CipherFactory
+    {
+        private CipherFactory()
+        {
+
+        }
+
+        private static readonly short[] rc2Ekb =
+        {
+            0x5d, 0xbe, 0x9b, 0x8b, 0x11, 0x99, 0x6e, 0x4d, 0x59, 0xf3, 0x85, 0xa6, 0x3f, 0xb7, 0x83, 0xc5,
+            0xe4, 0x73, 0x6b, 0x3a, 0x68, 0x5a, 0xc0, 0x47, 0xa0, 0x64, 0x34, 0x0c, 0xf1, 0xd0, 0x52, 0xa5,
+            0xb9, 0x1e, 0x96, 0x43, 0x41, 0xd8, 0xd4, 0x2c, 0xdb, 0xf8, 0x07, 0x77, 0x2a, 0xca, 0xeb, 0xef,
+            0x10, 0x1c, 0x16, 0x0d, 0x38, 0x72, 0x2f, 0x89, 0xc1, 0xf9, 0x80, 0xc4, 0x6d, 0xae, 0x30, 0x3d,
+            0xce, 0x20, 0x63, 0xfe, 0xe6, 0x1a, 0xc7, 0xb8, 0x50, 0xe8, 0x24, 0x17, 0xfc, 0x25, 0x6f, 0xbb,
+            0x6a, 0xa3, 0x44, 0x53, 0xd9, 0xa2, 0x01, 0xab, 0xbc, 0xb6, 0x1f, 0x98, 0xee, 0x9a, 0xa7, 0x2d,
+            0x4f, 0x9e, 0x8e, 0xac, 0xe0, 0xc6, 0x49, 0x46, 0x29, 0xf4, 0x94, 0x8a, 0xaf, 0xe1, 0x5b, 0xc3,
+            0xb3, 0x7b, 0x57, 0xd1, 0x7c, 0x9c, 0xed, 0x87, 0x40, 0x8c, 0xe2, 0xcb, 0x93, 0x14, 0xc9, 0x61,
+            0x2e, 0xe5, 0xcc, 0xf6, 0x5e, 0xa8, 0x5c, 0xd6, 0x75, 0x8d, 0x62, 0x95, 0x58, 0x69, 0x76, 0xa1,
+            0x4a, 0xb5, 0x55, 0x09, 0x78, 0x33, 0x82, 0xd7, 0xdd, 0x79, 0xf5, 0x1b, 0x0b, 0xde, 0x26, 0x21,
+            0x28, 0x74, 0x04, 0x97, 0x56, 0xdf, 0x3c, 0xf0, 0x37, 0x39, 0xdc, 0xff, 0x06, 0xa4, 0xea, 0x42,
+            0x08, 0xda, 0xb4, 0x71, 0xb0, 0xcf, 0x12, 0x7a, 0x4e, 0xfa, 0x6c, 0x1d, 0x84, 0x00, 0xc8, 0x7f,
+            0x91, 0x45, 0xaa, 0x2b, 0xc2, 0xb1, 0x8f, 0xd5, 0xba, 0xf2, 0xad, 0x19, 0xb2, 0x67, 0x36, 0xf7,
+            0x0f, 0x0a, 0x92, 0x7d, 0xe3, 0x9d, 0xe9, 0x90, 0x3e, 0x23, 0x27, 0x66, 0x13, 0xec, 0x81, 0x15,
+            0xbd, 0x22, 0xbf, 0x9f, 0x7e, 0xa9, 0x51, 0x4b, 0x4c, 0xfb, 0x02, 0xd3, 0x70, 0x86, 0x31, 0xe7,
+            0x3b, 0x05, 0x03, 0x54, 0x60, 0x48, 0x65, 0x18, 0xd2, 0xcd, 0x5f, 0x32, 0x88, 0x0e, 0x35, 0xfd
+        };
+
+        public static object CreateContentCipher(bool forEncryption, ICipherParameters encKey,
+            AlgorithmIdentifier encryptionAlgID)
+        {
+            DerObjectIdentifier encAlg = encryptionAlgID.Algorithm;
+
+            if (encAlg.Equals(PkcsObjectIdentifiers.rc4))
+            {
+                IStreamCipher cipher = new RC4Engine();
+
+                cipher.Init(forEncryption, encKey);
+
+                return cipher;
+            }
+            else
+            {
+                BufferedBlockCipher cipher = CreateCipher(encryptionAlgID.Algorithm);
+
+                Asn1Object sParams = encryptionAlgID.Parameters.ToAsn1Object();
+
+                if (sParams != null && !(sParams is DerNull))
+                {
+                    if (encAlg.Equals(PkcsObjectIdentifiers.DesEde3Cbc)
+                        || encAlg.Equals(AlgorithmIdentifierFactory.IDEA_CBC)
+                        || encAlg.Equals(NistObjectIdentifiers.IdAes128Cbc)
+                        || encAlg.Equals(NistObjectIdentifiers.IdAes192Cbc)
+                        || encAlg.Equals(NistObjectIdentifiers.IdAes256Cbc)
+                        || encAlg.Equals(NttObjectIdentifiers.IdCamellia128Cbc)
+                        || encAlg.Equals(NttObjectIdentifiers.IdCamellia192Cbc)
+                        || encAlg.Equals(NttObjectIdentifiers.IdCamellia256Cbc)
+                        || encAlg.Equals(KisaObjectIdentifiers.IdSeedCbc)
+                        || encAlg.Equals(OiwObjectIdentifiers.DesCbc))
+                    {
+                        cipher.Init(forEncryption, new ParametersWithIV(encKey,
+                            Asn1OctetString.GetInstance(sParams).GetOctets()));
+                    }
+                    else if (encAlg.Equals(AlgorithmIdentifierFactory.CAST5_CBC))
+                    {
+                        Cast5CbcParameters cbcParams = Cast5CbcParameters.GetInstance(sParams);
+
+                        cipher.Init(forEncryption, new ParametersWithIV(encKey, cbcParams.GetIV()));
+                    }
+                    else if (encAlg.Equals(PkcsObjectIdentifiers.RC2Cbc))
+                    {
+                        RC2CbcParameter cbcParams = RC2CbcParameter.GetInstance(sParams);
+
+                        cipher.Init(forEncryption, new ParametersWithIV(new RC2Parameters(((KeyParameter)encKey).GetKey(), rc2Ekb[cbcParams.RC2ParameterVersion.IntValue]), cbcParams.GetIV()));
+                    }
+                    else
+                    {
+                        throw new InvalidOperationException("cannot match parameters");
+                    }
+                }
+                else
+                {
+                    if (encAlg.Equals(PkcsObjectIdentifiers.DesEde3Cbc)
+                        || encAlg.Equals(AlgorithmIdentifierFactory.IDEA_CBC)
+                        || encAlg.Equals(AlgorithmIdentifierFactory.CAST5_CBC))
+                    {
+                        cipher.Init(forEncryption, new ParametersWithIV(encKey, new byte[8]));
+                    }
+                    else
+                    {
+                        cipher.Init(forEncryption, encKey);
+                    }
+                }
+
+                return cipher;
+            }
+
+        }
+
+        private static BufferedBlockCipher CreateCipher(DerObjectIdentifier algorithm)
+        {
+            IBlockCipher cipher;
+
+            if (NistObjectIdentifiers.IdAes128Cbc.Equals(algorithm)
+        || NistObjectIdentifiers.IdAes192Cbc.Equals(algorithm)
+        || NistObjectIdentifiers.IdAes256Cbc.Equals(algorithm))
+            {
+                cipher = new CbcBlockCipher(new AesEngine());
+            }
+            else if (PkcsObjectIdentifiers.DesEde3Cbc.Equals(algorithm))
+            {
+                cipher = new CbcBlockCipher(new DesEdeEngine());
+            }
+            else if (OiwObjectIdentifiers.DesCbc.Equals(algorithm))
+            {
+                cipher = new CbcBlockCipher(new DesEngine());
+            }
+            else if (PkcsObjectIdentifiers.RC2Cbc.Equals(algorithm))
+            {
+                cipher = new CbcBlockCipher(new RC2Engine());
+            }
+            else if (MiscObjectIdentifiers.cast5CBC.Equals(algorithm))
+            {
+                cipher = new CbcBlockCipher(new Cast5Engine());
+            }
+            else
+            {
+                throw new InvalidOperationException("cannot recognise cipher: " + algorithm);
+            }
+
+            return new PaddedBufferedBlockCipher(cipher, new Pkcs7Padding());
+        }
+
+    }
+}
diff --git a/crypto/src/crypto/util/CipherKeyGeneratorFactory.cs b/crypto/src/crypto/util/CipherKeyGeneratorFactory.cs
new file mode 100644
index 000000000..f714c40fd
--- /dev/null
+++ b/crypto/src/crypto/util/CipherKeyGeneratorFactory.cs
@@ -0,0 +1,101 @@
+using System;
+using Org.BouncyCastle.Asn1;
+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.Generators;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Utilities
+{
+    public class CipherKeyGeneratorFactory
+    {
+        private CipherKeyGeneratorFactory()
+        {
+
+        }
+
+        /**
+   * Create a key generator for the passed in Object Identifier.
+   *
+   * @param algorithm the Object Identifier indicating the algorithn the generator is for.
+   * @param random a source of random to initialise the generator with.
+   * @return an initialised CipherKeyGenerator.
+   * @throws IllegalArgumentException if the algorithm cannot be identified.
+   */
+        public static CipherKeyGenerator CreateKeyGenerator(DerObjectIdentifier algorithm, SecureRandom random)
+        {
+            if (NistObjectIdentifiers.IdAes128Cbc.Equals(algorithm))
+            {
+                return createCipherKeyGenerator(random, 128);
+            }
+            else if (NistObjectIdentifiers.IdAes192Cbc.Equals(algorithm))
+            {
+                return createCipherKeyGenerator(random, 192);
+            }
+            else if (NistObjectIdentifiers.IdAes256Cbc.Equals(algorithm))
+            {
+                return createCipherKeyGenerator(random, 256);
+            }
+            else if (PkcsObjectIdentifiers.DesEde3Cbc.Equals(algorithm))
+            {
+                DesEdeKeyGenerator keyGen = new DesEdeKeyGenerator();
+
+                keyGen.Init(new KeyGenerationParameters(random, 192));
+
+                return keyGen;
+            }
+            else if (NttObjectIdentifiers.IdCamellia128Cbc.Equals(algorithm))
+            {
+                return createCipherKeyGenerator(random, 128);
+            }
+            else if (NttObjectIdentifiers.IdCamellia192Cbc.Equals(algorithm))
+            {
+                return createCipherKeyGenerator(random, 192);
+            }
+            else if (NttObjectIdentifiers.IdCamellia256Cbc.Equals(algorithm))
+            {
+                return createCipherKeyGenerator(random, 256);
+            }
+            else if (KisaObjectIdentifiers.IdSeedCbc.Equals(algorithm))
+            {
+                return createCipherKeyGenerator(random, 128);
+            }
+            else if (AlgorithmIdentifierFactory.CAST5_CBC.Equals(algorithm))
+            {
+                return createCipherKeyGenerator(random, 128);
+            }
+            else if (OiwObjectIdentifiers.DesCbc.Equals(algorithm))
+            {
+                DesKeyGenerator keyGen = new DesKeyGenerator();
+
+                keyGen.Init(new KeyGenerationParameters(random, 64));
+
+                return keyGen;
+            }
+            else if (PkcsObjectIdentifiers.rc4.Equals(algorithm))
+            {
+                return createCipherKeyGenerator(random, 128);
+            }
+            else if (PkcsObjectIdentifiers.RC2Cbc.Equals(algorithm))
+            {
+                return createCipherKeyGenerator(random, 128);
+            }
+            else
+            {
+                throw new InvalidOperationException("cannot recognise cipher: " + algorithm);
+            }
+        }
+
+        private static CipherKeyGenerator createCipherKeyGenerator(SecureRandom random, int keySize)
+        {
+            CipherKeyGenerator keyGen = new CipherKeyGenerator();
+
+            keyGen.Init(new KeyGenerationParameters(random, keySize));
+
+            return keyGen;
+        }
+    }
+}
\ No newline at end of file
diff --git a/crypto/src/pkcs/PrivateKeyInfoFactory.cs b/crypto/src/pkcs/PrivateKeyInfoFactory.cs
index 75a56983a..0d5026909 100644
--- a/crypto/src/pkcs/PrivateKeyInfoFactory.cs
+++ b/crypto/src/pkcs/PrivateKeyInfoFactory.cs
@@ -124,9 +124,9 @@ namespace Org.BouncyCastle.Pkcs
                 ECDomainParameters dp = priv.Parameters;
 
                 // ECGOST3410
-                if (dp is ECGOST3410Parameters)
+                if (dp is ECGost3410Parameters)
                 {
-                    ECGOST3410Parameters domainParameters = (ECGOST3410Parameters) dp;
+                    ECGost3410Parameters domainParameters = (ECGost3410Parameters) dp;
 
                     Gost3410PublicKeyAlgParameters gostParams = new Gost3410PublicKeyAlgParameters(
                         (domainParameters).PublicKeyParamSet,
diff --git a/crypto/src/security/DigestUtilities.cs b/crypto/src/security/DigestUtilities.cs
index 24a68f63d..7685e3384 100644
--- a/crypto/src/security/DigestUtilities.cs
+++ b/crypto/src/security/DigestUtilities.cs
@@ -213,8 +213,8 @@ namespace Org.BouncyCastle.Security
                     case DigestAlgorithm.DSTU7564_384: return new Dstu7564Digest(384);
                     case DigestAlgorithm.DSTU7564_512: return new Dstu7564Digest(512);
                     case DigestAlgorithm.GOST3411: return new Gost3411Digest();
-                    case DigestAlgorithm.GOST3411_2012_256: return new GOST3411_2012_256Digest();
-                    case DigestAlgorithm.GOST3411_2012_512: return new GOST3411_2012_512Digest();
+                    case DigestAlgorithm.GOST3411_2012_256: return new Gost3411_2012_256Digest();
+                    case DigestAlgorithm.GOST3411_2012_512: return new Gost3411_2012_512Digest();
                     case DigestAlgorithm.KECCAK_224: return new KeccakDigest(224);
                     case DigestAlgorithm.KECCAK_256: return new KeccakDigest(256);
                     case DigestAlgorithm.KECCAK_288: return new KeccakDigest(288);
diff --git a/crypto/src/security/PrivateKeyFactory.cs b/crypto/src/security/PrivateKeyFactory.cs
index 9f2d2e9c1..f7709160d 100644
--- a/crypto/src/security/PrivateKeyFactory.cs
+++ b/crypto/src/security/PrivateKeyFactory.cs
@@ -192,7 +192,7 @@ namespace Org.BouncyCastle.Security
                      || algOid.Equals(RosstandartObjectIdentifiers.id_tc26_gost_3410_12_256))
             {
                 Gost3410PublicKeyAlgParameters gostParams = Gost3410PublicKeyAlgParameters.GetInstance(keyInfo.PrivateKeyAlgorithm.Parameters);
-                ECGOST3410Parameters ecSpec = null;
+                ECGost3410Parameters ecSpec = null;
                 BigInteger d = null;
                 Asn1Object p = keyInfo.PrivateKeyAlgorithm.Parameters.ToAsn1Object();
                 if (p is Asn1Sequence && (Asn1Sequence.GetInstance(p).Count == 2 || Asn1Sequence.GetInstance(p).Count == 3))
@@ -200,7 +200,7 @@ namespace Org.BouncyCastle.Security
 
                     ECDomainParameters ecP = ECGost3410NamedCurves.GetByOid(gostParams.PublicKeyParamSet);
 
-                    ecSpec = new ECGOST3410Parameters(
+                    ecSpec = new ECGost3410Parameters(
                         new ECNamedDomainParameters(
                             gostParams.PublicKeyParamSet, ecP),
                             gostParams.PublicKeyParamSet,
@@ -237,7 +237,7 @@ namespace Org.BouncyCastle.Security
                         if (ecP == null)
                         {
                             ECDomainParameters gParam = ECGost3410NamedCurves.GetByOid(oid);
-                            ecSpec = new ECGOST3410Parameters(new ECNamedDomainParameters(
+                            ecSpec = new ECGost3410Parameters(new ECNamedDomainParameters(
                                     oid,
                                     gParam.Curve,
                                     gParam.G,
@@ -248,7 +248,7 @@ namespace Org.BouncyCastle.Security
                         }
                         else
                         {
-                            ecSpec = new ECGOST3410Parameters(new ECNamedDomainParameters(
+                            ecSpec = new ECGost3410Parameters(new ECNamedDomainParameters(
                                     oid,
                                     ecP.Curve,
                                     ecP.G,
@@ -265,7 +265,7 @@ namespace Org.BouncyCastle.Security
                     else
                     {
                         X9ECParameters ecP = X9ECParameters.GetInstance(parameters.Parameters);
-                        ecSpec = new ECGOST3410Parameters(new ECNamedDomainParameters(
+                        ecSpec = new ECGost3410Parameters(new ECNamedDomainParameters(
                                 algOid,
                                 ecP.Curve,
                                 ecP.G,
@@ -292,7 +292,7 @@ namespace Org.BouncyCastle.Security
 
                 return new ECPrivateKeyParameters(
                     d,
-                    new ECGOST3410Parameters(
+                    new ECGost3410Parameters(
                         ecSpec,
                         gostParams.PublicKeyParamSet,
                         gostParams.DigestParamSet,
diff --git a/crypto/src/security/PublicKeyFactory.cs b/crypto/src/security/PublicKeyFactory.cs
index 3623c3ee2..7a34d71df 100644
--- a/crypto/src/security/PublicKeyFactory.cs
+++ b/crypto/src/security/PublicKeyFactory.cs
@@ -261,8 +261,8 @@ namespace Org.BouncyCastle.Security
 
                 Gost3410PublicKeyAlgParameters gostParams = Gost3410PublicKeyAlgParameters.GetInstance(keyInfo.AlgorithmID.Parameters);
 
-                ECGOST3410Parameters ecDomainParameters =
-                    new ECGOST3410Parameters(
+                ECGost3410Parameters ecDomainParameters =
+                    new ECGost3410Parameters(
                         new ECNamedDomainParameters(gostParams.PublicKeyParamSet, ECGost3410NamedCurves.GetByOid(gostParams.PublicKeyParamSet)),
                         gostParams.PublicKeyParamSet,
                         gostParams.DigestParamSet,
diff --git a/crypto/src/x509/SubjectPublicKeyInfoFactory.cs b/crypto/src/x509/SubjectPublicKeyInfoFactory.cs
index 234bcff34..395c31263 100644
--- a/crypto/src/x509/SubjectPublicKeyInfoFactory.cs
+++ b/crypto/src/x509/SubjectPublicKeyInfoFactory.cs
@@ -98,9 +98,9 @@ namespace Org.BouncyCastle.X509
                 ECPublicKeyParameters _key = (ECPublicKeyParameters) publicKey;
 
 
-                if (_key.Parameters is ECGOST3410Parameters)
+                if (_key.Parameters is ECGost3410Parameters)
                 {
-                    ECGOST3410Parameters gostParams = (ECGOST3410Parameters)_key.Parameters;
+                    ECGost3410Parameters gostParams = (ECGost3410Parameters)_key.Parameters;
 
                     BigInteger bX = _key.Q.AffineXCoord.ToBigInteger();
                     BigInteger bY = _key.Q.AffineYCoord.ToBigInteger();
diff --git a/crypto/test/src/crmf/test/CrmfTest.cs b/crypto/test/src/crmf/test/CrmfTest.cs
new file mode 100644
index 000000000..b1f18cc7b
--- /dev/null
+++ b/crypto/test/src/crmf/test/CrmfTest.cs
@@ -0,0 +1,188 @@
+using System;
+using System.Collections;
+using NUnit.Core;
+using NUnit.Framework;
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.Crmf;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Cmp.Tests;
+using Org.BouncyCastle.Cms;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Operators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Pkcs;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.Operators;
+
+namespace Org.BouncyCastle.Crmf.Tests
+{
+    [TestFixture]
+    public class CrmfTest : SimpleTest
+    {
+
+
+        public override string Name => "CRMF Tests";
+
+
+        public override void PerformTest()
+        {
+            TestFromJVM();
+            TestBasicMessage();
+            TestBasicMessageWithArchiveControl();
+            TestBasicMessageWithArchiveControlJVMGenerated();
+        }
+        
+        [Test]
+        public void TestFromJVM()
+        {
+            var pubKey = PublicKeyFactory.CreateKey(Hex.Decode(
+                "305c300d06092a864886f70d0101010500034b003048024100bbb3f6a5031fbb1feedbfed7584a4f6321ccdc16b9526b0f6e31859328db35a6ec420a98e14fb3bcf192004b1aa6fc9269410204785cc01317232feb545a7b410203010001"));
+            var privKey = PrivateKeyFactory.CreateKey(Hex.Decode("30820153020100300d06092a864886f70d01010105000482013d30820139020100024100bbb3f6a5031fbb1feedbfed7584a4f6321ccdc16b9526b0f6e31859328db35a6ec420a98e14fb3bcf192004b1aa6fc9269410204785cc01317232feb545a7b41020301000102400093b384b9021c4cd59888e956cb1e653e736833235315b0e938116da19a9276b1ea1fe33da580a497313f08eb3e7c14627508a4284be04ea3e6ba8cb4b0a5c9022100e2fe0d9f35bfd7ecf196227e5e915a2464478ea7033c6dff4ce6a02961759a49022100d3b093770745dfea42c5c5c31f1a6b797a60dfb5503ae60f70b864452c4a193902203cc761c65b91feb3070cf8377602dd6c191dbfe8a04931fac6108a9a09ea7f61022071bb2a5f06af49cfc8340d3df995ee2c03cdcc22d389f15456511abdf73f9031022065bc10d43192cb3131c53be18a0d41a060d4e0a3324a47e3eb4bf720e1b46b10"));
+
+            var rawMsg = Hex.Decode("3081cc30760201013071a511300f310d300b0603550403130454657374a65c300d06092a864886f70d0101010500034b003048024100bbb3f6a5031fbb1feedbfed7584a4f6321ccdc16b9526b0f6e31859328db35a6ec420a98e14fb3bcf192004b1aa6fc9269410204785cc01317232feb545a7b410203010001a152300d06092a864886f70d01010505000341003120cdb58edfef4a2e1a4bfe96b972007c1d1c949221d266efe28b45ba036b9d534f5dca261dce8f21e134d97e55c3bd76d1460781fd9703f8f9907d1f036c20");
+
+            var msg = new CertificateRequestMessage(rawMsg);
+            IsTrue("Pop Valid",msg.IsValidSigningKeyPop(new Asn1VerifierFactoryProvider(pubKey)));
+
+            //
+            // Vandalize message to check for failure.
+            //
+
+            rawMsg[7] ^= 1;
+            msg = new CertificateRequestMessage(rawMsg);
+                  
+            IsTrue("Pop Verified Vandalized Message!", !msg.IsValidSigningKeyPop(new Asn1VerifierFactoryProvider(pubKey)));
+
+        }
+
+
+
+        [Test]
+        public void TestBasicMessage()
+        {
+            var rsaKeyPairGenerator = new RsaKeyPairGenerator();
+            rsaKeyPairGenerator.Init(new RsaKeyGenerationParameters(BigInteger.ValueOf(65537), new SecureRandom(), 2048, 100));
+            var rsaKeyPair = rsaKeyPairGenerator.GenerateKeyPair();
+
+            var certReqBuild = new CertificateRequestMessageBuilder(BigInteger.One);
+                      
+            certReqBuild.SetSubject(new X509Name("CN=Test"))
+                .SetPublicKey(SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(rsaKeyPair.Public))                
+                .SetProofOfPossessionSignKeySigner(new Asn1SignatureFactory("SHA1WithRSA", rsaKeyPair.Private));
+
+            var certificateRequestMessage = certReqBuild.Build();
+                            
+            IsTrue("Signing Key Pop Valid",certificateRequestMessage.IsValidSigningKeyPop(new Asn1VerifierFactoryProvider(rsaKeyPair.Public)));
+            IsTrue(certificateRequestMessage.GetCertTemplate().Subject.Equivalent(new X509Name("CN=Test")));
+            IsTrue(certificateRequestMessage.GetCertTemplate().PublicKey.Equals(SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(rsaKeyPair.Public)));
+        }
+
+        [Test]
+        public void TestBasicMessageWithArchiveControl()
+        {
+            var rsaKeyPairGenerator = new RsaKeyPairGenerator();
+            rsaKeyPairGenerator.Init(new RsaKeyGenerationParameters(BigInteger.ValueOf(65537), new SecureRandom(), 2048, 100));
+            var rsaKeyPair = rsaKeyPairGenerator.GenerateKeyPair();
+
+            var tcb = new TestCertBuilder()
+            {
+                PublicKey = rsaKeyPair.Public,
+                Subject = new X509Name("CN=Test"),
+                Issuer = new X509Name("CN=Test"),
+                NotBefore = DateTime.UtcNow.AddDays(-1),
+                NotAfter = DateTime.UtcNow.AddDays(1),
+                SignatureAlgorithm = "Sha1WithRSAEncryption"
+            };
+
+            var cert = tcb.Build(rsaKeyPair.Private);         
+
+            var publicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(rsaKeyPair.Public);
+            var privateInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(rsaKeyPair.Private);
+
+
+            var certificateRequestMessageBuilder = new CertificateRequestMessageBuilder(BigInteger.One);
+            certificateRequestMessageBuilder.SetSubject(new X509Name("CN=Test"));
+            certificateRequestMessageBuilder.SetPublicKey(publicKeyInfo);
+           
+            certificateRequestMessageBuilder.AddControl(
+                new PkiArchiveControlBuilder(privateInfo, new GeneralName(new X509Name("CN=Test")))
+                    .AddRecipientGenerator(new CmsKeyTransRecipientInfoGenerator(cert, new Asn1KeyWrapper("RSA/None/OAEPwithSHA256andMGF1Padding", cert)))
+                    .Build(new CmsContentEncryptorBuilder(NistObjectIdentifiers.IdAes128Cbc).Build())
+            );
+
+            var msg = certificateRequestMessageBuilder.Build();
+
+            IsTrue(Arrays.AreEqual(msg.GetCertTemplate().Subject.GetEncoded(), new X509Name("CN=Test").GetEncoded()));
+            IsTrue(Arrays.AreEqual(msg.GetCertTemplate().PublicKey.GetEncoded(),publicKeyInfo.GetEncoded()));
+
+            checkCertReqMsgWithArchiveControl(rsaKeyPair,msg);
+            checkCertReqMsgWithArchiveControl(rsaKeyPair, new CertificateRequestMessage(msg.GetEncoded()));
+         
+        }
+
+        [Test]
+        public void TestBasicMessageWithArchiveControlJVMGenerated()
+        {
+            AsymmetricKeyParameter publicKey = PublicKeyFactory.CreateKey(
+                Hex.Decode("305c300d06092a864886f70d0101010500034b003048024100a9a94b7b98dc3daf8cac032a14bd4510832b0e007edbdafc065e328645a35828b8185cdbf73ed495c88436b11a9322965595d2e4c1dd63c3c4d41812f876b3070203010001"));
+            AsymmetricKeyParameter privateKey = PrivateKeyFactory.CreateKey(
+                Hex.Decode("30820154020100300d06092a864886f70d01010105000482013e3082013a020100024100a9a94b7b98dc3daf8cac032a14bd4510832b0e007edbdafc065e328645a35828b8185cdbf73ed495c88436b11a9322965595d2e4c1dd63c3c4d41812f876b307020301000102400831deacfe21a9331902d7f648e1297c563196b00c70971fb439098cb5c1618925bdbac4c66b30f8956660220f326f51e5a1725ce690165154fb62fa14497265022100e54943be1b4951e127f6e79c5ab333cba4b0fff0b5e59328d6393ba98dc0e6c3022100bd6da58ce195146a1d3825ec2a622cf4962da653096bea87fbd9a94db266a66d0221008948bcceeef78f97089ec53ed0efcb6b7b489f7638f32491a6f2cdce4f99d89102204eb1b066d8883054ed12985e863506ec0d3fa5ab356cc99ff876b228ff0639f9022024049aaf39bf9a0ddfbd4caee277d0a9f07d075faae12571176a5c0ca40415c0"));
+        
+            CertificateRequestMessage msg = new CertificateRequestMessage(
+                Hex.Decode("308202af308202ab0201013071a511300f310d300b0603550403130454657374a65c300d06092a864886f70d0101010500034b003048024100a9a94b7b98dc3daf8cac032a14bd4510832b0e007edbdafc065e328645a35828b8185cdbf73ed495c88436b11a9322965595d2e4c1dd63c3c4d41812f876b3070203010001308202313082022d06092b0601050507050104a082021ea082021a0201003171306f0201003019300f310d300b06035504030c04546573740206016859de5806300d06092a864886f70d0101010500044066f1a72f808908af784b83c07895276104d7c4caaee6090212ce5b27517aec510425b784352b5342c999f844b8796286f10a59807e290f06aa39f8cba86dd6bf308201a0060b2a864886f70d0109100115301d060960864801650304010204104aceaa277cc7974ea2a775ff9db6062580820170c648e70c25c4789d2ff4ed398e5536efb45d2dd8ba76a628ad30bf9596a18337afc0f596f0c18e05fb3fa9944ed9691dae1d9b327b5bbafaaa63efb0e22d675811c27bfb023b80184325fd4b67b3b9e41bf43c5583a86433b230e09a34b61397ddff0eadf10c883fc1f01860e2a56ab4002dcc4d4925c53e09dde0b99928fdf602bce544722155cebd8816e91a411a99feea07695774cd8883034022d57f64e9cd3383c3125c48db2936b7395a22b17910be1f2c0b8650bdb5bd752ffc40fcd30169e5ae3a4ac7ad9cc850e9c17bbcf8e1a1898d0d8be19145c484467b8f1124657a5e08c10fc67416274990cc16d55c9fb76c265dd436b7e803425892297f1a08e4fab8e178874b2b3bf9c749693d609db208e9a3ebbddd26cd6a1b33c0201532170dc6c303e7ac0c42ba0bc54dfb928b228842b6bb08d8dc411d262dabf140a8b5a5c67ea486c1877a2fc000981d54cf2decaf1cfeebcf83134992b09a2b1fe9e02da25b874604b5d8bbd609875ba8"));
+
+            AsymmetricCipherKeyPair rsaKeyPair = new AsymmetricCipherKeyPair(publicKey,privateKey);
+
+
+            SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKey);
+
+
+            Console.WriteLine(msg.GetCertTemplate().Subject.Equivalent(new X509Name("CN=Test")));
+
+            IsTrue(msg.GetCertTemplate().Subject.Equivalent(new X509Name("CN=Test")));
+            IsTrue(Arrays.AreEqual(msg.GetCertTemplate().PublicKey.GetEncoded(), publicKeyInfo.GetEncoded()));
+
+            checkCertReqMsgWithArchiveControl(rsaKeyPair, msg);
+            checkCertReqMsgWithArchiveControl(rsaKeyPair, new CertificateRequestMessage(msg.GetEncoded()));
+        
+            checkCertReqMsgWithArchiveControl(rsaKeyPair,msg);
+        }
+
+        private void checkCertReqMsgWithArchiveControl(AsymmetricCipherKeyPair kp, CertificateRequestMessage certReqMessage)
+        {
+            var archiveControl =
+                (PkiArchiveControl) certReqMessage.GetControl(CrmfObjectIdentifiers.id_regCtrl_pkiArchiveOptions);
+            IsEquals("Archive type", PkiArchiveControl.encryptedPrivKey, archiveControl.ArchiveType);
+
+            IsTrue(archiveControl.EnvelopedData);
+            RecipientInformationStore recips = archiveControl.GetEnvelopedData().GetRecipientInfos();
+
+            ArrayList collection =  (ArrayList)recips.GetRecipients();
+
+            IsTrue(collection.Count == 1);
+            KeyTransRecipientInformation info = (KeyTransRecipientInformation)collection[0];
+
+            EncKeyWithID encKeyWithId = EncKeyWithID.GetInstance(info.GetContent(kp.Private));
+                   
+
+            IsTrue(encKeyWithId.HasIdentifier);
+            IsTrue(!encKeyWithId.IsIdentifierUtf8String); // GeneralName at this point.
+            
+            IsTrue("Name", X509Name.GetInstance(GeneralName.GetInstance(encKeyWithId.Identifier).Name).Equivalent(new X509Name("CN=Test")));
+          
+            PrivateKeyInfo privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(kp.Private);
+            IsTrue("Private Key", Arrays.AreEqual(privateKeyInfo.GetEncoded(), encKeyWithId.PrivateKey.GetEncoded()));
+                            
+        }
+
+    }
+}
\ No newline at end of file
diff --git a/crypto/test/src/crypto/test/ECGOST3410_2012Test.cs b/crypto/test/src/crypto/test/ECGOST3410_2012Test.cs
index 94726bc92..8c5997835 100644
--- a/crypto/test/src/crypto/test/ECGOST3410_2012Test.cs
+++ b/crypto/test/src/crypto/test/ECGOST3410_2012Test.cs
@@ -29,7 +29,7 @@ namespace Org.BouncyCastle.Crypto.Tests
 
             DerObjectIdentifier oid = ECGost3410NamedCurves.GetOid("Tc26-Gost-3410-12-512-paramSetA");
             ECNamedDomainParameters ecp = new ECNamedDomainParameters(oid, ECGost3410NamedCurves.GetByOid(oid));
-            ECGOST3410Parameters gostParams = new ECGOST3410Parameters(ecp, oid, RosstandartObjectIdentifiers.id_tc26_gost_3411_12_512,null);
+            ECGost3410Parameters gostParams = new ECGost3410Parameters(ecp, oid, RosstandartObjectIdentifiers.id_tc26_gost_3411_12_512,null);
             ECKeyGenerationParameters paramameters = new ECKeyGenerationParameters(gostParams, new SecureRandom());
             ECKeyPairGenerator engine = new ECKeyPairGenerator();
             engine.Init(paramameters);
@@ -49,8 +49,8 @@ namespace Org.BouncyCastle.Crypto.Tests
                     keyParameters = (ECPublicKeyParameters)PublicKeyFactory.CreateKey(info);
 
                     { // Specifically cast and test gost parameters.
-                        ECGOST3410Parameters gParam = (ECGOST3410Parameters)generatedKeyParameters.Parameters;
-                        ECGOST3410Parameters rParam = (ECGOST3410Parameters)keyParameters.Parameters;
+                        ECGost3410Parameters gParam = (ECGost3410Parameters)generatedKeyParameters.Parameters;
+                        ECGost3410Parameters rParam = (ECGost3410Parameters)keyParameters.Parameters;
 
 
                         bool ok = SafeEquals(gParam.DigestParamSet, rParam.DigestParamSet) &&
@@ -64,8 +64,8 @@ namespace Org.BouncyCastle.Crypto.Tests
 
                     }
 
-                    if (!((ECGOST3410Parameters)keyParameters.Parameters).Name.Equals(
-                        ((ECGOST3410Parameters)generatedKeyParameters.Parameters).Name))
+                    if (!((ECGost3410Parameters)keyParameters.Parameters).Name.Equals(
+                        ((ECGost3410Parameters)generatedKeyParameters.Parameters).Name))
                     {
                         return new SimpleTestResult(false, "Name does not match");
                     }
@@ -124,7 +124,7 @@ namespace Org.BouncyCastle.Crypto.Tests
            
                 DerObjectIdentifier oid = ECGost3410NamedCurves.GetOid("Tc26-Gost-3410-12-512-paramSetA");
                 ECNamedDomainParameters ecp = new ECNamedDomainParameters(oid, ECGost3410NamedCurves.GetByOid(oid));
-                ECGOST3410Parameters gostParams = new ECGOST3410Parameters(ecp, oid, RosstandartObjectIdentifiers.id_tc26_gost_3411_12_512,null);
+                ECGost3410Parameters gostParams = new ECGost3410Parameters(ecp, oid, RosstandartObjectIdentifiers.id_tc26_gost_3411_12_512,null);
                 ECKeyGenerationParameters parameters = new ECKeyGenerationParameters(gostParams, new SecureRandom());
                 ECKeyPairGenerator engine = new ECKeyPairGenerator();
                 engine.Init(parameters);
@@ -145,8 +145,8 @@ namespace Org.BouncyCastle.Crypto.Tests
                     keyParameters = (ECPrivateKeyParameters)PrivateKeyFactory.CreateKey(info);
 
                     { // Specifically cast and test gost parameters.
-                        ECGOST3410Parameters gParam = (ECGOST3410Parameters)generatedKeyParameters.Parameters;
-                        ECGOST3410Parameters rParam = (ECGOST3410Parameters)keyParameters.Parameters;
+                        ECGost3410Parameters gParam = (ECGost3410Parameters)generatedKeyParameters.Parameters;
+                        ECGost3410Parameters rParam = (ECGost3410Parameters)keyParameters.Parameters;
 
                         bool ok = SafeEquals(gParam.DigestParamSet, rParam.DigestParamSet) &&
                             SafeEquals(gParam.EncryptionParamSet, rParam.EncryptionParamSet) &&
@@ -169,8 +169,8 @@ namespace Org.BouncyCastle.Crypto.Tests
                         return new SimpleTestResult(false, "D does not match");
                     }
 
-                    if (!((ECGOST3410Parameters)keyParameters.Parameters).Name.Equals(
-                        ((ECGOST3410Parameters)generatedKeyParameters.Parameters).Name))
+                    if (!((ECGost3410Parameters)keyParameters.Parameters).Name.Equals(
+                        ((ECGost3410Parameters)generatedKeyParameters.Parameters).Name))
                     {
                         return new SimpleTestResult(false, "Name does not match");
                     }
@@ -232,17 +232,17 @@ namespace Org.BouncyCastle.Crypto.Tests
                     return new SimpleTestResult(false, "Q does not match");
                 }
 
-                if (!((ECGOST3410Parameters)pkInfo.Parameters).PublicKeyParamSet.ToString().Equals("1.2.643.7.1.2.1.1.1"))
+                if (!((ECGost3410Parameters)pkInfo.Parameters).PublicKeyParamSet.ToString().Equals("1.2.643.7.1.2.1.1.1"))
                 {
                     return new SimpleTestResult(false, "PublicKeyParamSet does not match");
                 }
 
-                if (!((ECGOST3410Parameters)pkInfo.Parameters).DigestParamSet.ToString().Equals("1.2.643.7.1.1.2.2"))
+                if (!((ECGost3410Parameters)pkInfo.Parameters).DigestParamSet.ToString().Equals("1.2.643.7.1.1.2.2"))
                 {
                     return new SimpleTestResult(false, "DigestParamSet does not match");
                 }
 
-                if (((ECGOST3410Parameters)pkInfo.Parameters).EncryptionParamSet != null)
+                if (((ECGost3410Parameters)pkInfo.Parameters).EncryptionParamSet != null)
                 {
                     return new SimpleTestResult(false, "EncryptionParamSet is not null");
                 }
@@ -266,17 +266,17 @@ namespace Org.BouncyCastle.Crypto.Tests
                 }
 
 
-                if (!((ECGOST3410Parameters)pkInfo.Parameters).PublicKeyParamSet.ToString().Equals("1.2.643.7.1.2.1.2.1"))
+                if (!((ECGost3410Parameters)pkInfo.Parameters).PublicKeyParamSet.ToString().Equals("1.2.643.7.1.2.1.2.1"))
                 {
                     return new SimpleTestResult(false, "PublicKeyParamSet does not match");
                 }
 
-                if (!((ECGOST3410Parameters)pkInfo.Parameters).DigestParamSet.ToString().Equals("1.2.643.7.1.1.2.3"))
+                if (!((ECGost3410Parameters)pkInfo.Parameters).DigestParamSet.ToString().Equals("1.2.643.7.1.1.2.3"))
                 {
                     return new SimpleTestResult(false, "DigestParamSet does not match");
                 }
 
-                if (((ECGOST3410Parameters)pkInfo.Parameters).EncryptionParamSet != null)
+                if (((ECGost3410Parameters)pkInfo.Parameters).EncryptionParamSet != null)
                 {
                     return new SimpleTestResult(false, "EncryptionParamSet is not null");
                 }
@@ -304,17 +304,17 @@ namespace Org.BouncyCastle.Crypto.Tests
                     return new SimpleTestResult(false, "D does not match");
                 }
 
-                if (!((ECGOST3410Parameters)pkInfo.Parameters).PublicKeyParamSet.ToString().Equals("1.2.643.7.1.2.1.1.1"))
+                if (!((ECGost3410Parameters)pkInfo.Parameters).PublicKeyParamSet.ToString().Equals("1.2.643.7.1.2.1.1.1"))
                 {
                     return new SimpleTestResult(false, "PublicKeyParamSet does not match");
                 }
 
-                if (!((ECGOST3410Parameters)pkInfo.Parameters).DigestParamSet.ToString().Equals("1.2.643.7.1.1.2.2"))
+                if (!((ECGost3410Parameters)pkInfo.Parameters).DigestParamSet.ToString().Equals("1.2.643.7.1.1.2.2"))
                 {
                     return new SimpleTestResult(false, "DigestParamSet does not match");
                 }
 
-                if (((ECGOST3410Parameters)pkInfo.Parameters).EncryptionParamSet != null)
+                if (((ECGost3410Parameters)pkInfo.Parameters).EncryptionParamSet != null)
                 {
                     return new SimpleTestResult(false, "EncryptionParamSet is not null");
                 }
@@ -337,17 +337,17 @@ namespace Org.BouncyCastle.Crypto.Tests
                     return new SimpleTestResult(false, "D does not match");
                 }
 
-                if (!((ECGOST3410Parameters)pkInfo.Parameters).PublicKeyParamSet.ToString().Equals("1.2.643.7.1.2.1.2.1"))
+                if (!((ECGost3410Parameters)pkInfo.Parameters).PublicKeyParamSet.ToString().Equals("1.2.643.7.1.2.1.2.1"))
                 {
                     return new SimpleTestResult(false, "PublicKeyParamSet does not match");
                 }
 
-                if (!((ECGOST3410Parameters)pkInfo.Parameters).DigestParamSet.ToString().Equals("1.2.643.7.1.1.2.3"))
+                if (!((ECGost3410Parameters)pkInfo.Parameters).DigestParamSet.ToString().Equals("1.2.643.7.1.1.2.3"))
                 {
                     return new SimpleTestResult(false, "DigestParamSet does not match");
                 }
 
-                if (((ECGOST3410Parameters)pkInfo.Parameters).EncryptionParamSet != null)
+                if (((ECGost3410Parameters)pkInfo.Parameters).EncryptionParamSet != null)
                 {
                     return new SimpleTestResult(false, "EncryptionParamSet is not null");
                 }
@@ -363,7 +363,7 @@ namespace Org.BouncyCastle.Crypto.Tests
         {
             DerObjectIdentifier oid = ECGost3410NamedCurves.GetOid(oidStr);
             ECNamedDomainParameters ecp = new ECNamedDomainParameters(oid, ECGost3410NamedCurves.GetByOid(oid));
-            ECGOST3410Parameters gostParams = new ECGOST3410Parameters(ecp, oid, digest, null);
+            ECGost3410Parameters gostParams = new ECGost3410Parameters(ecp, oid, digest, null);
             ECKeyGenerationParameters parameters = new ECKeyGenerationParameters(gostParams, new SecureRandom());
             ECKeyPairGenerator engine = new ECKeyPairGenerator();
             engine.Init(parameters);
@@ -378,8 +378,8 @@ namespace Org.BouncyCastle.Crypto.Tests
 
 
             { // Specifically cast and test gost parameters.
-                ECGOST3410Parameters gParam = (ECGOST3410Parameters)generatedKeyParameters.Parameters;
-                ECGOST3410Parameters rParam = (ECGOST3410Parameters)recoveredKeyParameters.Parameters;
+                ECGost3410Parameters gParam = (ECGost3410Parameters)generatedKeyParameters.Parameters;
+                ECGost3410Parameters rParam = (ECGost3410Parameters)recoveredKeyParameters.Parameters;
 
                 bool ok = SafeEquals(gParam.DigestParamSet, rParam.DigestParamSet) &&
                     SafeEquals(gParam.EncryptionParamSet, rParam.EncryptionParamSet) &&
@@ -398,8 +398,8 @@ namespace Org.BouncyCastle.Crypto.Tests
                 return new SimpleTestResult(false, "isPrivate does not match");
             }
 
-            if (!((ECGOST3410Parameters)recoveredKeyParameters.Parameters).Name.Equals(
-                ((ECGOST3410Parameters)generatedKeyParameters.Parameters).Name))
+            if (!((ECGost3410Parameters)recoveredKeyParameters.Parameters).Name.Equals(
+                ((ECGost3410Parameters)generatedKeyParameters.Parameters).Name))
             {
                 return new SimpleTestResult(false, "Name does not match");
             }
@@ -449,7 +449,7 @@ namespace Org.BouncyCastle.Crypto.Tests
         {         
             DerObjectIdentifier oid = ECGost3410NamedCurves.GetOid(oidStr);
             ECNamedDomainParameters ecp = new ECNamedDomainParameters(oid, ECGost3410NamedCurves.GetByOid(oid));
-            ECGOST3410Parameters gostParams = new ECGOST3410Parameters(ecp,oid,digest,null);
+            ECGost3410Parameters gostParams = new ECGost3410Parameters(ecp,oid,digest,null);
             ECKeyGenerationParameters parameters = new ECKeyGenerationParameters(gostParams, new SecureRandom());
             ECKeyPairGenerator engine = new ECKeyPairGenerator();
             engine.Init(parameters);
@@ -461,8 +461,8 @@ namespace Org.BouncyCastle.Crypto.Tests
             ECPublicKeyParameters recoveredKeyParameters = (ECPublicKeyParameters)PublicKeyFactory.CreateKey(info);
 
             { // Specifically cast and test gost parameters.
-                ECGOST3410Parameters gParam = (ECGOST3410Parameters)generatedKeyParameters.Parameters;
-                ECGOST3410Parameters rParam = (ECGOST3410Parameters)recoveredKeyParameters.Parameters;
+                ECGost3410Parameters gParam = (ECGost3410Parameters)generatedKeyParameters.Parameters;
+                ECGost3410Parameters rParam = (ECGost3410Parameters)recoveredKeyParameters.Parameters;
 
 
                 bool ok = SafeEquals(gParam.DigestParamSet, rParam.DigestParamSet) &&
@@ -476,8 +476,8 @@ namespace Org.BouncyCastle.Crypto.Tests
 
             }
 
-            if (!((ECGOST3410Parameters)recoveredKeyParameters.Parameters).Name.Equals(
-                   ((ECGOST3410Parameters)generatedKeyParameters.Parameters).Name))
+            if (!((ECGost3410Parameters)recoveredKeyParameters.Parameters).Name.Equals(
+                   ((ECGost3410Parameters)generatedKeyParameters.Parameters).Name))
             {
                 return new SimpleTestResult(false, "Name does not match");
             }
diff --git a/crypto/test/src/crypto/test/EGOST3410_2012SignatureTest.cs b/crypto/test/src/crypto/test/EGOST3410_2012SignatureTest.cs
index 0065174ed..7c9801430 100644
--- a/crypto/test/src/crypto/test/EGOST3410_2012SignatureTest.cs
+++ b/crypto/test/src/crypto/test/EGOST3410_2012SignatureTest.cs
@@ -65,7 +65,7 @@ namespace Org.BouncyCastle.Crypto.Tests
                     new BigInteger("17614944419213781543809391949654080031942662045363639260709847859438286763994")), // y
                 spec);
 
-            ECGOST3410_2012Signer signer = new ECGOST3410_2012Signer();
+            ECGost3410_2012Signer signer = new ECGost3410_2012Signer();
             signer.Init(true, new ParametersWithRandom(privateKey, k));
 
             byte[] rev = e.ToByteArray();
@@ -104,7 +104,7 @@ namespace Org.BouncyCastle.Crypto.Tests
             {
                 DerObjectIdentifier oid = RosstandartObjectIdentifiers.id_tc26_gost_3410_12_256_paramSetA;
                 ECNamedDomainParameters ecp = new ECNamedDomainParameters(oid, ECGost3410NamedCurves.GetByOid(oid));
-                ECGOST3410Parameters gostParams = new ECGOST3410Parameters(ecp, oid,
+                ECGost3410Parameters gostParams = new ECGost3410Parameters(ecp, oid,
                     RosstandartObjectIdentifiers.id_tc26_gost_3411_12_256, null);
                 ECKeyGenerationParameters parameters = new ECKeyGenerationParameters(gostParams, new SecureRandom());
                 ECKeyPairGenerator engine = new ECKeyPairGenerator();
@@ -119,7 +119,7 @@ namespace Org.BouncyCastle.Crypto.Tests
             {
                 DerObjectIdentifier oid = RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512_paramSetA;
                 ECNamedDomainParameters ecp = new ECNamedDomainParameters(oid, ECGost3410NamedCurves.GetByOid(oid));
-                ECGOST3410Parameters gostParams = new ECGOST3410Parameters(ecp, oid,
+                ECGost3410Parameters gostParams = new ECGost3410Parameters(ecp, oid,
                     RosstandartObjectIdentifiers.id_tc26_gost_3411_12_512, null);
                 ECKeyGenerationParameters parameters = new ECKeyGenerationParameters(gostParams, new SecureRandom());
                 ECKeyPairGenerator engine = new ECKeyPairGenerator();
@@ -141,13 +141,13 @@ namespace Org.BouncyCastle.Crypto.Tests
             ECPrivateKeyParameters sKey = (ECPrivateKeyParameters)p.Private;
             ECPublicKeyParameters vKey = (ECPublicKeyParameters)p.Public;
 
-            ECGOST3410_2012Signer s = new ECGOST3410_2012Signer();
+            ECGost3410_2012Signer s = new ECGost3410_2012Signer();
 
             s.Init(true, sKey);
             BigInteger[] sig = s.GenerateSignature(data);
 
 
-            s = new ECGOST3410_2012Signer();
+            s = new ECGost3410_2012Signer();
             s.Init(false, vKey);
 
             if (!s.VerifySignature(data, sig[0], sig[1]))
@@ -159,8 +159,8 @@ namespace Org.BouncyCastle.Crypto.Tests
             // Test with Digest signer.
             //           
             Gost3410DigestSigner digestSigner = new Gost3410DigestSigner(
-                new ECGOST3410_2012Signer(),
-                DigestUtilities.GetDigest(((ECGOST3410Parameters)vKey.Parameters).DigestParamSet));
+                new ECGost3410_2012Signer(),
+                DigestUtilities.GetDigest(((ECGost3410Parameters)vKey.Parameters).DigestParamSet));
             digestSigner.Init(true, sKey);
             digestSigner.BlockUpdate(data, 0, data.Length);
             byte[] sigBytes = digestSigner.GenerateSignature();
@@ -171,8 +171,8 @@ namespace Org.BouncyCastle.Crypto.Tests
             }
 
             digestSigner = new Gost3410DigestSigner(
-                new ECGOST3410_2012Signer(),
-                DigestUtilities.GetDigest(((ECGOST3410Parameters)vKey.Parameters).DigestParamSet));
+                new ECGost3410_2012Signer(),
+                DigestUtilities.GetDigest(((ECGost3410Parameters)vKey.Parameters).DigestParamSet));
             digestSigner.Init(false, vKey);
             digestSigner.BlockUpdate(data, 0, data.Length);
 
diff --git a/crypto/test/src/crypto/test/GOST3411_2012_256DigestTest.cs b/crypto/test/src/crypto/test/GOST3411_2012_256DigestTest.cs
index 5b20f46be..1f2ef1823 100644
--- a/crypto/test/src/crypto/test/GOST3411_2012_256DigestTest.cs
+++ b/crypto/test/src/crypto/test/GOST3411_2012_256DigestTest.cs
@@ -61,7 +61,7 @@ namespace Org.BouncyCastle.Crypto.Tests
         };
 
         public GOST3411_2012_256DigestTest()
-            : base(new GOST3411_2012_256Digest(), messages, digests)
+            : base(new Gost3411_2012_256Digest(), messages, digests)
         {
         }
 
@@ -69,7 +69,7 @@ namespace Org.BouncyCastle.Crypto.Tests
         {
 			base.PerformTest();
 
-            HMac gMac = new HMac(new GOST3411_2012_256Digest());
+            HMac gMac = new HMac(new Gost3411_2012_256Digest());
 
             gMac.Init(new KeyParameter(Hex.Decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f")));
 
@@ -88,7 +88,7 @@ namespace Org.BouncyCastle.Crypto.Tests
 
         protected override IDigest CloneDigest(IDigest digest)
         {
-			return new GOST3411_2012_256Digest((GOST3411_2012_256Digest)digest);
+			return new Gost3411_2012_256Digest((Gost3411_2012_256Digest)digest);
         }
 
         [Test]
diff --git a/crypto/test/src/crypto/test/GOST3411_2012_512DigestTest.cs b/crypto/test/src/crypto/test/GOST3411_2012_512DigestTest.cs
index 05b33e7f9..f4398952b 100644
--- a/crypto/test/src/crypto/test/GOST3411_2012_512DigestTest.cs
+++ b/crypto/test/src/crypto/test/GOST3411_2012_512DigestTest.cs
@@ -61,7 +61,7 @@ namespace Org.BouncyCastle.Crypto.Tests
 		{
 			base.PerformTest();
 
-			HMac gMac = new HMac(new GOST3411_2012_512Digest());
+			HMac gMac = new HMac(new Gost3411_2012_512Digest());
 
 			gMac.Init(new KeyParameter(Hex.Decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f")));
 
@@ -79,13 +79,13 @@ namespace Org.BouncyCastle.Crypto.Tests
 		}
 
         public GOST3411_2012_512DigestTest()
-            : base(new GOST3411_2012_512Digest(), messages, digests)
+            : base(new Gost3411_2012_512Digest(), messages, digests)
         {
         }
 
         protected override IDigest CloneDigest(IDigest digest)
         {
-            return new GOST3411_2012_512Digest((GOST3411_2012_512Digest)digest);
+            return new Gost3411_2012_512Digest((Gost3411_2012_512Digest)digest);
         }
 
         [Test]