summary refs log tree commit diff
diff options
context:
space:
mode:
authorOren Novotny <oren@novotny.org>2020-02-24 09:59:34 -0500
committerOren Novotny <oren@novotny.org>2020-02-24 09:59:34 -0500
commitc5338c98dc8e092a8c4c92bb48c4dd2ccbb7a7ee (patch)
tree8630e7edbcf42a3a364ba013b19a7dd4b543af3c
parentMerge pull request #19 from novotnyllc/dependabot/nuget/coverlet.collector-1.1.0 (diff)
parentImprovements to permitted sub-trees (diff)
downloadBouncyCastle.NET-ed25519-c5338c98dc8e092a8c4c92bb48c4dd2ccbb7a7ee.tar.xz
merge from master
-rw-r--r--crypto/License.html2
-rw-r--r--crypto/Readme.html5
-rw-r--r--crypto/src/AssemblyInfo.cs2
-rw-r--r--crypto/src/asn1/ASN1StreamParser.cs11
-rw-r--r--crypto/src/asn1/Asn1InputStream.cs110
-rw-r--r--crypto/src/asn1/Asn1OctetString.cs15
-rw-r--r--crypto/src/asn1/BerOctetString.cs103
-rw-r--r--crypto/src/asn1/ConstructedOctetStream.cs45
-rw-r--r--crypto/src/asn1/DefiniteLengthInputStream.cs23
-rw-r--r--crypto/src/asn1/DerBMPString.cs28
-rw-r--r--crypto/src/asn1/DerInteger.cs25
-rw-r--r--crypto/src/asn1/DerObjectIdentifier.cs10
-rw-r--r--crypto/src/asn1/DerOctetString.cs12
-rw-r--r--crypto/src/asn1/LimitedInputStream.cs19
-rw-r--r--crypto/src/asn1/cms/SignedData.cs13
-rw-r--r--crypto/src/asn1/cryptopro/GOST3410PublicKeyAlgParameters.cs3
-rw-r--r--crypto/src/asn1/nist/NISTObjectIdentifiers.cs4
-rw-r--r--crypto/src/asn1/pkcs/AuthenticatedSafe.cs38
-rw-r--r--crypto/src/asn1/pkcs/CertBag.cs16
-rw-r--r--crypto/src/asn1/pkcs/Pfx.cs30
-rw-r--r--crypto/src/asn1/pkcs/SafeBag.cs18
-rw-r--r--crypto/src/asn1/x509/AuthorityInformationAccess.cs20
-rw-r--r--crypto/src/asn1/x509/AuthorityKeyIdentifier.cs105
-rw-r--r--crypto/src/asn1/x509/BasicConstraints.cs43
-rw-r--r--crypto/src/asn1/x509/CRLDistPoint.cs32
-rw-r--r--crypto/src/asn1/x509/CertificatePolicies.cs34
-rw-r--r--crypto/src/asn1/x509/ExtendedKeyUsage.cs41
-rw-r--r--crypto/src/asn1/x509/GeneralNames.cs41
-rw-r--r--crypto/src/asn1/x509/KeyUsage.cs22
-rw-r--r--crypto/src/asn1/x509/SubjectKeyIdentifier.cs56
-rw-r--r--crypto/src/asn1/x509/X509Extensions.cs25
-rw-r--r--crypto/src/asn1/x9/X962Parameters.cs9
-rw-r--r--crypto/src/bcpg/ECPublicBCPGKey.cs6
-rw-r--r--crypto/src/bcpg/SignatureSubpacketsReader.cs3
-rw-r--r--crypto/src/cms/CMSSignedData.cs10
-rw-r--r--crypto/src/crypto.csproj6
-rw-r--r--crypto/src/crypto/encodings/Pkcs1Encoding.cs2
-rw-r--r--crypto/src/crypto/parameters/Ed25519PrivateKeyParameters.cs34
-rw-r--r--crypto/src/crypto/parameters/Ed448PrivateKeyParameters.cs34
-rw-r--r--crypto/src/crypto/signers/Ed25519Signer.cs10
-rw-r--r--crypto/src/crypto/signers/Ed25519ctxSigner.cs10
-rw-r--r--crypto/src/crypto/signers/Ed25519phSigner.cs6
-rw-r--r--crypto/src/crypto/signers/Ed448Signer.cs10
-rw-r--r--crypto/src/crypto/signers/Ed448phSigner.cs6
-rw-r--r--crypto/src/crypto/tls/CipherSuite.cs16
-rw-r--r--crypto/src/crypto/tls/TlsAeadCipher.cs3
-rw-r--r--crypto/src/crypto/tls/TlsDHUtilities.cs8
-rw-r--r--crypto/src/crypto/tls/TlsEccUtilities.cs10
-rw-r--r--crypto/src/crypto/tls/TlsProtocol.cs13
-rw-r--r--crypto/src/crypto/tls/TlsServerProtocol.cs44
-rw-r--r--crypto/src/crypto/tls/TlsUtilities.cs52
-rw-r--r--crypto/src/math/ec/ECAlgorithms.cs5
-rw-r--r--crypto/src/math/ec/multiplier/DoubleAddMultiplier.cs5
-rw-r--r--crypto/src/math/ec/multiplier/MixedNafR2LMultiplier.cs1
-rw-r--r--crypto/src/math/ec/multiplier/MontgomeryLadderMultiplier.cs5
-rw-r--r--crypto/src/math/ec/multiplier/NafL2RMultiplier.cs3
-rw-r--r--crypto/src/math/ec/multiplier/NafR2LMultiplier.cs5
-rw-r--r--crypto/src/math/ec/multiplier/ReferenceMultiplier.cs3
-rw-r--r--crypto/src/math/ec/multiplier/ZSignedDigitL2RMultiplier.cs5
-rw-r--r--crypto/src/math/ec/multiplier/ZSignedDigitR2LMultiplier.cs5
-rw-r--r--crypto/src/math/ec/rfc7748/X25519Field.cs37
-rw-r--r--crypto/src/math/ec/rfc7748/X448Field.cs27
-rw-r--r--crypto/src/math/ec/rfc8032/Ed25519.cs6
-rw-r--r--crypto/src/math/ec/rfc8032/Ed448.cs6
-rw-r--r--crypto/src/openpgp/PGPKeyRing.cs2
-rw-r--r--crypto/src/openpgp/PgpCompressedData.cs6
-rw-r--r--crypto/src/openpgp/PgpEncryptedDataList.cs15
-rw-r--r--crypto/src/openpgp/PgpLiteralData.cs8
-rw-r--r--crypto/src/openpgp/PgpMarker.cs13
-rw-r--r--crypto/src/openpgp/PgpOnePassSignature.cs14
-rw-r--r--crypto/src/openpgp/PgpPublicKeyEncryptedData.cs9
-rw-r--r--crypto/src/openpgp/PgpPublicKeyRing.cs13
-rw-r--r--crypto/src/openpgp/PgpSecretKey.cs10
-rw-r--r--crypto/src/openpgp/PgpSignature.cs10
-rw-r--r--crypto/src/openpgp/PgpUtilities.cs13
-rw-r--r--crypto/src/pkcs/Pkcs12Store.cs60
-rw-r--r--crypto/src/pkix/PkixNameConstraintValidator.cs15
-rw-r--r--crypto/src/security/PrivateKeyFactory.cs6
-rw-r--r--crypto/src/security/PublicKeyFactory.cs2
-rw-r--r--crypto/src/tsp/TimeStampToken.cs15
-rw-r--r--crypto/src/util/Arrays.cs21
-rw-r--r--crypto/src/util/io/pem/PemReader.cs11
-rw-r--r--crypto/test/src/asn1/test/InputStreamTest.cs63
-rw-r--r--crypto/test/src/asn1/test/PKCS12Test.cs28
-rw-r--r--crypto/test/src/crypto/test/ChaCha20Poly1305Test.cs67
-rw-r--r--crypto/test/src/openssl/test/ReaderTest.cs6
-rw-r--r--crypto/test/src/pkcs/test/PKCS12StoreTest.cs79
-rw-r--r--crypto/test/src/tsp/test/TimeStampTokenInfoTest.cs2
-rw-r--r--crypto/test/src/util/io/pem/test/AllTests.cs8
-rw-r--r--crypto/test/src/util/test/SimpleTest.cs13
90 files changed, 1149 insertions, 716 deletions
diff --git a/crypto/License.html b/crypto/License.html
index 482f20a0f..f091a2934 100644
--- a/crypto/License.html
+++ b/crypto/License.html
@@ -9,7 +9,7 @@
 <h2>The Bouncy Castle Cryptographic C#&reg; API</h2>
 <h3>License:</h3>
 The Bouncy Castle License<br>
-Copyright (c) 2000-2019 The Legion of the Bouncy Castle Inc.
+Copyright (c) 2000-2020 The Legion of the Bouncy Castle Inc.
 (https://www.bouncycastle.org)<br>
 Permission is hereby granted, free of charge, to any person obtaining a
 copy of this software and associated documentation files (the "Software"), to deal in the
diff --git a/crypto/Readme.html b/crypto/Readme.html
index fc00814ad..30f0337e0 100644
--- a/crypto/Readme.html
+++ b/crypto/Readme.html
@@ -305,10 +305,15 @@ We state, where EC MQV has not otherwise been disabled or removed:
         <h5>Defects Fixed</h5>
         <ul>
             <li>EdDSA verifiers now reject overly long signatures.</li>
+            <li>Fixed field reduction for custom secp128r1 curve.</li>
+            <li>ASN.1: Enforce no leading zeroes in OID branches (longer than 1 character).</li>
         </ul>
         <h5>Additional Features and Functionality</h5>
         <ul>
             <li>TLS: BasicTlsPskIdentity now reusable (returns cloned array from GetPsk).</li>
+            <li>Improved performance for multiple ECDSA verifications using same public key.</li>
+            <li>Support has been added for ChaCha20-Poly1305 AEAD mode from RFC 7539.</li>
+            <li>PKCS12: Improved support for certificate-only key stores without password.</li>
         </ul>
 
         <h4><a class="mozTocH4" name="mozTocId85319"></a>Release 1.8.5, Thursday January 31, 2019</h4>
diff --git a/crypto/src/AssemblyInfo.cs b/crypto/src/AssemblyInfo.cs
index 43935c8dc..f2eec4ad8 100644
--- a/crypto/src/AssemblyInfo.cs
+++ b/crypto/src/AssemblyInfo.cs
@@ -85,4 +85,4 @@ namespace System.Reflection
     }
 }
 
-#endif
\ No newline at end of file
+#endif
diff --git a/crypto/src/asn1/ASN1StreamParser.cs b/crypto/src/asn1/ASN1StreamParser.cs
index 3eaaadaee..860dc99b1 100644
--- a/crypto/src/asn1/ASN1StreamParser.cs
+++ b/crypto/src/asn1/ASN1StreamParser.cs
@@ -59,7 +59,7 @@ namespace Org.BouncyCastle.Asn1
 			if (_in is IndefiniteLengthInputStream)
 			{
 				if (!constructed)
-					throw new IOException("indefinite length primitive encoding encountered");
+					throw new IOException("indefinite-length primitive encoding encountered");
 
 				return ReadIndef(tag);
 			}
@@ -134,12 +134,13 @@ namespace Org.BouncyCastle.Asn1
 			//
 			// calculate length
 			//
-			int length = Asn1InputStream.ReadLength(_in, _limit);
+			int length = Asn1InputStream.ReadLength(_in, _limit,
+                tagNo == Asn1Tags.OctetString || tagNo == Asn1Tags.Sequence || tagNo == Asn1Tags.Set || tagNo == Asn1Tags.External);
 
