summary refs log tree commit diff
path: root/crypto
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2015-11-08 17:18:27 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2015-11-08 17:18:27 +0700
commitd644e956bb0dd3fe0731c3050c185f27ab6d9e1f (patch)
tree2e4464b274efeb8ce3205c7a736bd65dea7b8262 /crypto
parentMerge pull request #10 from peterdettman/pcl (diff)
parentMerge branch 'master' of git.bouncycastle.org:bc-csharp (diff)
downloadBouncyCastle.NET-ed25519-d644e956bb0dd3fe0731c3050c185f27ab6d9e1f.tar.xz
Merge branch 'master' of git.bouncycastle.org:bc-csharp into pcl
Diffstat (limited to 'crypto')
-rw-r--r--crypto/bzip2/src/CBZip2InputStream.cs6
-rw-r--r--crypto/bzip2/src/CBZip2OutputStream.cs21
-rw-r--r--crypto/crypto.csproj5
-rw-r--r--crypto/src/asn1/Asn1Set.cs28
-rw-r--r--crypto/src/asn1/BEROctetStringGenerator.cs39
-rw-r--r--crypto/src/asn1/DerGeneralizedTime.cs9
-rw-r--r--crypto/src/asn1/DerSequence.cs7
-rw-r--r--crypto/src/asn1/DerSet.cs7
-rw-r--r--crypto/src/asn1/cmp/CertResponse.cs3
-rw-r--r--crypto/src/asn1/cmp/ErrorMsgContent.cs3
-rw-r--r--crypto/src/asn1/crmf/CertReqMsg.cs3
-rw-r--r--crypto/src/asn1/util/Dump.cs4
-rw-r--r--crypto/src/asn1/util/FilterStream.cs14
-rw-r--r--crypto/src/asn1/x509/AlgorithmIdentifier.cs64
-rw-r--r--crypto/src/bcpg/ArmoredInputStream.cs10
-rw-r--r--crypto/src/bcpg/ArmoredOutputStream.cs66
-rw-r--r--crypto/src/bcpg/BcpgInputStream.cs25
-rw-r--r--crypto/src/bcpg/BcpgOutputStream.cs31
-rw-r--r--crypto/src/bcpg/PublicKeyEncSessionPacket.cs2
-rw-r--r--crypto/src/cms/CMSAuthenticatedDataGenerator.cs6
-rw-r--r--crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs51
-rw-r--r--crypto/src/cms/CMSCompressedData.cs3
-rw-r--r--crypto/src/cms/CMSCompressedDataGenerator.cs5
-rw-r--r--crypto/src/cms/CMSCompressedDataStreamGenerator.cs35
-rw-r--r--crypto/src/cms/CMSContentInfoParser.cs3
-rw-r--r--crypto/src/cms/CMSEnvelopedDataGenerator.cs4
-rw-r--r--crypto/src/cms/CMSEnvelopedDataStreamGenerator.cs48
-rw-r--r--crypto/src/cms/CMSProcessableFile.cs3
-rw-r--r--crypto/src/cms/CMSProcessableInputStream.cs3
-rw-r--r--crypto/src/cms/CMSSignedDataGenerator.cs2
-rw-r--r--crypto/src/cms/CMSSignedDataParser.cs8
-rw-r--r--crypto/src/cms/CMSSignedDataStreamGenerator.cs163
-rw-r--r--crypto/src/cms/CMSTypedStream.cs3
-rw-r--r--crypto/src/crypto/digests/GeneralDigest.cs36
-rw-r--r--crypto/src/crypto/engines/AesEngine.cs135
-rw-r--r--crypto/src/crypto/engines/AesFastEngine.cs129
-rw-r--r--crypto/src/crypto/engines/AesLightEngine.cs139
-rw-r--r--crypto/src/crypto/generators/DHParametersHelper.cs10
-rw-r--r--crypto/src/crypto/generators/NaccacheSternKeyPairGenerator.cs4
-rw-r--r--crypto/src/crypto/generators/RsaKeyPairGenerator.cs2
-rw-r--r--crypto/src/crypto/io/CipherStream.cs31
-rw-r--r--crypto/src/crypto/io/DigestStream.cs28
-rw-r--r--crypto/src/crypto/io/MacStream.cs30
-rw-r--r--crypto/src/crypto/io/SignerStream.cs30
-rw-r--r--crypto/src/crypto/modes/GCMBlockCipher.cs9
-rw-r--r--crypto/src/crypto/operators/Asn1Signature.cs7
-rw-r--r--crypto/src/crypto/parameters/SkeinParameters.cs2
-rw-r--r--crypto/src/crypto/prng/ThreadedSeedGenerator.cs3
-rw-r--r--crypto/src/crypto/tls/ByteQueueStream.cs5
-rw-r--r--crypto/src/crypto/tls/CertificateUrl.cs2
-rw-r--r--crypto/src/crypto/tls/DtlsReliableHandshake.cs4
-rw-r--r--crypto/src/crypto/tls/RecordStream.cs6
-rw-r--r--crypto/src/crypto/tls/TlsProtocol.cs2
-rw-r--r--crypto/src/crypto/tls/TlsStream.cs8
-rw-r--r--crypto/src/math/BigInteger.cs54
-rw-r--r--crypto/src/math/Primes.cs103
-rw-r--r--crypto/src/ocsp/BasicOCSPRespGenerator.cs2
-rw-r--r--crypto/src/openpgp/PgpCompressedDataGenerator.cs55
-rw-r--r--crypto/src/openpgp/PgpUtilities.cs4
-rw-r--r--crypto/src/openpgp/WrappedGeneratorStream.cs24
-rw-r--r--crypto/src/pkcs/Pkcs10CertificationRequest.cs4
-rw-r--r--crypto/src/pkix/PkixCertPath.cs2
-rw-r--r--crypto/src/util/Platform.cs18
-rw-r--r--crypto/src/util/io/BaseInputStream.cs12
-rw-r--r--crypto/src/util/io/BaseOutputStream.cs12
-rw-r--r--crypto/src/util/io/FilterStream.cs10
-rw-r--r--crypto/src/util/io/TeeInputStream.cs31
-rw-r--r--crypto/src/util/io/TeeOutputStream.cs17
-rw-r--r--crypto/src/util/zlib/ZDeflaterOutputStream.cs29
-rw-r--r--crypto/src/util/zlib/ZInflaterInputStream.cs12
-rw-r--r--crypto/src/util/zlib/ZInputStream.cs36
-rw-r--r--crypto/src/util/zlib/ZOutputStream.cs64
-rw-r--r--crypto/src/x509/X509Certificate.cs2
-rw-r--r--crypto/src/x509/X509Crl.cs2
-rw-r--r--crypto/src/x509/X509V1CertificateGenerator.cs3
-rw-r--r--crypto/src/x509/X509V2AttributeCertificate.cs4
-rw-r--r--crypto/src/x509/X509V2AttributeCertificateGenerator.cs6
-rw-r--r--crypto/src/x509/X509V2CRLGenerator.cs5
-rw-r--r--crypto/src/x509/X509V3CertificateGenerator.cs9
-rw-r--r--crypto/test/src/asn1/test/GenerationTest.cs18
-rw-r--r--crypto/test/src/asn1/test/TimeTest.cs4
-rw-r--r--crypto/test/src/math/ec/test/ECAlgorithmsTest.cs106
-rw-r--r--crypto/test/src/math/ec/test/ECPointPerformanceTest.cs1
-rw-r--r--crypto/test/src/math/test/AllTests.cs1
-rw-r--r--crypto/test/src/math/test/PrimesTest.cs179
-rw-r--r--crypto/test/src/openpgp/test/PGPRSATest.cs2
-rw-r--r--crypto/test/src/openpgp/test/PgpKeyRingTest.cs140
-rw-r--r--crypto/test/src/util/test/SimpleTest.cs18
-rw-r--r--crypto/test/src/util/test/UncloseableStream.cs22
89 files changed, 1617 insertions, 700 deletions
diff --git a/crypto/bzip2/src/CBZip2InputStream.cs b/crypto/bzip2/src/CBZip2InputStream.cs
index 7411f0a21..82ff83e42 100644
--- a/crypto/bzip2/src/CBZip2InputStream.cs
+++ b/crypto/bzip2/src/CBZip2InputStream.cs
@@ -25,6 +25,8 @@
 using System;
 using System.IO;
 
+using Org.BouncyCastle.Utilities;
+
 namespace Org.BouncyCastle.Apache.Bzip2
 {
 	/**
@@ -286,10 +288,10 @@ namespace Org.BouncyCastle.Apache.Bzip2
             Cadvise();
         }
 
-		private void BsFinishedWithStream() {
+        private void BsFinishedWithStream() {
             try {
                 if (this.bsStream != null) {
-                    this.bsStream.Dispose();
+                    Platform.Dispose(this.bsStream);
                     this.bsStream = null;
                 }
             } catch {
diff --git a/crypto/bzip2/src/CBZip2OutputStream.cs b/crypto/bzip2/src/CBZip2OutputStream.cs
index 690c8a058..361592796 100644
--- a/crypto/bzip2/src/CBZip2OutputStream.cs
+++ b/crypto/bzip2/src/CBZip2OutputStream.cs
@@ -25,6 +25,8 @@
 using System;
 using System.IO;
 
+using Org.BouncyCastle.Utilities;
+
 namespace Org.BouncyCastle.Apache.Bzip2
 {
 	/**
@@ -384,23 +386,32 @@ namespace Org.BouncyCastle.Apache.Bzip2
 //            Close();
 //        }
 
+#if PORTABLE
         protected override void Dispose(bool disposing)
         {
             if (disposing)
             {
                 if (closed)
-                {
                     return;
-                }
 
                 Finish();
-
                 closed = true;
-                
-                bsStream.Dispose();
+                Platform.Dispose(this.bsStream);
             }
             base.Dispose(disposing);
         }
+#else
+        public override void Close() {
+            if (closed)
+                return;
+
+            Finish();
+            closed = true;
+            Platform.Dispose(this.bsStream);
+
+            base.Close();
+        }
+#endif
 
         public void Finish() {
             if (finished) {
diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj
index b147fa9c7..cdb48bfff 100644
--- a/crypto/crypto.csproj
+++ b/crypto/crypto.csproj
@@ -11865,6 +11865,11 @@
                     BuildAction = "Compile"
                 />
                 <File
+                    RelPath = "test\src\math\test\PrimesTest.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
                     RelPath = "test\src\ocsp\test\AllTests.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
diff --git a/crypto/src/asn1/Asn1Set.cs b/crypto/src/asn1/Asn1Set.cs
index 418b560fd..58e7e26f8 100644
--- a/crypto/src/asn1/Asn1Set.cs
+++ b/crypto/src/asn1/Asn1Set.cs
@@ -75,8 +75,8 @@ namespace Org.BouncyCastle.Asn1
          *          be converted.
          */
         public static Asn1Set GetInstance(
-            Asn1TaggedObject	obj,
-            bool				explicitly)
+            Asn1TaggedObject obj,
+            bool explicitly)
         {
             Asn1Object inner = obj.GetObject();
 
@@ -85,7 +85,7 @@ namespace Org.BouncyCastle.Asn1
                 if (!obj.IsExplicit())
                     throw new ArgumentException("object implicit - explicit expected.");
 
-                return (Asn1Set) inner;
+                return (Asn1Set)inner;
             }
 
             //
@@ -100,7 +100,7 @@ namespace Org.BouncyCastle.Asn1
 
             if (inner is Asn1Set)
             {
-                return (Asn1Set) inner;
+                return (Asn1Set)inner;
             }
 
             //
@@ -110,7 +110,7 @@ namespace Org.BouncyCastle.Asn1
             if (inner is Asn1Sequence)
             {
                 Asn1EncodableVector v = new Asn1EncodableVector();
-                Asn1Sequence s = (Asn1Sequence) inner;
+                Asn1Sequence s = (Asn1Sequence)inner;
 
                 foreach (Asn1Encodable ae in s)
                 {
@@ -149,14 +149,14 @@ namespace Org.BouncyCastle.Asn1
          */
         public virtual Asn1Encodable this[int index]
         {
-            get { return (Asn1Encodable) _set[index]; }
+            get { return (Asn1Encodable)_set[index]; }
         }
 
         [Obsolete("Use 'object[index]' syntax instead")]
         public Asn1Encodable GetObjectAt(
             int index)
         {
-             return this[index];
+            return this[index];
         }
 
         [Obsolete("Use 'Count' property instead")]
@@ -207,8 +207,8 @@ namespace Org.BouncyCastle.Asn1
                     return ((Asn1Set)obj).Parser;
 
                 // NB: Asn1OctetString implements Asn1OctetStringParser directly
-//				if (obj is Asn1OctetString)
-//					return ((Asn1OctetString)obj).Parser;
+                //				if (obj is Asn1OctetString)
+                //					return ((Asn1OctetString)obj).Parser;
 
                 return obj;
             }
@@ -303,12 +303,18 @@ namespace Org.BouncyCastle.Asn1
             Asn1Encodable[] items = new Asn1Encodable[_set.Count];
             byte[][] keys = new byte[_set.Count][];
 
-            //List<Asn1Encodable[]> t;
+            for (int i = 0; i < _set.Count; ++i)
+            {
+                Asn1Encodable item = (Asn1Encodable)_set[i];
+                items[i] = item;
+                keys[i] = item.GetEncoded(Asn1Encodable.Der);
+            }
 
+            Array.Sort(keys, items, new DerComparer());
 
             for (int i = 0; i < _set.Count; ++i)
             {
-                _set[i] = sorted[i];
+                _set[i] = items[i];
             }
 #endif
         }
diff --git a/crypto/src/asn1/BEROctetStringGenerator.cs b/crypto/src/asn1/BEROctetStringGenerator.cs
index 6d7d1b66e..f34538f38 100644
--- a/crypto/src/asn1/BEROctetStringGenerator.cs
+++ b/crypto/src/asn1/BEROctetStringGenerator.cs
@@ -102,19 +102,32 @@ namespace Org.BouncyCastle.Asn1
 				}
 			}
 
-		    protected override void Dispose(bool disposing)
-		    {
-		        if (disposing)
-		        {
-                    if (_off != 0)
-                    {
-                        DerOctetString.Encode(_derOut, _buf, 0, _off);
-                    }
-
-                    _gen.WriteBerEnd();
-		        }
-		        base.Dispose(disposing);
-		    }
+#if PORTABLE
+            protected override void Dispose(bool disposing)
+            {
+                if (disposing)
+                {
+				    if (_off != 0)
+				    {
+					    DerOctetString.Encode(_derOut, _buf, 0, _off);
+				    }
+
+				    _gen.WriteBerEnd();
+                }
+                base.Dispose(disposing);
+            }
+#else
+            public override void Close()
+			{
+				if (_off != 0)
+				{
+					DerOctetString.Encode(_derOut, _buf, 0, _off);
+				}
+
+				_gen.WriteBerEnd();
+				base.Close();
+			}
+#endif
 		}
 	}
 }
diff --git a/crypto/src/asn1/DerGeneralizedTime.cs b/crypto/src/asn1/DerGeneralizedTime.cs
index 57527f3a0..4de0feaa6 100644
--- a/crypto/src/asn1/DerGeneralizedTime.cs
+++ b/crypto/src/asn1/DerGeneralizedTime.cs
@@ -262,8 +262,13 @@ namespace Org.BouncyCastle.Asn1
             DateTimeStyles style = DateTimeStyles.None;
             if (format.EndsWith("Z"))
             {
-                style = DateTimeStyles.AssumeUniversal;
-                
+                try
+                {
+                    style = (DateTimeStyles)Enums.GetEnumValue(typeof(DateTimeStyles), "AssumeUniversal");
+                }
+                catch (Exception)
+                {
+                }
 
                 style |= DateTimeStyles.AdjustToUniversal;
             }
diff --git a/crypto/src/asn1/DerSequence.cs b/crypto/src/asn1/DerSequence.cs
index 1a86dc429..a76cf2882 100644
--- a/crypto/src/asn1/DerSequence.cs
+++ b/crypto/src/asn1/DerSequence.cs
@@ -1,6 +1,9 @@
+using System;
 using System.Collections;
 using System.IO;
 
+using Org.BouncyCastle.Utilities;
+
 namespace Org.BouncyCastle.Asn1
 {
 	public class DerSequence
@@ -75,9 +78,9 @@ namespace Org.BouncyCastle.Asn1
 				dOut.WriteObject(obj);
 			}
 
-            dOut.Dispose();
+            Platform.Dispose(dOut);
 
-			byte[] bytes = bOut.ToArray();
+            byte[] bytes = bOut.ToArray();
 
 			derOut.WriteEncoded(Asn1Tags.Sequence | Asn1Tags.Constructed, bytes);
 		}
diff --git a/crypto/src/asn1/DerSet.cs b/crypto/src/asn1/DerSet.cs
index 6d3f438bd..3df1a6766 100644
--- a/crypto/src/asn1/DerSet.cs
+++ b/crypto/src/asn1/DerSet.cs
@@ -1,5 +1,8 @@
+using System;
 using System.IO;
 
+using Org.BouncyCastle.Utilities;
+
 namespace Org.BouncyCastle.Asn1
 {
 	/**
@@ -98,9 +101,9 @@ namespace Org.BouncyCastle.Asn1
 				dOut.WriteObject(obj);
 			}
 
-            dOut.Dispose();
+            Platform.Dispose(dOut);
 
-			byte[] bytes = bOut.ToArray();
+            byte[] bytes = bOut.ToArray();
 
 			derOut.WriteEncoded(Asn1Tags.Set | Asn1Tags.Constructed, bytes);
 		}
diff --git a/crypto/src/asn1/cmp/CertResponse.cs b/crypto/src/asn1/cmp/CertResponse.cs
index 246b8ce70..80813b8b7 100644
--- a/crypto/src/asn1/cmp/CertResponse.cs
+++ b/crypto/src/asn1/cmp/CertResponse.cs
@@ -107,8 +107,7 @@ namespace Org.BouncyCastle.Asn1.Cmp
 		public override Asn1Object ToAsn1Object()
 		{
 			Asn1EncodableVector v = new Asn1EncodableVector(certReqId, status);
-			v.AddOptional(certifiedKeyPair);
-			v.AddOptional(rspInfo);
+			v.AddOptional(certifiedKeyPair, rspInfo);
 			return new DerSequence(v);
 		}
 	}
diff --git a/crypto/src/asn1/cmp/ErrorMsgContent.cs b/crypto/src/asn1/cmp/ErrorMsgContent.cs
index f4dc584ea..2d6353b65 100644
--- a/crypto/src/asn1/cmp/ErrorMsgContent.cs
+++ b/crypto/src/asn1/cmp/ErrorMsgContent.cs
@@ -86,8 +86,7 @@ namespace Org.BouncyCastle.Asn1.Cmp
 		public override Asn1Object ToAsn1Object()
 		{
 			Asn1EncodableVector v = new Asn1EncodableVector(pkiStatusInfo);
-			v.AddOptional(errorCode);
-			v.AddOptional(errorDetails);
+			v.AddOptional(errorCode, errorDetails);
 			return new DerSequence(v);
 		}
 	}
diff --git a/crypto/src/asn1/crmf/CertReqMsg.cs b/crypto/src/asn1/crmf/CertReqMsg.cs
index 2ca319a57..20fd4179a 100644
--- a/crypto/src/asn1/crmf/CertReqMsg.cs
+++ b/crypto/src/asn1/crmf/CertReqMsg.cs
@@ -98,8 +98,7 @@ namespace Org.BouncyCastle.Asn1.Crmf
         public override Asn1Object ToAsn1Object()
         {
             Asn1EncodableVector v = new Asn1EncodableVector(certReq);
-            v.AddOptional(popo);
-            v.AddOptional(regInfo);
+            v.AddOptional(popo, regInfo);
             return new DerSequence(v);
         }
     }
diff --git a/crypto/src/asn1/util/Dump.cs b/crypto/src/asn1/util/Dump.cs
index 99ced5836..e313fe879 100644
--- a/crypto/src/asn1/util/Dump.cs
+++ b/crypto/src/asn1/util/Dump.cs
@@ -2,6 +2,8 @@
 using System;
 using System.IO;
 
+using Org.BouncyCastle.Utilities;
+
 namespace Org.BouncyCastle.Asn1.Utilities
 {
     public sealed class Dump
@@ -21,7 +23,7 @@ namespace Org.BouncyCastle.Asn1.Utilities
                 Console.WriteLine(Asn1Dump.DumpAsString(obj));
             }
 
-			bIn.Close();
+            Platform.Dispose(bIn);
         }
     }
 }
diff --git a/crypto/src/asn1/util/FilterStream.cs b/crypto/src/asn1/util/FilterStream.cs
index 3d08446cd..0c38c5b6e 100644
--- a/crypto/src/asn1/util/FilterStream.cs
+++ b/crypto/src/asn1/util/FilterStream.cs
@@ -1,6 +1,8 @@
 using System;
 using System.IO;
 
+using Org.BouncyCastle.Utilities;
+
 namespace Org.BouncyCastle.Asn1.Utilities
 {
     [Obsolete("Use Org.BouncyCastle.Utilities.IO.FilterStream")]
@@ -32,16 +34,22 @@ namespace Org.BouncyCastle.Asn1.Utilities
             get { return s.Position; }
             set { s.Position = value; }
         }
-
+#if PORTABLE
         protected override void Dispose(bool disposing)
         {
             if (disposing)
             {
-                s.Dispose();
+                Platform.Dispose(s);
             }
             base.Dispose(disposing);
         }
-
+#else
+        public override void Close()
+        {
+            Platform.Dispose(s);
+            base.Close();
+        }
+#endif
         public override void Flush()
         {
             s.Flush();
diff --git a/crypto/src/asn1/x509/AlgorithmIdentifier.cs b/crypto/src/asn1/x509/AlgorithmIdentifier.cs
index c6f4af5bf..00e7ad8bc 100644
--- a/crypto/src/asn1/x509/AlgorithmIdentifier.cs
+++ b/crypto/src/asn1/x509/AlgorithmIdentifier.cs
@@ -5,9 +5,8 @@ namespace Org.BouncyCastle.Asn1.X509
     public class AlgorithmIdentifier
         : Asn1Encodable
     {
-        private readonly DerObjectIdentifier	objectID;
+        private readonly DerObjectIdentifier	algorithm;
         private readonly Asn1Encodable			parameters;
-        private readonly bool					parametersDefined;
 
         public static AlgorithmIdentifier GetInstance(
             Asn1TaggedObject	obj,
@@ -19,39 +18,32 @@ namespace Org.BouncyCastle.Asn1.X509
         public static AlgorithmIdentifier GetInstance(
             object obj)
         {
-            if (obj == null || obj is AlgorithmIdentifier)
-                return (AlgorithmIdentifier) obj;
-
-            // TODO: delete
-            if (obj is DerObjectIdentifier)
-                return new AlgorithmIdentifier((DerObjectIdentifier) obj);
-
-            // TODO: delete
-            if (obj is string)
-                return new AlgorithmIdentifier((string) obj);
-
+            if (obj == null)
+                return null;
+            if (obj is AlgorithmIdentifier)
+                return (AlgorithmIdentifier)obj;
             return new AlgorithmIdentifier(Asn1Sequence.GetInstance(obj));
         }
 
         public AlgorithmIdentifier(
-            DerObjectIdentifier objectID)
+            DerObjectIdentifier algorithm)
         {
-            this.objectID = objectID;
+            this.algorithm = algorithm;
         }
 
+        [Obsolete("Use version taking a DerObjectIdentifier")]
         public AlgorithmIdentifier(
-            string objectID)
+            string algorithm)
         {
-            this.objectID = new DerObjectIdentifier(objectID);
+            this.algorithm = new DerObjectIdentifier(algorithm);
         }
 
         public AlgorithmIdentifier(
-            DerObjectIdentifier	objectID,
+            DerObjectIdentifier algorithm,
             Asn1Encodable		parameters)
         {
-            this.objectID = objectID;
+            this.algorithm = algorithm;
             this.parameters = parameters;
-            this.parametersDefined = true;
         }
 
         internal AlgorithmIdentifier(
@@ -60,13 +52,8 @@ namespace Org.BouncyCastle.Asn1.X509
             if (seq.Count < 1 || seq.Count > 2)
                 throw new ArgumentException("Bad sequence size: " + seq.Count);
 
-            this.objectID = DerObjectIdentifier.GetInstance(seq[0]);
-            this.parametersDefined = (seq.Count == 2);
-
-            if (parametersDefined)
-            {
-                this.parameters = seq[1];
-            }
+            this.algorithm = DerObjectIdentifier.GetInstance(seq[0]);
+            this.parameters = seq.Count < 2 ? null : seq[1];
         }
 
         /// <summary>
@@ -74,18 +61,19 @@ namespace Org.BouncyCastle.Asn1.X509
         /// </summary>
 		public virtual DerObjectIdentifier Algorithm
 		{
-			get { return objectID; }
+			get { return algorithm; }
 		}
 
+        [Obsolete("Use 'Algorithm' property instead")]
         public virtual DerObjectIdentifier ObjectID
         {
-            get { return objectID; }
+            get { return algorithm; }
         }
 
         /// <summary>
         /// Return the parameters structure in the Parameters entry of this identifier.
         /// </summary>
-        public Asn1Encodable Parameters
+        public virtual Asn1Encodable Parameters
         {
             get { return parameters; }
         }
@@ -100,20 +88,8 @@ namespace Org.BouncyCastle.Asn1.X509
          */
         public override Asn1Object ToAsn1Object()
         {
-            Asn1EncodableVector v = new Asn1EncodableVector(objectID);
-
-            if (parametersDefined)
-            {
-                if (parameters != null)
-                {
-                    v.Add(parameters);
-                }
-                else
-                {
-                    v.Add(DerNull.Instance);
-                }
-            }
-
+            Asn1EncodableVector v = new Asn1EncodableVector(algorithm);
+            v.AddOptional(parameters);
             return new DerSequence(v);
         }
     }
diff --git a/crypto/src/bcpg/ArmoredInputStream.cs b/crypto/src/bcpg/ArmoredInputStream.cs
index c7bb85942..d5d9f7ffb 100644
--- a/crypto/src/bcpg/ArmoredInputStream.cs
+++ b/crypto/src/bcpg/ArmoredInputStream.cs
@@ -504,13 +504,21 @@ namespace Org.BouncyCastle.Bcpg
             return pos - offset;
         }
 
+#if PORTABLE
         protected override void Dispose(bool disposing)
         {
             if (disposing)
             {
-                input.Dispose();
+                Platform.Dispose(input);
             }
             base.Dispose(disposing);
         }
+#else
+		public override void Close()
+		{
+            Platform.Dispose(input);
+			base.Close();
+		}
+#endif
     }
 }
diff --git a/crypto/src/bcpg/ArmoredOutputStream.cs b/crypto/src/bcpg/ArmoredOutputStream.cs
index 44b2b78e7..1f0e412d8 100644
--- a/crypto/src/bcpg/ArmoredOutputStream.cs
+++ b/crypto/src/bcpg/ArmoredOutputStream.cs
@@ -283,40 +283,60 @@ namespace Org.BouncyCastle.Bcpg
          * <b>Note</b>: Close() does not close the underlying stream. So it is possible to write
          * multiple objects using armoring to a single stream.
          */
+#if PORTABLE
         protected override void Dispose(bool disposing)
         {
             if (disposing)
-        {
-            if (type != null)
             {
-                if (bufPtr > 0)
-                {
-                    Encode(outStream, buf, bufPtr);
-                }
+                if (type == null)
+                    return;
 
-                DoWrite(nl + '=');
+                DoClose();
 
-                int crcV = crc.Value;
-
-                buf[0] = ((crcV >> 16) & 0xff);
-                buf[1] = ((crcV >> 8) & 0xff);
-                buf[2] = (crcV & 0xff);
+                type = null;
+                start = true;
+            }
+            base.Dispose(disposing);
+        }
+#else
+        public override void Close()
+        {
+            if (type == null)
+                return;
 
-                Encode(outStream, buf, 3);
+            DoClose();
 
-                DoWrite(nl);
-                DoWrite(footerStart);
-                DoWrite(type);
-                DoWrite(footerTail);
-                DoWrite(nl);
+            type = null;
+            start = true;
 
-                outStream.Flush();
+            base.Close();
+        }
+#endif
 
-                type = null;
-                start = true;
-                }
+        private void DoClose()
+        {
+            if (bufPtr > 0)
+            {
+                Encode(outStream, buf, bufPtr);
             }
-            base.Dispose(disposing);
+
+            DoWrite(nl + '=');
+
+            int crcV = crc.Value;
+
+            buf[0] = ((crcV >> 16) & 0xff);
+            buf[1] = ((crcV >> 8) & 0xff);
+            buf[2] = (crcV & 0xff);
+
+            Encode(outStream, buf, 3);
+
+            DoWrite(nl);
+            DoWrite(footerStart);
+            DoWrite(type);
+            DoWrite(footerTail);
+            DoWrite(nl);
+
+            outStream.Flush();
         }
 
         private void WriteHeaderEntry(
diff --git a/crypto/src/bcpg/BcpgInputStream.cs b/crypto/src/bcpg/BcpgInputStream.cs
index 9835891b1..f9627fde0 100644
--- a/crypto/src/bcpg/BcpgInputStream.cs
+++ b/crypto/src/bcpg/BcpgInputStream.cs
@@ -2,6 +2,7 @@ using System;
 using System.IO;
 
 using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Utilities;
 using Org.BouncyCastle.Utilities.IO;
 
 namespace Org.BouncyCastle.Bcpg
@@ -246,14 +247,22 @@ namespace Org.BouncyCastle.Bcpg
             }
         }
 
-	    protected override void Dispose(bool disposing)
-	    {
-	        if (disposing)
-	        {
-	            m_in.Dispose();
-	        }
-	        base.Dispose(disposing);
-	    }
+#if PORTABLE
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                Platform.Dispose(m_in);
+            }
+            base.Dispose(disposing);
+        }
+#else
+		public override void Close()
+		{
+            Platform.Dispose(m_in);
+			base.Close();
+		}
+#endif
 
 		/// <summary>
 		/// A stream that overlays our input stream, allowing the user to only read a segment of it.
diff --git a/crypto/src/bcpg/BcpgOutputStream.cs b/crypto/src/bcpg/BcpgOutputStream.cs
index f62fadc19..7ab661edb 100644
--- a/crypto/src/bcpg/BcpgOutputStream.cs
+++ b/crypto/src/bcpg/BcpgOutputStream.cs
@@ -1,6 +1,7 @@
 using System;
 using System.IO;
 
+using Org.BouncyCastle.Utilities;
 using Org.BouncyCastle.Utilities.IO;
 
 namespace Org.BouncyCastle.Bcpg
@@ -379,15 +380,25 @@ namespace Org.BouncyCastle.Bcpg
             }
         }
 
-	    protected override void Dispose(bool disposing)
-	    {
-	        if (disposing)
-	        {
-                this.Finish();
-                outStr.Flush();                
-                outStr.Dispose();
-	        }
-	       base.Dispose(disposing);
-	    }
+#if PORTABLE
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+			    this.Finish();
+			    outStr.Flush();
+                Platform.Dispose(outStr);
+            }
+            base.Dispose(disposing);
+        }
+#else
+        public override void Close()
+        {
+			this.Finish();
+			outStr.Flush();
+            Platform.Dispose(outStr);
+			base.Close();
+        }
+#endif
     }
 }
diff --git a/crypto/src/bcpg/PublicKeyEncSessionPacket.cs b/crypto/src/bcpg/PublicKeyEncSessionPacket.cs
index eefe4495b..831b5a189 100644
--- a/crypto/src/bcpg/PublicKeyEncSessionPacket.cs
+++ b/crypto/src/bcpg/PublicKeyEncSessionPacket.cs
@@ -107,7 +107,7 @@ namespace Org.BouncyCastle.Bcpg
                 pOut.Write(data[i]);
             }
 
-            pOut.Dispose();
+            Platform.Dispose(pOut);
 
             bcpgOut.WritePacket(PacketTag.PublicKeyEncryptedSession , bOut.ToArray(), true);
 		}
diff --git a/crypto/src/cms/CMSAuthenticatedDataGenerator.cs b/crypto/src/cms/CMSAuthenticatedDataGenerator.cs
index 0a37ca4f5..131a4753f 100644
--- a/crypto/src/cms/CMSAuthenticatedDataGenerator.cs
+++ b/crypto/src/cms/CMSAuthenticatedDataGenerator.cs
@@ -9,6 +9,7 @@ using Org.BouncyCastle.Crypto.Generators;
 using Org.BouncyCastle.Crypto.IO;
 using Org.BouncyCastle.Crypto.Parameters;
 using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
 using Org.BouncyCastle.Utilities.IO;
 
 namespace Org.BouncyCastle.Cms
@@ -83,10 +84,9 @@ namespace Org.BouncyCastle.Cms
 
 				content.Write(mOut);
 
-                mOut.Dispose();
-                bOut.Dispose();
+                Platform.Dispose(mOut);
 
-				encContent = new BerOctetString(bOut.ToArray());
+                encContent = new BerOctetString(bOut.ToArray());
 
 				byte[] macOctets = MacUtilities.DoFinal(mac);
 				macResult = new DerOctetString(macOctets);
diff --git a/crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs b/crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs
index 6638ccff7..a135cdd11 100644
--- a/crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs
+++ b/crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs
@@ -9,6 +9,7 @@ using Org.BouncyCastle.Crypto.Generators;
 using Org.BouncyCastle.Crypto.IO;
 using Org.BouncyCastle.Crypto.Parameters;
 using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
 using Org.BouncyCastle.Utilities.IO;
 
 namespace Org.BouncyCastle.Cms
@@ -251,26 +252,46 @@ namespace Org.BouncyCastle.Cms
 				macStream.Write(bytes, off, len);
 			}
 
-		    protected override void Dispose(bool disposing)
-		    {
-		        if (disposing)
-		        {
-                    macStream.Dispose();
+#if PORTABLE
+            protected override void Dispose(bool disposing)
+            {
+                if (disposing)
+                {
+                    Platform.Dispose(macStream);
 
                     // TODO Parent context(s) should really be be closed explicitly
 
-                    eiGen.Close();
+				    eiGen.Close();
 
-                    // [TODO] auth attributes go here 
-                    byte[] macOctets = MacUtilities.DoFinal(mac);
-                    authGen.AddObject(new DerOctetString(macOctets));
-                    // [TODO] unauth attributes go here
+				    // [TODO] auth attributes go here 
+				    byte[] macOctets = MacUtilities.DoFinal(mac);
+				    authGen.AddObject(new DerOctetString(macOctets));
+				    // [TODO] unauth attributes go here
 
-                    authGen.Close();
-                    cGen.Close();
-		        }
-		        base.Dispose(disposing);
-		    }
+				    authGen.Close();
+				    cGen.Close();
+                }
+                base.Dispose(disposing);
+            }
+#else
+            public override void Close()
+			{
+                Platform.Dispose(macStream);
+
+                // TODO Parent context(s) should really be be closed explicitly
+
+				eiGen.Close();
+
+				// [TODO] auth attributes go here 
+				byte[] macOctets = MacUtilities.DoFinal(mac);
+				authGen.AddObject(new DerOctetString(macOctets));
+				// [TODO] unauth attributes go here
+
+				authGen.Close();
+				cGen.Close();
+                base.Close();
+			}
+#endif
 		}
 	}
 }
diff --git a/crypto/src/cms/CMSCompressedData.cs b/crypto/src/cms/CMSCompressedData.cs
index a351d7206..21651f041 100644
--- a/crypto/src/cms/CMSCompressedData.cs
+++ b/crypto/src/cms/CMSCompressedData.cs
@@ -3,6 +3,7 @@ using System.IO;
 
 using Org.BouncyCastle.Asn1;
 using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Utilities;
 using Org.BouncyCastle.Utilities.Zlib;
 
 namespace Org.BouncyCastle.Cms
@@ -56,7 +57,7 @@ namespace Org.BouncyCastle.Cms
 			}
 			finally
 			{
-				zIn.Dispose();
+                Platform.Dispose(zIn);
 			}
         }
 
diff --git a/crypto/src/cms/CMSCompressedDataGenerator.cs b/crypto/src/cms/CMSCompressedDataGenerator.cs
index f147bb7ea..d51de1026 100644
--- a/crypto/src/cms/CMSCompressedDataGenerator.cs
+++ b/crypto/src/cms/CMSCompressedDataGenerator.cs
@@ -5,6 +5,7 @@ using System.IO;
 using Org.BouncyCastle.Asn1;
 using Org.BouncyCastle.Asn1.Cms;
 using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities;
 using Org.BouncyCastle.Utilities.Zlib;
 
 namespace Org.BouncyCastle.Cms
@@ -45,9 +46,9 @@ namespace Org.BouncyCastle.Cms
 
 				content.Write(zOut);
 
-				zOut.Dispose();
+                Platform.Dispose(zOut);
 
-				comAlgId = new AlgorithmIdentifier(new DerObjectIdentifier(compressionOid));
+                comAlgId = new AlgorithmIdentifier(new DerObjectIdentifier(compressionOid));
 				comOcts = new BerOctetString(bOut.ToArray());
             }
             catch (IOException e)
diff --git a/crypto/src/cms/CMSCompressedDataStreamGenerator.cs b/crypto/src/cms/CMSCompressedDataStreamGenerator.cs
index c5a4afa1c..0cb1bb641 100644
--- a/crypto/src/cms/CMSCompressedDataStreamGenerator.cs
+++ b/crypto/src/cms/CMSCompressedDataStreamGenerator.cs
@@ -4,6 +4,7 @@ using System.IO;
 using Org.BouncyCastle.Asn1;
 using Org.BouncyCastle.Asn1.Cms;
 using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities;
 using Org.BouncyCastle.Utilities.IO;
 using Org.BouncyCastle.Utilities.Zlib;
 
@@ -124,20 +125,34 @@ namespace Org.BouncyCastle.Cms
 				_out.Write(bytes, off, len);
 			}
 
-		    protected override void Dispose(bool disposing)
-		    {
-		        if (disposing)
-		        {
-                    _out.Dispose();
+#if PORTABLE
+            protected override void Dispose(bool disposing)
+            {
+                if (disposing)
+                {
+                    Platform.Dispose(_out);
 
                     // TODO Parent context(s) should really be be closed explicitly
 
                     _eiGen.Close();
-                    _cGen.Close();
-                    _sGen.Close();
-		        }
-		        base.Dispose(disposing);
-		    }
+				    _cGen.Close();
+				    _sGen.Close();
+                }
+                base.Dispose(disposing);
+            }
+#else
+            public override void Close()
+			{
+                Platform.Dispose(_out);
+
+                // TODO Parent context(s) should really be be closed explicitly
+
+                _eiGen.Close();
+				_cGen.Close();
+				_sGen.Close();
+				base.Close();
+			}
+#endif
 		}
 	}
 }
diff --git a/crypto/src/cms/CMSContentInfoParser.cs b/crypto/src/cms/CMSContentInfoParser.cs
index 5b1606394..a7b43f295 100644
--- a/crypto/src/cms/CMSContentInfoParser.cs
+++ b/crypto/src/cms/CMSContentInfoParser.cs
@@ -3,6 +3,7 @@ using System.IO;
 
 using Org.BouncyCastle.Asn1;
 using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Utilities;
 
 namespace Org.BouncyCastle.Cms
 {
@@ -41,7 +42,7 @@ namespace Org.BouncyCastle.Cms
 		*/
 		public void Close()
 		{
-            this.data.Dispose();
+            Platform.Dispose(this.data);
 		}
 	}
 }
diff --git a/crypto/src/cms/CMSEnvelopedDataGenerator.cs b/crypto/src/cms/CMSEnvelopedDataGenerator.cs
index 5071af4ad..d260e998a 100644
--- a/crypto/src/cms/CMSEnvelopedDataGenerator.cs
+++ b/crypto/src/cms/CMSEnvelopedDataGenerator.cs
@@ -80,9 +80,9 @@ namespace Org.BouncyCastle.Cms
 
 				content.Write(cOut);
 
-                cOut.Dispose();
+                Platform.Dispose(cOut);
 
-				encContent = new BerOctetString(bOut.ToArray());
+                encContent = new BerOctetString(bOut.ToArray());
 			}
 			catch (SecurityUtilityException e)
 			{
diff --git a/crypto/src/cms/CMSEnvelopedDataStreamGenerator.cs b/crypto/src/cms/CMSEnvelopedDataStreamGenerator.cs
index cb5b246eb..0a9e5bece 100644
--- a/crypto/src/cms/CMSEnvelopedDataStreamGenerator.cs
+++ b/crypto/src/cms/CMSEnvelopedDataStreamGenerator.cs
@@ -255,15 +255,16 @@ namespace Org.BouncyCastle.Cms
 				_out.Write(bytes, off, len);
 			}
 