-			if (length < 0) // indefinite length method
+			if (length < 0) // indefinite-length method
 			{
 				if (!isConstructed)
-					throw new IOException("indefinite length primitive encoding encountered");
+					throw new IOException("indefinite-length primitive encoding encountered");
 
 				IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(_in, _limit);
 				Asn1StreamParser sp = new Asn1StreamParser(indIn, _limit);
@@ -158,7 +159,7 @@ namespace Org.BouncyCastle.Asn1
 			}
 			else
 			{
-				DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(_in, length);
+				DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(_in, length, _limit);
 
 				if ((tag & Asn1Tags.Application) != 0)
 				{
diff --git a/crypto/src/asn1/Asn1InputStream.cs b/crypto/src/asn1/Asn1InputStream.cs
index 0c7461c98..4f99301b3 100644
--- a/crypto/src/asn1/Asn1InputStream.cs
+++ b/crypto/src/asn1/Asn1InputStream.cs
@@ -2,6 +2,7 @@ using System;
 using System.Diagnostics;
 using System.IO;
 
+using Org.BouncyCastle.Utilities;
 using Org.BouncyCastle.Utilities.IO;
 
 namespace Org.BouncyCastle.Asn1
@@ -22,10 +23,12 @@ namespace Org.BouncyCastle.Asn1
         internal static int FindLimit(Stream input)
         {
             if (input is LimitedInputStream)
-            {
-                return ((LimitedInputStream)input).GetRemaining();
-            }
-            else if (input is MemoryStream)
+                return ((LimitedInputStream)input).Limit;
+
+            if (input is Asn1InputStream)
+                return ((Asn1InputStream)input).Limit;
+
+            if (input is MemoryStream)
             {
                 MemoryStream mem = (MemoryStream)input;
                 return (int)(mem.Length - mem.Position);
@@ -77,7 +80,7 @@ namespace Org.BouncyCastle.Asn1
         {
             bool isConstructed = (tag & Asn1Tags.Constructed) != 0;
 
-            DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(this.s, length);
+            DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(this.s, length, limit);
 
             if ((tag & Asn1Tags.Application) != 0)
             {
@@ -95,10 +98,27 @@ namespace Org.BouncyCastle.Asn1
                 switch (tagNo)
                 {
                     case Asn1Tags.OctetString:
+                    {
                         //
                         // yes, people actually do this...
                         //
-                        return new BerOctetString(ReadVector(defIn));
+                        Asn1EncodableVector v = ReadVector(defIn);
+                        Asn1OctetString[] strings = new Asn1OctetString[v.Count];
+
+                        for (int i = 0; i != strings.Length; i++)
+                        {
+                            Asn1Encodable asn1Obj = v[i];
+                            if (!(asn1Obj is Asn1OctetString))
+                            {
+                                throw new Asn1Exception("unknown object encountered in constructed OCTET STRING: "
+                                    + Platform.GetTypeName(asn1Obj));
+                            }
+
+                            strings[i] = (Asn1OctetString)asn1Obj;
+                        }
+
+                        return new BerOctetString(strings);
+                    }
                     case Asn1Tags.Sequence:
                         return CreateDerSequence(defIn);
                     case Asn1Tags.Set:
@@ -162,12 +182,12 @@ namespace Org.BouncyCastle.Asn1
             //
             // calculate length
             //
-            int length = ReadLength(this.s, limit);
+            int length = ReadLength(this.s, limit, false);
 
-            if (length < 0) // indefinite length method
+            if (length < 0) // indefinite-length method
             {
                 if (!isConstructed)
-                    throw new IOException("indefinite length primitive encoding encountered");
+                    throw new IOException("indefinite-length primitive encoding encountered");
 
                 IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(this.s, limit);
                 Asn1StreamParser sp = new Asn1StreamParser(indIn, limit);
@@ -210,6 +230,11 @@ namespace Org.BouncyCastle.Asn1
             }
         }
 
+        internal virtual int Limit
+        {
+            get { return limit; }
+        }
+
         internal static int ReadTagNumber(
             Stream	s,
             int		tag)
@@ -228,9 +253,7 @@ namespace Org.BouncyCastle.Asn1
                 // X.690-0207 8.1.2.4.2
                 // "c) bits 7 to 1 of the first subsequent octet shall not all be zero."
                 if ((b & 0x7f) == 0) // Note: -1 will pass
-                {
-                    throw new IOException("Corrupted stream - invalid high tag number found");
-                }
+                    throw new IOException("corrupted stream - invalid high tag number found");
 
                 while ((b >= 0) && ((b & 0x80) != 0))
                 {
@@ -248,9 +271,7 @@ namespace Org.BouncyCastle.Asn1
             return tagNo;
         }
 
-        internal static int ReadLength(
-            Stream	s,
-            int		limit)
+        internal static int ReadLength(Stream s, int limit, bool isParsing)
         {
             int length = s.ReadByte();
             if (length < 0)
@@ -279,18 +300,18 @@ namespace Org.BouncyCastle.Asn1
                 }
 
                 if (length < 0)
-                    throw new IOException("Corrupted stream - negative length found");
+                    throw new IOException("corrupted stream - negative length found");
 
-                if (length >= limit)   // after all we must have read at least 1 byte
-                    throw new IOException("Corrupted stream - out of bounds length found");
+                if (length >= limit && !isParsing)   // after all we must have read at least 1 byte
+                    throw new IOException("corrupted stream - out of bounds length found: " + length + " >= " + limit);
             }
 
             return length;
         }
 
-        internal static byte[] GetBuffer(DefiniteLengthInputStream defIn, byte[][] tmpBuffers)
+        private static byte[] GetBuffer(DefiniteLengthInputStream defIn, byte[][] tmpBuffers)
         {
-            int len = defIn.GetRemaining();
+            int len = defIn.Remaining;
             if (len >= tmpBuffers.Length)
             {
                 return defIn.ToArray();
@@ -307,6 +328,49 @@ namespace Org.BouncyCastle.Asn1
             return buf;
         }
 
+        private static char[] GetBmpCharBuffer(DefiniteLengthInputStream defIn)
+        {
+            int remainingBytes = defIn.Remaining;
+            if (0 != (remainingBytes & 1))
+                throw new IOException("malformed BMPString encoding encountered");
+
+            char[] str = new char[remainingBytes / 2];
+            int stringPos = 0;
+
+            byte[] buf = new byte[8];
+            while (remainingBytes >= 8)
+            {
+                if (Streams.ReadFully(defIn, buf, 0, 8) != 8)
+                    throw new EndOfStreamException("EOF encountered in middle of BMPString");
+
+                str[stringPos    ] = (char)((buf[0] << 8) | (buf[1] & 0xFF));
+                str[stringPos + 1] = (char)((buf[2] << 8) | (buf[3] & 0xFF));
+                str[stringPos + 2] = (char)((buf[4] << 8) | (buf[5] & 0xFF));
+                str[stringPos + 3] = (char)((buf[6] << 8) | (buf[7] & 0xFF));
+                stringPos += 4;
+                remainingBytes -= 8;
+            }
+            if (remainingBytes > 0)
+            {
+                if (Streams.ReadFully(defIn, buf, 0, remainingBytes) != remainingBytes)
+                    throw new EndOfStreamException("EOF encountered in middle of BMPString");
+
+                int bufPos = 0;
+                do
+                {
+                    int b1 = buf[bufPos++] << 8;
+                    int b2 = buf[bufPos++] & 0xFF;
+                    str[stringPos++] = (char)(b1 | b2);
+                }
+                while (bufPos < remainingBytes);
+            }
+
+            if (0 != defIn.Remaining || str.Length != stringPos)
+                throw new InvalidOperationException();
+
+            return str;
+        }
+
         internal static Asn1Object CreatePrimitiveDerObject(
             int                         tagNo,
             DefiniteLengthInputStream   defIn,
@@ -314,6 +378,8 @@ namespace Org.BouncyCastle.Asn1
         {
             switch (tagNo)
             {
+                case Asn1Tags.BmpString:
+                    return new DerBmpString(GetBmpCharBuffer(defIn));
                 case Asn1Tags.Boolean:
                     return DerBoolean.FromOctetString(GetBuffer(defIn, tmpBuffers));
                 case Asn1Tags.Enumerated:
@@ -328,8 +394,6 @@ namespace Org.BouncyCastle.Asn1
             {
                 case Asn1Tags.BitString:
                     return DerBitString.FromAsn1Octets(bytes);
-                case Asn1Tags.BmpString:
-                    return new DerBmpString(bytes);
                 case Asn1Tags.GeneralizedTime:
                     return new DerGeneralizedTime(bytes);
                 case Asn1Tags.GeneralString:
@@ -339,7 +403,7 @@ namespace Org.BouncyCastle.Asn1
                 case Asn1Tags.IA5String:
                     return new DerIA5String(bytes);
                 case Asn1Tags.Integer:
-                    return new DerInteger(bytes);
+                    return new DerInteger(bytes, false);
                 case Asn1Tags.Null:
                     return DerNull.Instance;   // actual content is ignored (enforce 0 length?)
                 case Asn1Tags.NumericString:
diff --git a/crypto/src/asn1/Asn1OctetString.cs b/crypto/src/asn1/Asn1OctetString.cs
index 73b6e51bf..da7dfae46 100644
--- a/crypto/src/asn1/Asn1OctetString.cs
+++ b/crypto/src/asn1/Asn1OctetString.cs
@@ -67,20 +67,7 @@ namespace Org.BouncyCastle.Asn1
 			this.str = str;
         }
 
-        internal Asn1OctetString(
-            Asn1Encodable obj)
-        {
-            try
-            {
-				this.str = obj.GetEncoded(Asn1Encodable.Der);
-            }
-            catch (IOException e)
-            {
-                throw new ArgumentException("Error processing object : " + e.ToString());
-            }
-        }
-
-		public Stream GetOctetStream()
+        public Stream GetOctetStream()
 		{
 			return new MemoryStream(str, false);
 		}
diff --git a/crypto/src/asn1/BerOctetString.cs b/crypto/src/asn1/BerOctetString.cs
index a7c8ad33e..fb4291612 100644
--- a/crypto/src/asn1/BerOctetString.cs
+++ b/crypto/src/asn1/BerOctetString.cs
@@ -9,66 +9,77 @@ namespace Org.BouncyCastle.Asn1
     public class BerOctetString
         : DerOctetString, IEnumerable
     {
-		public static BerOctetString FromSequence(Asn1Sequence seq)
-		{
-			IList v = Platform.CreateArrayList();
-
-			foreach (Asn1Encodable obj in seq)
-			{
-				v.Add(obj);
-			}
-
-			return new BerOctetString(v);
-		}
+        private static readonly int DefaultChunkSize = 1000;
 
-		private const int MaxLength = 1000;
+        public static BerOctetString FromSequence(Asn1Sequence seq)
+        {
+            int count = seq.Count;
+            Asn1OctetString[] v = new Asn1OctetString[count];
+            for (int i = 0; i < count; ++i)
+            {
+                v[i] = Asn1OctetString.GetInstance(seq[i]);
+            }
+            return new BerOctetString(v);
+        }
 
-		/**
-         * convert a vector of octet strings into a single byte string
-         */
-        private static byte[] ToBytes(
-            IEnumerable octs)
+        private static byte[] ToBytes(Asn1OctetString[] octs)
         {
             MemoryStream bOut = new MemoryStream();
-			foreach (DerOctetString o in octs)
-			{
+            foreach (Asn1OctetString o in octs)
+            {
                 byte[] octets = o.GetOctets();
                 bOut.Write(octets, 0, octets.Length);
             }
-			return bOut.ToArray();
+            return bOut.ToArray();
+        }
+
+        private static Asn1OctetString[] ToOctetStringArray(IEnumerable e)
+        {
+            IList list = Platform.CreateArrayList(e);
+
+            int count = list.Count;
+            Asn1OctetString[] v = new Asn1OctetString[count];
+            for (int i = 0; i < count; ++i)
+            {
+                v[i] = Asn1OctetString.GetInstance(list[i]);
+            }
+            return v;
         }
 
-		private readonly IEnumerable octs;
+        private readonly int chunkSize;
+        private readonly Asn1OctetString[] octs;
+
+        [Obsolete("Will be removed")]
+        public BerOctetString(IEnumerable e)
+            : this(ToOctetStringArray(e))
+        {
+        }
 
-		/// <param name="str">The octets making up the octet string.</param>
-		public BerOctetString(
-			byte[] str)
-			: base(str)
+        public BerOctetString(byte[] str)
+			: this(str, DefaultChunkSize)
 		{
 		}
 
-		public BerOctetString(
-			IEnumerable octets)
-			: base(ToBytes(octets))
+        public BerOctetString(Asn1OctetString[] octs)
+            : this(octs, DefaultChunkSize)
         {
-            this.octs = octets;
         }
 
-        public BerOctetString(
-			Asn1Object obj)
-			: base(obj)
+        public BerOctetString(byte[] str, int chunkSize)
+            : this(str, null, chunkSize)
         {
         }
 
-        public BerOctetString(
-			Asn1Encodable obj)
-			: base(obj.ToAsn1Object())
+        public BerOctetString(Asn1OctetString[] octs, int chunkSize)
+            : this(ToBytes(octs), octs, chunkSize)
         {
         }
 
-        public override byte[] GetOctets()
+        private BerOctetString(byte[] str, Asn1OctetString[] octs, int chunkSize)
+            : base(str)
         {
-            return str;
+            this.octs = octs;
+            this.chunkSize = chunkSize;
         }
 
         /**
@@ -93,17 +104,17 @@ namespace Org.BouncyCastle.Asn1
 		private IList GenerateOcts()
         {
             IList vec = Platform.CreateArrayList();
-			for (int i = 0; i < str.Length; i += MaxLength)
-			{
-				int end = System.Math.Min(str.Length, i + MaxLength);
+            for (int i = 0; i < str.Length; i += chunkSize)
+            { 
+				int end = System.Math.Min(str.Length, i + chunkSize);
 
-				byte[] nStr = new byte[end - i];
+                byte[] nStr = new byte[end - i]; 
 
-				Array.Copy(str, i, nStr, 0, nStr.Length);
+                Array.Copy(str, i, nStr, 0, nStr.Length);
 
-				vec.Add(new DerOctetString(nStr));
-			}
-			return vec;
+                vec.Add(new DerOctetString(nStr));
+             } 
+             return vec; 
         }
 
         internal override void Encode(
@@ -118,7 +129,7 @@ namespace Org.BouncyCastle.Asn1
                 //
                 // write out the octet array
                 //
-                foreach (DerOctetString oct in this)
+                foreach (Asn1OctetString oct in this)
                 {
                     derOut.WriteObject(oct);
                 }
diff --git a/crypto/src/asn1/ConstructedOctetStream.cs b/crypto/src/asn1/ConstructedOctetStream.cs
index 1773b22cc..829a9a427 100644
--- a/crypto/src/asn1/ConstructedOctetStream.cs
+++ b/crypto/src/asn1/ConstructedOctetStream.cs
@@ -1,5 +1,6 @@
 using System.IO;
 
+using Org.BouncyCastle.Utilities;
 using Org.BouncyCastle.Utilities.IO;
 
 namespace Org.BouncyCastle.Asn1
@@ -25,13 +26,12 @@ namespace Org.BouncyCastle.Asn1
 				if (!_first)
 					return 0;
 
-				Asn1OctetStringParser s = (Asn1OctetStringParser)_parser.ReadObject();
-
-				if (s == null)
-					return 0;
+                Asn1OctetStringParser next = GetNextParser();
+                if (next == null)
+                    return 0;
 
 				_first = false;
-				_currentStream = s.GetOctetStream();
+				_currentStream = next.GetOctetStream();
 			}
 
 			int totalRead = 0;
@@ -49,15 +49,14 @@ namespace Org.BouncyCastle.Asn1
 				}
 				else
 				{
-					Asn1OctetStringParser aos = (Asn1OctetStringParser)_parser.ReadObject();
-
-					if (aos == null)
+                    Asn1OctetStringParser next = GetNextParser();
+                    if (next == null)
 					{
 						_currentStream = null;
 						return totalRead;
 					}
 
-					_currentStream = aos.GetOctetStream();
+					_currentStream = next.GetOctetStream();
 				}
 			}
 		}
@@ -69,13 +68,12 @@ namespace Org.BouncyCastle.Asn1
 				if (!_first)
 					return 0;
 
-				Asn1OctetStringParser s = (Asn1OctetStringParser)_parser.ReadObject();
-
-				if (s == null)
+                Asn1OctetStringParser next = GetNextParser();
+                if (next == null)
 					return 0;
 
 				_first = false;
-				_currentStream = s.GetOctetStream();
+				_currentStream = next.GetOctetStream();
 			}
 
 			for (;;)
@@ -83,20 +81,29 @@ namespace Org.BouncyCastle.Asn1
 				int b = _currentStream.ReadByte();
 
 				if (b >= 0)
-				{
 					return b;
-				}
-
-				Asn1OctetStringParser aos = (Asn1OctetStringParser)_parser.ReadObject();
 
-				if (aos == null)
+                Asn1OctetStringParser next = GetNextParser();
+                if (next == null)
 				{
 					_currentStream = null;
 					return -1;
 				}
 
-				_currentStream = aos.GetOctetStream();
+				_currentStream = next.GetOctetStream();
 			}
 		}
+
+        private Asn1OctetStringParser GetNextParser()
+        {
+            IAsn1Convertible asn1Obj = _parser.ReadObject();
+            if (asn1Obj == null)
+                return null;
+
+            if (asn1Obj is Asn1OctetStringParser)
+                return (Asn1OctetStringParser)asn1Obj;
+
+            throw new IOException("unknown object encountered: " + Platform.GetTypeName(asn1Obj));
+        }
 	}
 }
diff --git a/crypto/src/asn1/DefiniteLengthInputStream.cs b/crypto/src/asn1/DefiniteLengthInputStream.cs
index 4ae803c0e..d10ea4d12 100644
--- a/crypto/src/asn1/DefiniteLengthInputStream.cs
+++ b/crypto/src/asn1/DefiniteLengthInputStream.cs
@@ -13,10 +13,8 @@ namespace Org.BouncyCastle.Asn1
 		private readonly int _originalLength;
 		private int _remaining;
 
-        internal DefiniteLengthInputStream(
-            Stream	inStream,
-            int		length)
-            : base(inStream, length)
+        internal DefiniteLengthInputStream(Stream inStream, int length, int limit)
+            : base(inStream, limit)
         {
 			if (length < 0)
 				throw new ArgumentException("negative lengths not allowed", "length");
@@ -30,7 +28,7 @@ namespace Org.BouncyCastle.Asn1
 			}
         }
 
-		internal int Remaining
+        internal int Remaining
 		{
 			get { return _remaining; }
 		}
@@ -80,6 +78,14 @@ namespace Org.BouncyCastle.Asn1
             if (_remaining != buf.Length)
                 throw new ArgumentException("buffer length not right for data");
 
+            if (_remaining == 0)
+                return;
+
+            // make sure it's safe to do this!
+            int limit = Limit;
+            if (_remaining >= limit)
+                throw new IOException("corrupted stream - out of bounds length found: " + _remaining + " >= " + limit);
+
             if ((_remaining -= Streams.ReadFully(_in, buf)) != 0)
                 throw new EndOfStreamException("DEF length " + _originalLength + " object truncated by " + _remaining);
             SetParentEofDetect(true);
@@ -90,7 +96,12 @@ namespace Org.BouncyCastle.Asn1
 			if (_remaining == 0)
 				return EmptyBytes;
 
-			byte[] bytes = new byte[_remaining];
+            // make sure it's safe to do this!
+            int limit = Limit;
+            if (_remaining >= limit)
+                throw new IOException("corrupted stream - out of bounds length found: " + _remaining + " >= " + limit);
+
+            byte[] bytes = new byte[_remaining];
 			if ((_remaining -= Streams.ReadFully(_in, bytes)) != 0)
 				throw new EndOfStreamException("DEF length " + _originalLength + " object truncated by " + _remaining);
 			SetParentEofDetect(true);
diff --git a/crypto/src/asn1/DerBMPString.cs b/crypto/src/asn1/DerBMPString.cs
index 33d950ff8..061900b9c 100644
--- a/crypto/src/asn1/DerBMPString.cs
+++ b/crypto/src/asn1/DerBMPString.cs
@@ -55,32 +55,44 @@ namespace Org.BouncyCastle.Asn1
 		/**
          * basic constructor - byte encoded string.
          */
-        public DerBmpString(
-            byte[] str)
+        [Obsolete("Will become internal")]
+        public DerBmpString(byte[] str)
         {
 			if (str == null)
 				throw new ArgumentNullException("str");
 
-            char[] cs = new char[str.Length / 2];
+            int byteLen = str.Length;
+            if (0 != (byteLen & 1))
+                throw new ArgumentException("malformed BMPString encoding encountered", "str");
 
-			for (int i = 0; i != cs.Length; i++)
+            int charLen = byteLen / 2;
+            char[] cs = new char[charLen];
+
+            for (int i = 0; i != charLen; i++)
             {
                 cs[i] = (char)((str[2 * i] << 8) | (str[2 * i + 1] & 0xff));
             }
 
-			this.str = new string(cs);
+            this.str = new string(cs);
+        }
+
+        internal DerBmpString(char[] str)
+        {
+            if (str == null)
+                throw new ArgumentNullException("str");
+
+            this.str = new string(str);
         }
 
         /**
          * basic constructor
          */
-        public DerBmpString(
-            string str)
+        public DerBmpString(string str)
         {
 			if (str == null)
 				throw new ArgumentNullException("str");
 
-			this.str = str;
+            this.str = str;
         }
 
         public override string GetString()
diff --git a/crypto/src/asn1/DerInteger.cs b/crypto/src/asn1/DerInteger.cs
index 3e19a07b6..4f7b68d35 100644
--- a/crypto/src/asn1/DerInteger.cs
+++ b/crypto/src/asn1/DerInteger.cs
@@ -145,6 +145,18 @@ namespace Org.BouncyCastle.Asn1
             }
         }
 
+        public long LongValueExact
+        {
+            get
+            {
+                int count = bytes.Length - start;
+                if (count > 8)
+                    throw new ArithmeticException("ASN.1 Integer out of long range");
+
+                return LongValue(bytes, start, SignExtSigned);
+            }
+        }
+
         internal override void Encode(DerOutputStream derOut)
         {
             derOut.WriteEncoded(Asn1Tags.Integer, bytes);
@@ -182,6 +194,19 @@ namespace Org.BouncyCastle.Asn1
             return val;
         }
 
+        internal static long LongValue(byte[] bytes, int start, int signExt)
+        {
+            int length = bytes.Length;
+            int pos = System.Math.Max(start, length - 8);
+
+            long val = (sbyte)bytes[pos] & signExt;
+            while (++pos < length)
+            {
+                val = (val << 8) | bytes[pos];
+            }
+            return val;
+        }
+
         /**
          * Apply the correct validation for an INTEGER primitive following the BER rules.
          *
diff --git a/crypto/src/asn1/DerObjectIdentifier.cs b/crypto/src/asn1/DerObjectIdentifier.cs
index fb38d5f05..9a0571b57 100644
--- a/crypto/src/asn1/DerObjectIdentifier.cs
+++ b/crypto/src/asn1/DerObjectIdentifier.cs
@@ -24,8 +24,18 @@ namespace Org.BouncyCastle.Asn1
         {
             if (obj == null || obj is DerObjectIdentifier)
                 return (DerObjectIdentifier) obj;
+
+            if (obj is Asn1Encodable)
+            {
+                Asn1Object asn1Obj = ((Asn1Encodable)obj).ToAsn1Object();
+
+                if (asn1Obj is DerObjectIdentifier)
+                    return (DerObjectIdentifier)asn1Obj;
+            }
+
             if (obj is byte[])
                 return FromOctetString((byte[])obj);
+
             throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj), "obj");
         }
 
diff --git a/crypto/src/asn1/DerOctetString.cs b/crypto/src/asn1/DerOctetString.cs
index c046c9402..d79607950 100644
--- a/crypto/src/asn1/DerOctetString.cs
+++ b/crypto/src/asn1/DerOctetString.cs
@@ -1,3 +1,5 @@
+using System;
+
 namespace Org.BouncyCastle.Asn1
 {
     public class DerOctetString
@@ -10,9 +12,13 @@ namespace Org.BouncyCastle.Asn1
         {
         }
 
-		public DerOctetString(
-			Asn1Encodable obj)
-			: base(obj)
+        public DerOctetString(IAsn1Convertible obj)
+            : this(obj.ToAsn1Object())
+        {
+        }
+
+        public DerOctetString(Asn1Encodable obj)
+            : base(obj.GetEncoded(Asn1Encodable.Der))
         {
         }
 
diff --git a/crypto/src/asn1/LimitedInputStream.cs b/crypto/src/asn1/LimitedInputStream.cs
index 62486aa77..98a45876d 100644
--- a/crypto/src/asn1/LimitedInputStream.cs
+++ b/crypto/src/asn1/LimitedInputStream.cs
@@ -8,23 +8,20 @@ namespace Org.BouncyCastle.Asn1
         : BaseInputStream
     {
         protected readonly Stream _in;
-		private int _limit;
+        private int _limit;
 
-        internal LimitedInputStream(
-            Stream	inStream,
-			int		limit)
+        internal LimitedInputStream(Stream inStream, int limit)
         {
             this._in = inStream;
-			this._limit = limit;
+            this._limit = limit;
         }
 
-	    internal virtual int GetRemaining()
-	    {
-	        // TODO: maybe one day this can become more accurate
-	        return _limit;
-	    }
+        internal virtual int Limit
+        {
+            get { return _limit; }
+        }
 
-		protected virtual void SetParentEofDetect(bool on)
+        protected virtual void SetParentEofDetect(bool on)
         {
             if (_in is IndefiniteLengthInputStream)
             {
diff --git a/crypto/src/asn1/cms/SignedData.cs b/crypto/src/asn1/cms/SignedData.cs
index dfc1e2829..5eba8390d 100644
--- a/crypto/src/asn1/cms/SignedData.cs
+++ b/crypto/src/asn1/cms/SignedData.cs
@@ -25,16 +25,13 @@ namespace Org.BouncyCastle.Asn1.Cms
         private readonly bool			certsBer;
         private readonly bool		    crlsBer;
 
-        public static SignedData GetInstance(
-            object obj)
+        public static SignedData GetInstance(object obj)
         {
             if (obj is SignedData)
-                return (SignedData) obj;
-
-            if (obj is Asn1Sequence)
-                return new SignedData((Asn1Sequence) obj);
-
-            throw new ArgumentException("Unknown object in factory: " + Platform.GetTypeName(obj), "obj");
+                return (SignedData)obj;
+            if (obj == null)
+                return null;
+            return new SignedData(Asn1Sequence.GetInstance(obj));
         }
 
         public SignedData(
diff --git a/crypto/src/asn1/cryptopro/GOST3410PublicKeyAlgParameters.cs b/crypto/src/asn1/cryptopro/GOST3410PublicKeyAlgParameters.cs
index 32a8fb226..c32025ef6 100644
--- a/crypto/src/asn1/cryptopro/GOST3410PublicKeyAlgParameters.cs
+++ b/crypto/src/asn1/cryptopro/GOST3410PublicKeyAlgParameters.cs
@@ -49,7 +49,8 @@ namespace Org.BouncyCastle.Asn1.CryptoPro
             this.encryptionParamSet = encryptionParamSet;
         }
 
-		public Gost3410PublicKeyAlgParameters(
+        [Obsolete("Use 'GetInstance' instead")]
+        public Gost3410PublicKeyAlgParameters(
             Asn1Sequence seq)
         {
             this.publicKeyParamSet = (DerObjectIdentifier) seq[0];
diff --git a/crypto/src/asn1/nist/NISTObjectIdentifiers.cs b/crypto/src/asn1/nist/NISTObjectIdentifiers.cs
index 840718ccd..417fa8df9 100644
--- a/crypto/src/asn1/nist/NISTObjectIdentifiers.cs
+++ b/crypto/src/asn1/nist/NISTObjectIdentifiers.cs
@@ -35,6 +35,10 @@ namespace Org.BouncyCastle.Asn1.Nist
         public static readonly DerObjectIdentifier IdHMacWithSha3_256 = HashAlgs.Branch("14");
         public static readonly DerObjectIdentifier IdHMacWithSha3_384 = HashAlgs.Branch("15");
         public static readonly DerObjectIdentifier IdHMacWithSha3_512 = HashAlgs.Branch("16");
+        public static readonly DerObjectIdentifier IdShake128Len = HashAlgs.Branch("17");
+        public static readonly DerObjectIdentifier IdShake256Len = HashAlgs.Branch("18");
+        public static readonly DerObjectIdentifier IdKmacWithShake128 = HashAlgs.Branch("19");
+        public static readonly DerObjectIdentifier IdKmacWithShake256 = HashAlgs.Branch("20");
 
         public static readonly DerObjectIdentifier Aes = new DerObjectIdentifier(NistAlgorithm + ".1");
 
diff --git a/crypto/src/asn1/pkcs/AuthenticatedSafe.cs b/crypto/src/asn1/pkcs/AuthenticatedSafe.cs
index f3dabb89c..6a112d9df 100644
--- a/crypto/src/asn1/pkcs/AuthenticatedSafe.cs
+++ b/crypto/src/asn1/pkcs/AuthenticatedSafe.cs
@@ -1,3 +1,5 @@
+using System;
+
 using Org.BouncyCastle.Asn1;
 
 namespace Org.BouncyCastle.Asn1.Pkcs
@@ -5,33 +7,59 @@ namespace Org.BouncyCastle.Asn1.Pkcs
     public class AuthenticatedSafe
         : Asn1Encodable
     {
+        private static ContentInfo[] Copy(ContentInfo[] info)
+        {
+            return (ContentInfo[])info.Clone();
+        }
+
+        public static AuthenticatedSafe GetInstance(object obj)
+        {
+            if (obj is AuthenticatedSafe)
+                return (AuthenticatedSafe)obj;
+            if (obj == null)
+                return null;
+            return new AuthenticatedSafe(Asn1Sequence.GetInstance(obj));
+        }
+
         private readonly ContentInfo[] info;
+        private readonly bool isBer;
 
+        [Obsolete("Use 'GetInstance' instead")]
 		public AuthenticatedSafe(
             Asn1Sequence seq)
         {
             info = new ContentInfo[seq.Count];
 
-			for (int i = 0; i != info.Length; i++)
+            for (int i = 0; i != info.Length; i++)
             {
                 info[i] = ContentInfo.GetInstance(seq[i]);
             }
+
+            isBer = seq is BerSequence;
         }
 
 		public AuthenticatedSafe(
             ContentInfo[] info)
         {
-            this.info = (ContentInfo[]) info.Clone();
+            this.info = Copy(info);
+            this.isBer = true;
         }
 
 		public ContentInfo[] GetContentInfo()
         {
-            return (ContentInfo[]) info.Clone();
+            return Copy(info);
         }
 
-		public override Asn1Object ToAsn1Object()
+        public override Asn1Object ToAsn1Object()
         {
-			return new BerSequence(info);
+            if (isBer)
+            {
+                return new BerSequence(info);
+            }
+
+            // TODO bc-java uses DL sequence
+            //return new DLSequence(info);
+            return new DerSequence(info);
         }
     }
 }
diff --git a/crypto/src/asn1/pkcs/CertBag.cs b/crypto/src/asn1/pkcs/CertBag.cs
index e561fb890..61165c087 100644
--- a/crypto/src/asn1/pkcs/CertBag.cs
+++ b/crypto/src/asn1/pkcs/CertBag.cs
@@ -5,17 +5,25 @@ namespace Org.BouncyCastle.Asn1.Pkcs
     public class CertBag
         : Asn1Encodable
     {
-//		private readonly Asn1Sequence seq;
+        public static CertBag GetInstance(object obj)
+        {
+            if (obj is CertBag)
+                return (CertBag)obj;
+            if (obj == null)
+                return null;
+            return new CertBag(Asn1Sequence.GetInstance(obj));
+        }
+
         private readonly DerObjectIdentifier certID;
         private readonly Asn1Object certValue;
 
+        [Obsolete("Use 'GetInstance' instead")]
 		public CertBag(
             Asn1Sequence seq)
         {
 			if (seq.Count != 2)
 				throw new ArgumentException("Wrong number of elements in sequence", "seq");
 
-//			this.seq = seq;
             this.certID = DerObjectIdentifier.GetInstance(seq[0]);
             this.certValue = Asn1TaggedObject.GetInstance(seq[1]).GetObject();
         }
@@ -28,12 +36,12 @@ namespace Org.BouncyCastle.Asn1.Pkcs
             this.certValue = certValue;
         }
 
-		public DerObjectIdentifier CertID
+		public virtual DerObjectIdentifier CertID
 		{
 			get { return certID; }
 		}
 
-		public Asn1Object CertValue
+		public virtual Asn1Object CertValue
 		{
 			get { return certValue; }
 		}
diff --git a/crypto/src/asn1/pkcs/Pfx.cs b/crypto/src/asn1/pkcs/Pfx.cs
index 4f958a070..3aec8ed0f 100644
--- a/crypto/src/asn1/pkcs/Pfx.cs
+++ b/crypto/src/asn1/pkcs/Pfx.cs
@@ -11,29 +11,35 @@ namespace Org.BouncyCastle.Asn1.Pkcs
     public class Pfx
         : Asn1Encodable
     {
-        private ContentInfo	contentInfo;
-        private MacData		macData;
+        public static Pfx GetInstance(object obj)
+        {
+            if (obj is Pfx)
+                return (Pfx)obj;
+            if (obj == null)
+                return null;
+            return new Pfx(Asn1Sequence.GetInstance(obj));
+        }
+
+        private readonly ContentInfo contentInfo;
+        private readonly MacData macData;
 
+        [Obsolete("Use 'GetInstance' instead")]
 		public Pfx(
             Asn1Sequence seq)
         {
-            BigInteger version = ((DerInteger) seq[0]).Value;
-            if (version.IntValue != 3)
-            {
+            DerInteger version = DerInteger.GetInstance(seq[0]);
+            if (version.IntValueExact != 3)
                 throw new ArgumentException("wrong version for PFX PDU");
-            }
 
-			contentInfo = ContentInfo.GetInstance(seq[1]);
+            this.contentInfo = ContentInfo.GetInstance(seq[1]);
 
-			if (seq.Count == 3)
+            if (seq.Count == 3)
             {
-                macData = MacData.GetInstance(seq[2]);
+                this.macData = MacData.GetInstance(seq[2]);
             }
         }
 
-		public Pfx(
-            ContentInfo	contentInfo,
-            MacData		macData)
+		public Pfx(ContentInfo contentInfo, MacData macData)
         {
             this.contentInfo = contentInfo;
             this.macData = macData;
diff --git a/crypto/src/asn1/pkcs/SafeBag.cs b/crypto/src/asn1/pkcs/SafeBag.cs
index ea1ce951e..7951d4892 100644
--- a/crypto/src/asn1/pkcs/SafeBag.cs
+++ b/crypto/src/asn1/pkcs/SafeBag.cs
@@ -1,3 +1,5 @@
+using System;
+
 using Org.BouncyCastle.Asn1;
 
 namespace Org.BouncyCastle.Asn1.Pkcs
@@ -5,6 +7,15 @@ namespace Org.BouncyCastle.Asn1.Pkcs
     public class SafeBag
         : Asn1Encodable
     {
+        public static SafeBag GetInstance(object obj)
+        {
+            if (obj is SafeBag)
+                return (SafeBag)obj;
+            if (obj == null)
+                return null;
+            return new SafeBag(Asn1Sequence.GetInstance(obj));
+        }
+
         private readonly DerObjectIdentifier bagID;
         private readonly Asn1Object bagValue;
         private readonly Asn1Set bagAttributes;
@@ -28,14 +39,15 @@ namespace Org.BouncyCastle.Asn1.Pkcs
             this.bagAttributes = bagAttributes;
         }
 
+        [Obsolete("Use 'GetInstance' instead")]
 		public SafeBag(
             Asn1Sequence seq)
         {
-            this.bagID = (DerObjectIdentifier) seq[0];
-            this.bagValue = ((DerTaggedObject) seq[1]).GetObject();
+            this.bagID = (DerObjectIdentifier)seq[0];
+            this.bagValue = ((DerTaggedObject)seq[1]).GetObject();
             if (seq.Count == 3)
             {
-                this.bagAttributes = (Asn1Set) seq[2];
+                this.bagAttributes = (Asn1Set)seq[2];
             }
         }
 
diff --git a/crypto/src/asn1/x509/AuthorityInformationAccess.cs b/crypto/src/asn1/x509/AuthorityInformationAccess.cs
index 9329e2b98..f4b694cf0 100644
--- a/crypto/src/asn1/x509/AuthorityInformationAccess.cs
+++ b/crypto/src/asn1/x509/AuthorityInformationAccess.cs
@@ -26,7 +26,10 @@ namespace Org.BouncyCastle.Asn1.X509
     public class AuthorityInformationAccess
         : Asn1Encodable
     {
-        private readonly AccessDescription[] descriptions;
+        private static AccessDescription[] Copy(AccessDescription[] descriptions)
+        {
+            return (AccessDescription[])descriptions.Clone();
+        }
 
         public static AuthorityInformationAccess GetInstance(object obj)
         {
@@ -37,6 +40,13 @@ namespace Org.BouncyCastle.Asn1.X509
             return new AuthorityInformationAccess(Asn1Sequence.GetInstance(obj));
         }
 
+        public static AuthorityInformationAccess FromExtensions(X509Extensions extensions)
+        {
+            return GetInstance(X509Extensions.GetExtensionParsedValue(extensions, X509Extensions.AuthorityInfoAccess));
+        }
+
+        private readonly AccessDescription[] descriptions;
+
         private AuthorityInformationAccess(
             Asn1Sequence seq)
         {
@@ -57,6 +67,12 @@ namespace Org.BouncyCastle.Asn1.X509
             this.descriptions = new AccessDescription[]{ description };
         }
 
+        public AuthorityInformationAccess(
+            AccessDescription[] descriptions)
+        {
+            this.descriptions = Copy(descriptions);
+        }
+
         /**
          * create an AuthorityInformationAccess with the oid and location provided.
          */
@@ -67,7 +83,7 @@ namespace Org.BouncyCastle.Asn1.X509
 
         public AccessDescription[] GetAccessDescriptions()
         {
-            return (AccessDescription[])descriptions.Clone();
+            return Copy(descriptions);
         }
 
         public override Asn1Object ToAsn1Object()
diff --git a/crypto/src/asn1/x509/AuthorityKeyIdentifier.cs b/crypto/src/asn1/x509/AuthorityKeyIdentifier.cs
index aca1dc330..e7f12016a 100644
--- a/crypto/src/asn1/x509/AuthorityKeyIdentifier.cs
+++ b/crypto/src/asn1/x509/AuthorityKeyIdentifier.cs
@@ -5,6 +5,7 @@ using Org.BouncyCastle.Crypto;
 using Org.BouncyCastle.Crypto.Digests;
 using Org.BouncyCastle.Math;
 using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
 
 namespace Org.BouncyCastle.Asn1.X509
 {
@@ -25,56 +26,51 @@ namespace Org.BouncyCastle.Asn1.X509
     public class AuthorityKeyIdentifier
         : Asn1Encodable
     {
-        internal readonly Asn1OctetString	keyidentifier;
-        internal readonly GeneralNames		certissuer;
-        internal readonly DerInteger		certserno;
-
-		public static AuthorityKeyIdentifier GetInstance(
-            Asn1TaggedObject	obj,
-            bool				explicitly)
+        public static AuthorityKeyIdentifier GetInstance(Asn1TaggedObject obj, bool explicitly)
         {
             return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
         }
 
-		public static AuthorityKeyIdentifier GetInstance(
-            object obj)
+		public static AuthorityKeyIdentifier GetInstance(object obj)
         {
             if (obj is AuthorityKeyIdentifier)
-            {
-                return (AuthorityKeyIdentifier) obj;
-            }
-
-			if (obj is Asn1Sequence)
-            {
-                return new AuthorityKeyIdentifier((Asn1Sequence) obj);
-            }
+                return (AuthorityKeyIdentifier)obj;
+            if (obj is X509Extension)
+                return GetInstance(X509Extension.ConvertValueToObject((X509Extension)obj));
+            if (obj == null)
+                return null;
+            return new AuthorityKeyIdentifier(Asn1Sequence.GetInstance(obj));
+		}
 
-	        if (obj is X509Extension)
-			{
-				return GetInstance(X509Extension.ConvertValueToObject((X509Extension) obj));
-			}
+        public static AuthorityKeyIdentifier FromExtensions(X509Extensions extensions)
+        {
+            return GetInstance(X509Extensions.GetExtensionParsedValue(extensions, X509Extensions.AuthorityKeyIdentifier));
+        }
 
-            throw new ArgumentException("unknown object in factory: " + Platform.GetTypeName(obj), "obj");
-		}
+        private readonly Asn1OctetString keyidentifier;
+        private readonly GeneralNames certissuer;
+        private readonly DerInteger certserno;
 
-		protected internal AuthorityKeyIdentifier(
+        protected internal AuthorityKeyIdentifier(
             Asn1Sequence seq)
         {
-			foreach (Asn1TaggedObject o in seq)
+            foreach (Asn1Encodable element in seq)
 			{
-				switch (o.TagNo)
+                Asn1TaggedObject obj = Asn1TaggedObject.GetInstance(element);
+
+				switch (obj.TagNo)
                 {
-					case 0:
-						this.keyidentifier = Asn1OctetString.GetInstance(o, false);
-						break;
-					case 1:
-						this.certissuer = GeneralNames.GetInstance(o, false);
-						break;
-					case 2:
-						this.certserno = DerInteger.GetInstance(o, false);
-						break;
-					default:
-						throw new ArgumentException("illegal tag");
+				case 0:
+					this.keyidentifier = Asn1OctetString.GetInstance(obj, false);
+					break;
+				case 1:
+					this.certissuer = GeneralNames.GetInstance(obj, false);
+					break;
+				case 2:
+					this.certserno = DerInteger.GetInstance(obj, false);
+					break;
+				default:
+					throw new ArgumentException("illegal tag");
                 }
             }
         }
@@ -94,14 +90,8 @@ namespace Org.BouncyCastle.Asn1.X509
          **/
         public AuthorityKeyIdentifier(
             SubjectPublicKeyInfo spki)
+            : this(spki, null, null)
         {
-            IDigest digest = new Sha1Digest();
-            byte[] resBuf = new byte[digest.GetDigestSize()];
-
-			byte[] bytes = spki.PublicKeyData.GetBytes();
-            digest.BlockUpdate(bytes, 0, bytes.Length);
-            digest.DoFinal(resBuf, 0);
-            this.keyidentifier = new DerOctetString(resBuf);
         }
 
         /**
@@ -115,27 +105,24 @@ namespace Org.BouncyCastle.Asn1.X509
         {
             IDigest digest = new Sha1Digest();
             byte[] resBuf = new byte[digest.GetDigestSize()];
-
 			byte[] bytes = spki.PublicKeyData.GetBytes();
             digest.BlockUpdate(bytes, 0, bytes.Length);
             digest.DoFinal(resBuf, 0);
 
 			this.keyidentifier = new DerOctetString(resBuf);
             this.certissuer = name;
-            this.certserno = new DerInteger(serialNumber);
+            this.certserno = serialNumber == null ? null : new DerInteger(serialNumber);
         }
 
-		/**
+        /**
 		 * create an AuthorityKeyIdentifier with the GeneralNames tag and
 		 * the serial number provided.
 		 */
 		public AuthorityKeyIdentifier(
 			GeneralNames	name,
 			BigInteger		serialNumber)
+            : this((byte[])null, name, serialNumber)
 		{
-			this.keyidentifier = null;
-			this.certissuer = GeneralNames.GetInstance(name.ToAsn1Object());
-			this.certserno = new DerInteger(serialNumber);
 		}
 
 		/**
@@ -143,13 +130,11 @@ namespace Org.BouncyCastle.Asn1.X509
 		 */
 		public AuthorityKeyIdentifier(
 			byte[] keyIdentifier)
+            : this(keyIdentifier, null, null)
 		{
-			this.keyidentifier = new DerOctetString(keyIdentifier);
-			this.certissuer = null;
-			this.certserno = null;
 		}
 
-		/**
+        /**
 		 * create an AuthorityKeyIdentifier with a precomupted key identifier
 		 * and the GeneralNames tag and the serial number provided as well.
 		 */
@@ -158,9 +143,9 @@ namespace Org.BouncyCastle.Asn1.X509
 			GeneralNames	name,
 			BigInteger		serialNumber)
 		{
-			this.keyidentifier = new DerOctetString(keyIdentifier);
-			this.certissuer = GeneralNames.GetInstance(name.ToAsn1Object());
-			this.certserno = new DerInteger(serialNumber);
+			this.keyidentifier = keyIdentifier == null ? null : new DerOctetString(keyIdentifier);
+			this.certissuer = name;
+			this.certserno = serialNumber == null ? null : new DerInteger(serialNumber);
 		}
 
 		public byte[] GetKeyIdentifier()
@@ -178,7 +163,7 @@ namespace Org.BouncyCastle.Asn1.X509
             get { return certserno == null ? null : certserno.Value; }
         }
 
-		/**
+        /**
          * Produce an object suitable for an Asn1OutputStream.
          */
         public override Asn1Object ToAsn1Object()
@@ -192,7 +177,9 @@ namespace Org.BouncyCastle.Asn1.X509
 
 		public override string ToString()
         {
-            return ("AuthorityKeyIdentifier: KeyID(" + this.keyidentifier.GetOctets() + ")");
+            string keyID = (keyidentifier != null) ? Hex.ToHexString(keyidentifier.GetOctets()) : "null";
+
+            return "AuthorityKeyIdentifier: KeyID(" + keyID + ")";
         }
     }
 }
diff --git a/crypto/src/asn1/x509/BasicConstraints.cs b/crypto/src/asn1/x509/BasicConstraints.cs
index 079294d1b..deecae241 100644
--- a/crypto/src/asn1/x509/BasicConstraints.cs
+++ b/crypto/src/asn1/x509/BasicConstraints.cs
@@ -8,38 +8,31 @@ namespace Org.BouncyCastle.Asn1.X509
     public class BasicConstraints
         : Asn1Encodable
     {
-        private readonly DerBoolean	cA;
-        private readonly DerInteger	pathLenConstraint;
-
-		public static BasicConstraints GetInstance(
-            Asn1TaggedObject	obj,
-            bool				explicitly)
+		public static BasicConstraints GetInstance(Asn1TaggedObject obj, bool explicitly)
         {
             return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
         }
 
-		public static BasicConstraints GetInstance(
-            object obj)
+		public static BasicConstraints GetInstance(object obj)
         {
-            if (obj == null || obj is BasicConstraints)
-            {
-                return (BasicConstraints) obj;
-            }
-
-			if (obj is Asn1Sequence)
-            {
-                return new BasicConstraints((Asn1Sequence) obj);
-            }
+            if (obj is BasicConstraints)
+                return (BasicConstraints)obj;
+            if (obj is X509Extension)
+                return GetInstance(X509Extension.ConvertValueToObject((X509Extension)obj));
+            if (obj == null)
+                return null;
+            return new BasicConstraints(Asn1Sequence.GetInstance(obj));
+		}
 
-			if (obj is X509Extension)
-			{
-				return GetInstance(X509Extension.ConvertValueToObject((X509Extension) obj));
-			}
+        public static BasicConstraints FromExtensions(X509Extensions extensions)
+        {
+            return GetInstance(X509Extensions.GetExtensionParsedValue(extensions, X509Extensions.BasicConstraints));
+        }
 
-            throw new ArgumentException("unknown object in factory: " + Platform.GetTypeName(obj), "obj");
-		}
+        private readonly DerBoolean cA;
+        private readonly DerInteger pathLenConstraint;
 
-		private BasicConstraints(
+        private BasicConstraints(
             Asn1Sequence seq)
         {
 			if (seq.Count > 0)
@@ -105,7 +98,7 @@ namespace Org.BouncyCastle.Asn1.X509
          */
         public override Asn1Object ToAsn1Object()
         {
-            Asn1EncodableVector v = new Asn1EncodableVector();
+            Asn1EncodableVector v = new Asn1EncodableVector(2);
             v.AddOptional(cA,
                 pathLenConstraint); // yes some people actually do this when cA is false...
             return new DerSequence(v);
diff --git a/crypto/src/asn1/x509/CRLDistPoint.cs b/crypto/src/asn1/x509/CRLDistPoint.cs
index 56ba79ca5..446bb19db 100644
--- a/crypto/src/asn1/x509/CRLDistPoint.cs
+++ b/crypto/src/asn1/x509/CRLDistPoint.cs
@@ -8,32 +8,28 @@ namespace Org.BouncyCastle.Asn1.X509
     public class CrlDistPoint
         : Asn1Encodable
     {
-        internal readonly Asn1Sequence seq;
-
-		public static CrlDistPoint GetInstance(
-            Asn1TaggedObject	obj,
-            bool				explicitly)
+		public static CrlDistPoint GetInstance(Asn1TaggedObject obj, bool explicitly)
         {
             return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
         }
 
-		public static CrlDistPoint GetInstance(
-            object obj)
+		public static CrlDistPoint GetInstance(object obj)
         {
-            if (obj is CrlDistPoint || obj == null)
-            {
-                return (CrlDistPoint) obj;
-            }
+            if (obj is CrlDistPoint)
+                return (CrlDistPoint)obj;
+            if (obj == null)
+                return null;
+            return new CrlDistPoint(Asn1Sequence.GetInstance(obj));
+		}
 
-			if (obj is Asn1Sequence)
-            {
-                return new CrlDistPoint((Asn1Sequence) obj);
-            }
+        public static CrlDistPoint FromExtensions(X509Extensions extensions)
+        {
+            return GetInstance(X509Extensions.GetExtensionParsedValue(extensions, X509Extensions.CrlDistributionPoints));
+        }
 
-            throw new ArgumentException("unknown object in factory: " + Platform.GetTypeName(obj), "obj");
-		}
+        internal readonly Asn1Sequence seq;
 
-		private CrlDistPoint(
+        private CrlDistPoint(
             Asn1Sequence seq)
         {
             this.seq = seq;
diff --git a/crypto/src/asn1/x509/CertificatePolicies.cs b/crypto/src/asn1/x509/CertificatePolicies.cs
index a83565bb2..97214bd3f 100644
--- a/crypto/src/asn1/x509/CertificatePolicies.cs
+++ b/crypto/src/asn1/x509/CertificatePolicies.cs
@@ -6,13 +6,17 @@ namespace Org.BouncyCastle.Asn1.X509
     public class CertificatePolicies
         : Asn1Encodable
     {
-        private readonly PolicyInformation[] policyInformation;
+        private static PolicyInformation[] Copy(PolicyInformation[] policyInfo)
+        {
+            return (PolicyInformation[])policyInfo.Clone();
+        }
 
         public static CertificatePolicies GetInstance(object obj)
         {
-            if (obj == null || obj is CertificatePolicies)
+            if (obj is CertificatePolicies)
                 return (CertificatePolicies)obj;
-
+            if (obj == null)
+                return null;
             return new CertificatePolicies(Asn1Sequence.GetInstance(obj));
         }
 
@@ -21,6 +25,13 @@ namespace Org.BouncyCastle.Asn1.X509
             return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
         }
 
+        public static CertificatePolicies FromExtensions(X509Extensions extensions)
+        {
+            return GetInstance(X509Extensions.GetExtensionParsedValue(extensions, X509Extensions.CertificatePolicies));
+        }
+
+        private readonly PolicyInformation[] policyInformation;
+
         /**
          * Construct a CertificatePolicies object containing one PolicyInformation.
          * 
@@ -33,7 +44,7 @@ namespace Org.BouncyCastle.Asn1.X509
 
         public CertificatePolicies(PolicyInformation[] policyInformation)
         {
-            this.policyInformation = policyInformation;
+            this.policyInformation = Copy(policyInformation);
         }
 
         private CertificatePolicies(Asn1Sequence seq)
@@ -48,7 +59,20 @@ namespace Org.BouncyCastle.Asn1.X509
 
         public virtual PolicyInformation[] GetPolicyInformation()
         {
-            return (PolicyInformation[])policyInformation.Clone();
+            return Copy(policyInformation);
+        }
+
+        public virtual PolicyInformation GetPolicyInformation(DerObjectIdentifier policyIdentifier)
+        {
+            for (int i = 0; i != policyInformation.Length; i++)
+            {
+                if (policyIdentifier.Equals(policyInformation[i].PolicyIdentifier))
+                {
+                    return policyInformation[i];
+                }
+            }
+
+            return null;
         }
 
         /**
diff --git a/crypto/src/asn1/x509/ExtendedKeyUsage.cs b/crypto/src/asn1/x509/ExtendedKeyUsage.cs
index 8f7e6a353..7e8c7a37c 100644
--- a/crypto/src/asn1/x509/ExtendedKeyUsage.cs
+++ b/crypto/src/asn1/x509/ExtendedKeyUsage.cs
@@ -14,9 +14,6 @@ namespace Org.BouncyCastle.Asn1.X509
     public class ExtendedKeyUsage
         : Asn1Encodable
     {
-        internal readonly IDictionary usageTable = Platform.CreateHashtable();
-        internal readonly Asn1Sequence seq;
-
         public static ExtendedKeyUsage GetInstance(
             Asn1TaggedObject	obj,
             bool				explicitly)
@@ -28,34 +25,32 @@ namespace Org.BouncyCastle.Asn1.X509
             object obj)
         {
             if (obj is ExtendedKeyUsage)
-            {
-                return (ExtendedKeyUsage) obj;
-            }
-
-            if (obj is Asn1Sequence)
-            {
-                return new ExtendedKeyUsage((Asn1Sequence) obj);
-            }
-
+                return (ExtendedKeyUsage)obj;
             if (obj is X509Extension)
-            {
-                return GetInstance(X509Extension.ConvertValueToObject((X509Extension) obj));
-            }
+                return GetInstance(X509Extension.ConvertValueToObject((X509Extension)obj));
+            if (obj == null)
+                return null;
+            return new ExtendedKeyUsage(Asn1Sequence.GetInstance(obj));
+        }
 
-            throw new ArgumentException("Invalid ExtendedKeyUsage: " + Platform.GetTypeName(obj));
+        public static ExtendedKeyUsage FromExtensions(X509Extensions extensions)
+        {
+            return GetInstance(X509Extensions.GetExtensionParsedValue(extensions, X509Extensions.ExtendedKeyUsage));
         }
 
+        internal readonly IDictionary usageTable = Platform.CreateHashtable();
+        internal readonly Asn1Sequence seq;
+
         private ExtendedKeyUsage(
             Asn1Sequence seq)
         {
             this.seq = seq;
 
-            foreach (object o in seq)
+            foreach (Asn1Encodable element in seq)
             {
-                if (!(o is DerObjectIdentifier))
-                    throw new ArgumentException("Only DerObjectIdentifier instances allowed in ExtendedKeyUsage.");
+                DerObjectIdentifier oid = DerObjectIdentifier.GetInstance(element);
 
-                this.usageTable[o] = o;
+                this.usageTable[oid] = oid;
             }
         }
 
@@ -86,10 +81,10 @@ namespace Org.BouncyCastle.Asn1.X509
 
             foreach (object usage in usages)
             {
-                Asn1Encodable o = KeyPurposeID.GetInstance(usage);
+                DerObjectIdentifier oid = DerObjectIdentifier.GetInstance(usage);
 
-                v.Add(o);
-                this.usageTable[o] = o;
+                v.Add(oid);
+                this.usageTable[oid] = oid;
             }
 
             this.seq = new DerSequence(v);
diff --git a/crypto/src/asn1/x509/GeneralNames.cs b/crypto/src/asn1/x509/GeneralNames.cs
index fcd2ecb24..c105f3b6e 100644
--- a/crypto/src/asn1/x509/GeneralNames.cs
+++ b/crypto/src/asn1/x509/GeneralNames.cs
@@ -8,32 +8,33 @@ namespace Org.BouncyCastle.Asn1.X509
 	public class GeneralNames
 		: Asn1Encodable
 	{
-		private readonly GeneralName[] names;
+        private static GeneralName[] Copy(GeneralName[] names)
+        {
+            return (GeneralName[])names.Clone();
+        }
 
-		public static GeneralNames GetInstance(
-			object obj)
+        public static GeneralNames GetInstance(object obj)
 		{
-			if (obj == null || obj is GeneralNames)
-			{
-				return (GeneralNames) obj;
-			}
-
-			if (obj is Asn1Sequence)
-			{
-				return new GeneralNames((Asn1Sequence) obj);
-			}
-
-            throw new ArgumentException("unknown object in factory: " + Platform.GetTypeName(obj), "obj");
+            if (obj is GeneralNames)
+                return (GeneralNames)obj;
+            if (obj == null)
+                return null;
+            return new GeneralNames(Asn1Sequence.GetInstance(obj));
 		}
 
-		public static GeneralNames GetInstance(
-			Asn1TaggedObject	obj,
-			bool				explicitly)
+		public static GeneralNames GetInstance(Asn1TaggedObject obj, bool explicitly)
 		{
 			return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
 		}
 
-		/// <summary>Construct a GeneralNames object containing one GeneralName.</summary>
+        public static GeneralNames FromExtensions(X509Extensions extensions, DerObjectIdentifier extOid)
+        {
+            return GetInstance(X509Extensions.GetExtensionParsedValue(extensions, extOid));
+        }
+
+        private readonly GeneralName[] names;
+
+        /// <summary>Construct a GeneralNames object containing one GeneralName.</summary>
 		/// <param name="name">The name to be contained.</param>
 		public GeneralNames(
 			GeneralName name)
@@ -44,7 +45,7 @@ namespace Org.BouncyCastle.Asn1.X509
         public GeneralNames(
             GeneralName[] names)
         {
-            this.names = (GeneralName[])names.Clone();
+            this.names = Copy(names);
         }
 
 		private GeneralNames(
@@ -60,7 +61,7 @@ namespace Org.BouncyCastle.Asn1.X509
 
 		public GeneralName[] GetNames()
 		{
-			return (GeneralName[]) names.Clone();
+            return Copy(names);
 		}
 
 		/**
diff --git a/crypto/src/asn1/x509/KeyUsage.cs b/crypto/src/asn1/x509/KeyUsage.cs
index aeaffb708..b31b54341 100644
--- a/crypto/src/asn1/x509/KeyUsage.cs
+++ b/crypto/src/asn1/x509/KeyUsage.cs
@@ -30,23 +30,23 @@ namespace Org.BouncyCastle.Asn1.X509
         public const int EncipherOnly     = (1 << 0);
         public const int DecipherOnly     = (1 << 15);
 
-		public static new KeyUsage GetInstance(
-			object obj)
+		public static new KeyUsage GetInstance(object obj)
 		{
 			if (obj is KeyUsage)
-			{
 				return (KeyUsage)obj;
-			}
-
-			if (obj is X509Extension)
-			{
-				return GetInstance(X509Extension.ConvertValueToObject((X509Extension) obj));
-			}
-
+            if (obj is X509Extension)
+				return GetInstance(X509Extension.ConvertValueToObject((X509Extension)obj));
+            if (obj == null)
+                return null;
 			return new KeyUsage(DerBitString.GetInstance(obj));
 		}
 
-		/**
+        public static KeyUsage FromExtensions(X509Extensions extensions)
+        {
+            return GetInstance(X509Extensions.GetExtensionParsedValue(extensions, X509Extensions.KeyUsage));
+        }
+
+        /**
          * Basic constructor.
          *
          * @param usage - the bitwise OR of the Key Usage flags giving the
diff --git a/crypto/src/asn1/x509/SubjectKeyIdentifier.cs b/crypto/src/asn1/x509/SubjectKeyIdentifier.cs
index f2e6cc006..bb694681b 100644
--- a/crypto/src/asn1/x509/SubjectKeyIdentifier.cs
+++ b/crypto/src/asn1/x509/SubjectKeyIdentifier.cs
@@ -15,54 +15,44 @@ namespace Org.BouncyCastle.Asn1.X509
     public class SubjectKeyIdentifier
         : Asn1Encodable
     {
-        private readonly byte[] keyIdentifier;
-
-		public static SubjectKeyIdentifier GetInstance(
-            Asn1TaggedObject	obj,
-            bool				explicitly)
+		public static SubjectKeyIdentifier GetInstance(Asn1TaggedObject obj, bool explicitly)
         {
             return GetInstance(Asn1OctetString.GetInstance(obj, explicitly));
         }
 
-		public static SubjectKeyIdentifier GetInstance(
-            object obj)
+		public static SubjectKeyIdentifier GetInstance(object obj)
         {
             if (obj is SubjectKeyIdentifier)
-            {
-                return (SubjectKeyIdentifier) obj;
-            }
-
-			if (obj is SubjectPublicKeyInfo)
-            {
-                return new SubjectKeyIdentifier((SubjectPublicKeyInfo) obj);
-            }
-
-			if (obj is Asn1OctetString)
-            {
-                return new SubjectKeyIdentifier((Asn1OctetString) obj);
-            }
-
-			if (obj is X509Extension)
-			{
-				return GetInstance(X509Extension.ConvertValueToObject((X509Extension) obj));
-			}
-
-            throw new ArgumentException("Invalid SubjectKeyIdentifier: " + Platform.GetTypeName(obj));
+                return (SubjectKeyIdentifier)obj;
+            if (obj is SubjectPublicKeyInfo)
+                return new SubjectKeyIdentifier((SubjectPublicKeyInfo)obj);
+            if (obj is X509Extension)
+                return GetInstance(X509Extension.ConvertValueToObject((X509Extension)obj));
+            if (obj == null)
+                return null;
+            return new SubjectKeyIdentifier(Asn1OctetString.GetInstance(obj));
         }
 
-		public SubjectKeyIdentifier(
+        public static SubjectKeyIdentifier FromExtensions(X509Extensions extensions)
+        {
+            return GetInstance(X509Extensions.GetExtensionParsedValue(extensions, X509Extensions.SubjectKeyIdentifier));
+        }
+
+        private readonly byte[] keyIdentifier;
+
+        public SubjectKeyIdentifier(
             byte[] keyID)
         {
 			if (keyID == null)
 				throw new ArgumentNullException("keyID");
 
-			this.keyIdentifier = keyID;
+			this.keyIdentifier = Arrays.Clone(keyID);
         }
 
 		public SubjectKeyIdentifier(
             Asn1OctetString keyID)
+            : this(keyID.GetOctets())
         {
-            this.keyIdentifier = keyID.GetOctets();
         }
 
 		/**
@@ -79,12 +69,12 @@ namespace Org.BouncyCastle.Asn1.X509
 
 		public byte[] GetKeyIdentifier()
 		{
-			return keyIdentifier;
+            return Arrays.Clone(keyIdentifier);
 		}
 
-		public override Asn1Object ToAsn1Object()
+        public override Asn1Object ToAsn1Object()
 		{
-			return new DerOctetString(keyIdentifier);
+			return new DerOctetString(GetKeyIdentifier());
 		}
 
 		/**
diff --git a/crypto/src/asn1/x509/X509Extensions.cs b/crypto/src/asn1/x509/X509Extensions.cs
index d1b9fa39a..42121fa60 100644
--- a/crypto/src/asn1/x509/X509Extensions.cs
+++ b/crypto/src/asn1/x509/X509Extensions.cs
@@ -172,6 +172,16 @@ namespace Org.BouncyCastle.Asn1.X509
         private readonly IDictionary extensions = Platform.CreateHashtable();
         private readonly IList ordering;
 
+        public static X509Extension GetExtension(X509Extensions extensions, DerObjectIdentifier oid)
+        {
+            return null == extensions ? null : extensions.GetExtension(oid);
+        }
+
+        public static Asn1Encodable GetExtensionParsedValue(X509Extensions extensions, DerObjectIdentifier oid)
+        {
+            return null == extensions ? null : extensions.GetExtensionParsedValue(oid);
+        }
+
 		public static X509Extensions GetInstance(
             Asn1TaggedObject	obj,
             bool				explicitly)
@@ -368,7 +378,20 @@ namespace Org.BouncyCastle.Asn1.X509
         public X509Extension GetExtension(
             DerObjectIdentifier oid)
         {
-             return (X509Extension) extensions[oid];
+             return (X509Extension)extensions[oid];
+        }
+
+        /**
+         * return the parsed value of the extension represented by the object identifier
+         * passed in.
+         *
+         * @return the parsed value of the extension if it's present, null otherwise.
+         */
+        public Asn1Encodable GetExtensionParsedValue(DerObjectIdentifier oid)
+        {
+            X509Extension ext = GetExtension(oid);
+
+            return ext == null ? null : ext.GetParsedValue();
         }
 
 		/**
diff --git a/crypto/src/asn1/x9/X962Parameters.cs b/crypto/src/asn1/x9/X962Parameters.cs
index 04a5c9cbe..5bdabc647 100644
--- a/crypto/src/asn1/x9/X962Parameters.cs
+++ b/crypto/src/asn1/x9/X962Parameters.cs
@@ -49,7 +49,14 @@ namespace Org.BouncyCastle.Asn1.X9
             this._params = namedCurve;
         }
 
-		public X962Parameters(
+        public X962Parameters(
+            Asn1Null obj)
+        {
+            this._params = obj;
+        }
+
+        [Obsolete("Use 'GetInstance' instead")]
+        public X962Parameters(
             Asn1Object obj)
         {
             this._params = obj;
diff --git a/crypto/src/bcpg/ECPublicBCPGKey.cs b/crypto/src/bcpg/ECPublicBCPGKey.cs
index c473139e7..df19caac3 100644
--- a/crypto/src/bcpg/ECPublicBCPGKey.cs
+++ b/crypto/src/bcpg/ECPublicBCPGKey.cs
@@ -81,10 +81,10 @@ namespace Org.BouncyCastle.Bcpg
             BcpgInputStream bcpgIn)
         {
             int length = bcpgIn.ReadByte();
+            if (length < 0)
+                throw new EndOfStreamException();
             if (length == 0 || length == 0xFF)
-            {
-                throw new IOException("future extensions not yet implemented.");
-            }
+                throw new IOException("future extensions not yet implemented");
 
             byte[] buffer = new byte[length + 2];
             bcpgIn.ReadFully(buffer, 2, buffer.Length - 2);
diff --git a/crypto/src/bcpg/SignatureSubpacketsReader.cs b/crypto/src/bcpg/SignatureSubpacketsReader.cs
index 80bedb07c..45dc96885 100644
--- a/crypto/src/bcpg/SignatureSubpacketsReader.cs
+++ b/crypto/src/bcpg/SignatureSubpacketsReader.cs
@@ -52,6 +52,9 @@ namespace Org.BouncyCastle.Bcpg
 			if (tag < 0)
 				throw new EndOfStreamException("unexpected EOF reading signature sub packet");
 
+            if (bodyLen <= 0)
+                throw new EndOfStreamException("out of range data found in signature sub packet");
+
             byte[] data = new byte[bodyLen - 1];
 
             //
diff --git a/crypto/src/cms/CMSSignedData.cs b/crypto/src/cms/CMSSignedData.cs
index 979be6535..8634b2b3a 100644
--- a/crypto/src/cms/CMSSignedData.cs
+++ b/crypto/src/cms/CMSSignedData.cs
@@ -280,6 +280,16 @@ namespace Org.BouncyCastle.Cms
 			return contentInfo.GetEncoded();
 		}
 
+        /**
+         * return the ASN.1 encoded representation of this object using the specified encoding.
+         *
+         * @param encoding the ASN.1 encoding format to use ("BER" or "DER").
+         */
+        public byte[] GetEncoded(string encoding)
+        {
+            return contentInfo.GetEncoded(encoding);
+        }
+
 		/**
 		* Replace the signerinformation store associated with this
 		* CmsSignedData object with the new one passed in. You would
diff --git a/crypto/src/crypto.csproj b/crypto/src/crypto.csproj
index 43117bb4d..0fc60462d 100644
--- a/crypto/src/crypto.csproj
+++ b/crypto/src/crypto.csproj
@@ -6,7 +6,7 @@
     <AssemblyOriginatorKeyFile>..\..\BouncyCastle.snk</AssemblyOriginatorKeyFile>
     <SignAssembly>true</SignAssembly>
     <Product>Bouncy Castle for .NET ($(TargetFramework))</Product>
-    <Copyright>© 2000-2019 Legion of the Bouncy Castle Inc. </Copyright>
+    <Copyright>© 2000-2020 Legion of the Bouncy Castle Inc. </Copyright>
     <Company>The Legion of the Bouncy Castle Inc.</Company>
     <Authors>Oren Novotny</Authors>
     <Title>Bouncy Castle Portable</Title>
@@ -15,7 +15,7 @@
     <DebugType>embedded</DebugType>
     <PackageLicenseUrl>https://www.bouncycastle.org/csharp/licence.html</PackageLicenseUrl>
     <PackageProjectUrl>https://www.bouncycastle.org/csharp/</PackageProjectUrl>
-    <PackageReleaseNotes>https://www.bouncycastle.org/csharp/#RELEASENOTES185</PackageReleaseNotes>
+    <PackageReleaseNotes>https://www.bouncycastle.org/csharp/#RELEASENOTES186</PackageReleaseNotes>
     <RepositoryType>git</RepositoryType>
     <RepositoryUrl>https://github.com/onovotny/bc-csharp</RepositoryUrl>
     <PackageIconUrl>https://www.bouncycastle.org/images/csharp_logo.gif</PackageIconUrl>
@@ -36,7 +36,7 @@
   <ItemGroup>
     <Compile Include="..\bzip2\src\**\*.cs" LinkBase="bzip2" />
     <None Include="..\..\BouncyCastle.snk" />
-    <PackageReference Include="NerdBank.GitVersioning" Version="3.0.28" PrivateAssets="All" />
+    <PackageReference Include="NerdBank.GitVersioning" Version="3.0.50" PrivateAssets="All" />
     <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
   </ItemGroup>
   
diff --git a/crypto/src/crypto/encodings/Pkcs1Encoding.cs b/crypto/src/crypto/encodings/Pkcs1Encoding.cs
index b2d60fe4c..ce2f15a38 100644
--- a/crypto/src/crypto/encodings/Pkcs1Encoding.cs
+++ b/crypto/src/crypto/encodings/Pkcs1Encoding.cs
@@ -41,7 +41,7 @@ namespace Org.BouncyCastle.Crypto.Encodings
         {
             string strictProperty = Platform.GetEnvironmentVariable(StrictLengthEnabledProperty);
 
-            strictLengthEnabled = new bool[]{ strictProperty == null || strictProperty.Equals("true")};
+            strictLengthEnabled = new bool[]{ strictProperty == null || Platform.EqualsIgnoreCase("true", strictProperty) };
         }
 
 
diff --git a/crypto/src/crypto/parameters/Ed25519PrivateKeyParameters.cs b/crypto/src/crypto/parameters/Ed25519PrivateKeyParameters.cs
index 8046a0b1b..531bca0e9 100644
--- a/crypto/src/crypto/parameters/Ed25519PrivateKeyParameters.cs
+++ b/crypto/src/crypto/parameters/Ed25519PrivateKeyParameters.cs
@@ -16,6 +16,8 @@ namespace Org.BouncyCastle.Crypto.Parameters
 
         private readonly byte[] data = new byte[KeySize];
 
+        private Ed25519PublicKeyParameters cachedPublicKey;
+
         public Ed25519PrivateKeyParameters(SecureRandom random)
             : base(true)
         {
@@ -47,23 +49,33 @@ namespace Org.BouncyCastle.Crypto.Parameters
 
         public Ed25519PublicKeyParameters GeneratePublicKey()
         {
-            byte[] publicKey = new byte[Ed25519.PublicKeySize];
-            Ed25519.GeneratePublicKey(data, 0, publicKey, 0);
-            return new Ed25519PublicKeyParameters(publicKey, 0);
+            lock (data)
+            {
+                if (null == cachedPublicKey)
+                {
+                    byte[] publicKey = new byte[Ed25519.PublicKeySize];
+                    Ed25519.GeneratePublicKey(data, 0, publicKey, 0);
+                    cachedPublicKey = new Ed25519PublicKeyParameters(publicKey, 0);
+                }
+
+                return cachedPublicKey;
+            }
         }
 
+        [Obsolete("Use overload that doesn't take a public key")]
         public void Sign(Ed25519.Algorithm algorithm, Ed25519PublicKeyParameters publicKey, byte[] ctx, byte[] msg, int msgOff, int msgLen,
             byte[] sig, int sigOff)
         {
+            Sign(algorithm, ctx, msg, msgOff, msgLen, sig, sigOff);
+        }
+
+        public void Sign(Ed25519.Algorithm algorithm, byte[] ctx, byte[] msg, int msgOff, int msgLen,
+            byte[] sig, int sigOff)
+        {
+            Ed25519PublicKeyParameters publicKey = GeneratePublicKey();
+
             byte[] pk = new byte[Ed25519.PublicKeySize];
-            if (null == publicKey)
-            {
-                Ed25519.GeneratePublicKey(data, 0, pk, 0);
-            }
-            else
-            {
-                publicKey.Encode(pk, 0);
-            }
+            publicKey.Encode(pk, 0);
 
             switch (algorithm)
             {
diff --git a/crypto/src/crypto/parameters/Ed448PrivateKeyParameters.cs b/crypto/src/crypto/parameters/Ed448PrivateKeyParameters.cs
index f2fc4d533..1b38143fa 100644
--- a/crypto/src/crypto/parameters/Ed448PrivateKeyParameters.cs
+++ b/crypto/src/crypto/parameters/Ed448PrivateKeyParameters.cs
@@ -16,6 +16,8 @@ namespace Org.BouncyCastle.Crypto.Parameters
 
         private readonly byte[] data = new byte[KeySize];
 
+        private Ed448PublicKeyParameters cachedPublicKey;
+
         public Ed448PrivateKeyParameters(SecureRandom random)
             : base(true)
         {
@@ -47,23 +49,33 @@ namespace Org.BouncyCastle.Crypto.Parameters
 
         public Ed448PublicKeyParameters GeneratePublicKey()
         {
-            byte[] publicKey = new byte[Ed448.PublicKeySize];
-            Ed448.GeneratePublicKey(data, 0, publicKey, 0);
-            return new Ed448PublicKeyParameters(publicKey, 0);
+            lock (data)
+            {
+                if (null == cachedPublicKey)
+                {
+                    byte[] publicKey = new byte[Ed448.PublicKeySize];
+                    Ed448.GeneratePublicKey(data, 0, publicKey, 0);
+                    cachedPublicKey = new Ed448PublicKeyParameters(publicKey, 0);
+                }
+
+                return cachedPublicKey;
+            }
         }
 
+        [Obsolete("Use overload that doesn't take a public key")]
         public void Sign(Ed448.Algorithm algorithm, Ed448PublicKeyParameters publicKey, byte[] ctx, byte[] msg, int msgOff, int msgLen,
             byte[] sig, int sigOff)
         {
+            Sign(algorithm, ctx, msg, msgOff, msgLen, sig, sigOff);
+        }
+
+        public void Sign(Ed448.Algorithm algorithm, byte[] ctx, byte[] msg, int msgOff, int msgLen,
+            byte[] sig, int sigOff)
+        {
+            Ed448PublicKeyParameters publicKey = GeneratePublicKey();
+
             byte[] pk = new byte[Ed448.PublicKeySize];
-            if (null == publicKey)
-            {
-                Ed448.GeneratePublicKey(data, 0, pk, 0);
-            }
-            else
-            {
-                publicKey.Encode(pk, 0);
-            }
+            publicKey.Encode(pk, 0);
 
             switch (algorithm)
             {
diff --git a/crypto/src/crypto/signers/Ed25519Signer.cs b/crypto/src/crypto/signers/Ed25519Signer.cs
index a916601e6..e58d14ea4 100644
--- a/crypto/src/crypto/signers/Ed25519Signer.cs
+++ b/crypto/src/crypto/signers/Ed25519Signer.cs
@@ -32,10 +32,8 @@ namespace Org.BouncyCastle.Crypto.Signers
 
             if (forSigning)
             {
-                // TODO Allow IAsymmetricCipherKeyPair to be an ICipherParameters?
-
                 this.privateKey = (Ed25519PrivateKeyParameters)parameters;
-                this.publicKey = privateKey.GeneratePublicKey();
+                this.publicKey = null;
             }
             else
             {
@@ -61,7 +59,7 @@ namespace Org.BouncyCastle.Crypto.Signers
             if (!forSigning || null == privateKey)
                 throw new InvalidOperationException("Ed25519Signer not initialised for signature generation.");
 
-            return buffer.GenerateSignature(privateKey, publicKey);
+            return buffer.GenerateSignature(privateKey);
         }
 
         public virtual bool VerifySignature(byte[] signature)
@@ -79,7 +77,7 @@ namespace Org.BouncyCastle.Crypto.Signers
 
         private class Buffer : MemoryStream
         {
-            internal byte[] GenerateSignature(Ed25519PrivateKeyParameters privateKey, Ed25519PublicKeyParameters publicKey)
+            internal byte[] GenerateSignature(Ed25519PrivateKeyParameters privateKey)
             {
                 lock (this)
                 {
@@ -91,7 +89,7 @@ namespace Org.BouncyCastle.Crypto.Signers
                     int count = (int)Position;
 #endif
                     byte[] signature = new byte[Ed25519PrivateKeyParameters.SignatureSize];
-                    privateKey.Sign(Ed25519.Algorithm.Ed25519, publicKey, null, buf, 0, count, signature, 0);
+                    privateKey.Sign(Ed25519.Algorithm.Ed25519, null, buf, 0, count, signature, 0);
                     Reset();
                     return signature;
                 }
diff --git a/crypto/src/crypto/signers/Ed25519ctxSigner.cs b/crypto/src/crypto/signers/Ed25519ctxSigner.cs
index ab7201b62..2b5296e96 100644
--- a/crypto/src/crypto/signers/Ed25519ctxSigner.cs
+++ b/crypto/src/crypto/signers/Ed25519ctxSigner.cs
@@ -34,10 +34,8 @@ namespace Org.BouncyCastle.Crypto.Signers
 
             if (forSigning)
             {
-                // TODO Allow IAsymmetricCipherKeyPair to be an ICipherParameters?
-
                 this.privateKey = (Ed25519PrivateKeyParameters)parameters;
-                this.publicKey = privateKey.GeneratePublicKey();
+                this.publicKey = null;
             }
             else
             {
@@ -63,7 +61,7 @@ namespace Org.BouncyCastle.Crypto.Signers
             if (!forSigning || null == privateKey)
                 throw new InvalidOperationException("Ed25519ctxSigner not initialised for signature generation.");
 
-            return buffer.GenerateSignature(privateKey, publicKey, context);
+            return buffer.GenerateSignature(privateKey, context);
         }
 
         public virtual bool VerifySignature(byte[] signature)
@@ -81,7 +79,7 @@ namespace Org.BouncyCastle.Crypto.Signers
 
         private class Buffer : MemoryStream
         {
-            internal byte[] GenerateSignature(Ed25519PrivateKeyParameters privateKey, Ed25519PublicKeyParameters publicKey, byte[] ctx)
+            internal byte[] GenerateSignature(Ed25519PrivateKeyParameters privateKey, byte[] ctx)
             {
                 lock (this)
                 {
@@ -93,7 +91,7 @@ namespace Org.BouncyCastle.Crypto.Signers
                     int count = (int)Position;
 #endif
                     byte[] signature = new byte[Ed25519PrivateKeyParameters.SignatureSize];
-                    privateKey.Sign(Ed25519.Algorithm.Ed25519ctx, publicKey, ctx, buf, 0, count, signature, 0);
+                    privateKey.Sign(Ed25519.Algorithm.Ed25519ctx, ctx, buf, 0, count, signature, 0);
                     Reset();
                     return signature;
                 }
diff --git a/crypto/src/crypto/signers/Ed25519phSigner.cs b/crypto/src/crypto/signers/Ed25519phSigner.cs
index 2538b16f5..cb3c3080a 100644
--- a/crypto/src/crypto/signers/Ed25519phSigner.cs
+++ b/crypto/src/crypto/signers/Ed25519phSigner.cs
@@ -33,10 +33,8 @@ namespace Org.BouncyCastle.Crypto.Signers
 
             if (forSigning)
             {
-                // TODO Allow AsymmetricCipherKeyPair to be a CipherParameters?
-
                 this.privateKey = (Ed25519PrivateKeyParameters)parameters;
-                this.publicKey = privateKey.GeneratePublicKey();
+                this.publicKey = null;
             }
             else
             {
@@ -67,7 +65,7 @@ namespace Org.BouncyCastle.Crypto.Signers
                 throw new InvalidOperationException("Prehash digest failed");
 
             byte[] signature = new byte[Ed25519PrivateKeyParameters.SignatureSize];
-            privateKey.Sign(Ed25519.Algorithm.Ed25519ph, publicKey, context, msg, 0, Ed25519.PrehashSize, signature, 0);
+            privateKey.Sign(Ed25519.Algorithm.Ed25519ph, context, msg, 0, Ed25519.PrehashSize, signature, 0);
             return signature;
         }
 
diff --git a/crypto/src/crypto/signers/Ed448Signer.cs b/crypto/src/crypto/signers/Ed448Signer.cs
index b0563d544..9d1495f2e 100644
--- a/crypto/src/crypto/signers/Ed448Signer.cs
+++ b/crypto/src/crypto/signers/Ed448Signer.cs
@@ -34,10 +34,8 @@ namespace Org.BouncyCastle.Crypto.Signers
 
             if (forSigning)
             {
-                // TODO Allow IAsymmetricCipherKeyPair to be an ICipherParameters?
-
                 this.privateKey = (Ed448PrivateKeyParameters)parameters;
-                this.publicKey = privateKey.GeneratePublicKey();
+                this.publicKey = null;
             }
             else
             {
@@ -63,7 +61,7 @@ namespace Org.BouncyCastle.Crypto.Signers
             if (!forSigning || null == privateKey)
                 throw new InvalidOperationException("Ed448Signer not initialised for signature generation.");
 
-            return buffer.GenerateSignature(privateKey, publicKey, context);
+            return buffer.GenerateSignature(privateKey, context);
         }
 
         public virtual bool VerifySignature(byte[] signature)
@@ -81,7 +79,7 @@ namespace Org.BouncyCastle.Crypto.Signers
 
         private class Buffer : MemoryStream
         {
-            internal byte[] GenerateSignature(Ed448PrivateKeyParameters privateKey, Ed448PublicKeyParameters publicKey, byte[] ctx)
+            internal byte[] GenerateSignature(Ed448PrivateKeyParameters privateKey, byte[] ctx)
             {
                 lock (this)
                 {
@@ -93,7 +91,7 @@ namespace Org.BouncyCastle.Crypto.Signers
                     int count = (int)Position;
 #endif
                     byte[] signature = new byte[Ed448PrivateKeyParameters.SignatureSize];
-                    privateKey.Sign(Ed448.Algorithm.Ed448, publicKey, ctx, buf, 0, count, signature, 0);
+                    privateKey.Sign(Ed448.Algorithm.Ed448, ctx, buf, 0, count, signature, 0);
                     Reset();
                     return signature;
                 }
diff --git a/crypto/src/crypto/signers/Ed448phSigner.cs b/crypto/src/crypto/signers/Ed448phSigner.cs
index d656c1392..f01b6bfd4 100644
--- a/crypto/src/crypto/signers/Ed448phSigner.cs
+++ b/crypto/src/crypto/signers/Ed448phSigner.cs
@@ -33,10 +33,8 @@ namespace Org.BouncyCastle.Crypto.Signers
 
             if (forSigning)
             {
-                // TODO Allow AsymmetricCipherKeyPair to be a CipherParameters?
-
                 this.privateKey = (Ed448PrivateKeyParameters)parameters;
-                this.publicKey = privateKey.GeneratePublicKey();
+                this.publicKey = null;
             }
             else
             {
@@ -67,7 +65,7 @@ namespace Org.BouncyCastle.Crypto.Signers
                 throw new InvalidOperationException("Prehash digest failed");
 
             byte[] signature = new byte[Ed448PrivateKeyParameters.SignatureSize];
-            privateKey.Sign(Ed448.Algorithm.Ed448ph, publicKey, context, msg, 0, Ed448.PrehashSize, signature, 0);
+            privateKey.Sign(Ed448.Algorithm.Ed448ph, context, msg, 0, Ed448.PrehashSize, signature, 0);
             return signature;
         }
 
diff --git a/crypto/src/crypto/tls/CipherSuite.cs b/crypto/src/crypto/tls/CipherSuite.cs
index 679a8be85..5aa556389 100644
--- a/crypto/src/crypto/tls/CipherSuite.cs
+++ b/crypto/src/crypto/tls/CipherSuite.cs
@@ -346,22 +346,6 @@ namespace Org.BouncyCastle.Crypto.Tls
         public const int DRAFT_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 = 0xCCAD;
         public const int DRAFT_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 = 0xCCAE;
 
-        /*
-         * draft-zauner-tls-aes-ocb-04 (code points TBD)
-         */
-        public const int DRAFT_TLS_DHE_RSA_WITH_AES_128_OCB = 0xFF00;
-        public const int DRAFT_TLS_DHE_RSA_WITH_AES_256_OCB = 0xFF01;
-        public const int DRAFT_TLS_ECDHE_RSA_WITH_AES_128_OCB = 0xFF02;
-        public const int DRAFT_TLS_ECDHE_RSA_WITH_AES_256_OCB = 0xFF03;
-        public const int DRAFT_TLS_ECDHE_ECDSA_WITH_AES_128_OCB = 0xFF04;
-        public const int DRAFT_TLS_ECDHE_ECDSA_WITH_AES_256_OCB = 0xFF05;
-        public const int DRAFT_TLS_PSK_WITH_AES_128_OCB = 0xFF10;
-        public const int DRAFT_TLS_PSK_WITH_AES_256_OCB = 0xFF11;
-        public const int DRAFT_TLS_DHE_PSK_WITH_AES_128_OCB = 0xFF12;
-        public const int DRAFT_TLS_DHE_PSK_WITH_AES_256_OCB = 0xFF13;
-        public const int DRAFT_TLS_ECDHE_PSK_WITH_AES_128_OCB = 0xFF14;
-        public const int DRAFT_TLS_ECDHE_PSK_WITH_AES_256_OCB = 0xFF15;
-
         public static bool IsScsv(int cipherSuite)
         {
             switch (cipherSuite)
diff --git a/crypto/src/crypto/tls/TlsAeadCipher.cs b/crypto/src/crypto/tls/TlsAeadCipher.cs
index cc0575cf0..9a65d5ee5 100644
--- a/crypto/src/crypto/tls/TlsAeadCipher.cs
+++ b/crypto/src/crypto/tls/TlsAeadCipher.cs
@@ -105,7 +105,10 @@ namespace Org.BouncyCastle.Crypto.Tls
                 decryptKey = server_write_key;
             }
 
+            // NOTE: Ensure dummy nonce is not part of the generated sequence(s)
             byte[] dummyNonce = new byte[fixed_iv_length + record_iv_length];
+            dummyNonce[0] = (byte)~encryptImplicitNonce[0];
+            dummyNonce[1] = (byte)~decryptImplicitNonce[1];
 
             this.encryptCipher.Init(true, new AeadParameters(encryptKey, 8 * macSize, dummyNonce));
             this.decryptCipher.Init(false, new AeadParameters(decryptKey, 8 * macSize, dummyNonce));
diff --git a/crypto/src/crypto/tls/TlsDHUtilities.cs b/crypto/src/crypto/tls/TlsDHUtilities.cs
index 59006018e..fb521336e 100644
--- a/crypto/src/crypto/tls/TlsDHUtilities.cs
+++ b/crypto/src/crypto/tls/TlsDHUtilities.cs
@@ -359,14 +359,6 @@ namespace Org.BouncyCastle.Crypto.Tls
             case CipherSuite.DRAFT_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
 
             /*
-             * draft-zauner-tls-aes-ocb-04
-             */
-            case CipherSuite.DRAFT_TLS_DHE_RSA_WITH_AES_128_OCB:
-            case CipherSuite.DRAFT_TLS_DHE_RSA_WITH_AES_256_OCB:
-            case CipherSuite.DRAFT_TLS_DHE_PSK_WITH_AES_128_OCB:
-            case CipherSuite.DRAFT_TLS_DHE_PSK_WITH_AES_256_OCB:
-
-            /*
              * DH_anon cipher suites are consider ephemeral DH 
              */
             case CipherSuite.TLS_DH_anon_WITH_3DES_EDE_CBC_SHA:
diff --git a/crypto/src/crypto/tls/TlsEccUtilities.cs b/crypto/src/crypto/tls/TlsEccUtilities.cs
index 7b7e89f84..5ef72a74e 100644
--- a/crypto/src/crypto/tls/TlsEccUtilities.cs
+++ b/crypto/src/crypto/tls/TlsEccUtilities.cs
@@ -247,16 +247,6 @@ namespace Org.BouncyCastle.Crypto.Tls
             case CipherSuite.DRAFT_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256:
             case CipherSuite.DRAFT_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
 
-            /*
-             * draft-zauner-tls-aes-ocb-04
-             */
-            case CipherSuite.DRAFT_TLS_ECDHE_RSA_WITH_AES_128_OCB:
-            case CipherSuite.DRAFT_TLS_ECDHE_RSA_WITH_AES_256_OCB:
-            case CipherSuite.DRAFT_TLS_ECDHE_ECDSA_WITH_AES_128_OCB:
-            case CipherSuite.DRAFT_TLS_ECDHE_ECDSA_WITH_AES_256_OCB:
-            case CipherSuite.DRAFT_TLS_ECDHE_PSK_WITH_AES_128_OCB:
-            case CipherSuite.DRAFT_TLS_ECDHE_PSK_WITH_AES_256_OCB:
-
                 return true;
 
             default:
diff --git a/crypto/src/crypto/tls/TlsProtocol.cs b/crypto/src/crypto/tls/TlsProtocol.cs
index cc6ae0259..9e5d5c12e 100644
--- a/crypto/src/crypto/tls/TlsProtocol.cs
+++ b/crypto/src/crypto/tls/TlsProtocol.cs
@@ -1263,24 +1263,19 @@ namespace Org.BouncyCastle.Crypto.Tls
             case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256:
             case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM:
             case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.DRAFT_TLS_DHE_PSK_WITH_AES_128_OCB:
             case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM:
-            case CipherSuite.DRAFT_TLS_DHE_PSK_WITH_AES_256_OCB:
             case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256:
             case CipherSuite.DRAFT_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256:
             case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
             case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM:
             case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8:
             case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.DRAFT_TLS_DHE_RSA_WITH_AES_128_OCB:
             case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
             case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM:
             case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8:
-            case CipherSuite.DRAFT_TLS_DHE_RSA_WITH_AES_256_OCB:
             case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
             case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
             case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256:
-            case CipherSuite.DRAFT_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
             case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
             case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
             case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
@@ -1293,20 +1288,14 @@ namespace Org.BouncyCastle.Crypto.Tls
             case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM:
             case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
             case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.DRAFT_TLS_ECDHE_ECDSA_WITH_AES_128_OCB:
             case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM:
             case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8:
-            case CipherSuite.DRAFT_TLS_ECDHE_ECDSA_WITH_AES_256_OCB:
             case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
             case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
             case CipherSuite.DRAFT_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
-            case CipherSuite.DRAFT_TLS_ECDHE_PSK_WITH_AES_128_OCB:
-            case CipherSuite.DRAFT_TLS_ECDHE_PSK_WITH_AES_256_OCB:
             case CipherSuite.DRAFT_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256:
             case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
             case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.DRAFT_TLS_ECDHE_RSA_WITH_AES_128_OCB:
-            case CipherSuite.DRAFT_TLS_ECDHE_RSA_WITH_AES_256_OCB:
             case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
             case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
             case CipherSuite.DRAFT_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
@@ -1315,10 +1304,8 @@ namespace Org.BouncyCastle.Crypto.Tls
             case CipherSuite.TLS_PSK_WITH_AES_128_CCM:
             case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8:
             case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.DRAFT_TLS_PSK_WITH_AES_128_OCB:
             case CipherSuite.TLS_PSK_WITH_AES_256_CCM:
             case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8:
-            case CipherSuite.DRAFT_TLS_PSK_WITH_AES_256_OCB:
             case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256:
             case CipherSuite.DRAFT_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256:
             case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256:
diff --git a/crypto/src/crypto/tls/TlsServerProtocol.cs b/crypto/src/crypto/tls/TlsServerProtocol.cs
index 1ba90cfdc..85b450c9e 100644
--- a/crypto/src/crypto/tls/TlsServerProtocol.cs
+++ b/crypto/src/crypto/tls/TlsServerProtocol.cs
@@ -390,37 +390,31 @@ namespace Org.BouncyCastle.Crypto.Tls
 
         protected override void HandleAlertWarningMessage(byte alertDescription)
         {
-            base.HandleAlertWarningMessage(alertDescription);
-
-            switch (alertDescription)
-            {
-            case AlertDescription.no_certificate:
+            /*
+             * SSL 3.0 If the server has sent a certificate request Message, the client must send
+             * either the certificate message or a no_certificate alert.
+             */
+            if (AlertDescription.no_certificate == alertDescription && null != mCertificateRequest
+                && TlsUtilities.IsSsl(mTlsServerContext))
             {
-                /*
-                 * SSL 3.0 If the server has sent a certificate request Message, the client must send
-                 * either the certificate message or a no_certificate alert.
-                 */
-                if (TlsUtilities.IsSsl(Context) && this.mCertificateRequest != null)
+                switch (mConnectionState)
                 {
-                    switch (this.mConnectionState)
-                    {
-                    case CS_SERVER_HELLO_DONE:
-                    case CS_CLIENT_SUPPLEMENTAL_DATA:
+                case CS_SERVER_HELLO_DONE:
+                case CS_CLIENT_SUPPLEMENTAL_DATA:
+                {
+                    if (mConnectionState < CS_CLIENT_SUPPLEMENTAL_DATA)
                     {
-                        if (mConnectionState < CS_CLIENT_SUPPLEMENTAL_DATA)
-                        {
-                            mTlsServer.ProcessClientSupplementalData(null);
-                        }
-
-                        NotifyClientCertificate(Certificate.EmptyChain);
-                        this.mConnectionState = CS_CLIENT_CERTIFICATE;
-                        return;
-                    }
+                        mTlsServer.ProcessClientSupplementalData(null);
                     }
+
+                    NotifyClientCertificate(Certificate.EmptyChain);
+                    this.mConnectionState = CS_CLIENT_CERTIFICATE;
+                    return;
+                }
                 }
-                throw new TlsFatalAlert(AlertDescription.unexpected_message);
             }
-            } 
+
+            base.HandleAlertWarningMessage(alertDescription);
         }
 
         protected virtual void NotifyClientCertificate(Certificate clientCertificate)
diff --git a/crypto/src/crypto/tls/TlsUtilities.cs b/crypto/src/crypto/tls/TlsUtilities.cs
index 9f4aac651..6ee71021f 100644
--- a/crypto/src/crypto/tls/TlsUtilities.cs
+++ b/crypto/src/crypto/tls/TlsUtilities.cs
@@ -1391,14 +1391,6 @@ namespace Org.BouncyCastle.Crypto.Tls
             case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256:
                 return EncryptionAlgorithm.AES_128_GCM;
 
-            case CipherSuite.DRAFT_TLS_DHE_PSK_WITH_AES_128_OCB:
-            case CipherSuite.DRAFT_TLS_DHE_RSA_WITH_AES_128_OCB:
-            case CipherSuite.DRAFT_TLS_ECDHE_ECDSA_WITH_AES_128_OCB:
-            case CipherSuite.DRAFT_TLS_ECDHE_PSK_WITH_AES_128_OCB:
-            case CipherSuite.DRAFT_TLS_ECDHE_RSA_WITH_AES_128_OCB:
-            case CipherSuite.DRAFT_TLS_PSK_WITH_AES_128_OCB:
-                return EncryptionAlgorithm.AES_128_OCB_TAGLEN96;
-
             case CipherSuite.TLS_DH_anon_WITH_AES_256_CBC_SHA:
             case CipherSuite.TLS_DH_anon_WITH_AES_256_CBC_SHA256:
             case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA:
@@ -1462,14 +1454,6 @@ namespace Org.BouncyCastle.Crypto.Tls
             case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384:
                 return EncryptionAlgorithm.AES_256_GCM;
 
-            case CipherSuite.DRAFT_TLS_DHE_PSK_WITH_AES_256_OCB:
-            case CipherSuite.DRAFT_TLS_DHE_RSA_WITH_AES_256_OCB:
-            case CipherSuite.DRAFT_TLS_ECDHE_ECDSA_WITH_AES_256_OCB:
-            case CipherSuite.DRAFT_TLS_ECDHE_PSK_WITH_AES_256_OCB:
-            case CipherSuite.DRAFT_TLS_ECDHE_RSA_WITH_AES_256_OCB:
-            case CipherSuite.DRAFT_TLS_PSK_WITH_AES_256_OCB:
-                return EncryptionAlgorithm.AES_256_OCB_TAGLEN96;
-
             case CipherSuite.TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA:
             case CipherSuite.TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256:
             case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA:
@@ -1684,12 +1668,10 @@ namespace Org.BouncyCastle.Crypto.Tls
             case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256:
             case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM:
             case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.DRAFT_TLS_DHE_PSK_WITH_AES_128_OCB:
             case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA:
             case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384:
             case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM:
             case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.DRAFT_TLS_DHE_PSK_WITH_AES_256_OCB:
             case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256:
             case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256:
             case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
@@ -1709,13 +1691,11 @@ namespace Org.BouncyCastle.Crypto.Tls
             case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM:
             case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8:
             case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.DRAFT_TLS_DHE_RSA_WITH_AES_128_OCB:
             case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
             case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
             case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM:
             case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8:
             case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.DRAFT_TLS_DHE_RSA_WITH_AES_256_OCB:
             case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA:
             case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
             case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
@@ -1737,11 +1717,9 @@ namespace Org.BouncyCastle.Crypto.Tls
             case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
             case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
             case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.DRAFT_TLS_ECDHE_ECDSA_WITH_AES_128_OCB:
             case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
             case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:
             case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.DRAFT_TLS_ECDHE_ECDSA_WITH_AES_256_OCB:
             case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
             case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
             case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
@@ -1788,10 +1766,8 @@ namespace Org.BouncyCastle.Crypto.Tls
             case CipherSuite.TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA:
             case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA:
             case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256:
-            case CipherSuite.DRAFT_TLS_ECDHE_PSK_WITH_AES_128_OCB:
             case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA:
             case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384:
-            case CipherSuite.DRAFT_TLS_ECDHE_PSK_WITH_AES_256_OCB:
             case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256:
             case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
             case CipherSuite.DRAFT_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256:
@@ -1805,11 +1781,9 @@ namespace Org.BouncyCastle.Crypto.Tls
             case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
             case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
             case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.DRAFT_TLS_ECDHE_RSA_WITH_AES_128_OCB:
             case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
             case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
             case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.DRAFT_TLS_ECDHE_RSA_WITH_AES_256_OCB:
             case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
             case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
             case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384:
@@ -1825,13 +1799,11 @@ namespace Org.BouncyCastle.Crypto.Tls
             case CipherSuite.TLS_PSK_WITH_AES_128_CCM:
             case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8:
             case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.DRAFT_TLS_PSK_WITH_AES_128_OCB:
             case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA:
             case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA384:
             case CipherSuite.TLS_PSK_WITH_AES_256_CCM:
             case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8:
             case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.DRAFT_TLS_PSK_WITH_AES_256_OCB:
             case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256:
             case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256:
             case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384:
@@ -1928,21 +1900,17 @@ namespace Org.BouncyCastle.Crypto.Tls
             case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384:
             case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM:
             case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.DRAFT_TLS_DHE_PSK_WITH_AES_128_OCB:
             case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM:
             case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.DRAFT_TLS_DHE_PSK_WITH_AES_256_OCB:
             case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256:
             case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384:
             case CipherSuite.DRAFT_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256:
             case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM:
             case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8:
             case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.DRAFT_TLS_DHE_RSA_WITH_AES_128_OCB:
             case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM:
             case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8:
             case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.DRAFT_TLS_DHE_RSA_WITH_AES_256_OCB:
             case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
             case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
             case CipherSuite.DRAFT_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
@@ -1957,21 +1925,15 @@ namespace Org.BouncyCastle.Crypto.Tls
             case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM:
             case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
             case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.DRAFT_TLS_ECDHE_ECDSA_WITH_AES_128_OCB:
             case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM:
             case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8:
             case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.DRAFT_TLS_ECDHE_ECDSA_WITH_AES_256_OCB:
             case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
             case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
             case CipherSuite.DRAFT_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
-            case CipherSuite.DRAFT_TLS_ECDHE_PSK_WITH_AES_128_OCB:
-            case CipherSuite.DRAFT_TLS_ECDHE_PSK_WITH_AES_256_OCB:
             case CipherSuite.DRAFT_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256:
             case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.DRAFT_TLS_ECDHE_RSA_WITH_AES_128_OCB:
             case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.DRAFT_TLS_ECDHE_RSA_WITH_AES_256_OCB:
             case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
             case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
             case CipherSuite.DRAFT_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
@@ -1980,11 +1942,9 @@ namespace Org.BouncyCastle.Crypto.Tls
             case CipherSuite.TLS_PSK_WITH_AES_128_CCM:
             case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8:
             case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.DRAFT_TLS_PSK_WITH_AES_128_OCB:
             case CipherSuite.TLS_PSK_WITH_AES_256_CCM:
             case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8:
             case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.DRAFT_TLS_PSK_WITH_AES_256_OCB:
             case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256:
             case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384:
             case CipherSuite.DRAFT_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256:
@@ -2214,10 +2174,8 @@ namespace Org.BouncyCastle.Crypto.Tls
             case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384:
             case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM:
             case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.DRAFT_TLS_DHE_PSK_WITH_AES_128_OCB:
             case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM:
             case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.DRAFT_TLS_DHE_PSK_WITH_AES_256_OCB:
             case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256:
             case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384:
             case CipherSuite.DRAFT_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256:
@@ -2225,12 +2183,10 @@ namespace Org.BouncyCastle.Crypto.Tls
             case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM:
             case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8:
             case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.DRAFT_TLS_DHE_RSA_WITH_AES_128_OCB:
             case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
             case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM:
             case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8:
             case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.DRAFT_TLS_DHE_RSA_WITH_AES_256_OCB:
             case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
             case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
             case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256:
@@ -2256,26 +2212,20 @@ namespace Org.BouncyCastle.Crypto.Tls
             case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM:
             case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
             case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.DRAFT_TLS_ECDHE_ECDSA_WITH_AES_128_OCB:
             case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:
             case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM:
             case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8:
             case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.DRAFT_TLS_ECDHE_ECDSA_WITH_AES_256_OCB:
             case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
             case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
             case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
             case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
             case CipherSuite.DRAFT_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
-            case CipherSuite.DRAFT_TLS_ECDHE_PSK_WITH_AES_128_OCB:
-            case CipherSuite.DRAFT_TLS_ECDHE_PSK_WITH_AES_256_OCB:
             case CipherSuite.DRAFT_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256:
             case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
             case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.DRAFT_TLS_ECDHE_RSA_WITH_AES_128_OCB:
             case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
             case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.DRAFT_TLS_ECDHE_RSA_WITH_AES_256_OCB:
             case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
             case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
             case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384:
@@ -2286,11 +2236,9 @@ namespace Org.BouncyCastle.Crypto.Tls
             case CipherSuite.TLS_PSK_WITH_AES_128_CCM:
             case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8:
             case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256:
-            case CipherSuite.DRAFT_TLS_PSK_WITH_AES_128_OCB:
             case CipherSuite.TLS_PSK_WITH_AES_256_CCM:
             case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8:
             case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384:
-            case CipherSuite.DRAFT_TLS_PSK_WITH_AES_256_OCB:
             case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256:
             case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384:
             case CipherSuite.DRAFT_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256:
diff --git a/crypto/src/math/ec/ECAlgorithms.cs b/crypto/src/math/ec/ECAlgorithms.cs
index 4976b73b0..64e68fccc 100644
--- a/crypto/src/math/ec/ECAlgorithms.cs
+++ b/crypto/src/math/ec/ECAlgorithms.cs
@@ -168,8 +168,9 @@ namespace Org.BouncyCastle.Math.EC
         }
 
         /**
-         * Simple shift-and-add multiplication. Serves as reference implementation
-         * to verify (possibly faster) implementations, and for very small scalars.
+         * Simple shift-and-add multiplication. Serves as reference implementation to verify (possibly
+         * faster) implementations, and for very small scalars. CAUTION: This implementation is NOT
+         * constant-time in any way. It is only intended to be used for diagnostics.
          * 
          * @param p
          *            The point to multiply.
diff --git a/crypto/src/math/ec/multiplier/DoubleAddMultiplier.cs b/crypto/src/math/ec/multiplier/DoubleAddMultiplier.cs
index 18a72c0a2..6648727f9 100644
--- a/crypto/src/math/ec/multiplier/DoubleAddMultiplier.cs
+++ b/crypto/src/math/ec/multiplier/DoubleAddMultiplier.cs
@@ -1,5 +1,8 @@
-namespace Org.BouncyCastle.Math.EC.Multiplier
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Multiplier
 {
+    [Obsolete("Will be removed")]
     public class DoubleAddMultiplier
         : AbstractECMultiplier
     {
diff --git a/crypto/src/math/ec/multiplier/MixedNafR2LMultiplier.cs b/crypto/src/math/ec/multiplier/MixedNafR2LMultiplier.cs
index a4c201832..2bed8920c 100644
--- a/crypto/src/math/ec/multiplier/MixedNafR2LMultiplier.cs
+++ b/crypto/src/math/ec/multiplier/MixedNafR2LMultiplier.cs
@@ -6,6 +6,7 @@ namespace Org.BouncyCastle.Math.EC.Multiplier
      * Class implementing the NAF (Non-Adjacent Form) multiplication algorithm (right-to-left) using
      * mixed coordinates.
      */
+    [Obsolete("Will be removed")]
     public class MixedNafR2LMultiplier 
         : AbstractECMultiplier
     {
diff --git a/crypto/src/math/ec/multiplier/MontgomeryLadderMultiplier.cs b/crypto/src/math/ec/multiplier/MontgomeryLadderMultiplier.cs
index e2470a383..45df2fdae 100644
--- a/crypto/src/math/ec/multiplier/MontgomeryLadderMultiplier.cs
+++ b/crypto/src/math/ec/multiplier/MontgomeryLadderMultiplier.cs
@@ -1,5 +1,8 @@
-namespace Org.BouncyCastle.Math.EC.Multiplier
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Multiplier
 {
+    [Obsolete("Will be removed")]
     public class MontgomeryLadderMultiplier 
         : AbstractECMultiplier
     {
diff --git a/crypto/src/math/ec/multiplier/NafL2RMultiplier.cs b/crypto/src/math/ec/multiplier/NafL2RMultiplier.cs
index ac80cf905..d41a0d651 100644
--- a/crypto/src/math/ec/multiplier/NafL2RMultiplier.cs
+++ b/crypto/src/math/ec/multiplier/NafL2RMultiplier.cs
@@ -1,8 +1,11 @@
+using System;
+
 namespace Org.BouncyCastle.Math.EC.Multiplier
 {
     /**
      * Class implementing the NAF (Non-Adjacent Form) multiplication algorithm (left-to-right).
      */
+    [Obsolete("Will be removed")]
     public class NafL2RMultiplier
         : AbstractECMultiplier
     {
diff --git a/crypto/src/math/ec/multiplier/NafR2LMultiplier.cs b/crypto/src/math/ec/multiplier/NafR2LMultiplier.cs
index 1fa69fae8..8157cf05e 100644
--- a/crypto/src/math/ec/multiplier/NafR2LMultiplier.cs
+++ b/crypto/src/math/ec/multiplier/NafR2LMultiplier.cs
@@ -1,8 +1,11 @@
-namespace Org.BouncyCastle.Math.EC.Multiplier
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Multiplier
 {
     /**
      * Class implementing the NAF (Non-Adjacent Form) multiplication algorithm (right-to-left).
      */
+    [Obsolete("Will be removed")]
     public class NafR2LMultiplier 
         : AbstractECMultiplier
     {
diff --git a/crypto/src/math/ec/multiplier/ReferenceMultiplier.cs b/crypto/src/math/ec/multiplier/ReferenceMultiplier.cs
index 4848ada39..40563cdc7 100644
--- a/crypto/src/math/ec/multiplier/ReferenceMultiplier.cs
+++ b/crypto/src/math/ec/multiplier/ReferenceMultiplier.cs
@@ -1,5 +1,8 @@
+using System;
+
 namespace Org.BouncyCastle.Math.EC.Multiplier
 {
+    [Obsolete("Will be removed")]
     public class ReferenceMultiplier
         : AbstractECMultiplier
     {
diff --git a/crypto/src/math/ec/multiplier/ZSignedDigitL2RMultiplier.cs b/crypto/src/math/ec/multiplier/ZSignedDigitL2RMultiplier.cs
index 554ac61b3..1c7a5d104 100644
--- a/crypto/src/math/ec/multiplier/ZSignedDigitL2RMultiplier.cs
+++ b/crypto/src/math/ec/multiplier/ZSignedDigitL2RMultiplier.cs
@@ -1,5 +1,8 @@
-namespace Org.BouncyCastle.Math.EC.Multiplier
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Multiplier
 {
+    [Obsolete("Will be removed")]
     public class ZSignedDigitL2RMultiplier 
         : AbstractECMultiplier
     {
diff --git a/crypto/src/math/ec/multiplier/ZSignedDigitR2LMultiplier.cs b/crypto/src/math/ec/multiplier/ZSignedDigitR2LMultiplier.cs
index 91c06cbb8..46d234c37 100644
--- a/crypto/src/math/ec/multiplier/ZSignedDigitR2LMultiplier.cs
+++ b/crypto/src/math/ec/multiplier/ZSignedDigitR2LMultiplier.cs
@@ -1,5 +1,8 @@
-namespace Org.BouncyCastle.Math.EC.Multiplier
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Multiplier
 {
+    [Obsolete("Will be removed")]
     public class ZSignedDigitR2LMultiplier 
         : AbstractECMultiplier
     {
diff --git a/crypto/src/math/ec/rfc7748/X25519Field.cs b/crypto/src/math/ec/rfc7748/X25519Field.cs
index 3a06941dd..6843e274a 100644
--- a/crypto/src/math/ec/rfc7748/X25519Field.cs
+++ b/crypto/src/math/ec/rfc7748/X25519Field.cs
@@ -49,6 +49,11 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748
             int z0 = z[0], z1 = z[1], z2 = z[2], z3 = z[3], z4 = z[4];
             int z5 = z[5], z6 = z[6], z7 = z[7], z8 = z[8], z9 = z[9];
 
+            z2 += (z1 >> 26); z1 &= M26;
+            z4 += (z3 >> 26); z3 &= M26;
+            z7 += (z6 >> 26); z6 &= M26;
+            z9 += (z8 >> 26); z8 &= M26;
+
             z3 += (z2 >> 25); z2 &= M25;
             z5 += (z4 >> 25); z4 &= M25;
             z8 += (z7 >> 25); z7 &= M25;
@@ -439,22 +444,22 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748
             Mul(t, x, rz);
         }
 
-        private static void Reduce(int[] z, int c)
-        {
-            int z9 = z[9], t = z9;
-                       z9   = t & M24; t >>= 24;
-            t += c;
-            t *= 19;
-            t += z[0]; z[0] = t & M26; t >>= 26;
-            t += z[1]; z[1] = t & M26; t >>= 26;
-            t += z[2]; z[2] = t & M25; t >>= 25;
-            t += z[3]; z[3] = t & M26; t >>= 26;
-            t += z[4]; z[4] = t & M25; t >>= 25;
-            t += z[5]; z[5] = t & M26; t >>= 26;
-            t += z[6]; z[6] = t & M26; t >>= 26;
-            t += z[7]; z[7] = t & M25; t >>= 25;
-            t += z[8]; z[8] = t & M26; t >>= 26;
-            t += z9;   z[9] = t;
+        private static void Reduce(int[] z, int x)
+        {
+            int t = z[9], z9 = t & M24;
+            t = (t >> 24) + x;
+
+            long cc = t * 19;
+            cc += z[0]; z[0] = (int)cc & M26; cc >>= 26;
+            cc += z[1]; z[1] = (int)cc & M26; cc >>= 26;
+            cc += z[2]; z[2] = (int)cc & M25; cc >>= 25;
+            cc += z[3]; z[3] = (int)cc & M26; cc >>= 26;
+            cc += z[4]; z[4] = (int)cc & M25; cc >>= 25;
+            cc += z[5]; z[5] = (int)cc & M26; cc >>= 26;
+            cc += z[6]; z[6] = (int)cc & M26; cc >>= 26;
+            cc += z[7]; z[7] = (int)cc & M25; cc >>= 25;
+            cc += z[8]; z[8] = (int)cc & M26; cc >>= 26;
+            z[9] = z9 + (int)cc;
         }
 
         public static void Sqr(int[] x, int[] z)
diff --git a/crypto/src/math/ec/rfc7748/X448Field.cs b/crypto/src/math/ec/rfc7748/X448Field.cs
index 14c9b4879..240518cde 100644
--- a/crypto/src/math/ec/rfc7748/X448Field.cs
+++ b/crypto/src/math/ec/rfc7748/X448Field.cs
@@ -45,6 +45,11 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748
             uint z0 = z[0], z1 = z[1], z2 = z[2], z3 = z[3], z4 = z[4], z5 = z[5], z6 = z[6], z7 = z[7];
             uint z8 = z[8], z9 = z[9], z10 = z[10], z11 = z[11], z12 = z[12], z13 = z[13], z14 = z[14], z15 = z[15];
 
+            z1   += (z0 >> 28); z0 &= M28;
+            z5   += (z4 >> 28); z4 &= M28;
+            z9   += (z8 >> 28); z8 &= M28;
+            z13  += (z12 >> 28); z12 &= M28;
+
             z2   += (z1 >> 28); z1 &= M28;
             z6   += (z5 >> 28); z5 &= M28;
             z10  += (z9 >> 28); z9 &= M28;
@@ -647,18 +652,22 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748
             Mul(t, x222, z);
         }
 
-        private static void Reduce(uint[] z, int c)
+        private static void Reduce(uint[] z, int x)
         {
-            uint z15 = z[15];
-            long t = z15;
-            z15 &= M28;
-            t = (t >> 28) + c;
-            z[8] += (uint)t;
-            for (int i = 0; i < 15; ++i)
+            uint u = z[15], z15 = u & M28;
+            int t = (int)(u >> 28) + x;
+
+            long cc = t;
+            for (int i = 0; i < 8; ++i)
+            {
+                cc += z[i]; z[i] = (uint)cc & M28; cc >>= 28;
+            }
+            cc += t;
+            for (int i = 8; i < 15; ++i)
             {
-                t += z[i]; z[i] = (uint)t & M28; t >>= 28;
+                cc += z[i]; z[i] = (uint)cc & M28; cc >>= 28;
             }
-            z[15] = z15 + (uint)t;
+            z[15] = z15 + (uint)cc;
         }
 
         public static void Sqr(uint[] x, uint[] z)
diff --git a/crypto/src/math/ec/rfc8032/Ed25519.cs b/crypto/src/math/ec/rfc8032/Ed25519.cs
index 238256cf7..95ba43472 100644
--- a/crypto/src/math/ec/rfc8032/Ed25519.cs
+++ b/crypto/src/math/ec/rfc8032/Ed25519.cs
@@ -314,7 +314,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
             ScalarMultBaseEncoded(s, pk, pkOff);
         }
 
-        private static sbyte[] GetWnaf(uint[] n, int width)
+        private static sbyte[] GetWnafVar(uint[] n, int width)
         {
             Debug.Assert(n[ScalarUints - 1] >> 28 == 0);
 
@@ -1000,8 +1000,8 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
 
             int width = 5;
 
-            sbyte[] ws_b = GetWnaf(nb, WnafWidthBase);
-            sbyte[] ws_p = GetWnaf(np, width);
+            sbyte[] ws_b = GetWnafVar(nb, WnafWidthBase);
+            sbyte[] ws_p = GetWnafVar(np, width);
 
             PointExt[] tp = PointPrecompVar(p, 1 << (width - 2));
 
diff --git a/crypto/src/math/ec/rfc8032/Ed448.cs b/crypto/src/math/ec/rfc8032/Ed448.cs
index 925f48eb1..12f24c1ff 100644
--- a/crypto/src/math/ec/rfc8032/Ed448.cs
+++ b/crypto/src/math/ec/rfc8032/Ed448.cs
@@ -323,7 +323,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
             ScalarMultBaseEncoded(s, pk, pkOff);
         }
 
-        private static sbyte[] GetWnaf(uint[] n, int width)
+        private static sbyte[] GetWnafVar(uint[] n, int width)
         {
             Debug.Assert(n[ScalarUints - 1] >> 30 == 0U);
 
@@ -1087,8 +1087,8 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
 
             int width = 5;
 
-            sbyte[] ws_b = GetWnaf(nb, WnafWidthBase);
-            sbyte[] ws_p = GetWnaf(np, width);
+            sbyte[] ws_b = GetWnafVar(nb, WnafWidthBase);
+            sbyte[] ws_p = GetWnafVar(np, width);
 
             PointExt[] tp = PointPrecompVar(p, 1 << (width - 2));
 
diff --git a/crypto/src/openpgp/PGPKeyRing.cs b/crypto/src/openpgp/PGPKeyRing.cs
index 6426f3f25..425eaca56 100644
--- a/crypto/src/openpgp/PGPKeyRing.cs
+++ b/crypto/src/openpgp/PGPKeyRing.cs
@@ -16,7 +16,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
 			BcpgInputStream bcpgInput)
 		{
 			return (bcpgInput.NextPacketTag() == PacketTag.Trust)
-				?	(TrustPacket) bcpgInput.ReadPacket()
+				?	(TrustPacket)bcpgInput.ReadPacket()
 				:	null;
 		}
 
diff --git a/crypto/src/openpgp/PgpCompressedData.cs b/crypto/src/openpgp/PgpCompressedData.cs
index e64a17c9c..c841b7474 100644
--- a/crypto/src/openpgp/PgpCompressedData.cs
+++ b/crypto/src/openpgp/PgpCompressedData.cs
@@ -14,7 +14,11 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
 		public PgpCompressedData(
             BcpgInputStream bcpgInput)
         {
-            data = (CompressedDataPacket) bcpgInput.ReadPacket();
+            Packet packet = bcpgInput.ReadPacket();
+            if (!(packet is CompressedDataPacket))
+                throw new IOException("unexpected packet in stream: " + packet);
+
+            this.data = (CompressedDataPacket)packet;
         }
 
 		/// <summary>The algorithm used for compression</summary>
diff --git a/crypto/src/openpgp/PgpEncryptedDataList.cs b/crypto/src/openpgp/PgpEncryptedDataList.cs
index 8dded7c05..1f605dab5 100644
--- a/crypto/src/openpgp/PgpEncryptedDataList.cs
+++ b/crypto/src/openpgp/PgpEncryptedDataList.cs
@@ -1,5 +1,6 @@
 using System;
 using System.Collections;
+using System.IO;
 
 using Org.BouncyCastle.Utilities;
 using Org.BouncyCastle.Utilities.Collections;
@@ -10,10 +11,10 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
     public class PgpEncryptedDataList
 		: PgpObject
     {
-        private IList list = Platform.CreateArrayList();
-        private InputStreamPacket data;
+        private readonly IList list = Platform.CreateArrayList();
+        private readonly InputStreamPacket data;
 
-		public PgpEncryptedDataList(
+        public PgpEncryptedDataList(
             BcpgInputStream bcpgInput)
         {
             while (bcpgInput.NextPacketTag() == PacketTag.PublicKeyEncryptedSession
@@ -22,9 +23,13 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
                 list.Add(bcpgInput.ReadPacket());
             }
 
-			data = (InputStreamPacket)bcpgInput.ReadPacket();
+            Packet packet = bcpgInput.ReadPacket();
+            if (!(packet is InputStreamPacket))
+                throw new IOException("unexpected packet in stream: " + packet);
 
-			for (int i = 0; i != list.Count; i++)
+            this.data = (InputStreamPacket)packet;
+
+            for (int i = 0; i != list.Count; i++)
             {
                 if (list[i] is SymmetricKeyEncSessionPacket)
                 {
diff --git a/crypto/src/openpgp/PgpLiteralData.cs b/crypto/src/openpgp/PgpLiteralData.cs
index 79bbc3984..d1b7b4a4d 100644
--- a/crypto/src/openpgp/PgpLiteralData.cs
+++ b/crypto/src/openpgp/PgpLiteralData.cs
@@ -16,12 +16,16 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
 		/// <summary>The special name indicating a "for your eyes only" packet.</summary>
         public const string Console = "_CONSOLE";
 
-		private LiteralDataPacket data;
+		private readonly LiteralDataPacket data;
 
 		public PgpLiteralData(
             BcpgInputStream bcpgInput)
         {
-            data = (LiteralDataPacket) bcpgInput.ReadPacket();
+            Packet packet = bcpgInput.ReadPacket();
+            if (!(packet is LiteralDataPacket))
+                throw new IOException("unexpected packet in stream: " + packet);
+
+            this.data = (LiteralDataPacket)packet;
         }
 
 		/// <summary>The format of the data stream - Binary or Text</summary>
diff --git a/crypto/src/openpgp/PgpMarker.cs b/crypto/src/openpgp/PgpMarker.cs
index 733e4e959..7257767ec 100644
--- a/crypto/src/openpgp/PgpMarker.cs
+++ b/crypto/src/openpgp/PgpMarker.cs
@@ -1,3 +1,6 @@
+using System;
+using System.IO;
+
 namespace Org.BouncyCastle.Bcpg.OpenPgp
 {
 	/// <remarks>
@@ -7,12 +10,16 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
     public class PgpMarker
 		: PgpObject
     {
-        private readonly MarkerPacket p;
+        private readonly MarkerPacket data;
 
 		public PgpMarker(
-            BcpgInputStream bcpgIn)
+            BcpgInputStream bcpgInput)
         {
-            p = (MarkerPacket) bcpgIn.ReadPacket();
+            Packet packet = bcpgInput.ReadPacket();
+            if (!(packet is MarkerPacket))
+                throw new IOException("unexpected packet in stream: " + packet);
+
+            this.data = (MarkerPacket)packet;
         }
 	}
 }
diff --git a/crypto/src/openpgp/PgpOnePassSignature.cs b/crypto/src/openpgp/PgpOnePassSignature.cs
index 68fc5994d..2fab5137e 100644
--- a/crypto/src/openpgp/PgpOnePassSignature.cs
+++ b/crypto/src/openpgp/PgpOnePassSignature.cs
@@ -9,14 +9,22 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
 	/// <remarks>A one pass signature object.</remarks>
     public class PgpOnePassSignature
     {
-        private OnePassSignaturePacket sigPack;
-        private int signatureType;
+        private static OnePassSignaturePacket Cast(Packet packet)
+        {
+            if (!(packet is OnePassSignaturePacket))
+                throw new IOException("unexpected packet in stream: " + packet);
+
+            return (OnePassSignaturePacket)packet;
+        }
+
+        private readonly OnePassSignaturePacket sigPack;
+        private readonly int signatureType;
 		private ISigner sig;
 		private byte lastb;
 
 		internal PgpOnePassSignature(
             BcpgInputStream bcpgInput)
-            : this((OnePassSignaturePacket) bcpgInput.ReadPacket())
+            : this(Cast(bcpgInput.ReadPacket()))
         {
         }
 
diff --git a/crypto/src/openpgp/PgpPublicKeyEncryptedData.cs b/crypto/src/openpgp/PgpPublicKeyEncryptedData.cs
index c2a351182..04fe3ad37 100644
--- a/crypto/src/openpgp/PgpPublicKeyEncryptedData.cs
+++ b/crypto/src/openpgp/PgpPublicKeyEncryptedData.cs
@@ -197,12 +197,17 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
                 byte[] enc = secKeyData[0];
 
                 int pLen = ((((enc[0] & 0xff) << 8) + (enc[1] & 0xff)) + 7) / 8;
-                byte[] pEnc = new byte[pLen];
+                if ((2 + pLen + 1) > enc.Length) 
+                    throw new PgpException("encoded length out of range");
 
+                byte[] pEnc = new byte[pLen];
                 Array.Copy(enc, 2, pEnc, 0, pLen);
 
-                byte[] keyEnc = new byte[enc[pLen + 2]];
+                int keyLen = enc[pLen + 2];
+                if ((2 + pLen + 1 + keyLen) > enc.Length)
+                    throw new PgpException("encoded length out of range");
 
+                byte[] keyEnc = new byte[keyLen];
                 Array.Copy(enc, 2 + pLen + 1, keyEnc, 0, keyEnc.Length);
 
                 ECPoint publicPoint = x9Params.Curve.DecodePoint(pEnc);
diff --git a/crypto/src/openpgp/PgpPublicKeyRing.cs b/crypto/src/openpgp/PgpPublicKeyRing.cs
index 92464d64f..c214623b4 100644
--- a/crypto/src/openpgp/PgpPublicKeyRing.cs
+++ b/crypto/src/openpgp/PgpPublicKeyRing.cs
@@ -45,7 +45,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
                     + "tag 0x" + ((int)initialTag).ToString("X"));
             }
 
-            PublicKeyPacket pubPk = (PublicKeyPacket) bcpgInput.ReadPacket();
+            PublicKeyPacket pubPk = ReadPublicKeyPacket(bcpgInput);
             TrustPacket trustPk = ReadOptionalTrustPacket(bcpgInput);
 
             // direct signatures and revocations
@@ -186,9 +186,18 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
             return found ? new PgpPublicKeyRing(keys) : null;
         }
 
+        internal static PublicKeyPacket ReadPublicKeyPacket(BcpgInputStream bcpgInput)
+        {
+            Packet packet = bcpgInput.ReadPacket();
+            if (!(packet is PublicKeyPacket))
+                throw new IOException("unexpected packet in stream: " + packet);
+
+            return (PublicKeyPacket)packet;
+        }
+
         internal static PgpPublicKey ReadSubkey(BcpgInputStream bcpgInput)
         {
-            PublicKeyPacket	pk = (PublicKeyPacket) bcpgInput.ReadPacket();
+            PublicKeyPacket	pk = ReadPublicKeyPacket(bcpgInput);
             TrustPacket kTrust = ReadOptionalTrustPacket(bcpgInput);
 
             // PGP 8 actually leaves out the signature.
diff --git a/crypto/src/openpgp/PgpSecretKey.cs b/crypto/src/openpgp/PgpSecretKey.cs
index b3986073d..01cceadbb 100644
--- a/crypto/src/openpgp/PgpSecretKey.cs
+++ b/crypto/src/openpgp/PgpSecretKey.cs
@@ -536,12 +536,15 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
 
                     for (int i = 0; i != 4; i++)
                     {
-                        int encLen = (((encData[pos] << 8) | (encData[pos + 1] & 0xff)) + 7) / 8;
+                        int encLen = ((((encData[pos] & 0xff) << 8) | (encData[pos + 1] & 0xff)) + 7) / 8;
 
                         data[pos] = encData[pos];
                         data[pos + 1] = encData[pos + 1];
                         pos += 2;
 
+                        if (encLen > (encData.Length - pos))
+                            throw new PgpException("out of range encLen found in encData");
+
                         byte[] tmp = RecoverKeyData(encAlgorithm, "/CFB/NoPadding", key, iv, encData, pos, encLen);
                         Array.Copy(tmp, 0, data, pos, encLen);
                         pos += encLen;
@@ -984,11 +987,14 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
             int pos = 0;
             for (int i = 0; i != 4; i++)
             {
-                int encLen = (((rawKeyData[pos] << 8) | (rawKeyData[pos + 1] & 0xff)) + 7) / 8;
+                int encLen = ((((rawKeyData[pos] & 0xff) << 8) | (rawKeyData[pos + 1] & 0xff)) + 7) / 8;
 
                 keyData[pos] = rawKeyData[pos];
                 keyData[pos + 1] = rawKeyData[pos + 1];
 
+                if (encLen > (rawKeyData.Length - (pos + 2)))
+                    throw new PgpException("out of range encLen found in rawKeyData");
+
                 byte[] tmp;
                 if (i == 0)
                 {
diff --git a/crypto/src/openpgp/PgpSignature.cs b/crypto/src/openpgp/PgpSignature.cs
index c8c541bef..fb6244725 100644
--- a/crypto/src/openpgp/PgpSignature.cs
+++ b/crypto/src/openpgp/PgpSignature.cs
@@ -12,6 +12,14 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
 	/// <remarks>A PGP signature object.</remarks>
     public class PgpSignature
     {
+        private static SignaturePacket Cast(Packet packet)
+        {
+            if (!(packet is SignaturePacket))
+                throw new IOException("unexpected packet in stream: " + packet);
+
+            return (SignaturePacket)packet;
+        }
+
         public const int BinaryDocument = 0x00;
         public const int CanonicalTextDocument = 0x01;
         public const int StandAlone = 0x02;
@@ -38,7 +46,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
 
 		internal PgpSignature(
             BcpgInputStream bcpgInput)
-            : this((SignaturePacket)bcpgInput.ReadPacket())
+            : this(Cast(bcpgInput.ReadPacket()))
         {
         }
 
diff --git a/crypto/src/openpgp/PgpUtilities.cs b/crypto/src/openpgp/PgpUtilities.cs
index 039aa5893..43d60908b 100644
--- a/crypto/src/openpgp/PgpUtilities.cs
+++ b/crypto/src/openpgp/PgpUtilities.cs
@@ -27,17 +27,20 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
 
 			try
 			{
-				Asn1Sequence s = (Asn1Sequence) Asn1Object.FromByteArray(encoding);
+                Asn1Sequence s = Asn1Sequence.GetInstance(encoding);
 
-				i1 = (DerInteger) s[0];
-				i2 = (DerInteger) s[1];
+				i1 = DerInteger.GetInstance(s[0]);
+                i2 = DerInteger.GetInstance(s[1]);
 			}
-			catch (IOException e)
+			catch (Exception e)
 			{
 				throw new PgpException("exception encoding signature", e);
 			}
 
-			return new MPInteger[]{ new MPInteger(i1.Value), new MPInteger(i2.Value) };
+			return new MPInteger[]{
+                new MPInteger(i1.Value),
+                new MPInteger(i2.Value)
+            };
 		}
 
 		public static MPInteger[] RsaSigToMpi(
diff --git a/crypto/src/pkcs/Pkcs12Store.cs b/crypto/src/pkcs/Pkcs12Store.cs
index 7db264232..e8a5c4490 100644
--- a/crypto/src/pkcs/Pkcs12Store.cs
+++ b/crypto/src/pkcs/Pkcs12Store.cs
@@ -19,6 +19,8 @@ namespace Org.BouncyCastle.Pkcs
 {
     public class Pkcs12Store
     {
+        public const string IgnoreUselessPasswordProperty = "Org.BouncyCastle.Pkcs12.IgnoreUselessPassword";
+
         private readonly IgnoresCaseHashtable	keys = new IgnoresCaseHashtable();
         private readonly IDictionary            localIds = Platform.CreateHashtable();
         private readonly IgnoresCaseHashtable	certs = new IgnoresCaseHashtable();
@@ -198,20 +200,22 @@ namespace Org.BouncyCastle.Pkcs
             if (input == null)
                 throw new ArgumentNullException("input");
 
-            Asn1Sequence obj = (Asn1Sequence) Asn1Object.FromStream(input);
-            Pfx bag = new Pfx(obj);
+            Pfx bag = Pfx.GetInstance(Asn1Object.FromStream(input));
             ContentInfo info = bag.AuthSafe;
             bool wrongPkcs12Zero = false;
 
-            if (password != null && bag.MacData != null) // check the mac code
-                            {
+            if (bag.MacData != null) // check the mac code
+            {
+                if (password == null)
+                    throw new ArgumentNullException("password", "no password supplied when one expected");
+
                 MacData mData = bag.MacData;
                 DigestInfo dInfo = mData.Mac;
                 AlgorithmIdentifier algId = dInfo.AlgorithmID;
                 byte[] salt = mData.GetSalt();
                 int itCount = mData.IterationCount.IntValue;
 
-                byte[] data = ((Asn1OctetString) info.Content).GetOctets();
+                byte[] data = Asn1OctetString.GetInstance(info.Content).GetOctets();
 
                 byte[] mac = CalculatePbeMac(algId.Algorithm, salt, itCount, password, false, data);
                 byte[] dig = dInfo.GetDigest();
@@ -228,8 +232,18 @@ namespace Org.BouncyCastle.Pkcs
                         throw new IOException("PKCS12 key store MAC invalid - wrong password or corrupted file.");
 
                     wrongPkcs12Zero = true;
-                                        }
-                                        }
+                }
+            }
+            else if (password != null)
+            {
+                string ignoreProperty = Platform.GetEnvironmentVariable(IgnoreUselessPasswordProperty);
+                bool ignore = ignoreProperty != null && Platform.EqualsIgnoreCase("true", ignoreProperty);
+
+                if (!ignore)
+                {
+                    throw new IOException("password supplied for keystore that does not require one");
+                }
+            }
 
             keys.Clear();
             localIds.Clear();
@@ -238,10 +252,9 @@ namespace Org.BouncyCastle.Pkcs
             IList certBags = Platform.CreateArrayList();
 
             if (info.ContentType.Equals(PkcsObjectIdentifiers.Data))
-                            {
-                byte[] octs = ((Asn1OctetString)info.Content).GetOctets();
-                AuthenticatedSafe authSafe = new AuthenticatedSafe(
-                    (Asn1Sequence) Asn1OctetString.FromByteArray(octs));
+            {
+                Asn1OctetString content = Asn1OctetString.GetInstance(info.Content);
+                AuthenticatedSafe authSafe = AuthenticatedSafe.GetInstance(content.GetOctets());
                 ContentInfo[] cis = authSafe.GetContentInfo();
 
                 foreach (ContentInfo ci in cis)
@@ -250,8 +263,8 @@ namespace Org.BouncyCastle.Pkcs
 
                     byte[] octets = null;
                     if (oid.Equals(PkcsObjectIdentifiers.Data))
-                                    {
-                        octets = ((Asn1OctetString)ci.Content).GetOctets();
+                    {
+                        octets = Asn1OctetString.GetInstance(ci.Content).GetOctets();
                     }
                     else if (oid.Equals(PkcsObjectIdentifiers.EncryptedData))
                                         {
@@ -268,8 +281,8 @@ namespace Org.BouncyCastle.Pkcs
                                         }
 
                     if (octets != null)
-                                        {
-                        Asn1Sequence seq = (Asn1Sequence)Asn1Object.FromByteArray(octets);
+                    {
+                        Asn1Sequence seq = Asn1Sequence.GetInstance(octets);
 
                         foreach (Asn1Sequence subSeq in seq)
                         {
@@ -527,15 +540,15 @@ namespace Org.BouncyCastle.Pkcs
                     X509Certificate x509c = c.Certificate;
                     X509CertificateEntry nextC = null;
 
-                    Asn1OctetString ext = x509c.GetExtensionValue(X509Extensions.AuthorityKeyIdentifier);
-                    if (ext != null)
+                    Asn1OctetString akiValue = x509c.GetExtensionValue(X509Extensions.AuthorityKeyIdentifier);
+                    if (akiValue != null)
                     {
-                        AuthorityKeyIdentifier id = AuthorityKeyIdentifier.GetInstance(
-                            Asn1Object.FromByteArray(ext.GetOctets()));
+                        AuthorityKeyIdentifier aki = AuthorityKeyIdentifier.GetInstance(akiValue.GetOctets());
 
-                        if (id.GetKeyIdentifier() != null)
+                        byte[] keyID = aki.GetKeyIdentifier();
+                        if (keyID != null)
                         {
-                            nextC = (X509CertificateEntry) chainCerts[new CertId(id.GetKeyIdentifier())];
+                            nextC = (X509CertificateEntry)chainCerts[new CertId(keyID)];
                         }
                     }
 
@@ -1099,6 +1112,11 @@ namespace Org.BouncyCastle.Pkcs
             {
                 get { return orig.Values; }
             }
+
+            public int Count
+            {
+                get { return orig.Count; }
+            }
         }
     }
 }
diff --git a/crypto/src/pkix/PkixNameConstraintValidator.cs b/crypto/src/pkix/PkixNameConstraintValidator.cs
index 4d5af28ea..fbec6fb72 100644
--- a/crypto/src/pkix/PkixNameConstraintValidator.cs
+++ b/crypto/src/pkix/PkixNameConstraintValidator.cs
@@ -47,11 +47,24 @@ namespace Org.BouncyCastle.Pkix
             if (subtree.Count < 1 || subtree.Count > dns.Count)
                 return false;
 
+            int start = 0;
+            Rdn subtreeRdnStart = Rdn.GetInstance(subtree[0]);
+            for (int j = 0; j < dns.Count; j++)
+            {
+                start = j;
+                Rdn dnsRdn = Rdn.GetInstance(dns[j]);
+                if (IetfUtilities.RdnAreEqual(subtreeRdnStart, dnsRdn))
+                    break;
+            }
+
+            if (subtree.Count > dns.Count - start)
+                return false;
+
             for (int j = 0; j < subtree.Count; ++j)
             {
                 // both subtree and dns are a ASN.1 Name and the elements are a RDN
                 Rdn subtreeRdn = Rdn.GetInstance(subtree[j]);
-                Rdn dnsRdn = Rdn.GetInstance(dns[j]);
+                Rdn dnsRdn = Rdn.GetInstance(dns[start + j]);
 
                 // check if types and values of all naming attributes are matching, other types which are not restricted are allowed, see https://tools.ietf.org/html/rfc5280#section-7.1
 
diff --git a/crypto/src/security/PrivateKeyFactory.cs b/crypto/src/security/PrivateKeyFactory.cs
index ddcb88992..b72ece365 100644
--- a/crypto/src/security/PrivateKeyFactory.cs
+++ b/crypto/src/security/PrivateKeyFactory.cs
@@ -107,7 +107,7 @@ namespace Org.BouncyCastle.Security
             }
             else if (algOid.Equals(X9ObjectIdentifiers.IdECPublicKey))
             {
-                X962Parameters para = new X962Parameters(algID.Parameters.ToAsn1Object());
+                X962Parameters para = X962Parameters.GetInstance(algID.Parameters.ToAsn1Object());
 
                 X9ECParameters x9;
                 if (para.IsNamedCurve)
@@ -132,8 +132,8 @@ namespace Org.BouncyCastle.Security
             }
             else if (algOid.Equals(CryptoProObjectIdentifiers.GostR3410x2001))
             {
-                Gost3410PublicKeyAlgParameters gostParams = new Gost3410PublicKeyAlgParameters(
-                    Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object()));
+                Gost3410PublicKeyAlgParameters gostParams = Gost3410PublicKeyAlgParameters.GetInstance(
+                    algID.Parameters.ToAsn1Object());
 
                 ECDomainParameters ecP = ECGost3410NamedCurves.GetByOid(gostParams.PublicKeyParamSet);
 
diff --git a/crypto/src/security/PublicKeyFactory.cs b/crypto/src/security/PublicKeyFactory.cs
index 7b19f1c0f..6813452a6 100644
--- a/crypto/src/security/PublicKeyFactory.cs
+++ b/crypto/src/security/PublicKeyFactory.cs
@@ -133,7 +133,7 @@ namespace Org.BouncyCastle.Security
             }
             else if (algOid.Equals(X9ObjectIdentifiers.IdECPublicKey))
             {
-                X962Parameters para = new X962Parameters(algID.Parameters.ToAsn1Object());
+                X962Parameters para = X962Parameters.GetInstance(algID.Parameters.ToAsn1Object());
 
                 X9ECParameters x9;
                 if (para.IsNamedCurve)
diff --git a/crypto/src/tsp/TimeStampToken.cs b/crypto/src/tsp/TimeStampToken.cs
index 105208a7d..643813552 100644
--- a/crypto/src/tsp/TimeStampToken.cs
+++ b/crypto/src/tsp/TimeStampToken.cs
@@ -244,9 +244,18 @@ namespace Org.BouncyCastle.Tsp
 		 */
 		public byte[] GetEncoded()
 		{
-			return tsToken.GetEncoded();
-		}
-
+            return tsToken.GetEncoded(Asn1Encodable.Der);
+        }
+
+        /**
+         * return the ASN.1 encoded representation of this object using the specified encoding.
+         *
+         * @param encoding the ASN.1 encoding format to use ("BER" or "DER").
+         */
+        public byte[] GetEncoded(string encoding)
+        {
+            return tsToken.GetEncoded(encoding);
+        }
 
 		// perhaps this should be done using an interface on the ASN.1 classes...
 		private class CertID
diff --git a/crypto/src/util/Arrays.cs b/crypto/src/util/Arrays.cs
index 6f2503d2d..7b1766bba 100644
--- a/crypto/src/util/Arrays.cs
+++ b/crypto/src/util/Arrays.cs
@@ -53,9 +53,7 @@ namespace Org.BouncyCastle.Utilities
         /// <param name="a">Left side.</param>
         /// <param name="b">Right side.</param>
         /// <returns>True if equal.</returns>
-        public static bool AreEqual(
-            byte[]	a,
-            byte[]	b)
+        public static bool AreEqual(byte[] a, byte[] b)
         {
             if (a == b)
                 return true;
@@ -66,6 +64,23 @@ namespace Org.BouncyCastle.Utilities
             return HaveSameContents(a, b);
         }
 
+        public static bool AreEqual(byte[] a, int aFromIndex, int aToIndex, byte[] b, int bFromIndex, int bToIndex)
+        {
+            int aLength = aToIndex - aFromIndex;
+            int bLength = bToIndex - bFromIndex;
+
+            if (aLength != bLength)
+                return false;
+
+            for (int i = 0; i < aLength; ++i)
+            {
+                if (a[aFromIndex + i] != b[bFromIndex + i])
+                    return false;
+            }
+
+            return true;
+        }
+
         [Obsolete("Use 'AreEqual' method instead")]
         public static bool AreSame(
             byte[]	a,
diff --git a/crypto/src/util/io/pem/PemReader.cs b/crypto/src/util/io/pem/PemReader.cs
index bf712b6de..61e132fa7 100644
--- a/crypto/src/util/io/pem/PemReader.cs
+++ b/crypto/src/util/io/pem/PemReader.cs
@@ -39,11 +39,14 @@ namespace Org.BouncyCastle.Utilities.IO.Pem
 			{
 				line = line.Substring(BeginString.Length);
 				int index = line.IndexOf('-');
-				string type = line.Substring(0, index);
 
-				if (index > 0)
-					return LoadObject(type);
-			}
+                if (index > 0 && Platform.EndsWith(line, "-----") && (line.Length - index) == 5)
+                {
+                    string type = line.Substring(0, index);
+
+                    return LoadObject(type);
+                }
+            }
 
 			return null;
 		}
diff --git a/crypto/test/src/asn1/test/InputStreamTest.cs b/crypto/test/src/asn1/test/InputStreamTest.cs
index 1d92759e0..4cfb304d1 100644
--- a/crypto/test/src/asn1/test/InputStreamTest.cs
+++ b/crypto/test/src/asn1/test/InputStreamTest.cs
@@ -3,6 +3,7 @@ using System.IO;
 
 using NUnit.Framework;
 
+using Org.BouncyCastle.Utilities.Encoders;
 using Org.BouncyCastle.Utilities.Test;
 
 namespace Org.BouncyCastle.Asn1.Tests
@@ -11,9 +12,15 @@ namespace Org.BouncyCastle.Asn1.Tests
 	public class InputStreamTest
 		: SimpleTest
 	{
-		private static readonly byte[] outOfBoundsLength = new byte[] { (byte)0x30, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff };
-		private static readonly byte[] negativeLength = new byte[] { (byte)0x30, (byte)0x84, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff };
-		private static readonly byte[] outsideLimitLength = new byte[] { (byte)0x30, (byte)0x83, (byte)0x0f, (byte)0xff, (byte)0xff };
+        private static readonly byte[] outOfBoundsLength = new byte[] { (byte)0x30, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff };
+        private static readonly byte[] negativeLength = new byte[] { (byte)0x30, (byte)0x84, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff };
+        private static readonly byte[] outsideLimitLength = new byte[] { (byte)0x30, (byte)0x83, (byte)0x0f, (byte)0xff, (byte)0xff };
+
+        private static readonly byte[] classCast1 = Base64.Decode("p1AkHmYAvfOEIrL4ESfrNg==");
+        private static readonly byte[] classCast2 = Base64.Decode("JICNbaBUTTq7uxj5mg==");
+        private static readonly byte[] classCast3 = Base64.Decode("JAKzADNCxhrrBSVS");
+        private static readonly byte[] memoryError1 = Base64.Decode("vm66gOiEe+FV/NvujMwSkUp5Lffw5caQlaRU5sdMPC70IGWmyK2/");
+        private static readonly byte[] memoryError2 = Base64.Decode("vm4ogOSEfVGsS3w+KTzb2A0ALYR8VBOQqQeuRwnsPC4AAGWEDLjd");
 
 		public override string Name
 		{
@@ -46,7 +53,7 @@ namespace Org.BouncyCastle.Asn1.Tests
 			}
 			catch (IOException e)
 			{
-				if (!e.Message.Equals("Corrupted stream - negative length found"))
+				if (!e.Message.Equals("corrupted stream - negative length found"))
 				{
 					Fail("wrong exception: " + e.Message);
 				}
@@ -61,12 +68,54 @@ namespace Org.BouncyCastle.Asn1.Tests
 			}
 			catch (IOException e)
 			{
-				if (!e.Message.Equals("Corrupted stream - out of bounds length found"))
-				{
+                if (!e.Message.Equals("corrupted stream - out of bounds length found: 1048575 >= 5"))
+                {
 					Fail("wrong exception: " + e.Message);
 				}
 			}
-		}
+
+            DoTestWithByteArray(classCast1, "unknown object encountered: Org.BouncyCastle.Asn1.DerApplicationSpecific");
+            DoTestWithByteArray(classCast2, "unknown object encountered: Org.BouncyCastle.Asn1.BerTaggedObjectParser");
+            DoTestWithByteArray(classCast3, "unknown object encountered in constructed OCTET STRING: Org.BouncyCastle.Asn1.DerTaggedObject");
+
+            DoTestWithByteArray(memoryError1, "corrupted stream - out of bounds length found: 2078365180 >= 39");
+            DoTestWithByteArray(memoryError2, "corrupted stream - out of bounds length found: 2102504523 >= 39");
+        }
+
+        private void DoTestWithByteArray(byte[] data, string message)
+        {
+            try
+            {
+                Asn1InputStream input = new Asn1InputStream(data);
+
+                IAsn1Convertible p;
+                while ((p = input.ReadObject()) != null)
+                {
+                    Asn1Sequence asn1 = Asn1Sequence.GetInstance(p);
+                    for (int i = 0; i < asn1.Count; i++)
+                    {
+                        IAsn1Convertible c = asn1[i];
+                    }
+                }
+            }
+            catch (IOException e)
+            {
+                IsEquals(e.Message, message, e.Message);
+            }
+            // TODO Without InMemoryRepresentable, the IOException may be swapped/wrapped with an Asn1ParsingException
+            catch (Asn1ParsingException e)
+            {
+                Exception messageException = e;
+
+                IOException ioe = e.InnerException as IOException;
+                if (ioe != null)
+                {
+                    messageException = ioe;
+                }
+
+                IsEquals(messageException.Message, message, messageException.Message);
+            }
+        }
 
 		public static void Main(
 			string[] args)
diff --git a/crypto/test/src/asn1/test/PKCS12Test.cs b/crypto/test/src/asn1/test/PKCS12Test.cs
index c20fa8cc6..5e4748728 100644
--- a/crypto/test/src/asn1/test/PKCS12Test.cs
+++ b/crypto/test/src/asn1/test/PKCS12Test.cs
@@ -114,9 +114,7 @@ namespace Org.BouncyCastle.Asn1.Tests
 
 		public override void PerformTest()
 		{
-			Asn1Sequence obj = (Asn1Sequence) Asn1Object.FromByteArray(pkcs12);
-
-			Pfx                 bag = new Pfx(obj);
+			Pfx                 bag = Pfx.GetInstance(pkcs12);
 			ContentInfo         info = bag.AuthSafe;
 			MacData             mData = bag.MacData;
 			DigestInfo          dInfo = mData.Mac;
@@ -124,9 +122,8 @@ namespace Org.BouncyCastle.Asn1.Tests
 			byte[]              salt = mData.GetSalt();
 			int                 itCount = mData.IterationCount.IntValue;
 
-			byte[] octets = ((Asn1OctetString) info.Content).GetOctets();
-			AuthenticatedSafe authSafe = new AuthenticatedSafe(
-				(Asn1Sequence) Asn1Object.FromByteArray(octets));
+			Asn1OctetString content = Asn1OctetString.GetInstance(info.Content);
+			AuthenticatedSafe authSafe = AuthenticatedSafe.GetInstance(content.GetOctets());
 			ContentInfo[] c = authSafe.GetContentInfo();
 
 			//
@@ -137,10 +134,10 @@ namespace Org.BouncyCastle.Asn1.Tests
 				Fail("Failed comparison data test");
 			}
 
-			octets = ((Asn1OctetString)c[0].Content).GetOctets();
-			Asn1Sequence seq = (Asn1Sequence) Asn1Object.FromByteArray(octets);
+            Asn1OctetString authSafeContent = Asn1OctetString.GetInstance(c[0].Content);
+            Asn1Sequence seq = Asn1Sequence.GetInstance(authSafeContent.GetOctets());
 
-			SafeBag b = new SafeBag((Asn1Sequence)seq[0]);
+            SafeBag b = SafeBag.GetInstance(seq[0]);
 			if (!b.BagID.Equals(PkcsObjectIdentifiers.Pkcs8ShroudedKeyBag))
 			{
 				Fail("Failed comparison shroudedKeyBag test");
@@ -152,9 +149,9 @@ namespace Org.BouncyCastle.Asn1.Tests
 
 			b = new SafeBag(PkcsObjectIdentifiers.Pkcs8ShroudedKeyBag, encInfo.ToAsn1Object(), b.BagAttributes);
 
-			byte[] encodedBytes = new DerSequence(b).GetEncoded();
+			byte[] contentOctets = new DerSequence(b).GetEncoded();
 
-			c[0] = new ContentInfo(PkcsObjectIdentifiers.Data, new BerOctetString(encodedBytes));
+			c[0] = new ContentInfo(PkcsObjectIdentifiers.Data, new BerOctetString(contentOctets));
 
 			//
 			// certificates
@@ -173,16 +170,19 @@ namespace Org.BouncyCastle.Asn1.Tests
 			//
 			authSafe = new AuthenticatedSafe(c);
 
-			info = new ContentInfo(PkcsObjectIdentifiers.Data, new BerOctetString(authSafe.GetEncoded()));
+            contentOctets = authSafe.GetEncoded();
+
+            info = new ContentInfo(PkcsObjectIdentifiers.Data, new BerOctetString(contentOctets));
 
-			mData = new MacData(new DigestInfo(algId, dInfo.GetDigest()), salt, itCount);
+            mData = new MacData(new DigestInfo(algId, dInfo.GetDigest()), salt, itCount);
 
 			bag = new Pfx(info, mData);
 
 			//
 			// comparison test
 			//
-			if (!Arrays.AreEqual(bag.GetEncoded(), pkcs12))
+            byte[] pfxEncoding = bag.GetEncoded();
+			if (!Arrays.AreEqual(pfxEncoding, pkcs12))
 			{
 				Fail("Failed comparison test");
 			}
diff --git a/crypto/test/src/crypto/test/ChaCha20Poly1305Test.cs b/crypto/test/src/crypto/test/ChaCha20Poly1305Test.cs
index 3f74669dc..9fade9a5e 100644
--- a/crypto/test/src/crypto/test/ChaCha20Poly1305Test.cs
+++ b/crypto/test/src/crypto/test/ChaCha20Poly1305Test.cs
@@ -193,7 +193,7 @@ namespace Org.BouncyCastle.Crypto.Tests
             SecureRandom random = new SecureRandom();
             random.SetSeed(DateTimeUtilities.CurrentUnixMs());
 
-            for (int i = 0; i < 10; ++i)
+            for (int i = 0; i < 100; ++i)
             {
                 RandomTest(random);
             }
@@ -205,8 +205,10 @@ namespace Org.BouncyCastle.Crypto.Tests
             byte[] K = new byte[kLength];
             random.NextBytes(K);
 
+            int pHead = random.Next(256);
             int pLength = random.Next(65536);
-            byte[] P = new byte[pLength];
+            int pTail = random.Next(256);
+            byte[] P = new byte[pHead + pLength + pTail];
             random.NextBytes(P);
 
             int aLength = random.Next(256);
@@ -223,28 +225,31 @@ namespace Org.BouncyCastle.Crypto.Tests
 
             AeadParameters parameters = new AeadParameters(new KeyParameter(K), 16 * 8, nonce, A);
             ChaCha20Poly1305 cipher = InitCipher(true, parameters);
-            byte[] C = new byte[cipher.GetOutputSize(P.Length)];
-            int predicted = cipher.GetUpdateOutputSize(P.Length);
 
-            int split = NextInt(random, SA.Length + 1);
-            cipher.ProcessAadBytes(SA, 0, split);
-            cipher.ProcessAadBytes(SA, split, SA.Length - split);
+            int ctLength = cipher.GetOutputSize(pLength);
+            byte[] C = new byte[saLength + ctLength];
+            Array.Copy(SA, 0, C, 0, saLength);
 
-            int len = cipher.ProcessBytes(P, 0, P.Length, C, 0);
+            int split = NextInt(random, saLength + 1);
+            cipher.ProcessAadBytes(C, 0, split);
+            cipher.ProcessAadBytes(C, split, saLength - split);
+
+            int predicted = cipher.GetUpdateOutputSize(pLength);
+            int len = cipher.ProcessBytes(P, pHead, pLength, C, saLength);
             if (predicted != len)
             {
                 Fail("encryption reported incorrect update length in randomised test");
             }
 
-            len += cipher.DoFinal(C, len);
-            if (C.Length != len)
+            len += cipher.DoFinal(C, saLength + len);
+            if (ctLength != len)
             {
                 Fail("encryption reported incorrect length in randomised test");
             }
 
             byte[] encT = cipher.GetMac();
-            byte[] tail = new byte[C.Length - P.Length];
-            Array.Copy(C, P.Length, tail, 0, tail.Length);
+            byte[] tail = new byte[ctLength - pLength];
+            Array.Copy(C, saLength + pLength, tail, 0, tail.Length);
 
             if (!AreEqual(encT, tail))
             {
@@ -252,22 +257,26 @@ namespace Org.BouncyCastle.Crypto.Tests
             }
 
             cipher.Init(false, parameters);
-            byte[] decP = new byte[cipher.GetOutputSize(C.Length)];
-            predicted = cipher.GetUpdateOutputSize(C.Length);
 
-            split = NextInt(random, SA.Length + 1);
-            cipher.ProcessAadBytes(SA, 0, split);
-            cipher.ProcessAadBytes(SA, split, SA.Length - split);
+            int decPHead = random.Next(256);
+            int decPLength = cipher.GetOutputSize(ctLength);
+            int decPTail = random.Next(256);
+            byte[] decP = new byte[decPHead + decPLength + decPTail];
+
+            split = NextInt(random, saLength + 1);
+            cipher.ProcessAadBytes(C, 0, split);
+            cipher.ProcessAadBytes(C, split, saLength - split);
 
-            len = cipher.ProcessBytes(C, 0, C.Length, decP, 0);
+            predicted = cipher.GetUpdateOutputSize(ctLength);
+            len = cipher.ProcessBytes(C, saLength, ctLength, decP, decPHead);
             if (predicted != len)
             {
                 Fail("decryption reported incorrect update length in randomised test");
             }
 
-            len += cipher.DoFinal(decP, len);
+            len += cipher.DoFinal(decP, decPHead + len);
 
-            if (!AreEqual(P, decP))
+            if (!AreEqual(P, pHead, pHead + pLength, decP, decPHead, decPHead + decPLength))
             {
                 Fail("incorrect decrypt in randomised test");
             }
@@ -282,16 +291,20 @@ namespace Org.BouncyCastle.Crypto.Tests
             // key reuse test
             //
             cipher.Init(false, AeadTestUtilities.ReuseKey(parameters));
-            decP = new byte[cipher.GetOutputSize(C.Length)];
 
-            split = NextInt(random, SA.Length + 1);
-            cipher.ProcessAadBytes(SA, 0, split);
-            cipher.ProcessAadBytes(SA, split, SA.Length - split);
+            decPHead = random.Next(256);
+            decPLength = cipher.GetOutputSize(ctLength);
+            decPTail = random.Next(256);
+            decP = new byte[decPHead + decPLength + decPTail];
+
+            split = NextInt(random, saLength + 1);
+            cipher.ProcessAadBytes(C, 0, split);
+            cipher.ProcessAadBytes(C, split, saLength - split);
 
-            len = cipher.ProcessBytes(C, 0, C.Length, decP, 0);
-            len += cipher.DoFinal(decP, len);
+            len = cipher.ProcessBytes(C, saLength, ctLength, decP, decPHead);
+            len += cipher.DoFinal(decP, decPHead + len);
 
-            if (!AreEqual(P, decP))
+            if (!AreEqual(P, pHead, pHead + pLength, decP, decPHead, decPHead + decPLength))
             {
                 Fail("incorrect decrypt in randomised test");
             }
diff --git a/crypto/test/src/openssl/test/ReaderTest.cs b/crypto/test/src/openssl/test/ReaderTest.cs
index a7efb6004..2e270ddc1 100644
--- a/crypto/test/src/openssl/test/ReaderTest.cs
+++ b/crypto/test/src/openssl/test/ReaderTest.cs
@@ -185,8 +185,8 @@ namespace Org.BouncyCastle.OpenSsl.Tests
             doOpenSslDsaTest("rc2_64_cbc");
             doOpenSslRsaTest("rc2_64_cbc");
 
-            doDudPasswordTest("7fd98", 0, "Corrupted stream - out of bounds length found");
-            doDudPasswordTest("ef677", 1, "Corrupted stream - out of bounds length found");
+            doDudPasswordTest("7fd98", 0, "corrupted stream - out of bounds length found: 599005160 >= 447");
+            doDudPasswordTest("ef677", 1, "corrupted stream - out of bounds length found: 2087569732 >= 447");
             doDudPasswordTest("800ce", 2, "unknown tag 26 encountered");
             doDudPasswordTest("b6cd8", 3, "DEF length 81 object truncated by 56");
             doDudPasswordTest("28ce09", 4, "DEF length 110 object truncated by 28");
@@ -202,7 +202,7 @@ namespace Org.BouncyCastle.OpenSsl.Tests
             doDudPasswordTest("5a3d16", 14, "corrupted stream detected");
             doDudPasswordTest("8d0c97", 15, "corrupted stream detected");
             doDudPasswordTest("bc0daf", 16, "corrupted stream detected");
-            doDudPasswordTest("aaf9c4d",17, "Corrupted stream - out of bounds length found");
+            doDudPasswordTest("aaf9c4d", 17, "corrupted stream - out of bounds length found: 1580418590 >= 447");
 
             // encrypted private key test
             pGet = new Password("password".ToCharArray());
diff --git a/crypto/test/src/pkcs/test/PKCS12StoreTest.cs b/crypto/test/src/pkcs/test/PKCS12StoreTest.cs
index cd9dfcfad..9db1a6651 100644
--- a/crypto/test/src/pkcs/test/PKCS12StoreTest.cs
+++ b/crypto/test/src/pkcs/test/PKCS12StoreTest.cs
@@ -398,6 +398,26 @@ namespace Org.BouncyCastle.Pkcs.Tests
 			+ "AHoAeQB0AGsAbwB3AG4AaQBrAGEwMTAhMAkGBSsOAwIaBQAEFKJpUOIj0OtI"
 			+ "j2CPp38YIFBEqvjsBAi8G+yhJe3A/wICCAA=");
 
+		private static readonly byte[] certsOnly = Base64.Decode(
+            "MIICnwIBAzCCApgGCSqGSIb3DQEHAaCCAokEggKFMIICgTCCAn0GCSqGSIb3"
+            + "DQEHAaCCAm4EggJqMIICZjCCAmIGCyqGSIb3DQEMCgEDoIICHDCCAhgGCiq"
+            + "GSIb3DQEJFgGgggIIBIICBDCCAgAwggFpoAMCAQICBHcheqIwDQYJKoZIhv"
+            + "cNAQELBQAwMjENMAsGA1UEChMERGVtbzENMAsGA1UECxMERGVtbzESMBAGA"
+            + "1UEAxMJRGVtbyBjZXJ0MCAXDTE5MDgzMTEzMDgzNloYDzIxMDkwNTE5MTMw"
+            + "ODM2WjAyMQ0wCwYDVQQKEwREZW1vMQ0wCwYDVQQLEwREZW1vMRIwEAYDVQQ"
+            + "DEwlEZW1vIGNlcnQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKOVC4"
+            + "Qeg0KPAPRB9WcZdvXitiJ+E6rd3czQGNzEFC6FesAllH3PHSWuUZ2YjhiVM"
+            + "YJyzwVP1II04iCRaIc65R45oVrHZ2ybWAOda2hBtySjQ2pIQQpoKE7nvL3j"
+            + "JcHoCIBJVf3c3xpfh7RucCOGiZDjU9CYPG8yznsazb5+fPF/AgMBAAGjITA"
+            + "fMB0GA1UdDgQWBBR/7wUDwa7T0vNzNgjOKdjz2Up9RzANBgkqhkiG9w0BAQ"
+            + "sFAAOBgQADzPFsaLhVYD/k9qMueYKi8Ftwijr37niF98cgAHEtq6TGsh3Se"
+            + "8gEK3dNJL18vm7NXgGsl8jUWsE9hCF9ar+/cDZ+KrZlZ5PLfifXJJKFqVAh"
+            + "sOORef0NRIVcTCoyQTW4pNpNZP9Ul5LJ3iIDjafgJMyEkRbavqdyfSqVTvY"
+            + "NpjEzMBkGCSqGSIb3DQEJFDEMHgoAYQBsAGkAYQBzMBYGDGCGSAGG+Watyn"
+            + "sBATEGBgRVHSUA");
+
+        private readonly SecureRandom Random = new SecureRandom();
+
 		/**
 		* we generate a self signed certificate for the sake of testing - RSA
 		*/
@@ -451,7 +471,43 @@ namespace Org.BouncyCastle.Pkcs.Tests
 			return new X509CertificateEntry(certGen.Generate(privKey));
 		}
 
-		public void doTestPkcs12Store()
+        private void DoTestCertsOnly()
+        {
+            Pkcs12Store pkcs12 = new Pkcs12StoreBuilder().Build();
+
+            pkcs12.Load(new MemoryStream(certsOnly, false), null);
+
+            IsTrue(pkcs12.ContainsAlias("alias"));
+
+            MemoryStream bOut = new MemoryStream();
+
+            pkcs12.Save(bOut, null, Random);
+
+            pkcs12 = new Pkcs12StoreBuilder().Build();
+
+            pkcs12.Load(new MemoryStream(bOut.ToArray(), false), null);
+
+            IsTrue(pkcs12.ContainsAlias("alias"));
+
+            try
+            {
+                pkcs12.Load(new MemoryStream(certsOnly, false), "1".ToCharArray());
+                Fail("no exception");
+            }
+            catch (IOException e)
+            {
+                IsEquals("password supplied for keystore that does not require one", e.Message);
+            }
+
+            // TODO Modify environment variables in tests?
+            //System.setProperty(Pkcs12Store.IgnoreUselessPasswordProperty, "true");
+
+            //pkcs12.Load(new MemoryStream(certsOnly, false), "1".ToCharArray());
+
+            //System.setProperty(Pkcs12Store.IgnoreUselessPasswordProperty, "false");
+        }
+
+		private void DoTestPkcs12Store()
 		{
 			BigInteger mod = new BigInteger("bb1be8074e4787a8d77967f1575ef72dd7582f9b3347724413c021beafad8f32dba5168e280cbf284df722283dad2fd4abc750e3d6487c2942064e2d8d80641aa5866d1f6f1f83eec26b9b46fecb3b1c9856a303148a5cc899c642fb16f3d9d72f52526c751dc81622c420c82e2cfda70fe8d13f16cc7d6a613a5b2a2b5894d1", 16);
 
@@ -502,7 +558,7 @@ namespace Org.BouncyCastle.Pkcs.Tests
 			// save test
 			//
 			MemoryStream bOut = new MemoryStream();
-			store.Save(bOut, passwd, new SecureRandom());
+			store.Save(bOut, passwd, Random);
 
 			stream = new MemoryStream(bOut.ToArray(), false);
 			store.Load(stream, passwd);
@@ -589,8 +645,8 @@ namespace Org.BouncyCastle.Pkcs.Tests
 			}
 
 			MemoryStream store1Stream = new MemoryStream();
-			store.Save(store1Stream, passwd, new SecureRandom());
-			testNoExtraLocalKeyID(store1Stream.ToArray());
+			store.Save(store1Stream, passwd, Random);
+			DoTestNoExtraLocalKeyID(store1Stream.ToArray());
 
 			//
 			// no friendly name test
@@ -655,7 +711,7 @@ namespace Org.BouncyCastle.Pkcs.Tests
 				Fail("Certificate chain wrong length");
 			}
 
-			store.Save(new MemoryStream(), storagePassword, new SecureRandom());
+			store.Save(new MemoryStream(), storagePassword, Random);
 
 			//
 			// basic certificate check
@@ -741,7 +797,7 @@ namespace Org.BouncyCastle.Pkcs.Tests
 			store.Load(stream, "".ToCharArray());
 		}
 
-		private void testSupportedTypes(AsymmetricKeyEntry privKey, X509CertificateEntry[] chain)
+		private void DoTestSupportedTypes(AsymmetricKeyEntry privKey, X509CertificateEntry[] chain)
 		{
 			basicStoreTest(privKey, chain,
 				PkcsObjectIdentifiers.PbeWithShaAnd3KeyTripleDesCbc,
@@ -763,7 +819,7 @@ namespace Org.BouncyCastle.Pkcs.Tests
 
 			MemoryStream bOut = new MemoryStream();
 
-			store.Save(bOut, passwd, new SecureRandom());
+			store.Save(bOut, passwd, Random);
 
 			store.Load(new MemoryStream(bOut.ToArray(), false), passwd);
 
@@ -851,11 +907,11 @@ namespace Org.BouncyCastle.Pkcs.Tests
 			}
 		}
 
-		private void testNoExtraLocalKeyID(byte[] store1data)
+		private void DoTestNoExtraLocalKeyID(byte[] store1data)
 		{
 			IAsymmetricCipherKeyPairGenerator kpg = GeneratorUtilities.GetKeyPairGenerator("RSA");
 			kpg.Init(new RsaKeyGenerationParameters(
-				BigInteger.ValueOf(0x10001), new SecureRandom(), 512, 25));
+				BigInteger.ValueOf(0x10001), Random, 512, 25));
 
 			AsymmetricCipherKeyPair newPair =  kpg.GenerateKeyPair();
 
@@ -882,7 +938,7 @@ namespace Org.BouncyCastle.Pkcs.Tests
 
 			MemoryStream bOut = new MemoryStream();
 
-			store2.Save(bOut, passwd, new SecureRandom());
+			store2.Save(bOut, passwd, Random);
 
 			store2.Load(new MemoryStream(bOut.ToArray(), false), passwd);
 
@@ -901,7 +957,8 @@ namespace Org.BouncyCastle.Pkcs.Tests
 
 		public override void PerformTest()
 		{
-			doTestPkcs12Store();
+            DoTestCertsOnly();
+			DoTestPkcs12Store();
 		}
 
 		public static void Main(
diff --git a/crypto/test/src/tsp/test/TimeStampTokenInfoTest.cs b/crypto/test/src/tsp/test/TimeStampTokenInfoTest.cs
index 5a26f5ef6..ea7f2c4dc 100644
--- a/crypto/test/src/tsp/test/TimeStampTokenInfoTest.cs
+++ b/crypto/test/src/tsp/test/TimeStampTokenInfoTest.cs
@@ -28,7 +28,7 @@ namespace Org.BouncyCastle.Tsp.Tests
 
 		private static readonly byte[] tstInfoDudDate = Hex.Decode(
 			  "303e02010106022a033021300906052b0e03021a050004140000000000000000000000000000000000000000"
-			+ "020118180f32303056313130313038313732315a");
+            + "020118180f32303030563130313038313732315a");
 
 		[Test]
 		public void TestTstInfo1()
diff --git a/crypto/test/src/util/io/pem/test/AllTests.cs b/crypto/test/src/util/io/pem/test/AllTests.cs
index 921c40cb8..c0ca667f5 100644
--- a/crypto/test/src/util/io/pem/test/AllTests.cs
+++ b/crypto/test/src/util/io/pem/test/AllTests.cs
@@ -63,6 +63,14 @@ namespace Org.BouncyCastle.Utilities.IO.Pem.Tests
 			lengthTest("RSA PRIVATE KEY", headers, new byte[103]);
 		}
 
+        [Test]
+        public void TestMalformed()
+        {
+            PemReader rd = new PemReader(new StringReader("-----BEGIN \n"));
+
+            Assert.IsNull(rd.ReadPemObject());
+        }
+
 		private void lengthTest(string type, IList headers, byte[] data)
 		{
 			StringWriter sw = new StringWriter();
diff --git a/crypto/test/src/util/test/SimpleTest.cs b/crypto/test/src/util/test/SimpleTest.cs
index 2e24964e2..89df289c6 100644
--- a/crypto/test/src/util/test/SimpleTest.cs
+++ b/crypto/test/src/util/test/SimpleTest.cs
@@ -91,12 +91,15 @@ namespace Org.BouncyCastle.Utilities.Test
                 throw new TestFailedException(SimpleTestResult.Failed(this, message));
         }
 
-        internal bool AreEqual(
-            byte[] a,
-            byte[] b)
+        internal bool AreEqual(byte[] a, byte[] b)
         {
-			return Arrays.AreEqual(a, b);
-		}
+            return Arrays.AreEqual(a, b);
+        }
+
+        internal bool AreEqual(byte[] a, int aFromIndex, int aToIndex, byte[] b, int bFromIndex, int bToIndex)
+        {
+            return Arrays.AreEqual(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex);
+        }
 
 		public virtual ITestResult Perform()
         {