-		    protected override void Dispose(bool disposing)
-		    {
-		        if (disposing)
-		        {
-                    _out.Dispose();
+#if PORTABLE
+            protected override void Dispose(bool disposing)
+            {
+                if (disposing)
+                {
+                    Platform.Dispose(_out);
 
-                    // TODO Parent context(s) should really be be closed explicitly
+                    // TODO Parent context(s) should really be closed explicitly
 
-                    _eiGen.Close();
+				    _eiGen.Close();
 
                     if (_outer.unprotectedAttributeGenerator != null)
                     {
@@ -274,11 +275,34 @@ namespace Org.BouncyCastle.Cms
                         _envGen.AddObject(new DerTaggedObject(false, 1, unprotectedAttrs));
                     }
 
-                    _envGen.Close();
-                    _cGen.Close();
-		        }
-		        base.Dispose(disposing);
-		    }
+				    _envGen.Close();
+				    _cGen.Close();
+                }
+                base.Dispose(disposing);
+            }
+#else
+            public override void Close()
+			{
+                Platform.Dispose(_out);
+
+                // TODO Parent context(s) should really be closed explicitly
+
+                _eiGen.Close();
+
+                if (_outer.unprotectedAttributeGenerator != null)
+                {
+                    Asn1.Cms.AttributeTable attrTable = _outer.unprotectedAttributeGenerator.GetAttributes(Platform.CreateHashtable());
+
+                    Asn1Set unprotectedAttrs = new BerSet(attrTable.ToAsn1EncodableVector());
+
+                    _envGen.AddObject(new DerTaggedObject(false, 1, unprotectedAttrs));
+                }
+
+				_envGen.Close();
+				_cGen.Close();
+				base.Close();
+			}
+#endif
 		}
 	}
 }
diff --git a/crypto/src/cms/CMSProcessableFile.cs b/crypto/src/cms/CMSProcessableFile.cs
index 46f88cd9f..5494b238a 100644
--- a/crypto/src/cms/CMSProcessableFile.cs
+++ b/crypto/src/cms/CMSProcessableFile.cs
@@ -2,6 +2,7 @@
 using System;
 using System.IO;
 
+using Org.BouncyCastle.Utilities;
 using Org.BouncyCastle.Utilities.IO;
 
 namespace Org.BouncyCastle.Cms
@@ -37,7 +38,7 @@ namespace Org.BouncyCastle.Cms
 		{
 			Stream inStr = GetInputStream();
 			Streams.PipeAll(inStr, zOut);
-			inStr.Dispose();
+            Platform.Dispose(inStr);
 		}
 
 		/// <returns>The file handle</returns>
diff --git a/crypto/src/cms/CMSProcessableInputStream.cs b/crypto/src/cms/CMSProcessableInputStream.cs
index 978caf862..b2abd6f71 100644
--- a/crypto/src/cms/CMSProcessableInputStream.cs
+++ b/crypto/src/cms/CMSProcessableInputStream.cs
@@ -1,6 +1,7 @@
 using System;
 using System.IO;
 
+using Org.BouncyCastle.Utilities;
 using Org.BouncyCastle.Utilities.IO;
 
 namespace Org.BouncyCastle.Cms
@@ -29,7 +30,7 @@ namespace Org.BouncyCastle.Cms
 			CheckSingleUsage();
 
 			Streams.PipeAll(input, output);
-            input.Dispose();
+            Platform.Dispose(input);
 		}
 
         [Obsolete]
diff --git a/crypto/src/cms/CMSSignedDataGenerator.cs b/crypto/src/cms/CMSSignedDataGenerator.cs
index 3d4dfeb95..f63ed874e 100644
--- a/crypto/src/cms/CMSSignedDataGenerator.cs
+++ b/crypto/src/cms/CMSSignedDataGenerator.cs
@@ -173,7 +173,7 @@ namespace Org.BouncyCastle.Cms
 					content.Write(sigStr);
                 }
 
-				sigStr.Dispose();
+                Platform.Dispose(sigStr);
                 byte[] sigBytes = ((IBlockResult)calculator.GetResult()).Collect();
 
 				Asn1Set unsignedAttr = null;
diff --git a/crypto/src/cms/CMSSignedDataParser.cs b/crypto/src/cms/CMSSignedDataParser.cs
index ec5a84fdf..e5e6edc58 100644
--- a/crypto/src/cms/CMSSignedDataParser.cs
+++ b/crypto/src/cms/CMSSignedDataParser.cs
@@ -384,7 +384,7 @@ namespace Org.BouncyCastle.Cms
 
 //			gen.AddSigners(parser.GetSignerInfos());
 
-            contentOut.Dispose();
+            Platform.Dispose(contentOut);
 
 			return outStr;
 		}
@@ -434,12 +434,12 @@ namespace Org.BouncyCastle.Cms
 
 			gen.AddSigners(parser.GetSignerInfos());
 
-            contentOut.Dispose();
+            Platform.Dispose(contentOut);
 
-			return outStr;
+            return outStr;
 		}
 
-		private static Asn1Set GetAsn1Set(
+        private static Asn1Set GetAsn1Set(
 			Asn1SetParser asn1SetParser)
 		{
 			return asn1SetParser == null
diff --git a/crypto/src/cms/CMSSignedDataStreamGenerator.cs b/crypto/src/cms/CMSSignedDataStreamGenerator.cs
index ceec09715..59837e397 100644
--- a/crypto/src/cms/CMSSignedDataStreamGenerator.cs
+++ b/crypto/src/cms/CMSSignedDataStreamGenerator.cs
@@ -636,7 +636,7 @@ namespace Org.BouncyCastle.Cms
 			{
 				content.Write(signedOut);
 			}
-            signedOut.Dispose();
+            Platform.Dispose(signedOut);
 		}
 
 		// RFC3852, section 5.1:
@@ -809,100 +809,113 @@ namespace Org.BouncyCastle.Cms
                 _out.Write(bytes, off, len);
             }
 
-		    protected override void Dispose(bool disposing)
-		    {
-		        if (disposing)
-		        {
-                    _out.Dispose();
+#if PORTABLE
+            protected override void Dispose(bool disposing)
+            {
+                if (disposing)
+                {
+                    DoClose();
+                }
+                base.Dispose(disposing);
+            }
+#else
+			public override void Close()
+            {
+                DoClose();
+				base.Close();
+			}
+#endif
 
-                    // TODO Parent context(s) should really be be closed explicitly
+            private void DoClose()
+            {
+                Platform.Dispose(_out);
 
-                    _eiGen.Close();
+                // TODO Parent context(s) should really be be closed explicitly
 
-                    outer._digests.Clear();    // clear the current preserved digest state
+                _eiGen.Close();
 
-                    if (outer._certs.Count > 0)
-                    {
-                        Asn1Set certs = CmsUtilities.CreateBerSetFromList(outer._certs);
+                outer._digests.Clear();    // clear the current preserved digest state
 
-                        WriteToGenerator(_sigGen, new BerTaggedObject(false, 0, certs));
-                    }
+                if (outer._certs.Count > 0)
+                {
+                    Asn1Set certs = CmsUtilities.CreateBerSetFromList(outer._certs);
 
-                    if (outer._crls.Count > 0)
-                    {
-                        Asn1Set crls = CmsUtilities.CreateBerSetFromList(outer._crls);
+                    WriteToGenerator(_sigGen, new BerTaggedObject(false, 0, certs));
+                }
 
-                        WriteToGenerator(_sigGen, new BerTaggedObject(false, 1, crls));
-                    }
+                if (outer._crls.Count > 0)
+                {
+                    Asn1Set crls = CmsUtilities.CreateBerSetFromList(outer._crls);
 
-                    //
-                    // Calculate the digest hashes
-                    //
-                    foreach (DictionaryEntry de in outer._messageDigests)
-                    {
-                        outer._messageHashes.Add(de.Key, DigestUtilities.DoFinal((IDigest)de.Value));
-                    }
+                    WriteToGenerator(_sigGen, new BerTaggedObject(false, 1, crls));
+                }
+
+                //
+                // Calculate the digest hashes
+                //
+                foreach (DictionaryEntry de in outer._messageDigests)
+                {
+                    outer._messageHashes.Add(de.Key, DigestUtilities.DoFinal((IDigest)de.Value));
+                }
 
-                    // TODO If the digest OIDs for precalculated signers weren't mixed in with
-                    // the others, we could fill in outer._digests here, instead of SignerInfoGenerator.Generate
+                // TODO If the digest OIDs for precalculated signers weren't mixed in with
+                // the others, we could fill in outer._digests here, instead of SignerInfoGenerator.Generate
 
-                    //
-                    // collect all the SignerInfo objects
-                    //
-                    Asn1EncodableVector signerInfos = new Asn1EncodableVector();
+                //
+                // collect all the SignerInfo objects
+                //
+                Asn1EncodableVector signerInfos = new Asn1EncodableVector();
 
-                    //
-                    // add the generated SignerInfo objects
-                    //
+                //
+                // add the generated SignerInfo objects
+                //
+                {
+                    foreach (DigestAndSignerInfoGeneratorHolder holder in outer._signerInfs)
                     {
-                        foreach (DigestAndSignerInfoGeneratorHolder holder in outer._signerInfs)
-                        {
-                            AlgorithmIdentifier digestAlgorithm = holder.DigestAlgorithm;
+                        AlgorithmIdentifier digestAlgorithm = holder.DigestAlgorithm;
 
-                            byte[] calculatedDigest = (byte[])outer._messageHashes[
-                                Helper.GetDigestAlgName(holder.digestOID)];
-                            outer._digests[holder.digestOID] = calculatedDigest.Clone();
+                        byte[] calculatedDigest = (byte[])outer._messageHashes[
+                            Helper.GetDigestAlgName(holder.digestOID)];
+                        outer._digests[holder.digestOID] = calculatedDigest.Clone();
 
-                            signerInfos.Add(holder.signerInf.Generate(_contentOID, digestAlgorithm, calculatedDigest));
-                        }
+                        signerInfos.Add(holder.signerInf.Generate(_contentOID, digestAlgorithm, calculatedDigest));
                     }
+                }
 
-                    //
-                    // add the precalculated SignerInfo objects.
-                    //
+                //
+                // add the precalculated SignerInfo objects.
+                //
+                {
+                    foreach (SignerInformation signer in outer._signers)
                     {
-                        foreach (SignerInformation signer in outer._signers)
-                        {
-                            // TODO Verify the content type and calculated digest match the precalculated SignerInfo
-                            //						if (!signer.ContentType.Equals(_contentOID))
-                            //						{
-                            //							// TODO The precalculated content type did not match - error?
-                            //						}
-                            //
-                            //						byte[] calculatedDigest = (byte[])outer._digests[signer.DigestAlgOid];
-                            //						if (calculatedDigest == null)
-                            //						{
-                            //							// TODO We can't confirm this digest because we didn't calculate it - error?
-                            //						}
-                            //						else
-                            //						{
-                            //							if (!Arrays.AreEqual(signer.GetContentDigest(), calculatedDigest))
-                            //							{
-                            //								// TODO The precalculated digest did not match - error?
-                            //							}
-                            //						}
-
-                            signerInfos.Add(signer.ToSignerInfo());
-                        }
+                        // TODO Verify the content type and calculated digest match the precalculated SignerInfo
+//						if (!signer.ContentType.Equals(_contentOID))
+//						{
+//							// TODO The precalculated content type did not match - error?
+//						}
+//
+//						byte[] calculatedDigest = (byte[])outer._digests[signer.DigestAlgOid];
+//						if (calculatedDigest == null)
+//						{
+//							// TODO We can't confirm this digest because we didn't calculate it - error?
+//						}
+//						else
+//						{
+//							if (!Arrays.AreEqual(signer.GetContentDigest(), calculatedDigest))
+//							{
+//								// TODO The precalculated digest did not match - error?
+//							}
+//						}
+
+                        signerInfos.Add(signer.ToSignerInfo());
                     }
+                }
 
-                    WriteToGenerator(_sigGen, new DerSet(signerInfos));
+                WriteToGenerator(_sigGen, new DerSet(signerInfos));
 
-                    _sigGen.Close();
-                    _sGen.Close();
-		        }
-		        base.Dispose(disposing);
-		    }
+				_sigGen.Close();
+                _sGen.Close();
+            }
 
 			private static void WriteToGenerator(
 				Asn1Generator	ag,
diff --git a/crypto/src/cms/CMSTypedStream.cs b/crypto/src/cms/CMSTypedStream.cs
index 73b439cce..681583765 100644
--- a/crypto/src/cms/CMSTypedStream.cs
+++ b/crypto/src/cms/CMSTypedStream.cs
@@ -2,6 +2,7 @@ using System;
 using System.IO;
 
 using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Utilities;
 using Org.BouncyCastle.Utilities.IO;
 
 namespace Org.BouncyCastle.Cms
@@ -52,7 +53,7 @@ namespace Org.BouncyCastle.Cms
 		public void Drain()
 		{
 			Streams.Drain(_in);
-			_in.Dispose();
+            Platform.Dispose(_in);
 		}
 
 		private class FullReaderStream : FilterStream
diff --git a/crypto/src/crypto/digests/GeneralDigest.cs b/crypto/src/crypto/digests/GeneralDigest.cs
index 54a09ae05..d40ad28bb 100644
--- a/crypto/src/crypto/digests/GeneralDigest.cs
+++ b/crypto/src/crypto/digests/GeneralDigest.cs
@@ -55,38 +55,44 @@ namespace Org.BouncyCastle.Crypto.Digests
             int     inOff,
             int     length)
         {
+            length = System.Math.Max(0, length);
+
             //
             // fill the current word
             //
-            while ((xBufOff != 0) && (length > 0))
+            int i = 0;
+            if (xBufOff != 0)
             {
-                Update(input[inOff]);
-                inOff++;
-                length--;
+                while (i < length)
+                {
+                    xBuf[xBufOff++] = input[inOff + i++];
+                    if (xBufOff == 4)
+                    {
+                        ProcessWord(xBuf, 0);
+                        xBufOff = 0;
+                        break;
+                    }
+                }
             }
 
             //
             // process whole words.
             //
-            while (length > xBuf.Length)
+            int limit = ((length - i) & ~3) + i;
+            for (; i < limit; i += 4)
             {
-                ProcessWord(input, inOff);
-
-                inOff += xBuf.Length;
-                length -= xBuf.Length;
-                byteCount += xBuf.Length;
+                ProcessWord(input, inOff + i);
             }
 
             //
             // load in the remainder.
             //
-            while (length > 0)
+            while (i < length)
             {
-                Update(input[inOff]);
-
-                inOff++;
-                length--;
+                xBuf[xBufOff++] = input[inOff + i++];
             }
+
+            byteCount += length;
         }
 
         public void Finish()
diff --git a/crypto/src/crypto/engines/AesEngine.cs b/crypto/src/crypto/engines/AesEngine.cs
index 164c43ee9..c84f4a964 100644
--- a/crypto/src/crypto/engines/AesEngine.cs
+++ b/crypto/src/crypto/engines/AesEngine.cs
@@ -288,17 +288,14 @@ namespace Org.BouncyCastle.Crypto.Engines
         * AES specified a fixed block size of 128 bits and key sizes 128/192/256 bits
         * This code is written assuming those are the only possible values
         */
-        private uint[][] GenerateWorkingKey(
-            byte[]	key,
-            bool	forEncryption)
+        private uint[][] GenerateWorkingKey(byte[] key, bool forEncryption)
         {
-            int KC = key.Length / 4;  // key length in words
-            int t;
-
-            if ((KC != 4) && (KC != 6) && (KC != 8)) 
+            int keyLen = key.Length;
+            if (keyLen < 16 || keyLen > 32 || (keyLen & 7) != 0)
                 throw new ArgumentException("Key length not 128/192/256 bits.");
 
-            ROUNDS = KC + 6;  // This is not always true for the generalized Rijndael that allows larger block sizes
+            int KC = keyLen >> 2;
+            this.ROUNDS = KC + 6;  // This is not always true for the generalized Rijndael that allows larger block sizes
 
             uint[][] W = new uint[ROUNDS + 1][]; // 4 words in a block
             for (int i = 0; i <= ROUNDS; ++i)
@@ -306,35 +303,109 @@ namespace Org.BouncyCastle.Crypto.Engines
                 W[i] = new uint[4];
             }
 
-            //
-            // copy the key into the round key array
-            //
-
-            t = 0;
-            for (int i = 0; i < key.Length; t++)
-            {
-                W[t >> 2][t & 3] = Pack.LE_To_UInt32(key, i);
-                i+=4;
-            }
-
-            //
-            // while not enough round key material calculated
-            // calculate new values
-            //
-            int k = (ROUNDS + 1) << 2;
-            for (int i = KC; (i < k); i++)
+            switch (KC)
             {
-                uint temp = W[(i-1)>>2][(i-1)&3];
-                if ((i % KC) == 0) 
+                case 4:
                 {
-                    temp = SubWord(Shift(temp, 8)) ^ rcon[(i / KC)-1];
-                } 
-                else if ((KC > 6) && ((i % KC) == 4)) 
+                    uint t0 = Pack.LE_To_UInt32(key,  0); W[0][0] = t0;
+                    uint t1 = Pack.LE_To_UInt32(key,  4); W[0][1] = t1;
+                    uint t2 = Pack.LE_To_UInt32(key,  8); W[0][2] = t2;
+                    uint t3 = Pack.LE_To_UInt32(key, 12); W[0][3] = t3;
+
+                    for (int i = 1; i <= 10; ++i)
+                    {
+                        uint u = SubWord(Shift(t3, 8)) ^ rcon[i - 1];
+                        t0 ^= u;  W[i][0] = t0;
+                        t1 ^= t0; W[i][1] = t1;
+                        t2 ^= t1; W[i][2] = t2;
+                        t3 ^= t2; W[i][3] = t3;
+                    }
+
+                    break;
+                }
+                case 6:
                 {
-                    temp = SubWord(temp);
+                    uint t0 = Pack.LE_To_UInt32(key,  0); W[0][0] = t0;
+                    uint t1 = Pack.LE_To_UInt32(key,  4); W[0][1] = t1;
+                    uint t2 = Pack.LE_To_UInt32(key,  8); W[0][2] = t2;
+                    uint t3 = Pack.LE_To_UInt32(key, 12); W[0][3] = t3;
+                    uint t4 = Pack.LE_To_UInt32(key, 16); W[1][0] = t4;
+                    uint t5 = Pack.LE_To_UInt32(key, 20); W[1][1] = t5;
+
+                    uint rcon = 1;
+                    uint u = SubWord(Shift(t5, 8)) ^ rcon; rcon <<= 1;
+                    t0 ^= u;  W[1][2] = t0;
+                    t1 ^= t0; W[1][3] = t1;
+                    t2 ^= t1; W[2][0] = t2;
+                    t3 ^= t2; W[2][1] = t3;
+                    t4 ^= t3; W[2][2] = t4;
+                    t5 ^= t4; W[2][3] = t5;
+
+                    for (int i = 3; i < 12; i += 3)
+                    {
+                        u = SubWord(Shift(t5, 8)) ^ rcon; rcon <<= 1;
+                        t0 ^= u;  W[i    ][0] = t0;
+                        t1 ^= t0; W[i    ][1] = t1;
+                        t2 ^= t1; W[i    ][2] = t2;
+                        t3 ^= t2; W[i    ][3] = t3;
+                        t4 ^= t3; W[i + 1][0] = t4;
+                        t5 ^= t4; W[i + 1][1] = t5;
+                        u = SubWord(Shift(t5, 8)) ^ rcon; rcon <<= 1;
+                        t0 ^= u;  W[i + 1][2] = t0;
+                        t1 ^= t0; W[i + 1][3] = t1;
+                        t2 ^= t1; W[i + 2][0] = t2;
+                        t3 ^= t2; W[i + 2][1] = t3;
+                        t4 ^= t3; W[i + 2][2] = t4;
+                        t5 ^= t4; W[i + 2][3] = t5;
+                    }
+
+                    u = SubWord(Shift(t5, 8)) ^ rcon;
+                    t0 ^= u;  W[12][0] = t0;
+                    t1 ^= t0; W[12][1] = t1;
+                    t2 ^= t1; W[12][2] = t2;
+                    t3 ^= t2; W[12][3] = t3;
+
+                    break;
                 }
+                case 8:
+                {
+                    uint t0 = Pack.LE_To_UInt32(key,  0); W[0][0] = t0;
+                    uint t1 = Pack.LE_To_UInt32(key,  4); W[0][1] = t1;
+                    uint t2 = Pack.LE_To_UInt32(key,  8); W[0][2] = t2;
+                    uint t3 = Pack.LE_To_UInt32(key, 12); W[0][3] = t3;
+                    uint t4 = Pack.LE_To_UInt32(key, 16); W[1][0] = t4;
+                    uint t5 = Pack.LE_To_UInt32(key, 20); W[1][1] = t5;
+                    uint t6 = Pack.LE_To_UInt32(key, 24); W[1][2] = t6;
+                    uint t7 = Pack.LE_To_UInt32(key, 28); W[1][3] = t7;
+
+                    uint u, rcon = 1;
+
+                    for (int i = 2; i < 14; i += 2)
+                    {
+                        u = SubWord(Shift(t7, 8)) ^ rcon; rcon <<= 1;
+                        t0 ^= u;  W[i    ][0] = t0;
+                        t1 ^= t0; W[i    ][1] = t1;
+                        t2 ^= t1; W[i    ][2] = t2;
+                        t3 ^= t2; W[i    ][3] = t3;
+                        u = SubWord(t3);
+                        t4 ^= u;  W[i + 1][0] = t4;
+                        t5 ^= t4; W[i + 1][1] = t5;
+                        t6 ^= t5; W[i + 1][2] = t6;
+                        t7 ^= t6; W[i + 1][3] = t7;
+                    }
+
+                    u = SubWord(Shift(t7, 8)) ^ rcon;
+                    t0 ^= u;  W[14][0] = t0;
+                    t1 ^= t0; W[14][1] = t1;
+                    t2 ^= t1; W[14][2] = t2;
+                    t3 ^= t2; W[14][3] = t3;
 
-                W[i>>2][i&3] = W[(i - KC)>>2][(i-KC)&3] ^ temp;
+                    break;
+                }
+                default:
+                {
+                    throw new InvalidOperationException("Should never get here");
+                }
             }
 
             if (!forEncryption)
diff --git a/crypto/src/crypto/engines/AesFastEngine.cs b/crypto/src/crypto/engines/AesFastEngine.cs
index 38ce1a946..18367a324 100644
--- a/crypto/src/crypto/engines/AesFastEngine.cs
+++ b/crypto/src/crypto/engines/AesFastEngine.cs
@@ -624,16 +624,14 @@ namespace Org.BouncyCastle.Crypto.Engines
         * AES specified a fixed block size of 128 bits and key sizes 128/192/256 bits
         * This code is written assuming those are the only possible values
         */
-        private uint[][] GenerateWorkingKey(
-            byte[]	key,
-            bool	forEncryption)
+        private uint[][] GenerateWorkingKey(byte[] key, bool forEncryption)
         {
-            int KC = key.Length / 4;  // key length in words
-
-            if (((KC != 4) && (KC != 6) && (KC != 8)) || ((KC * 4) != key.Length))
+            int keyLen = key.Length;
+            if (keyLen < 16 || keyLen > 32 || (keyLen & 7) != 0)
                 throw new ArgumentException("Key length not 128/192/256 bits.");
 
-            ROUNDS = KC + 6;  // This is not always true for the generalized Rijndael that allows larger block sizes
+            int KC = keyLen >> 2;
+            this.ROUNDS = KC + 6;  // This is not always true for the generalized Rijndael that allows larger block sizes
 
             uint[][] W = new uint[ROUNDS + 1][]; // 4 words in a block
             for (int i = 0; i <= ROUNDS; ++i)
@@ -641,32 +639,109 @@ namespace Org.BouncyCastle.Crypto.Engines
                 W[i] = new uint[4];
             }
 
-            //
-            // copy the key into the round key array
-            //
-
-            int t = 0;
-            for (int i = 0; i < key.Length; t++)
+            switch (KC)
+            {
+            case 4:
             {
-                W[t >> 2][t & 3] = Pack.LE_To_UInt32(key, i);
-                i+=4;
+                uint t0 = Pack.LE_To_UInt32(key,  0); W[0][0] = t0;
+                uint t1 = Pack.LE_To_UInt32(key,  4); W[0][1] = t1;
+                uint t2 = Pack.LE_To_UInt32(key,  8); W[0][2] = t2;
+                uint t3 = Pack.LE_To_UInt32(key, 12); W[0][3] = t3;
+
+                for (int i = 1; i <= 10; ++i)
+                {
+                    uint u = SubWord(Shift(t3, 8)) ^ rcon[i - 1];
+                    t0 ^= u;  W[i][0] = t0;
+                    t1 ^= t0; W[i][1] = t1;
+                    t2 ^= t1; W[i][2] = t2;
+                    t3 ^= t2; W[i][3] = t3;
+                }
+
+                break;
             }
+            case 6:
+            {
+                uint t0 = Pack.LE_To_UInt32(key,  0); W[0][0] = t0;
+                uint t1 = Pack.LE_To_UInt32(key,  4); W[0][1] = t1;
+                uint t2 = Pack.LE_To_UInt32(key,  8); W[0][2] = t2;
+                uint t3 = Pack.LE_To_UInt32(key, 12); W[0][3] = t3;
+                uint t4 = Pack.LE_To_UInt32(key, 16); W[1][0] = t4;
+                uint t5 = Pack.LE_To_UInt32(key, 20); W[1][1] = t5;
+
+                uint rcon = 1;
+                uint u = SubWord(Shift(t5, 8)) ^ rcon; rcon <<= 1;
+                t0 ^= u;  W[1][2] = t0;
+                t1 ^= t0; W[1][3] = t1;
+                t2 ^= t1; W[2][0] = t2;
+                t3 ^= t2; W[2][1] = t3;
+                t4 ^= t3; W[2][2] = t4;
+                t5 ^= t4; W[2][3] = t5;
+
+                for (int i = 3; i < 12; i += 3)
+                {
+                    u = SubWord(Shift(t5, 8)) ^ rcon; rcon <<= 1;
+                    t0 ^= u;  W[i    ][0] = t0;
+                    t1 ^= t0; W[i    ][1] = t1;
+                    t2 ^= t1; W[i    ][2] = t2;
+                    t3 ^= t2; W[i    ][3] = t3;
+                    t4 ^= t3; W[i + 1][0] = t4;
+                    t5 ^= t4; W[i + 1][1] = t5;
+                    u = SubWord(Shift(t5, 8)) ^ rcon; rcon <<= 1;
+                    t0 ^= u;  W[i + 1][2] = t0;
+                    t1 ^= t0; W[i + 1][3] = t1;
+                    t2 ^= t1; W[i + 2][0] = t2;
+                    t3 ^= t2; W[i + 2][1] = t3;
+                    t4 ^= t3; W[i + 2][2] = t4;
+                    t5 ^= t4; W[i + 2][3] = t5;
+                }
+
+                u = SubWord(Shift(t5, 8)) ^ rcon;
+                t0 ^= u;  W[12][0] = t0;
+                t1 ^= t0; W[12][1] = t1;
+                t2 ^= t1; W[12][2] = t2;
+                t3 ^= t2; W[12][3] = t3;
 
-            //
-            // while not enough round key material calculated
-            // calculate new values
-            //
-            int k = (ROUNDS + 1) << 2;
-            for (int i = KC; (i < k); i++)
+                break;
+            }
+            case 8:
             {
-                uint temp = W[(i-1)>>2][(i-1)&3];
-                if ((i % KC) == 0) {
-                    temp = SubWord(Shift(temp, 8)) ^ rcon[(i / KC)-1];
-                } else if ((KC > 6) && ((i % KC) == 4)) {
-                    temp = SubWord(temp);
+                uint t0 = Pack.LE_To_UInt32(key,  0); W[0][0] = t0;
+                uint t1 = Pack.LE_To_UInt32(key,  4); W[0][1] = t1;
+                uint t2 = Pack.LE_To_UInt32(key,  8); W[0][2] = t2;
+                uint t3 = Pack.LE_To_UInt32(key, 12); W[0][3] = t3;
+                uint t4 = Pack.LE_To_UInt32(key, 16); W[1][0] = t4;
+                uint t5 = Pack.LE_To_UInt32(key, 20); W[1][1] = t5;
+                uint t6 = Pack.LE_To_UInt32(key, 24); W[1][2] = t6;
+                uint t7 = Pack.LE_To_UInt32(key, 28); W[1][3] = t7;
+
+                uint u, rcon = 1;
+
+                for (int i = 2; i < 14; i += 2)
+                {
+                    u = SubWord(Shift(t7, 8)) ^ rcon; rcon <<= 1;
+                    t0 ^= u;  W[i    ][0] = t0;
+                    t1 ^= t0; W[i    ][1] = t1;
+                    t2 ^= t1; W[i    ][2] = t2;
+                    t3 ^= t2; W[i    ][3] = t3;
+                    u = SubWord(t3);
+                    t4 ^= u;  W[i + 1][0] = t4;
+                    t5 ^= t4; W[i + 1][1] = t5;
+                    t6 ^= t5; W[i + 1][2] = t6;
+                    t7 ^= t6; W[i + 1][3] = t7;
                 }
 
-                W[i>>2][i&3] = W[(i - KC)>>2][(i-KC)&3] ^ temp;
+                u = SubWord(Shift(t7, 8)) ^ rcon;
+                t0 ^= u;  W[14][0] = t0;
+                t1 ^= t0; W[14][1] = t1;
+                t2 ^= t1; W[14][2] = t2;
+                t3 ^= t2; W[14][3] = t3;
+
+                break;
+            }
+            default:
+            {
+                throw new InvalidOperationException("Should never get here");
+            }
             }
 
             if (!forEncryption)
diff --git a/crypto/src/crypto/engines/AesLightEngine.cs b/crypto/src/crypto/engines/AesLightEngine.cs
index a42b34971..a48fa5857 100644
--- a/crypto/src/crypto/engines/AesLightEngine.cs
+++ b/crypto/src/crypto/engines/AesLightEngine.cs
@@ -185,17 +185,14 @@ namespace Org.BouncyCastle.Crypto.Engines
         * AES specified a fixed block size of 128 bits and key sizes 128/192/256 bits
         * This code is written assuming those are the only possible values
         */
-        private uint[][] GenerateWorkingKey(
-            byte[]	key,
-            bool	forEncryption)
+        private uint[][] GenerateWorkingKey(byte[] key, bool forEncryption)
         {
-            int KC = key.Length / 4;  // key length in words
-            int t;
-
-            if ((KC != 4) && (KC != 6) && (KC != 8))
+            int keyLen = key.Length;
+            if (keyLen < 16 || keyLen > 32 || (keyLen & 7) != 0)
                 throw new ArgumentException("Key length not 128/192/256 bits.");
 
-            ROUNDS = KC + 6;  // This is not always true for the generalized Rijndael that allows larger block sizes
+            int KC = keyLen >> 2;
+            this.ROUNDS = KC + 6;  // This is not always true for the generalized Rijndael that allows larger block sizes
 
             uint[][] W = new uint[ROUNDS + 1][]; // 4 words in a block
             for (int i = 0; i <= ROUNDS; ++i)
@@ -203,40 +200,114 @@ namespace Org.BouncyCastle.Crypto.Engines
                 W[i] = new uint[4];
             }
 
-            //
-            // copy the key into the round key array
-            //
-
-            t = 0;
-            for (int i = 0; i < key.Length; t++)
-            {
-                W[t >> 2][t & 3] = Pack.LE_To_UInt32(key, i);
-                i+=4;
-            }
-
-            //
-            // while not enough round key material calculated
-            // calculate new values
-            //
-            int k = (ROUNDS + 1) << 2;
-            for (int i = KC; (i < k); i++)
+            switch (KC)
             {
-                uint temp = W[(i-1)>>2][(i-1)&3];
-                if ((i % KC) == 0) 
+                case 4:
                 {
-                    temp = SubWord(Shift(temp, 8)) ^ rcon[(i / KC)-1];
-                } 
-                else if ((KC > 6) && ((i % KC) == 4)) 
+                    uint t0 = Pack.LE_To_UInt32(key,  0); W[0][0] = t0;
+                    uint t1 = Pack.LE_To_UInt32(key,  4); W[0][1] = t1;
+                    uint t2 = Pack.LE_To_UInt32(key,  8); W[0][2] = t2;
+                    uint t3 = Pack.LE_To_UInt32(key, 12); W[0][3] = t3;
+
+                    for (int i = 1; i <= 10; ++i)
+                    {
+                        uint u = SubWord(Shift(t3, 8)) ^ rcon[i - 1];
+                        t0 ^= u;  W[i][0] = t0;
+                        t1 ^= t0; W[i][1] = t1;
+                        t2 ^= t1; W[i][2] = t2;
+                        t3 ^= t2; W[i][3] = t3;
+                    }
+
+                    break;
+                }
+                case 6:
                 {
-                    temp = SubWord(temp);
+                    uint t0 = Pack.LE_To_UInt32(key,  0); W[0][0] = t0;
+                    uint t1 = Pack.LE_To_UInt32(key,  4); W[0][1] = t1;
+                    uint t2 = Pack.LE_To_UInt32(key,  8); W[0][2] = t2;
+                    uint t3 = Pack.LE_To_UInt32(key, 12); W[0][3] = t3;
+                    uint t4 = Pack.LE_To_UInt32(key, 16); W[1][0] = t4;
+                    uint t5 = Pack.LE_To_UInt32(key, 20); W[1][1] = t5;
+
+                    uint rcon = 1;
+                    uint u = SubWord(Shift(t5, 8)) ^ rcon; rcon <<= 1;
+                    t0 ^= u;  W[1][2] = t0;
+                    t1 ^= t0; W[1][3] = t1;
+                    t2 ^= t1; W[2][0] = t2;
+                    t3 ^= t2; W[2][1] = t3;
+                    t4 ^= t3; W[2][2] = t4;
+                    t5 ^= t4; W[2][3] = t5;
+
+                    for (int i = 3; i < 12; i += 3)
+                    {
+                        u = SubWord(Shift(t5, 8)) ^ rcon; rcon <<= 1;
+                        t0 ^= u;  W[i    ][0] = t0;
+                        t1 ^= t0; W[i    ][1] = t1;
+                        t2 ^= t1; W[i    ][2] = t2;
+                        t3 ^= t2; W[i    ][3] = t3;
+                        t4 ^= t3; W[i + 1][0] = t4;
+                        t5 ^= t4; W[i + 1][1] = t5;
+                        u = SubWord(Shift(t5, 8)) ^ rcon; rcon <<= 1;
+                        t0 ^= u;  W[i + 1][2] = t0;
+                        t1 ^= t0; W[i + 1][3] = t1;
+                        t2 ^= t1; W[i + 2][0] = t2;
+                        t3 ^= t2; W[i + 2][1] = t3;
+                        t4 ^= t3; W[i + 2][2] = t4;
+                        t5 ^= t4; W[i + 2][3] = t5;
+                    }
+
+                    u = SubWord(Shift(t5, 8)) ^ rcon;
+                    t0 ^= u;  W[12][0] = t0;
+                    t1 ^= t0; W[12][1] = t1;
+                    t2 ^= t1; W[12][2] = t2;
+                    t3 ^= t2; W[12][3] = t3;
+
+                    break;
                 }
+                case 8:
+                {
+                    uint t0 = Pack.LE_To_UInt32(key,  0); W[0][0] = t0;
+                    uint t1 = Pack.LE_To_UInt32(key,  4); W[0][1] = t1;
+                    uint t2 = Pack.LE_To_UInt32(key,  8); W[0][2] = t2;
+                    uint t3 = Pack.LE_To_UInt32(key, 12); W[0][3] = t3;
+                    uint t4 = Pack.LE_To_UInt32(key, 16); W[1][0] = t4;
+                    uint t5 = Pack.LE_To_UInt32(key, 20); W[1][1] = t5;
+                    uint t6 = Pack.LE_To_UInt32(key, 24); W[1][2] = t6;
+                    uint t7 = Pack.LE_To_UInt32(key, 28); W[1][3] = t7;
+
+                    uint u, rcon = 1;
+
+                    for (int i = 2; i < 14; i += 2)
+                    {
+                        u = SubWord(Shift(t7, 8)) ^ rcon; rcon <<= 1;
+                        t0 ^= u;  W[i    ][0] = t0;
+                        t1 ^= t0; W[i    ][1] = t1;
+                        t2 ^= t1; W[i    ][2] = t2;
+                        t3 ^= t2; W[i    ][3] = t3;
+                        u = SubWord(t3);
+                        t4 ^= u;  W[i + 1][0] = t4;
+                        t5 ^= t4; W[i + 1][1] = t5;
+                        t6 ^= t5; W[i + 1][2] = t6;
+                        t7 ^= t6; W[i + 1][3] = t7;
+                    }
+
+                    u = SubWord(Shift(t7, 8)) ^ rcon;
+                    t0 ^= u;  W[14][0] = t0;
+                    t1 ^= t0; W[14][1] = t1;
+                    t2 ^= t1; W[14][2] = t2;
+                    t3 ^= t2; W[14][3] = t3;
 
-                W[i>>2][i&3] = W[(i - KC)>>2][(i-KC)&3] ^ temp;
+                    break;
+                }
+                default:
+                {
+                    throw new InvalidOperationException("Should never get here");
+                }
             }
 
-            if (!forEncryption) 
+            if (!forEncryption)
             {
-                for (int j = 1; j < ROUNDS; j++) 
+                for (int j = 1; j < ROUNDS; j++)
                 {
                     uint[] w = W[j];
                     for (int i = 0; i < 4; i++)
diff --git a/crypto/src/crypto/generators/DHParametersHelper.cs b/crypto/src/crypto/generators/DHParametersHelper.cs
index bf2de2add..385690430 100644
--- a/crypto/src/crypto/generators/DHParametersHelper.cs
+++ b/crypto/src/crypto/generators/DHParametersHelper.cs
@@ -44,10 +44,10 @@ namespace Org.BouncyCastle.Crypto.Generators
 
                     p = q.ShiftLeft(1).Add(BigInteger.One);
 
-                    if (!p.IsProbablePrime(certainty))
+                    if (!p.IsProbablePrime(certainty, true))
                         continue;
 
-                    if (certainty > 2 && !q.IsProbablePrime(certainty - 2))
+                    if (certainty > 2 && !q.IsProbablePrime(certainty, true))
                         continue;
 
                     break;
@@ -92,15 +92,15 @@ namespace Org.BouncyCastle.Crypto.Generators
                     if (q.BitLength != qLength)
                         continue;
 
-                    if (!q.RabinMillerTest(2, random))
+                    if (!q.RabinMillerTest(2, random, true))
                         continue;
 
                     p = q.ShiftLeft(1).Add(BigInteger.One);
 
-                    if (!p.RabinMillerTest(certainty, random))
+                    if (!p.RabinMillerTest(certainty, random, true))
                         continue;
 
-                    if (certainty > 2 && !q.RabinMillerTest(certainty - 2, random))
+                    if (certainty > 2 && !q.RabinMillerTest(certainty - 2, random, true))
                         continue;
 
                     /*
diff --git a/crypto/src/crypto/generators/NaccacheSternKeyPairGenerator.cs b/crypto/src/crypto/generators/NaccacheSternKeyPairGenerator.cs
index cff12ac44..d68106844 100644
--- a/crypto/src/crypto/generators/NaccacheSternKeyPairGenerator.cs
+++ b/crypto/src/crypto/generators/NaccacheSternKeyPairGenerator.cs
@@ -98,7 +98,7 @@ namespace Org.BouncyCastle.Crypto.Generators
 
 				p = _p.Multiply(_2au).Add(BigInteger.One);
 
-				if (!p.IsProbablePrime(certainty))
+				if (!p.IsProbablePrime(certainty, true))
 					continue;
 
 				for (;;)
@@ -110,7 +110,7 @@ namespace Org.BouncyCastle.Crypto.Generators
 
 					q = _q.Multiply(_2bv).Add(BigInteger.One);
 
-					if (q.IsProbablePrime(certainty))
+					if (q.IsProbablePrime(certainty, true))
 						break;
 				}
 
diff --git a/crypto/src/crypto/generators/RsaKeyPairGenerator.cs b/crypto/src/crypto/generators/RsaKeyPairGenerator.cs
index 2613b902b..449976550 100644
--- a/crypto/src/crypto/generators/RsaKeyPairGenerator.cs
+++ b/crypto/src/crypto/generators/RsaKeyPairGenerator.cs
@@ -150,7 +150,7 @@ namespace Org.BouncyCastle.Crypto.Generators
                 if (p.Mod(e).Equals(One))
                     continue;
 
-                if (!p.IsProbablePrime(parameters.Certainty))
+                if (!p.IsProbablePrime(parameters.Certainty, true))
                     continue;
 
                 if (!eIsKnownOddPrime && !e.Gcd(p.Subtract(One)).Equals(One))
diff --git a/crypto/src/crypto/io/CipherStream.cs b/crypto/src/crypto/io/CipherStream.cs
index f2083e878..bfce386a7 100644
--- a/crypto/src/crypto/io/CipherStream.cs
+++ b/crypto/src/crypto/io/CipherStream.cs
@@ -3,6 +3,7 @@ using System.Diagnostics;
 using System.IO;
 
 using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Utilities;
 
 namespace Org.BouncyCastle.Crypto.IO
 {
@@ -201,22 +202,36 @@ namespace Org.BouncyCastle.Crypto.IO
             set { throw new NotSupportedException(); }
         }
 
+#if PORTABLE
         protected override void Dispose(bool disposing)
         {
             if (disposing)
             {
-                if (outCipher != null)
-                {
-                    byte[] data = outCipher.DoFinal();
-                    stream.Write(data, 0, data.Length);
-                    stream.Flush();
-                }
-                stream.Dispose();
+			    if (outCipher != null)
+			    {
+				    byte[] data = outCipher.DoFinal();
+				    stream.Write(data, 0, data.Length);
+				    stream.Flush();
+			    }
+                Platform.Dispose(stream);
             }
             base.Dispose(disposing);
         }
+#else
+        public override void Close()
+        {
+			if (outCipher != null)
+			{
+				byte[] data = outCipher.DoFinal();
+				stream.Write(data, 0, data.Length);
+				stream.Flush();
+			}
+            Platform.Dispose(stream);
+            base.Close();
+        }
+#endif
 
-		public override void Flush()
+        public override void Flush()
         {
 			// Note: outCipher.DoFinal is only called during Close()
 			stream.Flush();
diff --git a/crypto/src/crypto/io/DigestStream.cs b/crypto/src/crypto/io/DigestStream.cs
index b0a69f03e..dce875792 100644
--- a/crypto/src/crypto/io/DigestStream.cs
+++ b/crypto/src/crypto/io/DigestStream.cs
@@ -1,6 +1,8 @@
 using System;
 using System.IO;
 
+using Org.BouncyCastle.Utilities;
+
 namespace Org.BouncyCastle.Crypto.IO
 {
 	public class DigestStream
@@ -110,16 +112,24 @@ namespace Org.BouncyCastle.Crypto.IO
 			set { stream.Position = value; }
 		}
 
-	    protected override void Dispose(bool disposing)
-	    {
-	        if (disposing)
-	        {
-	            stream.Dispose();
-	        }
-	        base.Dispose(disposing);
-	    }
+#if PORTABLE
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                Platform.Dispose(stream);
+            }
+            base.Dispose(disposing);
+        }
+#else
+		public override void Close()
+		{
+            Platform.Dispose(stream);
+            base.Close();
+		}
+#endif
 
-		public override  void Flush()
+        public override void Flush()
 		{
 			stream.Flush();
 		}
diff --git a/crypto/src/crypto/io/MacStream.cs b/crypto/src/crypto/io/MacStream.cs
index c7feabcae..d9b8323b5 100644
--- a/crypto/src/crypto/io/MacStream.cs
+++ b/crypto/src/crypto/io/MacStream.cs
@@ -1,6 +1,8 @@
 using System;
 using System.IO;
 
+using Org.BouncyCastle.Utilities;
+
 namespace Org.BouncyCastle.Crypto.IO
 {
 	public class MacStream
@@ -109,16 +111,24 @@ namespace Org.BouncyCastle.Crypto.IO
 			set { stream.Position = value; }
 		}
 
-	    protected override void Dispose(bool disposing)
-	    {
-	        if (disposing)
-	        {
-	            stream.Dispose();
-	        }
-	        base.Dispose(disposing);
-	    }
-
-		public override void Flush()
+#if PORTABLE
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                Platform.Dispose(stream);
+            }
+            base.Dispose(disposing);
+        }
+#else
+        public override void Close()
+        {
+            Platform.Dispose(stream);
+            base.Close();
+        }
+#endif
+
+        public override void Flush()
 		{
 			stream.Flush();
 		}
diff --git a/crypto/src/crypto/io/SignerStream.cs b/crypto/src/crypto/io/SignerStream.cs
index 2a609f6ee..1e37c8d34 100644
--- a/crypto/src/crypto/io/SignerStream.cs
+++ b/crypto/src/crypto/io/SignerStream.cs
@@ -1,6 +1,8 @@
 using System;
 using System.IO;
 
+using Org.BouncyCastle.Utilities;
+
 namespace Org.BouncyCastle.Crypto.IO
 {
 	public class SignerStream
@@ -110,16 +112,24 @@ namespace Org.BouncyCastle.Crypto.IO
 			set { stream.Position = value; }
 		}
 
-	    protected override void Dispose(bool disposing)
-	    {
-	        if (disposing)
-	        {
-	            stream.Dispose();
-	        }
-	        base.Dispose(disposing);
-	    }
-
-		public override  void Flush()
+#if PORTABLE
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                Platform.Dispose(stream);
+            }
+            base.Dispose(disposing);
+        }
+#else
+        public override void Close()
+        {
+            Platform.Dispose(stream);
+            base.Close();
+        }
+#endif
+
+        public override void Flush()
 		{
 			stream.Flush();
 		}
diff --git a/crypto/src/crypto/modes/GCMBlockCipher.cs b/crypto/src/crypto/modes/GCMBlockCipher.cs
index 8e6120eef..ecebc3de9 100644
--- a/crypto/src/crypto/modes/GCMBlockCipher.cs
+++ b/crypto/src/crypto/modes/GCMBlockCipher.cs
@@ -513,10 +513,11 @@ namespace Org.BouncyCastle.Crypto.Modes
 
         private byte[] GetNextCounterBlock()
         {
-            for (int i = 15; i >= 12; --i)
-            {
-                if (++counter[i] != 0) break;
-            }
+            uint c = 1;
+            c += counter[15]; counter[15] = (byte)c; c >>= 8;
+            c += counter[14]; counter[14] = (byte)c; c >>= 8;
+            c += counter[13]; counter[13] = (byte)c; c >>= 8;
+            c += counter[12]; counter[12] = (byte)c;
 
             byte[] tmp = new byte[BlockSize];
             // TODO Sure would be nice if ciphers could operate on int[]
diff --git a/crypto/src/crypto/operators/Asn1Signature.cs b/crypto/src/crypto/operators/Asn1Signature.cs
index ec59c11aa..3a20e4bff 100644
--- a/crypto/src/crypto/operators/Asn1Signature.cs
+++ b/crypto/src/crypto/operators/Asn1Signature.cs
@@ -303,12 +303,7 @@ namespace Org.BouncyCastle.Crypto.Operators
 			set { throw new NotImplementedException (); }
 		}
 
-        protected override void Dispose(bool disposing)
-        {
-            base.Dispose(disposing);
-        }
-
-        public override  void Flush()
+        public override void Flush()
 		{
 		}
 
diff --git a/crypto/src/crypto/parameters/SkeinParameters.cs b/crypto/src/crypto/parameters/SkeinParameters.cs
index 82a78968f..cc57ef5ff 100644
--- a/crypto/src/crypto/parameters/SkeinParameters.cs
+++ b/crypto/src/crypto/parameters/SkeinParameters.cs
@@ -240,7 +240,7 @@ namespace Org.BouncyCastle.Crypto.Parameters
 					outBytes.Write(emailAddress);
 					outBytes.Write(" ");
 					outBytes.Write(distinguisher);
-					outBytes.Dispose();
+                    Platform.Dispose(outBytes);
 					return Set(PARAM_TYPE_PERSONALISATION, bout.ToArray());
 				}
 				catch (IOException e)
diff --git a/crypto/src/crypto/prng/ThreadedSeedGenerator.cs b/crypto/src/crypto/prng/ThreadedSeedGenerator.cs
index 6b732161d..499aab267 100644
--- a/crypto/src/crypto/prng/ThreadedSeedGenerator.cs
+++ b/crypto/src/crypto/prng/ThreadedSeedGenerator.cs
@@ -73,8 +73,6 @@ namespace Org.BouncyCastle.Crypto.Prng
 
 				for (int i = 0; i < end; i++)
 				{
-				    using (var mre = new ManualResetEvent(false))
-				    {
 					while (this.counter == last)
 					{
 						try
@@ -90,7 +88,6 @@ namespace Org.BouncyCastle.Crypto.Prng
 							// ignore
 						}
 					}
-				    }
 
 					last = this.counter;
 
diff --git a/crypto/src/crypto/tls/ByteQueueStream.cs b/crypto/src/crypto/tls/ByteQueueStream.cs
index 3b8ffb02f..249e6099b 100644
--- a/crypto/src/crypto/tls/ByteQueueStream.cs
+++ b/crypto/src/crypto/tls/ByteQueueStream.cs
@@ -33,11 +33,6 @@ namespace Org.BouncyCastle.Crypto.Tls
             get { return true; }
         }
 
-        protected override void Dispose(bool disposing)
-        {
-            base.Dispose(disposing);
-        }
-
         public override void Flush()
         {
         }
diff --git a/crypto/src/crypto/tls/CertificateUrl.cs b/crypto/src/crypto/tls/CertificateUrl.cs
index b51121121..d285fa0f6 100644
--- a/crypto/src/crypto/tls/CertificateUrl.cs
+++ b/crypto/src/crypto/tls/CertificateUrl.cs
@@ -117,7 +117,7 @@ namespace Org.BouncyCastle.Crypto.Tls
                 this.Position = 0;
                 TlsUtilities.WriteUint16((int)length, this);
                 this.WriteTo(output);
-                this.Dispose();
+                Platform.Dispose(this);
             }
         }
     }
diff --git a/crypto/src/crypto/tls/DtlsReliableHandshake.cs b/crypto/src/crypto/tls/DtlsReliableHandshake.cs
index 527a02a22..c45e15f66 100644
--- a/crypto/src/crypto/tls/DtlsReliableHandshake.cs
+++ b/crypto/src/crypto/tls/DtlsReliableHandshake.cs
@@ -419,9 +419,9 @@ namespace Org.BouncyCastle.Crypto.Tls
 
             internal void SendToRecordLayer(DtlsRecordLayer recordLayer)
             {
-                var buffer = ToArray();
+                byte[] buffer = ToArray();
                 recordLayer.Send(buffer, 0, buffer.Length);
-                this.Dispose();
+                Platform.Dispose(this);
             }
         }
 
diff --git a/crypto/src/crypto/tls/RecordStream.cs b/crypto/src/crypto/tls/RecordStream.cs
index 4c57da502..d510ed94e 100644
--- a/crypto/src/crypto/tls/RecordStream.cs
+++ b/crypto/src/crypto/tls/RecordStream.cs
@@ -1,6 +1,8 @@
 using System;
 using System.IO;
 
+using Org.BouncyCastle.Utilities;
+
 namespace Org.BouncyCastle.Crypto.Tls
 {
     /// <summary>An implementation of the TLS 1.0/1.1/1.2 record layer, allowing downgrade to SSLv3.</summary>
@@ -287,7 +289,7 @@ namespace Org.BouncyCastle.Crypto.Tls
         {
             try
             {
-                mInput.Dispose();
+                Platform.Dispose(mInput);
             }
             catch (IOException)
             {
@@ -295,7 +297,7 @@ namespace Org.BouncyCastle.Crypto.Tls
 
             try
             {
-                mOutput.Dispose();
+                Platform.Dispose(mOutput);
             }
             catch (IOException)
             {
diff --git a/crypto/src/crypto/tls/TlsProtocol.cs b/crypto/src/crypto/tls/TlsProtocol.cs
index fb25029f7..c3a7572c6 100644
--- a/crypto/src/crypto/tls/TlsProtocol.cs
+++ b/crypto/src/crypto/tls/TlsProtocol.cs
@@ -1311,7 +1311,7 @@ namespace Org.BouncyCastle.Crypto.Tls
                 this.Position = 1;
                 TlsUtilities.WriteUint24((int)length, this);
                 protocol.WriteHandshakeMessage(ToArray(), 0, (int)Length);
-                this.Dispose();
+                Platform.Dispose(this);
             }
         }
     }
diff --git a/crypto/src/crypto/tls/TlsStream.cs b/crypto/src/crypto/tls/TlsStream.cs
index f78ba0344..bfd80edf2 100644
--- a/crypto/src/crypto/tls/TlsStream.cs
+++ b/crypto/src/crypto/tls/TlsStream.cs
@@ -28,6 +28,7 @@ namespace Org.BouncyCastle.Crypto.Tls
             get { return !handler.IsClosed; }
         }
 
+#if PORTABLE
         protected override void Dispose(bool disposing)
         {
             if (disposing)
@@ -36,6 +37,13 @@ namespace Org.BouncyCastle.Crypto.Tls
             }
             base.Dispose(disposing);
         }
+#else
+        public override void Close()
+        {
+            handler.Close();
+            base.Close();
+        }
+#endif
 
         public override void Flush()
         {
diff --git a/crypto/src/math/BigInteger.cs b/crypto/src/math/BigInteger.cs
index ebeb78788..3d0509fe0 100644
--- a/crypto/src/math/BigInteger.cs
+++ b/crypto/src/math/BigInteger.cs
@@ -702,7 +702,7 @@ namespace Org.BouncyCastle.Math
                 if (certainty < 1)
                     break;
 
-                if (CheckProbablePrime(certainty, random))
+                if (CheckProbablePrime(certainty, random, true))
                     break;
 
                 if (bitLength > 32)
@@ -714,7 +714,7 @@ namespace Org.BouncyCastle.Math
                         this.magnitude[this.magnitude.Length - 1] ^= ((random.Next() + 1) << 1);
                         this.mQuote = 0;
 
-                        if (CheckProbablePrime(certainty, random))
+                        if (CheckProbablePrime(certainty, random, true))
                             return;
                     }
                 }
@@ -1340,8 +1340,12 @@ namespace Org.BouncyCastle.Math
          * probability of 1 - (1/2)**certainty.
          * <p>From Knuth Vol 2, pg 395.</p>
          */
-        public bool IsProbablePrime(
-            int certainty)
+        public bool IsProbablePrime(int certainty)
+        {
+            return IsProbablePrime(certainty, false);
+        }
+
+        internal bool IsProbablePrime(int certainty, bool randomlySelected)
         {
             if (certainty <= 0)
                 return true;
@@ -1354,12 +1358,10 @@ namespace Org.BouncyCastle.Math
             if (n.Equals(One))
                 return false;
 
-            return n.CheckProbablePrime(certainty, RandomSource);
+            return n.CheckProbablePrime(certainty, RandomSource, randomlySelected);
         }
 
-        private bool CheckProbablePrime(
-            int		certainty,
-            Random	random)
+        private bool CheckProbablePrime(int certainty, Random random, bool randomlySelected)
         {
             Debug.Assert(certainty > 0);
             Debug.Assert(CompareTo(Two) > 0);
@@ -1395,7 +1397,7 @@ namespace Org.BouncyCastle.Math
 
 
             // TODO Is it worth trying to create a hybrid of these two?
-            return RabinMillerTest(certainty, random);
+            return RabinMillerTest(certainty, random, randomlySelected);
 //			return SolovayStrassenTest(certainty, random);
 
 //			bool rbTest = RabinMillerTest(certainty, random);
@@ -1408,10 +1410,36 @@ namespace Org.BouncyCastle.Math
 
         public bool RabinMillerTest(int certainty, Random random)
         {
+            return RabinMillerTest(certainty, random, false);
+        }
+
+        internal bool RabinMillerTest(int certainty, Random random, bool randomlySelected)
+        {
+            int bits = BitLength;
+
             Debug.Assert(certainty > 0);
-            Debug.Assert(BitLength > 2);
+            Debug.Assert(bits > 2);
             Debug.Assert(TestBit(0));
 
+            int iterations = ((certainty - 1) / 2) + 1;
+            if (randomlySelected)
+            {
+                int itersFor100Cert = bits >= 1024 ?  4
+                                    : bits >= 512  ?  8
+                                    : bits >= 256  ? 16
+                                    : 50;
+
+                if (certainty < 100)
+                {
+                    iterations = System.Math.Min(itersFor100Cert, iterations);
+                }
+                else
+                {
+                    iterations -= 50;
+                    iterations += itersFor100Cert;
+                }
+            }
+
             // let n = 1 + d . 2^s
             BigInteger n = this;
             int s = n.GetLowestSetBitMaskFirst(-1 << 1);
@@ -1449,10 +1477,8 @@ namespace Org.BouncyCastle.Math
                             return false;
                     }
                 }
-
-                certainty -= 2; // composites pass for only 1/4 possible 'a'
             }
-            while (certainty > 0);
+            while (--iterations > 0);
 
             return true;
         }
@@ -2494,7 +2520,7 @@ namespace Org.BouncyCastle.Math
 
             BigInteger n = Inc().SetBit(0);
 
-            while (!n.CheckProbablePrime(100, RandomSource))
+            while (!n.CheckProbablePrime(100, RandomSource, false))
             {
                 n = n.Add(Two);
             }
diff --git a/crypto/src/math/Primes.cs b/crypto/src/math/Primes.cs
index 420c3cc5a..fb279f103 100644
--- a/crypto/src/math/Primes.cs
+++ b/crypto/src/math/Primes.cs
@@ -11,6 +11,8 @@ namespace Org.BouncyCastle.Math
      */
     public abstract class Primes
     {
+        public static readonly int SmallFactorLimit = 211;
+
         private static readonly BigInteger One = BigInteger.One;
         private static readonly BigInteger Two = BigInteger.Two;
         private static readonly BigInteger Three = BigInteger.Three;
@@ -326,37 +328,80 @@ namespace Org.BouncyCastle.Math
              */
             int m = 2 * 3 * 5 * 7 * 11 * 13 * 17 * 19 * 23;
             int r = x.Mod(BigInteger.ValueOf(m)).IntValue;
-            if ((r & 1) != 0 && (r % 3) != 0 && (r % 5) != 0 && (r % 7) != 0 && (r % 11) != 0
-                && (r % 13) != 0 && (r % 17) != 0 && (r % 19) != 0 && (r % 23) != 0)
+            if ((r % 2) == 0 || (r % 3) == 0 || (r % 5) == 0 || (r % 7) == 0 || (r % 11) == 0 || (r % 13) == 0
+                || (r % 17) == 0 || (r % 19) == 0 || (r % 23) == 0)
             {
-                m = 29 * 31 * 37 * 41 * 43;
-                r = x.Mod(BigInteger.ValueOf(m)).IntValue;
-                if ((r % 29) != 0 && (r % 31) != 0 && (r % 37) != 0 && (r % 41) != 0 && (r % 43) != 0)
-                {
-                    m = 47 * 53 * 59 * 61 * 67;
-                    r = x.Mod(BigInteger.ValueOf(m)).IntValue;
-                    if ((r % 47) != 0 && (r % 53) != 0 && (r % 59) != 0 && (r % 61) != 0 && (r % 67) != 0)
-                    {
-                        m = 71 * 73 * 79 * 83;
-                        r = x.Mod(BigInteger.ValueOf(m)).IntValue;
-                        if ((r % 71) != 0 && (r % 73) != 0 && (r % 79) != 0 && (r % 83) != 0)
-                        {
-                            m = 89 * 97 * 101 * 103;
-                            r = x.Mod(BigInteger.ValueOf(m)).IntValue;
-                            if ((r % 89) != 0 && (r % 97) != 0 && (r % 101) != 0 && (r % 103) != 0)
-                            {
-                                m = 107 * 109 * 113 * 127;
-                                r = x.Mod(BigInteger.ValueOf(m)).IntValue;
-                                if ((r % 107) != 0 && (r % 109) != 0 && (r % 113) != 0 && (r % 127) != 0)
-                                {
-                                    return false;
-                                }
-                            }
-                        }
-                    }
-                }
+                return true;
             }
-            return true;
+
+            m = 29 * 31 * 37 * 41 * 43;
+            r = x.Mod(BigInteger.ValueOf(m)).IntValue;
+            if ((r % 29) == 0 || (r % 31) == 0 || (r % 37) == 0 || (r % 41) == 0 || (r % 43) == 0)
+            {
+                return true;
+            }
+
+            m = 47 * 53 * 59 * 61 * 67;
+            r = x.Mod(BigInteger.ValueOf(m)).IntValue;
+            if ((r % 47) == 0 || (r % 53) == 0 || (r % 59) == 0 || (r % 61) == 0 || (r % 67) == 0)
+            {
+                return true;
+            }
+
+            m = 71 * 73 * 79 * 83;
+            r = x.Mod(BigInteger.ValueOf(m)).IntValue;
+            if ((r % 71) == 0 || (r % 73) == 0 || (r % 79) == 0 || (r % 83) == 0)
+            {
+                return true;
+            }
+
+            m = 89 * 97 * 101 * 103;
+            r = x.Mod(BigInteger.ValueOf(m)).IntValue;
+            if ((r % 89) == 0 || (r % 97) == 0 || (r % 101) == 0 || (r % 103) == 0)
+            {
+                return true;
+            }
+
+            m = 107 * 109 * 113 * 127;
+            r = x.Mod(BigInteger.ValueOf(m)).IntValue;
+            if ((r % 107) == 0 || (r % 109) == 0 || (r % 113) == 0 || (r % 127) == 0)
+            {
+                return true;
+            }
+
+            m = 131 * 137 * 139 * 149;
+            r = x.Mod(BigInteger.ValueOf(m)).IntValue;
+            if ((r % 131) == 0 || (r % 137) == 0 || (r % 139) == 0 || (r % 149) == 0)
+            {
+                return true;
+            }
+
+            m = 151 * 157 * 163 * 167;
+            r = x.Mod(BigInteger.ValueOf(m)).IntValue;
+            if ((r % 151) == 0 || (r % 157) == 0 || (r % 163) == 0 || (r % 167) == 0)
+            {
+                return true;
+            }
+
+            m = 173 * 179 * 181 * 191;
+            r = x.Mod(BigInteger.ValueOf(m)).IntValue;
+            if ((r % 173) == 0 || (r % 179) == 0 || (r % 181) == 0 || (r % 191) == 0)
+            {
+                return true;
+            }
+
+            m = 193 * 197 * 199 * 211;
+            r = x.Mod(BigInteger.ValueOf(m)).IntValue;
+            if ((r % 193) == 0 || (r % 197) == 0 || (r % 199) == 0 || (r % 211) == 0)
+            {
+                return true;
+            }
+
+            /*
+             * NOTE: Unit tests depend on SMALL_FACTOR_LIMIT matching the
+             * highest small factor tested here.
+             */
+            return false;
         }
 
         private static bool ImplMRProbablePrimeToBase(BigInteger w, BigInteger wSubOne, BigInteger m, int a, BigInteger b)
diff --git a/crypto/src/ocsp/BasicOCSPRespGenerator.cs b/crypto/src/ocsp/BasicOCSPRespGenerator.cs
index 4ef73e09c..0dd4e0a09 100644
--- a/crypto/src/ocsp/BasicOCSPRespGenerator.cs
+++ b/crypto/src/ocsp/BasicOCSPRespGenerator.cs
@@ -217,7 +217,7 @@ namespace Org.BouncyCastle.Ocsp
 
                 streamCalculator.Stream.Write(encoded, 0, encoded.Length);
 
-                streamCalculator.Stream.Dispose();
+                Platform.Dispose(streamCalculator.Stream);
 
                 bitSig = new DerBitString(((IBlockResult)streamCalculator.GetResult()).Collect());
 			}
diff --git a/crypto/src/openpgp/PgpCompressedDataGenerator.cs b/crypto/src/openpgp/PgpCompressedDataGenerator.cs
index e3a889316..51b645279 100644
--- a/crypto/src/openpgp/PgpCompressedDataGenerator.cs
+++ b/crypto/src/openpgp/PgpCompressedDataGenerator.cs
@@ -2,6 +2,7 @@ using System;
 using System.IO;
 
 using Org.BouncyCastle.Apache.Bzip2;
+using Org.BouncyCastle.Utilities;
 using Org.BouncyCastle.Utilities.Zlib;
 
 namespace Org.BouncyCastle.Bcpg.OpenPgp
@@ -155,10 +156,8 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
 			{
 				if (dOut != pkOut)
 				{
-                    dOut.Dispose();
-                    dOut.Flush();
+                    Platform.Dispose(dOut);
 				}
-
 				dOut = null;
 
 				pkOut.Finish();
@@ -174,14 +173,22 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
 			{
 			}
 
-		    protected override void Dispose(bool disposing)
-		    {
-		        if (disposing)
-		        {
-		            Finish();
-		        }
-		        base.Dispose(disposing);
-		    }
+#if PORTABLE
+            protected override void Dispose(bool disposing)
+            {
+                if (disposing)
+                {
+				    Finish();
+                    return;
+                }
+                base.Dispose(disposing);
+            }
+#else
+            public override void Close()
+			{
+				Finish();
+			}
+#endif
 		}
 
 		private class SafeZOutputStream : ZOutputStream
@@ -191,14 +198,24 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
 			{
 			}
 
-		    protected override void Dispose(bool disposing)
-		    {
-		        if (disposing)
-		        {
-		            Finish();
-		            End();
-		        }
-		    }
+#if PORTABLE
+            protected override void Dispose(bool disposing)
+            {
+                if (disposing)
+                {
+				    Finish();
+				    End();
+                    return;
+                }
+                base.Dispose(disposing);
+            }
+#else
+            public override void Close()
+			{
+				Finish();
+				End();
+			}
+#endif
 		}
 	}
 }
diff --git a/crypto/src/openpgp/PgpUtilities.cs b/crypto/src/openpgp/PgpUtilities.cs
index fc85dac52..055f99636 100644
--- a/crypto/src/openpgp/PgpUtilities.cs
+++ b/crypto/src/openpgp/PgpUtilities.cs
@@ -382,8 +382,8 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
                 pOut.Write(buf, 0, len);
             }
 
-			pOut.Dispose();
-			inputStream.Dispose();
+            Platform.Dispose(pOut);
+            Platform.Dispose(inputStream);
 		}
 #endif
 
diff --git a/crypto/src/openpgp/WrappedGeneratorStream.cs b/crypto/src/openpgp/WrappedGeneratorStream.cs
index 60a1fbb0b..5f4a4b045 100644
--- a/crypto/src/openpgp/WrappedGeneratorStream.cs
+++ b/crypto/src/openpgp/WrappedGeneratorStream.cs
@@ -17,13 +17,21 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
 			this.gen = gen;
 		}
 
-	    protected override void Dispose(bool disposing)
-	    {
-	        if (disposing)
-	        {
-	            gen.Close();
-	        }
-	   //     base.Dispose(disposing);
-	    }
+#if PORTABLE
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                gen.Close();
+                return;
+            }
+            base.Dispose(disposing);
+        }
+#else
+		public override void Close()
+		{
+			gen.Close();
+		}
+#endif
 	}
 }
diff --git a/crypto/src/pkcs/Pkcs10CertificationRequest.cs b/crypto/src/pkcs/Pkcs10CertificationRequest.cs
index 7fccf32eb..1789f2a70 100644
--- a/crypto/src/pkcs/Pkcs10CertificationRequest.cs
+++ b/crypto/src/pkcs/Pkcs10CertificationRequest.cs
@@ -279,7 +279,7 @@ namespace Org.BouncyCastle.Pkcs
 
             streamCalculator.Stream.Write(reqInfoData, 0, reqInfoData.Length);
 
-            streamCalculator.Stream.Dispose();
+            Platform.Dispose(streamCalculator.Stream);
 
             // Generate Signature.
             sigBits = new DerBitString(((IBlockResult)streamCalculator.GetResult()).Collect());
@@ -342,7 +342,7 @@ namespace Org.BouncyCastle.Pkcs
 
                 streamCalculator.Stream.Write(b, 0, b.Length);
 
-                streamCalculator.Stream.Dispose();
+                Platform.Dispose(streamCalculator.Stream);
 
                 return ((IVerifier)streamCalculator.GetResult()).IsVerified(sigBits.GetBytes());
             }
diff --git a/crypto/src/pkix/PkixCertPath.cs b/crypto/src/pkix/PkixCertPath.cs
index c8ed91bee..d03709167 100644
--- a/crypto/src/pkix/PkixCertPath.cs
+++ b/crypto/src/pkix/PkixCertPath.cs
@@ -401,7 +401,7 @@ namespace Org.BouncyCastle.Pkix
 						pWrt.WriteObject(certificates[i]);
 					}
 
-					pWrt.Writer.Dispose();
+                    Platform.Dispose(pWrt.Writer);
 				}
 				catch (Exception)
 				{
diff --git a/crypto/src/util/Platform.cs b/crypto/src/util/Platform.cs
index 1b5ba462e..d4b18f182 100644
--- a/crypto/src/util/Platform.cs
+++ b/crypto/src/util/Platform.cs
@@ -19,7 +19,7 @@ namespace Org.BouncyCastle.Utilities
             MemoryStream buf = new MemoryStream();
             StreamWriter w = new StreamWriter(buf, Encoding.UTF8);
             w.WriteLine();
-            w.Close();
+            Dispose(w);
             byte[] bs = buf.ToArray();
             return Encoding.UTF8.GetString(bs, 0, bs.Length);
         }
@@ -186,5 +186,21 @@ namespace Org.BouncyCastle.Utilities
         }
 
         internal static readonly string NewLine = GetNewLine();
+
+#if PORTABLE
+        internal static void Dispose(IDisposable d)
+        {
+            d.Dispose();
+        }
+#else
+        internal static void Dispose(Stream s)
+        {
+            s.Close();
+        }
+        internal static void Dispose(TextWriter t)
+        {
+            t.Close();
+        }
+#endif
     }
 }
diff --git a/crypto/src/util/io/BaseInputStream.cs b/crypto/src/util/io/BaseInputStream.cs
index 2407bbabe..a5613d801 100644
--- a/crypto/src/util/io/BaseInputStream.cs
+++ b/crypto/src/util/io/BaseInputStream.cs
@@ -11,15 +11,23 @@ namespace Org.BouncyCastle.Utilities.IO
 		public sealed override bool CanRead { get { return !closed; } }
         public sealed override bool CanSeek { get { return false; } }
         public sealed override bool CanWrite { get { return false; } }
-		protected override void Dispose(bool disposing)
+
+#if PORTABLE
+        protected override void Dispose(bool disposing)
         {
             if (disposing)
             {
                 closed = true;
             }
-
             base.Dispose(disposing);
         }
+#else
+		public override void Close()
+        {
+            closed = true;
+            base.Close();
+        }
+#endif
 
         public sealed override void Flush() {}
         public sealed override long Length { get { throw new NotSupportedException(); } }
diff --git a/crypto/src/util/io/BaseOutputStream.cs b/crypto/src/util/io/BaseOutputStream.cs
index 56ce847e0..a0608d111 100644
--- a/crypto/src/util/io/BaseOutputStream.cs
+++ b/crypto/src/util/io/BaseOutputStream.cs
@@ -11,6 +11,8 @@ namespace Org.BouncyCastle.Utilities.IO
 		public sealed override bool CanRead { get { return false; } }
         public sealed override bool CanSeek { get { return false; } }
         public sealed override bool CanWrite { get { return !closed; } }
+
+#if PORTABLE
         protected override void Dispose(bool disposing)
         {
             if (disposing)
@@ -19,7 +21,15 @@ namespace Org.BouncyCastle.Utilities.IO
             }
             base.Dispose(disposing);
         }
-        public override void Flush() {}
+#else
+        public override void Close()
+        {
+            closed = true;
+            base.Close();
+        }
+#endif
+
+        public override void Flush() { }
         public sealed override long Length { get { throw new NotSupportedException(); } }
         public sealed override long Position
         {
diff --git a/crypto/src/util/io/FilterStream.cs b/crypto/src/util/io/FilterStream.cs
index 1aa1f9889..a92dee3e5 100644
--- a/crypto/src/util/io/FilterStream.cs
+++ b/crypto/src/util/io/FilterStream.cs
@@ -29,14 +29,22 @@ namespace Org.BouncyCastle.Utilities.IO
             get { return s.Position; }
             set { s.Position = value; }
         }
+#if PORTABLE
         protected override void Dispose(bool disposing)
         {
             if (disposing)
             {
-                s.Dispose();
+                Platform.Dispose(s);
             }
             base.Dispose(disposing);
         }
+#else
+        public override void Close()
+        {
+            Platform.Dispose(s);
+            base.Close();
+        }
+#endif
         public override void Flush()
         {
             s.Flush();
diff --git a/crypto/src/util/io/TeeInputStream.cs b/crypto/src/util/io/TeeInputStream.cs
index aeed3bae6..6996f3fbb 100644
--- a/crypto/src/util/io/TeeInputStream.cs
+++ b/crypto/src/util/io/TeeInputStream.cs
@@ -18,17 +18,26 @@ namespace Org.BouncyCastle.Utilities.IO
 			this.tee = tee;
 		}
 
-	    protected override void Dispose(bool disposing)
-	    {
-	        if (disposing)
-	        {
-	            input.Dispose();
-	            tee.Dispose();
-	        }
-	        base.Dispose(disposing);
-	    }
-
-		public override int Read(byte[] buf, int off, int len)
+#if PORTABLE
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                Platform.Dispose(input);
+                Platform.Dispose(tee);
+            }
+            base.Dispose(disposing);
+        }
+#else
+        public override void Close()
+		{
+            Platform.Dispose(input);
+            Platform.Dispose(tee);
+            base.Close();
+		}
+#endif
+
+        public override int Read(byte[] buf, int off, int len)
 		{
 			int i = input.Read(buf, off, len);
 
diff --git a/crypto/src/util/io/TeeOutputStream.cs b/crypto/src/util/io/TeeOutputStream.cs
index cebca89fe..a6c7fd5b5 100644
--- a/crypto/src/util/io/TeeOutputStream.cs
+++ b/crypto/src/util/io/TeeOutputStream.cs
@@ -18,17 +18,26 @@ namespace Org.BouncyCastle.Utilities.IO
 			this.tee = tee;
 		}
 
+#if PORTABLE
         protected override void Dispose(bool disposing)
         {
             if (disposing)
             {
-                output.Dispose();
-                tee.Dispose();
+                Platform.Dispose(output);
+                Platform.Dispose(tee);
             }
             base.Dispose(disposing);
         }
-        
-		public override void Write(byte[] buffer, int offset, int count)
+#else
+        public override void Close()
+		{
+            Platform.Dispose(output);
+            Platform.Dispose(tee);
+            base.Close();
+		}
+#endif
+
+        public override void Write(byte[] buffer, int offset, int count)
 		{
 			output.Write(buffer, offset, count);
 			tee.Write(buffer, offset, count);
diff --git a/crypto/src/util/zlib/ZDeflaterOutputStream.cs b/crypto/src/util/zlib/ZDeflaterOutputStream.cs
index 544ba8601..d0978942a 100644
--- a/crypto/src/util/zlib/ZDeflaterOutputStream.cs
+++ b/crypto/src/util/zlib/ZDeflaterOutputStream.cs
@@ -136,23 +136,36 @@ namespace Org.BouncyCastle.Utilities.Zlib {
             z=null;
         }
 
+#if PORTABLE
         protected override void Dispose(bool disposing)
         {
             if (disposing)
             {
-                try
-                {
-                    try { Finish(); }
-                    catch (IOException) { }
+                try{
+                    try{Finish();}
+                    catch (IOException) {}
                 }
-                finally
-                {
+                finally{
                     End();
-                    outp.Dispose();
-                    outp = null;
+                    Platform.Dispose(outp);
+                    outp=null;
                 }
             }
             base.Dispose(disposing);
         }
+#else
+        public override void Close() {
+            try{
+                try{Finish();}
+                catch (IOException) {}
+            }
+            finally{
+                End();
+                Platform.Dispose(outp);
+                outp=null;
+            }
+            base.Close();
+        }
+#endif
     }
 }
diff --git a/crypto/src/util/zlib/ZInflaterInputStream.cs b/crypto/src/util/zlib/ZInflaterInputStream.cs
index 9e82954b9..ef742bb00 100644
--- a/crypto/src/util/zlib/ZInflaterInputStream.cs
+++ b/crypto/src/util/zlib/ZInflaterInputStream.cs
@@ -114,15 +114,23 @@ namespace Org.BouncyCastle.Utilities.Zlib {
         public override void WriteByte(byte b) {
         }
 
+#if PORTABLE
         protected override void Dispose(bool disposing)
         {
             if (disposing)
             {
-                inp.Dispose();
+                Platform.Dispose(inp);
             }
             base.Dispose(disposing);
         }
-    
+#else
+        public override void Close()
+        {
+            Platform.Dispose(inp);
+            base.Close();
+        }
+#endif
+
         public override int ReadByte() {
             if(Read(buf1, 0, 1)<=0)
                 return -1;
diff --git a/crypto/src/util/zlib/ZInputStream.cs b/crypto/src/util/zlib/ZInputStream.cs
index 671cf68b0..4b7351555 100644
--- a/crypto/src/util/zlib/ZInputStream.cs
+++ b/crypto/src/util/zlib/ZInputStream.cs
@@ -93,18 +93,30 @@ namespace Org.BouncyCastle.Utilities.Zlib
 		public sealed override bool CanSeek { get { return false; } }
 		public sealed override bool CanWrite { get { return false; } }
 
-	    protected override void Dispose(bool disposing)
-	    {
-	        if (disposing)
-	        {
-                if (!closed)
-                {
-                    closed = true;
-                    input.Dispose();
-                }
-	        }
-	        base.Dispose(disposing);
-	    }
+#if PORTABLE
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+			    if (closed)
+                    return;
+
+                closed = true;
+                Platform.Dispose(input);
+            }
+            base.Dispose(disposing);
+        }
+#else
+        public override void Close()
+		{
+            if (closed)
+                return;
+
+            closed = true;
+            Platform.Dispose(input);
+            base.Close();
+		}
+#endif
 
 		public sealed override void Flush() {}
 
diff --git a/crypto/src/util/zlib/ZOutputStream.cs b/crypto/src/util/zlib/ZOutputStream.cs
index 2cef06397..d9f005f69 100644
--- a/crypto/src/util/zlib/ZOutputStream.cs
+++ b/crypto/src/util/zlib/ZOutputStream.cs
@@ -95,36 +95,52 @@ namespace Org.BouncyCastle.Utilities.Zlib
         public sealed override bool CanSeek { get { return false; } }
         public sealed override bool CanWrite { get { return !closed; } }
 
-	    protected override void Dispose(bool disposing)
-	    {
-	        if (disposing)
-	        {
-                if (this.closed)
-                    return;
+#if PORTABLE
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+			    if (closed)
+				    return;
+
+                DoClose();
+            }
+            base.Dispose(disposing);
+        }
+#else
+		public override void Close()
+		{
+			if (closed)
+				return;
+
+            DoClose();
+            base.Close();
+		}
+#endif
 
+        private void DoClose()
+        {
+            try
+            {
                 try
                 {
-                    try
-                    {
-                        Finish();
-                    }
-                    catch (IOException)
-                    {
-                        // Ignore
-                    }
+                    Finish();
                 }
-                finally
+                catch (IOException)
                 {
-                    this.closed = true;
-                    End();
-                    output.Dispose();
-                    output = null;
+                    // Ignore
                 }
-	        }
-	        base.Dispose(disposing);
-	    }
-        
-		public virtual void End()
+            }
+            finally
+            {
+                this.closed = true;
+                End();
+                Platform.Dispose(output);
+                output = null;
+            }
+        }
+
+        public virtual void End()
 		{
 			if (z == null)
 				return;
diff --git a/crypto/src/x509/X509Certificate.cs b/crypto/src/x509/X509Certificate.cs
index 93e3ee940..fc7f96aa9 100644
--- a/crypto/src/x509/X509Certificate.cs
+++ b/crypto/src/x509/X509Certificate.cs
@@ -576,7 +576,7 @@ namespace Org.BouncyCastle.X509
 
 			streamCalculator.Stream.Write(b, 0, b.Length);
 
-            streamCalculator.Stream.Dispose();
+            Platform.Dispose(streamCalculator.Stream);
 
             if (!((IVerifier)streamCalculator.GetResult()).IsVerified(this.GetSignature()))
 			{
diff --git a/crypto/src/x509/X509Crl.cs b/crypto/src/x509/X509Crl.cs
index 8d5cec8ef..53de3e91f 100644
--- a/crypto/src/x509/X509Crl.cs
+++ b/crypto/src/x509/X509Crl.cs
@@ -115,7 +115,7 @@ namespace Org.BouncyCastle.X509
 
             streamCalculator.Stream.Write(b, 0, b.Length);
 
-            streamCalculator.Stream.Dispose();
+            Platform.Dispose(streamCalculator.Stream);
 
             if (!((IVerifier)streamCalculator.GetResult()).IsVerified(this.GetSignature()))
             {
diff --git a/crypto/src/x509/X509V1CertificateGenerator.cs b/crypto/src/x509/X509V1CertificateGenerator.cs
index 1c59acba4..9adebcb16 100644
--- a/crypto/src/x509/X509V1CertificateGenerator.cs
+++ b/crypto/src/x509/X509V1CertificateGenerator.cs
@@ -10,6 +10,7 @@ using Org.BouncyCastle.Crypto.Operators;
 using Org.BouncyCastle.Math;
 using Org.BouncyCastle.Security;
 using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities;
 
 namespace Org.BouncyCastle.X509
 {
@@ -184,7 +185,7 @@ namespace Org.BouncyCastle.X509
 
             streamCalculator.Stream.Write(encoded, 0, encoded.Length);
 
-            streamCalculator.Stream.Dispose();
+            Platform.Dispose(streamCalculator.Stream);
 
             return GenerateJcaObject(tbsCert, (AlgorithmIdentifier)signatureCalculatorFactory.AlgorithmDetails, ((IBlockResult)streamCalculator.GetResult()).Collect());
 		}
diff --git a/crypto/src/x509/X509V2AttributeCertificate.cs b/crypto/src/x509/X509V2AttributeCertificate.cs
index bc9b39873..9376538a1 100644
--- a/crypto/src/x509/X509V2AttributeCertificate.cs
+++ b/crypto/src/x509/X509V2AttributeCertificate.cs
@@ -5,11 +5,11 @@ using System.IO;
 using Org.BouncyCastle.Asn1;
 using Org.BouncyCastle.Asn1.X509;
 using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Operators;
 using Org.BouncyCastle.Math;
 using Org.BouncyCastle.Security;
 using Org.BouncyCastle.Security.Certificates;
 using Org.BouncyCastle.Utilities;
-using Org.BouncyCastle.Crypto.Operators;
 
 namespace Org.BouncyCastle.X509
 {
@@ -186,7 +186,7 @@ namespace Org.BouncyCastle.X509
 
                 streamCalculator.Stream.Write(b, 0, b.Length);
 
-                streamCalculator.Stream.Dispose();
+                Platform.Dispose(streamCalculator.Stream);
             }
 			catch (IOException e)
 			{
diff --git a/crypto/src/x509/X509V2AttributeCertificateGenerator.cs b/crypto/src/x509/X509V2AttributeCertificateGenerator.cs
index fc7d91050..bf046cd1e 100644
--- a/crypto/src/x509/X509V2AttributeCertificateGenerator.cs
+++ b/crypto/src/x509/X509V2AttributeCertificateGenerator.cs
@@ -1,15 +1,15 @@
 using System;
 using System.Collections;
+using System.IO;
 
 using Org.BouncyCastle.Asn1;
 using Org.BouncyCastle.Asn1.X509;
 using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Operators;
 using Org.BouncyCastle.Math;
 using Org.BouncyCastle.Security;
 using Org.BouncyCastle.Security.Certificates;
 using Org.BouncyCastle.Utilities;
-using Org.BouncyCastle.Crypto.Operators;
-using System.IO;
 
 namespace Org.BouncyCastle.X509
 {
@@ -172,7 +172,7 @@ namespace Org.BouncyCastle.X509
 
             streamCalculator.Stream.Write(encoded, 0, encoded.Length);
 
-            streamCalculator.Stream.Dispose();
+            Platform.Dispose(streamCalculator.Stream);
 
             Asn1EncodableVector v = new Asn1EncodableVector();
 
diff --git a/crypto/src/x509/X509V2CRLGenerator.cs b/crypto/src/x509/X509V2CRLGenerator.cs
index 93accee71..566d50234 100644
--- a/crypto/src/x509/X509V2CRLGenerator.cs
+++ b/crypto/src/x509/X509V2CRLGenerator.cs
@@ -5,12 +5,13 @@ using System.IO;
 using Org.BouncyCastle.Asn1;
 using Org.BouncyCastle.Asn1.X509;
 using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Operators;
 using Org.BouncyCastle.Crypto.Parameters;
 using Org.BouncyCastle.Math;
 using Org.BouncyCastle.Security;
 using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities;
 using Org.BouncyCastle.Utilities.Collections;
-using Org.BouncyCastle.Crypto.Operators;
 
 namespace Org.BouncyCastle.X509
 {
@@ -241,7 +242,7 @@ namespace Org.BouncyCastle.X509
 
             streamCalculator.Stream.Write(encoded, 0, encoded.Length);
 
-            streamCalculator.Stream.Dispose();
+            Platform.Dispose(streamCalculator.Stream);
 
             return GenerateJcaObject(tbsCertList, (AlgorithmIdentifier)signatureCalculatorFactory.AlgorithmDetails, ((IBlockResult)streamCalculator.GetResult()).Collect());
         }
diff --git a/crypto/src/x509/X509V3CertificateGenerator.cs b/crypto/src/x509/X509V3CertificateGenerator.cs
index 2830a19dc..bc619c37b 100644
--- a/crypto/src/x509/X509V3CertificateGenerator.cs
+++ b/crypto/src/x509/X509V3CertificateGenerator.cs
@@ -1,15 +1,14 @@
 using System;
 using System.Collections;
-using System.IO;
 
 using Org.BouncyCastle.Asn1;
 using Org.BouncyCastle.Asn1.X509;
 using Org.BouncyCastle.Crypto;
 using Org.BouncyCastle.Crypto.Operators;
-using Org.BouncyCastle.Crypto.Parameters;
 using Org.BouncyCastle.Math;
 using Org.BouncyCastle.Security;
 using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities;
 using Org.BouncyCastle.X509.Extension;
 
 namespace Org.BouncyCastle.X509
@@ -318,11 +317,11 @@ namespace Org.BouncyCastle.X509
 
 			byte[] encoded = tbsCert.GetDerEncoded();
 
-			streamCalculator.Stream.Write (encoded, 0, encoded.Length);
+			streamCalculator.Stream.Write(encoded, 0, encoded.Length);
 
-            streamCalculator.Stream.Dispose ();
+            Platform.Dispose(streamCalculator.Stream);
 
-			return GenerateJcaObject(tbsCert, (AlgorithmIdentifier)signatureCalculatorFactory.AlgorithmDetails, ((IBlockResult)streamCalculator.GetResult()).Collect());
+            return GenerateJcaObject(tbsCert, (AlgorithmIdentifier)signatureCalculatorFactory.AlgorithmDetails, ((IBlockResult)streamCalculator.GetResult()).Collect());
 		}
 
 		private X509Certificate GenerateJcaObject(
diff --git a/crypto/test/src/asn1/test/GenerationTest.cs b/crypto/test/src/asn1/test/GenerationTest.cs
index 534f76bfd..862e66d22 100644
--- a/crypto/test/src/asn1/test/GenerationTest.cs
+++ b/crypto/test/src/asn1/test/GenerationTest.cs
@@ -53,8 +53,8 @@ namespace Org.BouncyCastle.Asn1.Tests
         private void TbsV1CertGenerate()
         {
 			V1TbsCertificateGenerator gen = new V1TbsCertificateGenerator();
-            DateTime startDate = new DateTime(1970, 1, 1, 0, 0, 1, DateTimeKind.Utc);
-            DateTime endDate = new DateTime(1970, 1, 1, 0, 0, 12, DateTimeKind.Utc);
+            DateTime startDate = MakeUtcDateTime(1970, 1, 1, 0, 0, 1);
+            DateTime endDate = MakeUtcDateTime(1970, 1, 1, 0, 0, 12);
 
             gen.SetSerialNumber(new DerInteger(1));
 
@@ -106,8 +106,8 @@ namespace Org.BouncyCastle.Asn1.Tests
 		private void TbsV3CertGenerate()
         {
 			V3TbsCertificateGenerator gen = new V3TbsCertificateGenerator();
-            DateTime startDate = new DateTime(1970, 1, 1, 0, 0, 1, DateTimeKind.Utc);
-            DateTime endDate = new DateTime(1970, 1, 1, 0, 0, 2, DateTimeKind.Utc);
+            DateTime startDate = MakeUtcDateTime(1970, 1, 1, 0, 0, 1);
+            DateTime endDate = MakeUtcDateTime(1970, 1, 1, 0, 0, 2);
 
 			gen.SetSerialNumber(new DerInteger(2));
 
@@ -166,8 +166,8 @@ namespace Org.BouncyCastle.Asn1.Tests
 		private void TbsV3CertGenWithNullSubject()
 		{
 			V3TbsCertificateGenerator gen = new V3TbsCertificateGenerator();
-            DateTime startDate = new DateTime(1970, 1, 1, 0, 0, 1, DateTimeKind.Utc);
-            DateTime endDate = new DateTime(1970, 1, 1, 0, 0, 2, DateTimeKind.Utc);
+            DateTime startDate = MakeUtcDateTime(1970, 1, 1, 0, 0, 1);
+            DateTime endDate = MakeUtcDateTime(1970, 1, 1, 0, 0, 2);
 
 			gen.SetSerialNumber(new DerInteger(2));
 
@@ -243,11 +243,11 @@ namespace Org.BouncyCastle.Asn1.Tests
 
             gen.SetIssuer(new X509Name("CN=AU,O=Bouncy Castle"));
 
-            gen.AddCrlEntry(new DerInteger(1), new Time(new DateTime(1970, 1, 1, 0, 0, 1, DateTimeKind.Utc)), ReasonFlags.AACompromise);
+            gen.AddCrlEntry(new DerInteger(1), new Time(MakeUtcDateTime(1970, 1, 1, 0, 0, 1)), ReasonFlags.AACompromise);
 
-            gen.SetNextUpdate(new Time(new DateTime(1970, 1, 1, 0, 0, 2, DateTimeKind.Utc)));
+            gen.SetNextUpdate(new Time(MakeUtcDateTime(1970, 1, 1, 0, 0, 2)));
 
-            gen.SetThisUpdate(new Time(new DateTime(1970, 1, 1, 0, 0, 0, 500, DateTimeKind.Utc)));
+            gen.SetThisUpdate(new Time(MakeUtcDateTime(1970, 1, 1, 0, 0, 0, 500)));
 
             gen.SetSignature(new AlgorithmIdentifier(PkcsObjectIdentifiers.Sha1WithRsaEncryption, DerNull.Instance));
 
diff --git a/crypto/test/src/asn1/test/TimeTest.cs b/crypto/test/src/asn1/test/TimeTest.cs
index 101a87935..04dac3c9e 100644
--- a/crypto/test/src/asn1/test/TimeTest.cs
+++ b/crypto/test/src/asn1/test/TimeTest.cs
@@ -15,9 +15,9 @@ namespace Org.BouncyCastle.Asn1.Tests
 			DateTime now = DateTime.UtcNow;
 
 			// Time classes only have a resolution of seconds
-			now = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second, DateTimeKind.Utc);
+			now = SimpleTest.MakeUtcDateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second);
 
-			Org.BouncyCastle.Asn1.Cms.Time cmsTime = new Org.BouncyCastle.Asn1.Cms.Time(now);
+            Org.BouncyCastle.Asn1.Cms.Time cmsTime = new Org.BouncyCastle.Asn1.Cms.Time(now);
 			Org.BouncyCastle.Asn1.X509.Time x509Time = new Org.BouncyCastle.Asn1.X509.Time(now);
 
 //			Assert.AreEqual(cmsTime.Date, x509Time.ToDateTime());
diff --git a/crypto/test/src/math/ec/test/ECAlgorithmsTest.cs b/crypto/test/src/math/ec/test/ECAlgorithmsTest.cs
index 23b3d9e07..0b3a203dd 100644
--- a/crypto/test/src/math/ec/test/ECAlgorithmsTest.cs
+++ b/crypto/test/src/math/ec/test/ECAlgorithmsTest.cs
@@ -20,61 +20,85 @@ namespace Org.BouncyCastle.Math.EC.Tests
         private static readonly SecureRandom RND = new SecureRandom();
 
         [Test]
-        [Ignore("SLOW! 44 sec")]
         public void TestSumOfMultiplies()
         {
+            X9ECParameters x9 = CustomNamedCurves.GetByName("secp256r1");
+            Assert.NotNull(x9);
+            DoTestSumOfMultiplies(x9);
+        }
+
+        [Test, Explicit]
+        public void TestSumOfMultipliesComplete()
+        {
             foreach (X9ECParameters x9 in GetTestCurves())
             {
-                ECPoint[] points = new ECPoint[SCALE];
-                BigInteger[] scalars = new BigInteger[SCALE];
-                for (int i = 0; i < SCALE; ++i)
-                {
-                    points[i] = GetRandomPoint(x9);
-                    scalars[i] = GetRandomScalar(x9);
-                }
-
-                ECPoint u = x9.Curve.Infinity;
-                for (int i = 0; i < SCALE; ++i)
-                {
-                    u = u.Add(points[i].Multiply(scalars[i]));
-
-                    ECPoint v = ECAlgorithms.SumOfMultiplies(CopyPoints(points, i + 1), CopyScalars(scalars, i + 1));
-
-                    ECPoint[] results = new ECPoint[] { u, v };
-                    x9.Curve.NormalizeAll(results);
-
-                    AssertPointsEqual("ECAlgorithms.SumOfMultiplies is incorrect", results[0], results[1]);
-                }
+                DoTestSumOfMultiplies(x9);
             }
         }
 
         [Test]
-        [Ignore("SLOW")]
         public void TestSumOfTwoMultiplies()
         {
+            X9ECParameters x9 = CustomNamedCurves.GetByName("secp256r1");
+            Assert.NotNull(x9);
+            DoTestSumOfTwoMultiplies(x9);
+        }
+
+        [Test, Explicit]
+        public void TestSumOfTwoMultipliesComplete()
+        {
             foreach (X9ECParameters x9 in GetTestCurves())
             {
-                ECPoint p = GetRandomPoint(x9);
-                BigInteger a = GetRandomScalar(x9);
+                DoTestSumOfTwoMultiplies(x9);
+            }
+        }
 
-                for (int i = 0; i < SCALE; ++i)
-                {
-                    ECPoint q = GetRandomPoint(x9);
-                    BigInteger b = GetRandomScalar(x9);
+        private void DoTestSumOfMultiplies(X9ECParameters x9)
+        {
+            ECPoint[] points = new ECPoint[SCALE];
+            BigInteger[] scalars = new BigInteger[SCALE];
+            for (int i = 0; i < SCALE; ++i)
+            {
+                points[i] = GetRandomPoint(x9);
+                scalars[i] = GetRandomScalar(x9);
+            }
+
+            ECPoint u = x9.Curve.Infinity;
+            for (int i = 0; i < SCALE; ++i)
+            {
+                u = u.Add(points[i].Multiply(scalars[i]));
 
-                    ECPoint u = p.Multiply(a).Add(q.Multiply(b));
-                    ECPoint v = ECAlgorithms.ShamirsTrick(p, a, q, b);
-                    ECPoint w = ECAlgorithms.SumOfTwoMultiplies(p, a, q, b);
+                ECPoint v = ECAlgorithms.SumOfMultiplies(CopyPoints(points, i + 1), CopyScalars(scalars, i + 1));
 
-                    ECPoint[] results = new ECPoint[] { u, v, w };
-                    x9.Curve.NormalizeAll(results);
+                ECPoint[] results = new ECPoint[] { u, v };
+                x9.Curve.NormalizeAll(results);
 
-                    AssertPointsEqual("ECAlgorithms.ShamirsTrick is incorrect", results[0], results[1]);
-                    AssertPointsEqual("ECAlgorithms.SumOfTwoMultiplies is incorrect", results[0], results[2]);
+                AssertPointsEqual("ECAlgorithms.SumOfMultiplies is incorrect", results[0], results[1]);
+            }
+        }
 
-                    p = q;
-                    a = b;
-                }
+        private void DoTestSumOfTwoMultiplies(X9ECParameters x9)
+        {
+            ECPoint p = GetRandomPoint(x9);
+            BigInteger a = GetRandomScalar(x9);
+
+            for (int i = 0; i < SCALE; ++i)
+            {
+                ECPoint q = GetRandomPoint(x9);
+                BigInteger b = GetRandomScalar(x9);
+
+                ECPoint u = p.Multiply(a).Add(q.Multiply(b));
+                ECPoint v = ECAlgorithms.ShamirsTrick(p, a, q, b);
+                ECPoint w = ECAlgorithms.SumOfTwoMultiplies(p, a, q, b);
+
+                ECPoint[] results = new ECPoint[] { u, v, w };
+                x9.Curve.NormalizeAll(results);
+
+                AssertPointsEqual("ECAlgorithms.ShamirsTrick is incorrect", results[0], results[1]);
+                AssertPointsEqual("ECAlgorithms.SumOfTwoMultiplies is incorrect", results[0], results[2]);
+
+                p = q;
+                a = b;
             }
         }
 
@@ -110,9 +134,9 @@ namespace Org.BouncyCastle.Math.EC.Tests
         private IList GetTestCurves()
         {
             ArrayList x9s = new ArrayList();
-            ArrayList names = new ArrayList();
-            CollectionUtilities.AddRange(names, ECNamedCurveTable.Names);
-            CollectionUtilities.AddRange(names, CustomNamedCurves.Names);
+            ISet names = new HashSet(ECNamedCurveTable.Names);
+            names.AddAll(CustomNamedCurves.Names);
+
             foreach (string name in names)
             {
                 X9ECParameters x9 = ECNamedCurveTable.GetByName(name);
diff --git a/crypto/test/src/math/ec/test/ECPointPerformanceTest.cs b/crypto/test/src/math/ec/test/ECPointPerformanceTest.cs
index fdfc491c8..2bcd5b502 100644
--- a/crypto/test/src/math/ec/test/ECPointPerformanceTest.cs
+++ b/crypto/test/src/math/ec/test/ECPointPerformanceTest.cs
@@ -173,7 +173,6 @@ namespace Org.BouncyCastle.Math.EC.Tests
         }
 
         [Test]
-        [Ignore("SLOW")]
         public void TestMultiply()
         {
             ArrayList nameList = new ArrayList();
diff --git a/crypto/test/src/math/test/AllTests.cs b/crypto/test/src/math/test/AllTests.cs
index f0eac21ad..53feff954 100644
--- a/crypto/test/src/math/test/AllTests.cs
+++ b/crypto/test/src/math/test/AllTests.cs
@@ -20,6 +20,7 @@ namespace Org.BouncyCastle.Math.Tests
             {
                 TestSuite suite = new TestSuite("Math tests");
                 suite.Add(new BigIntegerTest());
+                suite.Add(new PrimesTest());
                 return suite;
             }
         }
diff --git a/crypto/test/src/math/test/PrimesTest.cs b/crypto/test/src/math/test/PrimesTest.cs
new file mode 100644
index 000000000..4456ef2c1
--- /dev/null
+++ b/crypto/test/src/math/test/PrimesTest.cs
@@ -0,0 +1,179 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Math.Tests
+{
+    [TestFixture]
+    public class PrimesTest
+    {
+        private const int ITERATIONS = 10;
+        private const int PRIME_BITS = 256;
+        private const int PRIME_CERTAINTY = 100;
+
+        private static readonly BigInteger Two = BigInteger.Two;
+
+        private static readonly SecureRandom R = new SecureRandom();
+
+        [Test]
+        public void TestHasAnySmallFactors()
+        {
+            for (int iterations = 0; iterations < ITERATIONS; ++iterations)
+            {
+                BigInteger prime = RandomPrime();
+                Assert.False(Primes.HasAnySmallFactors(prime));
+
+                // NOTE: Loop through ALL small values to be sure no small primes are missing
+                for (int smallFactor = 2; smallFactor <= Primes.SmallFactorLimit; ++smallFactor)
+                {
+                    BigInteger nonPrimeWithSmallFactor = BigInteger.ValueOf(smallFactor).Multiply(prime);
+                    Assert.True(Primes.HasAnySmallFactors(nonPrimeWithSmallFactor));
+                }
+            }
+        }
+
+        [Test]
+        public void TestEnhancedMRProbablePrime()
+        {
+            int mrIterations = (PRIME_CERTAINTY + 1) / 2;
+            for (int iterations = 0; iterations < ITERATIONS; ++iterations)
+            {
+                BigInteger prime = RandomPrime();
+                Primes.MROutput mr = Primes.EnhancedMRProbablePrimeTest(prime, R, mrIterations);
+                Assert.False(mr.IsProvablyComposite);
+                Assert.False(mr.IsNotPrimePower);
+                Assert.Null(mr.Factor);
+
+                BigInteger primePower = prime;
+                for (int i = 0; i <= (iterations % 8); ++i)
+                {
+                    primePower = primePower.Multiply(prime);
+                }
+
+                Primes.MROutput mr2 = Primes.EnhancedMRProbablePrimeTest(primePower, R, mrIterations);
+                Assert.True(mr2.IsProvablyComposite);
+                Assert.False(mr2.IsNotPrimePower);
+                Assert.AreEqual(mr2.Factor, prime);
+
+                BigInteger nonPrimePower = RandomPrime().Multiply(prime);
+                Primes.MROutput mr3 = Primes.EnhancedMRProbablePrimeTest(nonPrimePower, R, mrIterations);
+                Assert.True(mr3.IsProvablyComposite);
+                Assert.True(mr3.IsNotPrimePower);
+                Assert.Null(mr.Factor);
+            }
+        }
+
+        [Test]
+        public void TestMRProbablePrime()
+        {
+            int mrIterations = (PRIME_CERTAINTY + 1) / 2;
+            for (int iterations = 0; iterations < ITERATIONS; ++iterations)
+            {
+                BigInteger prime = RandomPrime();
+                Assert.True(Primes.IsMRProbablePrime(prime, R, mrIterations));
+
+                BigInteger nonPrime = RandomPrime().Multiply(prime);
+                Assert.False(Primes.IsMRProbablePrime(nonPrime, R, mrIterations));
+            }
+        }
+
+        [Test]
+        public void TestMRProbablePrimeToBase()
+        {
+            int mrIterations = (PRIME_CERTAINTY + 1) / 2;
+            for (int iterations = 0; iterations < ITERATIONS; ++iterations)
+            {
+                BigInteger prime = RandomPrime();
+                Assert.True(ReferenceIsMRProbablePrime(prime, mrIterations));
+
+                BigInteger nonPrime = RandomPrime().Multiply(prime);
+                Assert.False(ReferenceIsMRProbablePrime(nonPrime, mrIterations));
+            }
+        }
+
+        [Test]
+        public void TestSTRandomPrime()
+        {
+            IDigest[] digests = new IDigest[] { new Sha1Digest(), new Sha256Digest() };
+            for (int digestIndex = 0; digestIndex < digests.Length; ++digestIndex)
+            {
+                int coincidenceCount = 0;
+
+                IDigest digest = digests[digestIndex];
+                for (int iterations = 0; iterations < ITERATIONS; ++iterations)
+                {
+                    try
+                    {
+                        byte[] inputSeed = new byte[16];
+                        R.NextBytes(inputSeed);
+    
+                        Primes.STOutput st = Primes.GenerateSTRandomPrime(digest, PRIME_BITS, inputSeed);
+                        Assert.True(IsPrime(st.Prime));
+
+                        Primes.STOutput st2 = Primes.GenerateSTRandomPrime(digest, PRIME_BITS, inputSeed);
+                        Assert.AreEqual(st.Prime, st2.Prime);
+                        Assert.AreEqual(st.PrimeGenCounter, st2.PrimeGenCounter);
+                        Assert.True(Arrays.AreEqual(st.PrimeSeed, st2.PrimeSeed));
+
+                        for (int i = 0; i < inputSeed.Length; ++i)
+                        {
+                            inputSeed[i] ^= 0xFF;
+                        }
+
+                        Primes.STOutput st3 = Primes.GenerateSTRandomPrime(digest, PRIME_BITS, inputSeed);
+                        Assert.True(!st.Prime.Equals(st3.Prime));
+                        Assert.False(Arrays.AreEqual(st.PrimeSeed, st3.PrimeSeed));
+
+                        if (st.PrimeGenCounter == st3.PrimeGenCounter)
+                        {
+                            ++coincidenceCount;
+                        }
+                    }
+                    catch (InvalidOperationException e)
+                    {
+                        if (e.Message.StartsWith("Too many iterations"))
+                        {
+                            --iterations;
+                            continue;
+                        }
+
+                        throw e;
+                    }
+                }
+
+                Assert.True(coincidenceCount * coincidenceCount < ITERATIONS);
+            }
+        }
+
+        private static bool ReferenceIsMRProbablePrime(BigInteger x, int numBases)
+        {
+            BigInteger xSubTwo = x.Subtract(Two);
+
+            for (int i = 0; i < numBases; ++i)
+            {
+                BigInteger b = BigIntegers.CreateRandomInRange(Two, xSubTwo, R);
+                if (!Primes.IsMRProbablePrimeToBase(x, b))
+                {
+                    return false;
+                }
+            }
+
+            return true;
+        }
+
+        private static bool IsPrime(BigInteger x)
+        {
+            return x.IsProbablePrime(PRIME_CERTAINTY);
+        }
+
+        private static BigInteger RandomPrime()
+        {
+            return new BigInteger(PRIME_BITS, PRIME_CERTAINTY, R);
+        }
+    }
+}
diff --git a/crypto/test/src/openpgp/test/PGPRSATest.cs b/crypto/test/src/openpgp/test/PGPRSATest.cs
index b56cdf67e..82b569bbb 100644
--- a/crypto/test/src/openpgp/test/PGPRSATest.cs
+++ b/crypto/test/src/openpgp/test/PGPRSATest.cs
@@ -985,7 +985,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
 
             sGen.Generate().Encode(bcOut);
 
-            bcOut.Dispose();
+            bcOut.Close();
 
             //
             // verify generated signature
diff --git a/crypto/test/src/openpgp/test/PgpKeyRingTest.cs b/crypto/test/src/openpgp/test/PgpKeyRingTest.cs
index 6c52ca8ba..5f38609cf 100644
--- a/crypto/test/src/openpgp/test/PgpKeyRingTest.cs
+++ b/crypto/test/src/openpgp/test/PgpKeyRingTest.cs
@@ -647,39 +647,60 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
             + "EQIABgUCOCpiHgAKCRDj8lhUEo8OeQ+QAKCbOTscyUnWHSrDo4fIy0MThEjhOgCe"
             + "L4Kb7TWkd/OHQScVBO8sTUz0+2g=");
 
-//		private static readonly byte[] pub6check = Base64.Decode("62O9");
+        private static readonly byte[] pub6check = Base64.Decode("62O9");
 
         //
-        // revoked sub key
+        // revoked master key
         //
         private static readonly byte[] pub7 = Base64.Decode(
-            "mQGiBEFOsIwRBADcjRx7nAs4RaWsQU6p8/ECLZD9sSeYc6CN6UDI96RKj0/hCzMs"
-            + "qlA0+9fzGZ7ZEJ34nuvDKlhKGC7co5eOiE0a9EijxgcrZU/LClZWa4YfyNg/ri6I"
-            + "yTyfOfrPQ33GNQt2iImDf3FKp7XKuY9nIxicGQEaW0kkuAmbV3oh0+9q8QCg/+fS"
-            + "epDEqEE/+nKONULGizKUjMED/RtL6RThRftZ9DOSdBytGYd48z35pca/qZ6HA36K"
-            + "PVQwi7V77VKQyKFLTOXPLnVyO85hyYB/Nv4DFHN+vcC7/49lfoyYMZlN+LarckHi"
-            + "NL154wmmzygB/KKysvWBLgkErEBCD0xBDd89iTQNlDtVQAWGORVffl6WWjOAkliG"
-            + "3dL6A/9A288HfFRnywqi3xddriV6wCPmStC3dkCS4vHk2ofS8uw4ZNoRlp1iEPna"
-            + "ai2Xa9DX1tkhaGk2k96MqqbBdGpbW8sMA9otJ9xdMjWEm/CgJUFUFQf3zaVy3mkM"
-            + "S2Lvb6P4Wc2l/diEEIyK8+PqJItSh0OVU3K9oM7ngHwVcalKILQVUkV2b2tlZCA8"
-            + "UmV2b2tlZEB0ZWQ+iQBOBBARAgAOBQJBTrCMBAsDAgECGQEACgkQvglkcFA/c63+"
-            + "QgCguh8rsJbPTtbhZcrqBi5Mo1bntLEAoPZQ0Kjmu2knRUpHBeUemHDB6zQeuQIN"
-            + "BEFOsIwQCAD2Qle3CH8IF3KiutapQvMF6PlTETlPtvFuuUs4INoBp1ajFOmPQFXz"
-            + "0AfGy0OplK33TGSGSfgMg71l6RfUodNQ+PVZX9x2Uk89PY3bzpnhV5JZzf24rnRP"
-            + "xfx2vIPFRzBhznzJZv8V+bv9kV7HAarTW56NoKVyOtQa8L9GAFgr5fSI/VhOSdvN"
-            + "ILSd5JEHNmszbDgNRR0PfIizHHxbLY7288kjwEPwpVsYjY67VYy4XTjTNP18F1dD"
-            + "ox0YbN4zISy1Kv884bEpQBgRjXyEpwpy1obEAxnIByl6ypUM2Zafq9AKUJsCRtMI"
-            + "PWakXUGfnHy9iUsiGSa6q6Jew1XpMgs7AAICB/93zriSvSHqsi1FeEmUBo431Jkh"
-            + "VerIzb6Plb1j6FIq+s3vyvx9K+dMvjotZqylWZj4GXpH+2xLJTjWkrGSfUZVI2Nk"
-            + "nyOFxUCKLLqaqVBFAQIjULfvQfGEWiGQKk9aRLkdG+D+8Y2N9zYoBXoQ9arvvS/t"
-            + "4mlOsiuaTe+BZ4x+BXTpF4b9sKZl7V8QP/TkoJWUdydkvxciHdWp7ssqyiKOFRhG"
-            + "818knDfFQ3cn2w/RnOb+7AF9wDncXDPYLfpPv9b2qZoLrXcyvlLffGDUdWs553ut"
-            + "1F5AprMURs8BGmY9BnjggfVubHdhTUoA4gVvrdaf+D9NwZAl0xK/5Y/oPuMZiQBG"
-            + "BBgRAgAGBQJBTrCMAAoJEL4JZHBQP3Ot09gAoMmLKloVDP+WhDXnsM5VikxysZ4+"
-            + "AKCrJAUO+lYAyPYwEwgK+bKmUGeKrIkARgQoEQIABgUCQU6wpQAKCRC+CWRwUD9z"
-            + "rQK4AJ98kKFxGU6yhHPr6jYBJPWemTNOXgCfeGB3ox4PXeS4DJDuLy9yllytOjo=");
-
-//		private static readonly byte[] pub7check = Base64.Decode("f/YQ");
+              "mQGiBFKQDEMRBACtcEzu15gGDrZKLuO2zgDJ9qFkweOxKyeO45LKIfUGBful"
+            + "lheoFHbsJIeNGjWbSOfWWtphTaSu9//BJt4xxg2pqVLYqzR+hEPpDy9kXxnZ"
+            + "LwwxjAP2TcOvuZKWe+JzoYQxDunOH4Zu9CPJhZhF3RNPw+tbv0jHfTV/chtb"
+            + "23Dj5wCg7eoM8bL9NYXacsAfkS//m+AB1MkD/jEZJqJSQHW8WVP7wKRrAZse"
+            + "N4l9b8+yY4RwLIodhD8wGsMYjkCF4yb/SQ5QlmLlvrHDLBofRzG+8oxldX4o"
+            + "GLZWvqPmW+BlS4QNSr+ZBu+OwnpClXG2pR+ExumXNoeArREyylrmOgD+0cUa"
+            + "8K2UbOxbJ8EioyOKxa7wjUVxmHmhBACAGQGLT/lpHA5zcU0g8AlSk8fsd+bB"
+            + "nwa/+9xdLqVsCTZdOWULtPOw9hbAdjjAy0L4M/MDAJYYtCEl9rB7aOc9PVdT"
+            + "h7CT9Ma6ltiSMKDlqWbDmogNEGx9Gz3GjiSGxAy/SN6JR1On4c60TAiTv6eE"
+            + "uEHszE6CH4qceK5W8HLLB4hJBCARAgAJBQJSkA0OAh0CAAoJEBCIvJhXZzdI"
+            + "X8wAn0qUP/jqAuPEX9g2XCr5jN3RKvKjAKDpx4NP7P1/yLN2ycFIgxKZ1plK"
+            + "CLACAAO0J3Jldm9rZSAoUmV2b2tlIFRlc3QpIDxyZXZva2VAdGVzdC50ZXN0"
+            + "PohiBBMRAgAiBQJSkAxDAhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAK"
+            + "CRAQiLyYV2c3SKw0AJ9kufxvnorVOv6a+WM+I/bNP+mjLQCgtPKuwTyeZU2k"
+            + "Sec1fJZUssDL1hGwAgADuQENBFKQDEMQBACruJ54GuhUaXgqGzu/HsCrgGQA"
+            + "n86PZW1qPCX28E9sayEmVOgzSDA/OT5c05P0PVLhMNEguSnUGC249MpZfPK/"
+            + "9LVKMXATZLzEB6lFX1YJdfrrb9KrQ5kdDhOcFXm1GIGBwLzjUmXYRVPH+TsT"
+            + "4QFvDpfIANQZfKK4UV5BJzJV5wADBQP/ew75dy1x58KWpPqfeH1OVln/Ui6e"
+            + "EDyyISic147+FIfVDuLtWoxMFE0ZPg47+rEQrhWC96izaSKPW97y5bkWz5PG"
+            + "CMChnLcg+3M91x/QCGzNhzVMiVpY5VhBDFP+7iiOaKYRiN/x7oasf2482Ny8"
+            + "1oiykOZUm8FCUQnRmJzIlbiISQQYEQIACQUCUpAMQwIbDAAKCRAQiLyYV2c3"
+            + "SL04AJ9VceD1DtcEDaWPDzFPgpe3ZfiXiQCfe5azYl26JpHSJvNKZRLi0I8H"
+            + "shCwAgAD");
+
+        private static readonly byte[] pub7sub = Base64.Decode(
+              "mQGiBFKQFFURBAD7CTE4RYPD7O+ki7pl/vXSZsSR0kQhCD9BR4lwE/Iffzmr"
+            + "vK8tmr2yLKWoXyoc3VF0Gdg/VATDcawBnKSjuCIsFZ58Edacb7uVRl4+ACiu"
+            + "OsvCKl9JuZ54SQ/tbD+NFS+HWNyVlWn7vDv8l+37DWNxuQRIYtQR+drAnIwQ"
+            + "g0O4owCg5a9cGAaN0zNVssUo6GFEoAI8nE0EAJMxQMcHTlLQQN1c549Ub0+E"
+            + "LV4dRIxjO7O6yi6Bg5udwS9Un1XeHF4GM7fj95WHi7o9sgErr2evhuGWl337"
+            + "ySytE1npk2F/jqevhAJazQTuilEuyjMbCShV39qJlEKtU9uHQYxN8oqGT9Ot"
+            + "lOoXXtrgfHbsrouCVwm4Jk14kzCaA/4okwrQwGkPlXRpVFyLn4GwrGivG7eh"
+            + "enRbAd2SQBiNVKmMsKLxHT1avZ11qcx6OU3ixdw5wYmq7TNR+5FXiz/e2MIq"
+            + "m7VhKONN21F7WC7siHxXfqqI/uz2tTPrFoLbnr/j/RZZRUMh6qUQrWpv58ci"
+            + "Bh+xkWCRantLCL9khuvRSrQncmV2b2tlIChSZXZva2UgVGVzdCkgPHJldm9r"
+            + "ZUB0ZXN0LnRlc3Q+iGIEExECACIFAlKQFFUCGwMGCwkIBwMCBhUIAgkKCwQW"
+            + "AgMBAh4BAheAAAoJEDKzvtpHqpp2DN4AoNS9M634KdvZT25DclGpb2bCFjv0"
+            + "AKDYXl5fIRGi583vFJ9C/q8hNGyNc7ACAAO5AQ0EUpAUVRAEALusV5UIL4gB"
+            + "6qQk++h+czV9KS0yxwgZyR+dJza+duEG88aNv28Wmjpfr3ZkvIiUaOcxFoct"
+            + "LgVGtPJM1HhWJtoA94CRBFTGzLfUIfXHcyXSdAw8Qh96svRl2w2KM+/pJl1r"
+            + "A3CWIy48jQei0mLwElRELLG7HJKYJxjCbg4+ihYTAAMGA/42PgHTV5VpF7YC"
+            + "XodlLOyGDVOoRjsvu0Gu/P88QnVP2jN57MJcla224aN3pGprtcbTwyjt+dtf"
+            + "5IJlB+3RZLczyqvT5hw7j9h81mr3RDbg3cn57xdYwQNP+6b6Wf9QRmaE813s"
+            + "g3kF0IJ0oFvwZdHnjndQ0JCrKaPflGSO6msjIYhTBCgRAgATBQJSkBXdDB0B"
+            + "U3VwZXJzZWRlZAAKCRAys77aR6qadmZPAJ0eJzmgBLTWK9RIbVtRUFzm736I"
+            + "hACgsPGHdZmLUFhV80fvYnUtB7TYGeKwAgADiEkEGBECAAkFAlKQFFUCGwwA"
+            + "CgkQMrO+2keqmnZGIACfRTkdqi6b7fjqkWxx7DysKBedgS8An1TJrhhkeJVd"
+            + "smkOCYLILgjrBHq4sAIAAw==");
 
         private static readonly byte[] pub8 = Base64.Decode(
             "mQGiBEEcraYRBADFYj+uFOhHz5SdECvJ3Z03P47gzmWLQ5HH8fPYC9rrv7AgqFFX"
@@ -1646,8 +1667,8 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
             byte[] encRing = pubRings.GetEncoded();
         }
 
-        [Test, Explicit]
-        public void PerformTest7()
+        [Test]
+        public void TestRevocation()
         {
             PgpPublicKeyRing pgpPub = new PgpPublicKeyRing(pub7);
             PgpPublicKey masterKey = null;
@@ -1657,28 +1678,64 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
                 if (k.IsMasterKey)
                 {
                     masterKey = k;
+                }
+            }
+
+            int count = 0;
+            PgpSignature sig = null;
+            foreach (PgpSignature pgpSig in masterKey.GetSignaturesOfType(PgpSignature.KeyRevocation))
+            {
+                sig = pgpSig;
+                ++count;
+            }
+
+            if (count != 1)
+            {
+                Fail("wrong number of revocations in test7.");
+            }
+
+            sig.InitVerify(masterKey);
+
+            if (!sig.VerifyCertification(masterKey))
+            {
+                Fail("failed to verify revocation certification");
+            }
+
+            pgpPub = new PgpPublicKeyRing(pub7sub);
+            masterKey = null;
+
+            foreach (PgpPublicKey k in pgpPub.GetPublicKeys())
+            {
+                if (k.IsMasterKey)
+                {
+                    masterKey = k;
                     continue;
                 }
 
-                int count = 0;
-                PgpSignature sig = null;
+                count = 0;
+                sig = null;
 
-                foreach (PgpSignature sigTemp in k.GetSignaturesOfType(PgpSignature.SubkeyRevocation))
+                foreach (PgpSignature pgpSig in k.GetSignaturesOfType(PgpSignature.SubkeyRevocation))
                 {
-                    sig = sigTemp;
-                    count++;
+                    sig = pgpSig;
+                    ++count;
                 }
 
                 if (count != 1)
                 {
-                    Fail("wrong number of revocations in test7.");
+                    Fail("wrong number of revocations in test7 subkey.");
+                }
+
+                if (sig.SignatureType != PgpSignature.SubkeyRevocation)
+                {
+                    Fail("wrong signature found");
                 }
 
                 sig.InitVerify(masterKey);
 
-                if (!sig.VerifyCertification(k))
+                if (!sig.VerifyCertification(masterKey, k))
                 {
-                    Fail("failed to verify revocation certification");
+                    Fail("failed to verify revocation certification of subkey");
                 }
             }
         }
@@ -2264,10 +2321,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
             PerformTest4();
             PerformTest5();
             PerformTest6();
-
-            // NB: This was commented out in the original Java source
-            //PerformTest7();
-
+            TestRevocation();
             PerformTest8();
             PerformTest9();
             PerformTest10();
diff --git a/crypto/test/src/util/test/SimpleTest.cs b/crypto/test/src/util/test/SimpleTest.cs
index 10c83374d..d759674ea 100644
--- a/crypto/test/src/util/test/SimpleTest.cs
+++ b/crypto/test/src/util/test/SimpleTest.cs
@@ -160,5 +160,23 @@ namespace Org.BouncyCastle.Utilities.Test
 		internal static readonly string NewLine = GetNewLine();
 
 		public abstract void PerformTest();
+
+        public static DateTime MakeUtcDateTime(int year, int month, int day, int hour, int minute, int second)
+        {
+#if PORTABLE
+            return new DateTime(year, month, day, hour, minute, second, DateTimeKind.Utc);
+#else
+            return new DateTime(year, month, day, hour, minute, second);
+#endif
+        }
+
+        public static DateTime MakeUtcDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond)
+        {
+#if PORTABLE
+            return new DateTime(year, month, day, hour, minute, second, millisecond, DateTimeKind.Utc);
+#else
+            return new DateTime(year, month, day, hour, minute, second, millisecond);
+#endif
+        }
     }
 }
diff --git a/crypto/test/src/util/test/UncloseableStream.cs b/crypto/test/src/util/test/UncloseableStream.cs
index 160d61795..2a3b4229b 100644
--- a/crypto/test/src/util/test/UncloseableStream.cs
+++ b/crypto/test/src/util/test/UncloseableStream.cs
@@ -14,9 +14,21 @@ namespace Org.BouncyCastle.Utilities.Test
 		{
 		}
 
-        //public override void Close()
-        //{
-        //    throw new Exception("Close() called on UncloseableStream");
-        //}
-	}
+#if PORTABLE
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+			    throw new Exception("UncloseableStream was disposed");
+            }
+
+            base.Dispose(disposing);
+        }
+#else
+        public override void Close()
+		{
+			throw new Exception("Close() called on UncloseableStream");
+		}
+#endif
+    }
 }