summary refs log tree commit diff
path: root/crypto/test/src
diff options
context:
space:
mode:
authorDavid Hook <david.hook@keyfactor.com>2022-11-07 17:30:00 +1100
committerDavid Hook <david.hook@keyfactor.com>2022-11-07 17:30:00 +1100
commit146be77300207031b6b9477b8e48428278e841b8 (patch)
treed7342aad04bca424b56229d1d5eba558bbb4afd3 /crypto/test/src
parentresolve conflicts (diff)
parentGOST 2012 private key reading (diff)
downloadBouncyCastle.NET-ed25519-146be77300207031b6b9477b8e48428278e841b8.tar.xz
Merge branch 'master' of gitlab.cryptoworkshop.com:root/bc-csharp
Diffstat (limited to 'crypto/test/src')
-rw-r--r--crypto/test/src/cms/test/CMSTestUtil.cs10
-rw-r--r--crypto/test/src/cms/test/SignedDataStreamTest.cs112
-rw-r--r--crypto/test/src/crypto/test/HkdfGeneratorTest.cs (renamed from crypto/test/src/crypto/test/HKDFGeneratorTest.cs)0
-rw-r--r--crypto/test/src/math/ec/test/ECPointPerformanceTest.cs14
-rw-r--r--crypto/test/src/math/test/BigIntegerTest.cs2
-rw-r--r--crypto/test/src/openpgp/test/DSA2Test.cs14
-rw-r--r--crypto/test/src/openpgp/test/PgpECDHTest.cs74
-rw-r--r--crypto/test/src/openpgp/test/PgpEdDsaTest.cs334
-rw-r--r--crypto/test/src/openpgp/test/PgpKeyRingTest.cs79
-rw-r--r--crypto/test/src/openssl/test/ReaderTest.cs18
-rw-r--r--crypto/test/src/security/test/TestDotNetUtil.cs32
-rw-r--r--crypto/test/src/tls/test/LoggingDatagramTransport.cs62
-rw-r--r--crypto/test/src/tls/test/MockDatagramAssociation.cs59
-rw-r--r--crypto/test/src/tls/test/UnreliableDatagramTransport.cs47
-rw-r--r--crypto/test/src/tsp/test/TSPTestUtil.cs2
-rw-r--r--crypto/test/src/util/test/SimpleTest.cs4
16 files changed, 826 insertions, 37 deletions
diff --git a/crypto/test/src/cms/test/CMSTestUtil.cs b/crypto/test/src/cms/test/CMSTestUtil.cs
index e98810c84..e7ec50f53 100644
--- a/crypto/test/src/cms/test/CMSTestUtil.cs
+++ b/crypto/test/src/cms/test/CMSTestUtil.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
 using System.IO;
 using System.Text;
 
+using Org.BouncyCastle.Asn1;
 using Org.BouncyCastle.Asn1.CryptoPro;
 using Org.BouncyCastle.Asn1.X509;
 using Org.BouncyCastle.Crypto;
@@ -455,6 +456,15 @@ namespace Org.BouncyCastle.Cms.Tests
 			return CollectionUtilities.CreateStore(crlList);
         }
 
+        internal static IStore<Asn1Encodable> MakeOtherRevocationInfoStore(byte[] ocspResponseBytes)
+        {
+            var otherRevocationInfoList = new List<Asn1Encodable>
+            {
+                Asn1Object.FromByteArray(ocspResponseBytes)
+            };
+            return CollectionUtilities.CreateStore(otherRevocationInfoList);
+        }
+
         private static AuthorityKeyIdentifier CreateAuthorityKeyId(
 			AsymmetricKeyParameter _pubKey)
 		{
diff --git a/crypto/test/src/cms/test/SignedDataStreamTest.cs b/crypto/test/src/cms/test/SignedDataStreamTest.cs
index 37f41783d..3d7892c6d 100644
--- a/crypto/test/src/cms/test/SignedDataStreamTest.cs
+++ b/crypto/test/src/cms/test/SignedDataStreamTest.cs
@@ -38,6 +38,40 @@ namespace Org.BouncyCastle.Cms.Tests
 		private static X509Crl signCrl;
 		private static X509Crl origCrl;
 
+		private static readonly byte[] OcspResponseBytes = Base64.Decode(
+			"MIIFnAoBAKCCBZUwggWRBgkrBgEFBQcwAQEEggWCMIIFfjCCARehgZ8wgZwx"
+			+ "CzAJBgNVBAYTAklOMRcwFQYDVQQIEw5BbmRocmEgcHJhZGVzaDESMBAGA1UE"
+			+ "BxMJSHlkZXJhYmFkMQwwCgYDVQQKEwNUQ1MxDDAKBgNVBAsTA0FUQzEeMBwG"
+			+ "A1UEAxMVVENTLUNBIE9DU1AgUmVzcG9uZGVyMSQwIgYJKoZIhvcNAQkBFhVv"
+			+ "Y3NwQHRjcy1jYS50Y3MuY28uaW4YDzIwMDMwNDAyMTIzNDU4WjBiMGAwOjAJ"
+			+ "BgUrDgMCGgUABBRs07IuoCWNmcEl1oHwIak1BPnX8QQUtGyl/iL9WJ1VxjxF"
+			+ "j0hAwJ/s1AcCAQKhERgPMjAwMjA4MjkwNzA5MjZaGA8yMDAzMDQwMjEyMzQ1"
+			+ "OFowDQYJKoZIhvcNAQEFBQADgYEAfbN0TCRFKdhsmvOdUoiJ+qvygGBzDxD/"
+			+ "VWhXYA+16AphHLIWNABR3CgHB3zWtdy2j7DJmQ/R7qKj7dUhWLSqclAiPgFt"
+			+ "QQ1YvSJAYfEIdyHkxv4NP0LSogxrumANcDyC9yt/W9yHjD2ICPBIqCsZLuLk"
+			+ "OHYi5DlwWe9Zm9VFwCGgggPMMIIDyDCCA8QwggKsoAMCAQICAQYwDQYJKoZI"
+			+ "hvcNAQEFBQAwgZQxFDASBgNVBAMTC1RDUy1DQSBPQ1NQMSYwJAYJKoZIhvcN"
+			+ "AQkBFhd0Y3MtY2FAdGNzLWNhLnRjcy5jby5pbjEMMAoGA1UEChMDVENTMQww"
+			+ "CgYDVQQLEwNBVEMxEjAQBgNVBAcTCUh5ZGVyYWJhZDEXMBUGA1UECBMOQW5k"
+			+ "aHJhIHByYWRlc2gxCzAJBgNVBAYTAklOMB4XDTAyMDgyOTA3MTE0M1oXDTAz"
+			+ "MDgyOTA3MTE0M1owgZwxCzAJBgNVBAYTAklOMRcwFQYDVQQIEw5BbmRocmEg"
+			+ "cHJhZGVzaDESMBAGA1UEBxMJSHlkZXJhYmFkMQwwCgYDVQQKEwNUQ1MxDDAK"
+			+ "BgNVBAsTA0FUQzEeMBwGA1UEAxMVVENTLUNBIE9DU1AgUmVzcG9uZGVyMSQw"
+			+ "IgYJKoZIhvcNAQkBFhVvY3NwQHRjcy1jYS50Y3MuY28uaW4wgZ8wDQYJKoZI"
+			+ "hvcNAQEBBQADgY0AMIGJAoGBAM+XWW4caMRv46D7L6Bv8iwtKgmQu0SAybmF"
+			+ "RJiz12qXzdvTLt8C75OdgmUomxp0+gW/4XlTPUqOMQWv463aZRv9Ust4f8MH"
+			+ "EJh4ekP/NS9+d8vEO3P40ntQkmSMcFmtA9E1koUtQ3MSJlcs441JjbgUaVnm"
+			+ "jDmmniQnZY4bU3tVAgMBAAGjgZowgZcwDAYDVR0TAQH/BAIwADALBgNVHQ8E"
+			+ "BAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwkwNgYIKwYBBQUHAQEEKjAoMCYG"
+			+ "CCsGAQUFBzABhhpodHRwOi8vMTcyLjE5LjQwLjExMDo3NzAwLzAtBgNVHR8E"
+			+ "JjAkMCKgIKAehhxodHRwOi8vMTcyLjE5LjQwLjExMC9jcmwuY3JsMA0GCSqG"
+			+ "SIb3DQEBBQUAA4IBAQB6FovM3B4VDDZ15o12gnADZsIk9fTAczLlcrmXLNN4"
+			+ "PgmqgnwF0Ymj3bD5SavDOXxbA65AZJ7rBNAguLUo+xVkgxmoBH7R2sBxjTCc"
+			+ "r07NEadxM3HQkt0aX5XYEl8eRoifwqYAI9h0ziZfTNes8elNfb3DoPPjqq6V"
+			+ "mMg0f0iMS4W8LjNPorjRB+kIosa1deAGPhq0eJ8yr0/s2QR2/WFD5P4aXc8I"
+			+ "KWleklnIImS3zqiPrq6tl2Bm8DZj7vXlTOwmraSQxUwzCKwYob1yGvNOUQTq"
+			+ "pG6jxn7jgDawHU1+WjWQe4Q34/pWeGLysxTraMa+Ug9kPe+jy/qRX2xwvKBZ");
+
 		private static AsymmetricCipherKeyPair SignKP
 		{
 			get { return signKP == null ? (signKP = CmsTestUtil.MakeKeyPair()) : signKP; }
@@ -341,7 +375,83 @@ namespace Org.BouncyCastle.Cms.Tests
 			Assert.IsTrue(col.Contains(OrigCrl));
 		}
 
-		[Test]
+        [Test]
+        public void TestCrlAndOtherRevocationInfoFormat()
+        {
+            MemoryStream bOut = new MemoryStream();
+
+            var x509Certs = CmsTestUtil.MakeCertStore(OrigCert, SignCert);
+            var x509Crls = CmsTestUtil.MakeCrlStore(SignCrl, OrigCrl);
+			var x509OtherRevocationInfos = CmsTestUtil.MakeOtherRevocationInfoStore(OcspResponseBytes);
+
+            CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
+            gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedGenerator.DigestSha1);
+            gen.AddCertificates(x509Certs);
+            gen.AddCrls(x509Crls);
+            gen.AddOtherRevocationInfos(CmsObjectIdentifiers.id_ri_ocsp_response, x509OtherRevocationInfos);
+
+            Stream sigOut = gen.Open(bOut);
+
+            byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage);
+            sigOut.Write(testBytes, 0, testBytes.Length);
+
+            sigOut.Close();
+
+            CheckSigParseable(bOut.ToArray());
+
+            CmsSignedDataParser sp = new CmsSignedDataParser(
+                new CmsTypedStream(new MemoryStream(testBytes, false)), bOut.ToArray());
+
+            sp.GetSignedContent().Drain();
+
+            // compute expected content digest
+            byte[] hash = DigestUtilities.CalculateDigest("SHA1", testBytes);
+
+            VerifySignatures(sp, hash);
+
+            //
+            // try using existing signer
+            //
+            gen = new CmsSignedDataStreamGenerator();
+            gen.AddSigners(sp.GetSignerInfos());
+            gen.AddCertificates(sp.GetCertificates());
+            gen.AddCrls(sp.GetCrls());
+
+            var spOtherRevocationInfos = sp.GetOtherRevInfos(CmsObjectIdentifiers.id_ri_ocsp_response);
+            gen.AddOtherRevocationInfos(CmsObjectIdentifiers.id_ri_ocsp_response, spOtherRevocationInfos);
+
+            bOut.SetLength(0);
+
+            sigOut = gen.Open(bOut, true);
+            sigOut.Write(testBytes, 0, testBytes.Length);
+            sigOut.Close();
+
+            VerifyEncodedData(bOut);
+
+            //
+            // look for the CRLs
+            //
+            var crls = new List<X509Crl>(x509Crls.EnumerateMatches(null));
+
+            Assert.AreEqual(2, crls.Count);
+            Assert.IsTrue(crls.Contains(SignCrl));
+            Assert.IsTrue(crls.Contains(OrigCrl));
+
+            //
+            // look for OtherRevocationInfo
+            //
+            var x509OtherRevocationInfoList = new List<Asn1Encodable>(
+				x509OtherRevocationInfos.EnumerateMatches(null));
+
+            Assert.AreEqual(1, x509OtherRevocationInfoList.Count);
+
+            var spOtherRevocationInfoList = new List<Asn1Encodable>(
+                spOtherRevocationInfos.EnumerateMatches(null));
+
+            Assert.AreEqual(1, spOtherRevocationInfoList.Count);
+        }
+
+        [Test]
 		public void TestSha1WithRsaNonData()
 		{
 			MemoryStream bOut = new MemoryStream();
diff --git a/crypto/test/src/crypto/test/HKDFGeneratorTest.cs b/crypto/test/src/crypto/test/HkdfGeneratorTest.cs
index fa540e41e..fa540e41e 100644
--- a/crypto/test/src/crypto/test/HKDFGeneratorTest.cs
+++ b/crypto/test/src/crypto/test/HkdfGeneratorTest.cs
diff --git a/crypto/test/src/math/ec/test/ECPointPerformanceTest.cs b/crypto/test/src/math/ec/test/ECPointPerformanceTest.cs
index 18051226b..49ae6d195 100644
--- a/crypto/test/src/math/ec/test/ECPointPerformanceTest.cs
+++ b/crypto/test/src/math/ec/test/ECPointPerformanceTest.cs
@@ -29,7 +29,7 @@ namespace Org.BouncyCastle.Math.EC.Tests
         private static string[] COORD_NAMES = new string[]{ "AFFINE", "HOMOGENEOUS", "JACOBIAN", "JACOBIAN-CHUDNOVSKY",
             "JACOBIAN-MODIFIED", "LAMBDA-AFFINE", "LAMBDA-PROJECTIVE", "SKEWED" };
 
-        private void RandMult(string curveName)
+        private static void RandMult(string curveName)
         {
             X9ECParameters spec = ECNamedCurveTable.GetByName(curveName);
             if (spec != null)
@@ -44,13 +44,13 @@ namespace Org.BouncyCastle.Math.EC.Tests
             }
         }
 
-        private void RandMult(string label, X9ECParameters spec)
+        private static void RandMult(string label, X9ECParameters spec)
         {
             ECCurve C = spec.Curve;
-            ECPoint G = (ECPoint)spec.G;
+            ECPoint G = spec.G;
             BigInteger n = spec.N;
 
-            SecureRandom random = new SecureRandom();
+            var random = new SecureRandom();
             random.SetSeed(DateTimeUtilities.CurrentUnixMs());
 
             Console.WriteLine(label);
@@ -98,7 +98,7 @@ namespace Org.BouncyCastle.Math.EC.Tests
             Console.Out.Flush();
         }
 
-        private double RandMult(SecureRandom random, ECPoint g, BigInteger n)
+        private static double RandMult(SecureRandom random, ECPoint g, BigInteger n)
         {
             BigInteger[] ks = new BigInteger[128];
             for (int i = 0; i < ks.Length; ++i)
@@ -107,7 +107,7 @@ namespace Org.BouncyCastle.Math.EC.Tests
             }
 
             int ki = 0;
-            ECPoint p = g;
+            ECPoint p;
 
             {
                 long startTime = DateTimeUtilities.CurrentUnixMs();
@@ -129,7 +129,7 @@ namespace Org.BouncyCastle.Math.EC.Tests
                 while (DateTimeUtilities.CurrentUnixMs() < goalTime);
             }
 
-            double minRate = Double.MaxValue, maxRate = Double.MinValue, totalRate = 0.0;
+            double minRate = double.MaxValue, maxRate = double.MinValue, totalRate = 0.0;
 
             for (int i = 1; i <= NUM_ROUNDS; i++)
             {
diff --git a/crypto/test/src/math/test/BigIntegerTest.cs b/crypto/test/src/math/test/BigIntegerTest.cs
index f5973c197..8f477d684 100644
--- a/crypto/test/src/math/test/BigIntegerTest.cs
+++ b/crypto/test/src/math/test/BigIntegerTest.cs
@@ -773,11 +773,13 @@ namespace Org.BouncyCastle.Math.Tests
                 BigInteger x = new BigInteger(128, random);
                 object y;
 
+#pragma warning disable SYSLIB0011 // Type or member is obsolete
                 var formatter = new BinaryFormatter();
                 formatter.Serialize(buf, x);
 
                 buf.Position = 0;
                 y = formatter.Deserialize(buf);
+#pragma warning restore SYSLIB0011 // Type or member is obsolete
 
                 Assert.AreEqual(buf.Length, buf.Position);
                 Assert.AreEqual(x, y);
diff --git a/crypto/test/src/openpgp/test/DSA2Test.cs b/crypto/test/src/openpgp/test/DSA2Test.cs
index 507afceae..54c2cb2b5 100644
--- a/crypto/test/src/openpgp/test/DSA2Test.cs
+++ b/crypto/test/src/openpgp/test/DSA2Test.cs
@@ -73,40 +73,40 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
 		[Test]
 		public void TestGenerateK1024H224()
 		{
-			doSigGenerateTest("DSA-1024-160.sec", "DSA-1024-160.pub", HashAlgorithmTag.Sha224);
+			DoSigGenerateTest("DSA-1024-160.sec", "DSA-1024-160.pub", HashAlgorithmTag.Sha224);
 		}
 
 		[Test]
 		public void TestGenerateK1024H256()
 		{
-			doSigGenerateTest("DSA-1024-160.sec", "DSA-1024-160.pub", HashAlgorithmTag.Sha256);
+			DoSigGenerateTest("DSA-1024-160.sec", "DSA-1024-160.pub", HashAlgorithmTag.Sha256);
 		}
 
 		[Test]
 		public void TestGenerateK1024H384()
 		{
-			doSigGenerateTest("DSA-1024-160.sec", "DSA-1024-160.pub", HashAlgorithmTag.Sha384);
+			DoSigGenerateTest("DSA-1024-160.sec", "DSA-1024-160.pub", HashAlgorithmTag.Sha384);
 		}
 
 		[Test]
 		public void TestGenerateK1024H512()
 		{
-			doSigGenerateTest("DSA-1024-160.sec", "DSA-1024-160.pub", HashAlgorithmTag.Sha512);
+			DoSigGenerateTest("DSA-1024-160.sec", "DSA-1024-160.pub", HashAlgorithmTag.Sha512);
 		}
 
 		[Test]
 		public void TestGenerateK2048H256()
 		{
-			doSigGenerateTest("DSA-2048-224.sec", "DSA-2048-224.pub", HashAlgorithmTag.Sha256);
+			DoSigGenerateTest("DSA-2048-224.sec", "DSA-2048-224.pub", HashAlgorithmTag.Sha256);
 		}
 
 		[Test]
 		public void TestGenerateK2048H512()
 		{
-			doSigGenerateTest("DSA-2048-224.sec", "DSA-2048-224.pub", HashAlgorithmTag.Sha512);
+			DoSigGenerateTest("DSA-2048-224.sec", "DSA-2048-224.pub", HashAlgorithmTag.Sha512);
 		}
 
-		private void doSigGenerateTest(
+		private void DoSigGenerateTest(
 			string				privateKeyFile,
 			string				publicKeyFile,
 			HashAlgorithmTag	digest)
diff --git a/crypto/test/src/openpgp/test/PgpECDHTest.cs b/crypto/test/src/openpgp/test/PgpECDHTest.cs
index aa4fc2117..45dd641f1 100644
--- a/crypto/test/src/openpgp/test/PgpECDHTest.cs
+++ b/crypto/test/src/openpgp/test/PgpECDHTest.cs
@@ -51,6 +51,41 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
                 "6HiuFH7VKWcxPUBjXwf5+Z3uOKEp28tBgNyDrdbr1BbqlgYzIKq/pe9zUbUXfitn" +
                 "vFc6HcGhvmRQreQ+Yw1x3x0HJeoPwg==");
 
+        private static readonly byte[] curve25519Message = Base64.Decode(
+            "hE4Dg5N9lpwvavoSAQdApL1xhvz/28almLuqHjyrzwVRnB+37yODIRZCkfPk"
+          + "GEIgd9uff5j8mYbI9ErePgRI47fDnQPu8mI4hTOhe8pHzyXSTwFf5CesSdME"
+          + "Td9g+UG6cYt/i+cHQWMQD7a53fMNFxPGVYLUFXC5cQh+KvBPghfdoFQMhbR+"
+          + "GDgauMrgtk//Os0WCYWJa7VZkD5ak3sbMwk=");
+
+        //private static readonly byte[] curve25519Pub =    Base64.Decode(
+        //    "mDMEXEzydhYJKwYBBAHaRw8BAQdAwHPDYhq7hIsCT0jHNxGh4Mbao9kDkcHZilME" +
+        //    "jfgnnG60N1Rlc3QgS2V5IChEbyBub3QgdXNlIGZvciByZWFsLikgPHRlc3RAd29v" +
+        //    "ZHMtZ2VibGVyLmNvbT6IlgQTFggAPhYhBIuq+f4gKmIa9ZKEqJdUhr00IJstBQJc" +
+        //    "TPJ2AhsDBQkB4TOABQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAAAoJEJdUhr00IJst" +
+        //    "dHAA/RDOjus5OZL2m9Q9dxOVnWNguT7Cr5cWdJxUeKAWE2c6AQCcQZWA4SmV1dkJ" +
+        //    "U0XKmLeu3xWDpqrydT4+vQXb/Qm9B7g4BFxM8nYSCisGAQQBl1UBBQEBB0AY3XTS" +
+        //    "6S1pwFNc1QhNpEKTStG+LAJpiHPK9QyXBbW9dQMBCAeIfgQYFggAJhYhBIuq+f4g" +
+        //    "KmIa9ZKEqJdUhr00IJstBQJcTPJ2AhsMBQkB4TOAAAoJEJdUhr00IJstmAsBAMRJ" +
+        //    "pvh8iegwrJDMoQc53ZqDRsbieElV6ofB80a+jkzZAQCgpAaY4hZc8GUan2JIqkg0" +
+        //    "gs23h4au7H79KqXYG4a+Bg==");
+
+        private static readonly byte[] curve25519Priv = Base64.Decode(
+        "lIYEXEzydhYJKwYBBAHaRw8BAQdAwHPDYhq7hIsCT0jHNxGh4Mbao9kDkcHZilME" +
+            "jfgnnG7+BwMCgEr7OFDl3dTpT73rmw6vIwiTGqjx+Xbe8cq4l24q2AOtzO+UR97q" +
+            "7ypL41jtt7BY7uoxhF+NCKzYEtRoqyaM0lfjDlOVRJP6SYRixK2UHLQ3VGVzdCBL" +
+            "ZXkgKERvIG5vdCB1c2UgZm9yIHJlYWwuKSA8dGVzdEB3b29kcy1nZWJsZXIuY29t" +
+            "PoiWBBMWCAA+FiEEi6r5/iAqYhr1koSol1SGvTQgmy0FAlxM8nYCGwMFCQHhM4AF" +
+            "CwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQl1SGvTQgmy10cAD9EM6O6zk5kvab" +
+            "1D13E5WdY2C5PsKvlxZ0nFR4oBYTZzoBAJxBlYDhKZXV2QlTRcqYt67fFYOmqvJ1" +
+            "Pj69Bdv9Cb0HnIsEXEzydhIKKwYBBAGXVQEFAQEHQBjddNLpLWnAU1zVCE2kQpNK" +
+            "0b4sAmmIc8r1DJcFtb11AwEIB/4HAwItKjH+kGqkMelkEdIRxSLFeCsB/A64n+os" +
+            "X9nWVYsrixEWT5JcRWBniI1PKt9Cm15Yt8KQSAFDJIj5tnEm28x5RM0CzFHQ9Ej2" +
+            "8Q2Lt0RoiH4EGBYIACYWIQSLqvn+ICpiGvWShKiXVIa9NCCbLQUCXEzydgIbDAUJ" +
+            "AeEzgAAKCRCXVIa9NCCbLZgLAQDESab4fInoMKyQzKEHOd2ag0bG4nhJVeqHwfNG" +
+            "vo5M2QEAoKQGmOIWXPBlGp9iSKpINILNt4eGrux+/Sql2BuGvgY=");
+
+        private static readonly char[] curve25519Pwd = "foobar".ToCharArray();
+
         private void Generate()
         {
             SecureRandom random = SecureRandom.GetInstance("SHA1PRNG");
@@ -105,6 +140,41 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
             PgpPrivateKey pgpPrivKey = secRing.GetSecretKey().ExtractPrivateKey(passPhrase);
         }
 
+        private void TestCurve25519Message()
+        {
+            PgpSecretKeyRing ring = new PgpSecretKeyRing(curve25519Priv);
+
+            PgpObjectFactory pgpF = new PgpObjectFactory(curve25519Message);
+
+            PgpEncryptedDataList encList = (PgpEncryptedDataList)pgpF.NextPgpObject();
+
+            PgpPublicKeyEncryptedData encP = (PgpPublicKeyEncryptedData)encList[0];
+
+            Stream clear = encP.GetDataStream(ring.GetSecretKey(encP.KeyId).ExtractPrivateKey(curve25519Pwd));
+
+            pgpF = new PgpObjectFactory(clear);
+
+            PgpCompressedData cd = (PgpCompressedData)pgpF.NextPgpObject();
+
+            PgpLiteralData ld = (PgpLiteralData)new PgpObjectFactory(cd.GetDataStream()).NextPgpObject();
+
+            clear = ld.GetInputStream();
+            MemoryStream bOut = new MemoryStream();
+
+            int ch;
+            while ((ch = clear.ReadByte()) >= 0)
+            {
+                bOut.WriteByte((byte)ch);
+            }
+
+            byte[] output = bOut.ToArray();
+
+            if (!AreEqual(output, Strings.ToByteArray("Hello world\n")))
+            {
+                Fail("wrong plain text in generated packet");
+            }
+        }
+
         private void TestDecrypt(PgpSecretKeyRing secretKeyRing)
         {
             PgpObjectFactory pgpF = new PgpObjectFactory(testMessage);
@@ -215,6 +285,8 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
 
             EncryptDecryptTest();
 
+            TestCurve25519Message();
+
             Generate();
         }
 
@@ -240,7 +312,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
                     {
                         certification.InitVerify(pubKeyRing.GetPublicKey());
 
-                        if (!certification.VerifyCertification((string)First(pubKeyRing.GetPublicKey().GetUserIds()), pubKeyRing.GetPublicKey()))
+                        if (!certification.VerifyCertification(First(pubKeyRing.GetPublicKey().GetUserIds()), pubKeyRing.GetPublicKey()))
                         {
                             Fail("subkey certification does not verify");
                         }
diff --git a/crypto/test/src/openpgp/test/PgpEdDsaTest.cs b/crypto/test/src/openpgp/test/PgpEdDsaTest.cs
new file mode 100644
index 000000000..c5b25320c
--- /dev/null
+++ b/crypto/test/src/openpgp/test/PgpEdDsaTest.cs
@@ -0,0 +1,334 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
+{
+    [TestFixture]
+    public class PgpEdDsaTest
+        : SimpleTest
+    {
+        private static readonly string edDSASampleKey =
+            "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
+                "Comment: Alice's OpenPGP certificate\n" +
+                "Comment: https://www.ietf.org/id/draft-bre-openpgp-samples-01.html\n" +
+                "\n" +
+                "mDMEXEcE6RYJKwYBBAHaRw8BAQdArjWwk3FAqyiFbFBKT4TzXcVBqPTB3gmzlC/U\n" +
+                "b7O1u120JkFsaWNlIExvdmVsYWNlIDxhbGljZUBvcGVucGdwLmV4YW1wbGU+iJAE\n" +
+                "ExYIADgCGwMFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AWIQTrhbtfozp14V6UTmPy\n" +
+                "MVUMT0fjjgUCXaWfOgAKCRDyMVUMT0fjjukrAPoDnHBSogOmsHOsd9qGsiZpgRnO\n" +
+                "dypvbm+QtXZqth9rvwD9HcDC0tC+PHAsO7OTh1S1TC9RiJsvawAfCPaQZoed8gK4\n" +
+                "OARcRwTpEgorBgEEAZdVAQUBAQdAQv8GIa2rSTzgqbXCpDDYMiKRVitCsy203x3s\n" +
+                "E9+eviIDAQgHiHgEGBYIACAWIQTrhbtfozp14V6UTmPyMVUMT0fjjgUCXEcE6QIb\n" +
+                "DAAKCRDyMVUMT0fjjlnQAQDFHUs6TIcxrNTtEZFjUFm1M0PJ1Dng/cDW4xN80fsn\n" +
+                "0QEA22Kr7VkCjeAEC08VSTeV+QFsmz55/lntWkwYWhmvOgE=\n" +
+                "=iIGO\n" +
+                "-----END PGP PUBLIC KEY BLOCK-----\n";
+
+        private static readonly string edDSASecretKey =
+            "-----BEGIN PGP PRIVATE KEY BLOCK-----\n" +
+                "Comment: Alice's OpenPGP Transferable Secret Key\n" +
+                "Comment: https://www.ietf.org/id/draft-bre-openpgp-samples-01.html\n" +
+                "\n" +
+                "lFgEXEcE6RYJKwYBBAHaRw8BAQdArjWwk3FAqyiFbFBKT4TzXcVBqPTB3gmzlC/U\n" +
+                "b7O1u10AAP9XBeW6lzGOLx7zHH9AsUDUTb2pggYGMzd0P3ulJ2AfvQ4RtCZBbGlj\n" +
+                "ZSBMb3ZlbGFjZSA8YWxpY2VAb3BlbnBncC5leGFtcGxlPoiQBBMWCAA4AhsDBQsJ\n" +
+                "CAcCBhUKCQgLAgQWAgMBAh4BAheAFiEE64W7X6M6deFelE5j8jFVDE9H444FAl2l\n" +
+                "nzoACgkQ8jFVDE9H447pKwD6A5xwUqIDprBzrHfahrImaYEZzncqb25vkLV2arYf\n" +
+                "a78A/R3AwtLQvjxwLDuzk4dUtUwvUYibL2sAHwj2kGaHnfICnF0EXEcE6RIKKwYB\n" +
+                "BAGXVQEFAQEHQEL/BiGtq0k84Km1wqQw2DIikVYrQrMttN8d7BPfnr4iAwEIBwAA\n" +
+                "/3/xFPG6U17rhTuq+07gmEvaFYKfxRB6sgAYiW6TMTpQEK6IeAQYFggAIBYhBOuF\n" +
+                "u1+jOnXhXpROY/IxVQxPR+OOBQJcRwTpAhsMAAoJEPIxVQxPR+OOWdABAMUdSzpM\n" +
+                "hzGs1O0RkWNQWbUzQ8nUOeD9wNbjE3zR+yfRAQDbYqvtWQKN4AQLTxVJN5X5AWyb\n" +
+                "Pnn+We1aTBhaGa86AQ==\n" +
+                "=n8OM\n" +
+                "-----END PGP PRIVATE KEY BLOCK-----\n";
+
+        private static readonly string revBlock =
+            "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
+                "Comment: Alice's revocation certificate\n" +
+                "Comment: https://www.ietf.org/id/draft-bre-openpgp-samples-01.html\n" +
+                "\n" +
+                "iHgEIBYIACAWIQTrhbtfozp14V6UTmPyMVUMT0fjjgUCXaWkOwIdAAAKCRDyMVUM\n" +
+                "T0fjjoBlAQDA9ukZFKRFGCooVcVoDVmxTaHLUXlIg9TPh2f7zzI9KgD/SLNXUOaH\n" +
+                "O6TozOS7C9lwIHwwdHdAxgf5BzuhLT9iuAM=\n" +
+                "=Tm8h\n" +
+                "-----END PGP PUBLIC KEY BLOCK-----\n";
+
+        public override string Name
+        {
+            get { return "PgpEdDsaTest"; }
+        }
+
+        private void EncryptDecryptTest(PgpPublicKey pubKey, PgpPrivateKey secKey)
+        {
+            byte[] text = {(byte)'h', (byte)'e', (byte)'l', (byte)'l', (byte)'o', (byte)' ', (byte)'w', (byte)'o', (byte)'r', (byte)'l', (byte)'d', (byte)'!', (byte)'\n'};
+
+            PgpLiteralDataGenerator lData = new PgpLiteralDataGenerator();
+            MemoryStream ldOut = new MemoryStream();
+            Stream pOut = lData.Open(ldOut, PgpLiteralDataGenerator.Utf8, PgpLiteralData.Console, text.Length, DateTime.UtcNow);
+
+            pOut.Write(text, 0, text.Length);
+            pOut.Close();
+
+            byte[] data = ldOut.ToArray();
+
+            MemoryStream cbOut = new MemoryStream();
+
+            PgpEncryptedDataGenerator cPk = new PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag.Cast5, new SecureRandom());
+            cPk.AddMethod(pubKey);
+
+            Stream cOut = cPk.Open(new UncloseableStream(cbOut), data.Length);
+
+            cOut.Write(data, 0, data.Length);
+            cOut.Close();
+
+            PgpObjectFactory pgpF = new PgpObjectFactory(cbOut.ToArray());
+
+            PgpEncryptedDataList encList = (PgpEncryptedDataList)pgpF.NextPgpObject();
+
+            PgpPublicKeyEncryptedData encP = (PgpPublicKeyEncryptedData)encList[0];
+
+            Stream clear = encP.GetDataStream(secKey);
+
+            pgpF = new PgpObjectFactory(clear);
+
+            PgpLiteralData ld = (PgpLiteralData)pgpF.NextPgpObject();
+
+            clear = ld.GetInputStream();
+            MemoryStream bOut = new MemoryStream();
+
+            int ch;
+            while ((ch = clear.ReadByte()) >= 0)
+            {
+                bOut.WriteByte((byte)ch);
+            }
+
+            byte[] output = bOut.ToArray();
+
+            if (!AreEqual(output, text))
+            {
+                Fail("wrong plain text in generated packet");
+            }
+        }
+
+        private void KeyRingTest()
+        {
+            SecureRandom random = new SecureRandom();
+
+            string identity = "eric@bouncycastle.org";
+            char[] passPhrase = "Hello, world!".ToCharArray();
+
+            Ed25519KeyPairGenerator edKp = new Ed25519KeyPairGenerator();
+            edKp.Init(new Ed25519KeyGenerationParameters(random));
+
+            PgpKeyPair dsaKeyPair = new PgpKeyPair(PublicKeyAlgorithmTag.EdDsa, edKp.GenerateKeyPair(), DateTime.UtcNow);
+
+            X25519KeyPairGenerator dhKp = new X25519KeyPairGenerator();
+            dhKp.Init(new X25519KeyGenerationParameters(random));
+
+            PgpKeyPair dhKeyPair = new PgpKeyPair(PublicKeyAlgorithmTag.ECDH, dhKp.GenerateKeyPair(), DateTime.UtcNow);
+
+            EncryptDecryptTest(dhKeyPair.PublicKey, dhKeyPair.PrivateKey);
+
+            PgpKeyRingGenerator keyRingGen = new PgpKeyRingGenerator(PgpSignature.PositiveCertification, dsaKeyPair,
+                identity, SymmetricKeyAlgorithmTag.Aes256, passPhrase, true, null, null, random);
+
+            keyRingGen.AddSubKey(dhKeyPair);
+
+            MemoryStream secretOut = new MemoryStream();
+
+            PgpSecretKeyRing secRing = keyRingGen.GenerateSecretKeyRing();
+
+            PgpPublicKeyRing pubRing = keyRingGen.GeneratePublicKeyRing();
+
+            secRing.Encode(secretOut);
+
+            secretOut.Close();
+            secRing = new PgpSecretKeyRing(secretOut.ToArray());
+
+            var publicKeys = new List<PgpPublicKey>(secRing.GetPublicKeys());
+
+            PgpPublicKey sKey = publicKeys[1];
+            PgpPublicKey vKey = secRing.GetPublicKey();
+
+            int count = 0;
+            foreach (var sig in sKey.GetSignatures())
+            {
+                if (sig.KeyId == vKey.KeyId
+                    && sig.SignatureType == PgpSignature.SubkeyBinding)
+                {
+                    count++;
+                    sig.InitVerify(vKey);
+
+                    if (!sig.VerifyCertification(vKey, sKey))
+                    {
+                        Fail("failed to verify sub-key signature.");
+                    }
+                }
+            }
+
+            IsTrue(count == 1);
+
+            secRing = new PgpSecretKeyRing(secretOut.ToArray());
+            PgpPublicKey pubKey = null;
+            PgpPrivateKey privKey = null;
+
+            foreach (var candidate in secRing.GetPublicKeys())
+            {
+                if (candidate.IsEncryptionKey)
+                {
+                    pubKey = candidate;
+                    privKey = secRing.GetSecretKey(pubKey.KeyId).ExtractPrivateKey(passPhrase);
+                    break;
+                }
+            }
+
+            EncryptDecryptTest(pubKey, privKey);
+        }
+
+        public override void PerformTest()
+        {
+            ArmoredInputStream aIn = new ArmoredInputStream(new MemoryStream(Strings.ToByteArray(edDSASampleKey), false));
+
+            PgpPublicKeyRing pubKeyRing = new PgpPublicKeyRing(aIn);
+
+            IsTrue(AreEqual(Hex.Decode("EB85 BB5F A33A 75E1 5E94 4E63 F231 550C 4F47 E38E"),
+                pubKeyRing.GetPublicKey().GetFingerprint()));
+
+            aIn = new ArmoredInputStream(new MemoryStream(Strings.ToByteArray(edDSASecretKey), false));
+
+            PgpSecretKeyRing secRing = new PgpSecretKeyRing(aIn);
+
+            IsTrue(secRing.GetSecretKey().IsSigningKey);
+
+            PgpSignatureGenerator pgpGen = new PgpSignatureGenerator(PublicKeyAlgorithmTag.EdDsa, HashAlgorithmTag.Sha256);
+
+            pgpGen.InitSign(PgpSignature.SubkeyBinding, secRing.GetSecretKey().ExtractPrivateKey(null));
+
+            PgpSignature sig = pgpGen.GenerateCertification(pubKeyRing.GetPublicKey(),
+                pubKeyRing.GetPublicKey(5145070902336167606L));
+
+            sig.InitVerify(pubKeyRing.GetPublicKey());
+
+            IsTrue(sig.VerifyCertification(pubKeyRing.GetPublicKey(), pubKeyRing.GetPublicKey(5145070902336167606L)));
+
+            EncryptDecryptTest(pubKeyRing.GetPublicKey(5145070902336167606L),
+                secRing.GetSecretKey(5145070902336167606L).ExtractPrivateKey(null));
+
+            aIn = new ArmoredInputStream(new MemoryStream(Strings.ToByteArray(revBlock), false));
+
+            PgpSignatureList sigs = (PgpSignatureList)new PgpObjectFactory(aIn).NextPgpObject();
+
+            sig = sigs[0];
+
+            sig.InitVerify(pubKeyRing.GetPublicKey());
+
+            IsTrue(sig.VerifyCertification(pubKeyRing.GetPublicKey()));
+
+            KeyRingTest();
+            SksKeyTest();
+            AliceKeyTest();
+        }
+
+        private void AliceKeyTest()
+        {
+            byte[] text = {(byte)'h', (byte)'e', (byte)'l', (byte)'l', (byte)'o', (byte)' ', (byte)'w', (byte)'o', (byte)'r', (byte)'l', (byte)'d', (byte)'!', (byte)'\n'};
+            ArmoredInputStream aIn = new ArmoredInputStream(new MemoryStream(Strings.ToByteArray(edDSASampleKey), false));
+
+            PgpPublicKeyRing rng = new PgpPublicKeyRing(aIn);
+
+            aIn = new ArmoredInputStream(new MemoryStream(Strings.ToByteArray(edDSASecretKey), false));
+
+            PgpSecretKeyRing secRing = new PgpSecretKeyRing(aIn);
+
+            PgpPublicKey pubKey = rng.GetPublicKey(5145070902336167606L);
+            PgpPrivateKey privKey = secRing.GetSecretKey(5145070902336167606L).ExtractPrivateKey(null);
+        
+            PgpLiteralDataGenerator lData = new PgpLiteralDataGenerator();
+            MemoryStream ldOut = new MemoryStream();
+            Stream pOut = lData.Open(ldOut, PgpLiteralDataGenerator.Utf8, PgpLiteralData.Console, text.Length, DateTime.UtcNow);
+
+            pOut.Write(text, 0, text.Length);
+            pOut.Close();
+
+            byte[] data = ldOut.ToArray();
+
+            MemoryStream cbOut = new MemoryStream();
+
+            PgpEncryptedDataGenerator cPk = new PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag.Aes128, true);
+
+            cPk.AddMethod(pubKey);
+
+            Stream cOut = cPk.Open(new UncloseableStream(cbOut), data.Length);
+
+            cOut.Write(data, 0, data.Length);
+            cOut.Close();
+
+            PgpObjectFactory pgpF = new PgpObjectFactory(cbOut.ToArray());
+
+            PgpEncryptedDataList encList = (PgpEncryptedDataList)pgpF.NextPgpObject();
+
+            PgpPublicKeyEncryptedData encP = (PgpPublicKeyEncryptedData)encList[0];
+
+            Stream clear = encP.GetDataStream(privKey);
+
+            pgpF = new PgpObjectFactory(clear);
+
+            PgpLiteralData ld = (PgpLiteralData)pgpF.NextPgpObject();
+
+            clear = ld.GetInputStream();
+            MemoryStream bOut = new MemoryStream();
+
+            int ch;
+            while ((ch = clear.ReadByte()) >= 0)
+            {
+                bOut.WriteByte((byte)ch);
+            }
+
+            byte[] output = bOut.ToArray();
+
+            if (!AreEqual(output, text))
+            {
+                Fail("wrong plain text in generated packet");
+            }
+        }
+
+        private void SksKeyTest()
+        {
+            byte[] data = Strings.ToByteArray("testing, 1, 2, 3, testing...");
+
+            ArmoredInputStream aIn = new ArmoredInputStream(GetTestDataAsStream("openpgp.eddsa-sks-pub-keyring.asc"));
+
+            // make sure we can parse it without falling over.
+            PgpPublicKeyRing rng = new PgpPublicKeyRing(aIn);
+
+            PgpEncryptedDataGenerator encDataGen = new PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag.Aes128, true);
+
+            encDataGen.AddMethod(rng.GetPublicKey(6752245936421807937L));
+
+            MemoryStream cbOut = new MemoryStream();
+
+            Stream cOut = encDataGen.Open(new UncloseableStream(cbOut), data.Length);
+            cOut.Write(data, 0, data.Length);
+            cOut.Close();
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/crypto/test/src/openpgp/test/PgpKeyRingTest.cs b/crypto/test/src/openpgp/test/PgpKeyRingTest.cs
index a5dc4963b..821a7f295 100644
--- a/crypto/test/src/openpgp/test/PgpKeyRingTest.cs
+++ b/crypto/test/src/openpgp/test/PgpKeyRingTest.cs
@@ -1346,6 +1346,35 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
           + "WDoIM5gfjeZgwht1vl6+7J+h20yjFrBdf7gJj9OcIGmwlpQ56qzbT4U++mw3"
           + "pW2tN2VuYtreceEoI4B6yUGMEhI9t/asLgn7wEAU2lpuE7ACAAM=");
 
+        private static readonly byte[] curve25519Pub = Base64.Decode(
+            "mDMEXEzydhYJKwYBBAHaRw8BAQdAwHPDYhq7hIsCT0jHNxGh4Mbao9kDkcHZilME" +
+            "jfgnnG60N1Rlc3QgS2V5IChEbyBub3QgdXNlIGZvciByZWFsLikgPHRlc3RAd29v" +
+            "ZHMtZ2VibGVyLmNvbT6IlgQTFggAPhYhBIuq+f4gKmIa9ZKEqJdUhr00IJstBQJc" +
+            "TPJ2AhsDBQkB4TOABQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAAAoJEJdUhr00IJst" +
+            "dHAA/RDOjus5OZL2m9Q9dxOVnWNguT7Cr5cWdJxUeKAWE2c6AQCcQZWA4SmV1dkJ" +
+            "U0XKmLeu3xWDpqrydT4+vQXb/Qm9B7g4BFxM8nYSCisGAQQBl1UBBQEBB0AY3XTS" +
+            "6S1pwFNc1QhNpEKTStG+LAJpiHPK9QyXBbW9dQMBCAeIfgQYFggAJhYhBIuq+f4g" +
+            "KmIa9ZKEqJdUhr00IJstBQJcTPJ2AhsMBQkB4TOAAAoJEJdUhr00IJstmAsBAMRJ" +
+            "pvh8iegwrJDMoQc53ZqDRsbieElV6ofB80a+jkzZAQCgpAaY4hZc8GUan2JIqkg0" +
+            "gs23h4au7H79KqXYG4a+Bg==");
+
+        private static readonly byte[] curve25519Priv = Base64.Decode(
+        "lIYEXEzydhYJKwYBBAHaRw8BAQdAwHPDYhq7hIsCT0jHNxGh4Mbao9kDkcHZilME" +
+            "jfgnnG7+BwMCgEr7OFDl3dTpT73rmw6vIwiTGqjx+Xbe8cq4l24q2AOtzO+UR97q" +
+            "7ypL41jtt7BY7uoxhF+NCKzYEtRoqyaM0lfjDlOVRJP6SYRixK2UHLQ3VGVzdCBL" +
+            "ZXkgKERvIG5vdCB1c2UgZm9yIHJlYWwuKSA8dGVzdEB3b29kcy1nZWJsZXIuY29t" +
+            "PoiWBBMWCAA+FiEEi6r5/iAqYhr1koSol1SGvTQgmy0FAlxM8nYCGwMFCQHhM4AF" +
+            "CwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQl1SGvTQgmy10cAD9EM6O6zk5kvab" +
+            "1D13E5WdY2C5PsKvlxZ0nFR4oBYTZzoBAJxBlYDhKZXV2QlTRcqYt67fFYOmqvJ1" +
+            "Pj69Bdv9Cb0HnIsEXEzydhIKKwYBBAGXVQEFAQEHQBjddNLpLWnAU1zVCE2kQpNK" +
+            "0b4sAmmIc8r1DJcFtb11AwEIB/4HAwItKjH+kGqkMelkEdIRxSLFeCsB/A64n+os" +
+            "X9nWVYsrixEWT5JcRWBniI1PKt9Cm15Yt8KQSAFDJIj5tnEm28x5RM0CzFHQ9Ej2" +
+            "8Q2Lt0RoiH4EGBYIACYWIQSLqvn+ICpiGvWShKiXVIa9NCCbLQUCXEzydgIbDAUJ" +
+            "AeEzgAAKCRCXVIa9NCCbLZgLAQDESab4fInoMKyQzKEHOd2ag0bG4nhJVeqHwfNG" +
+            "vo5M2QEAoKQGmOIWXPBlGp9iSKpINILNt4eGrux+/Sql2BuGvgY=");
+
+        //private static readonly char[] curve25519Pwd = "foobar".ToCharArray();
+
         [Test]
         public void PerformTest1()
         {
@@ -1744,15 +1773,12 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
         [Test]
         public void PerformTest4()
         {
-            PgpSecretKeyRingBundle secretRings1 = new PgpSecretKeyRingBundle(sec4);
-            int count = 0;
-
+            PgpSecretKeyRingBundle secretRings = new PgpSecretKeyRingBundle(sec4);
+            byte[] encRing = secretRings.GetEncoded();
+            secretRings = new PgpSecretKeyRingBundle(encRing);
 
-            byte[] encRing = secretRings1.GetEncoded();
-
-            PgpSecretKeyRingBundle secretRings2 = new PgpSecretKeyRingBundle(encRing);
-
-            foreach (PgpSecretKeyRing pgpSec1 in secretRings1.GetKeyRings())
+            int count = 0;
+            foreach (PgpSecretKeyRing pgpSec1 in secretRings.GetKeyRings())
             {
                 count++;
 
@@ -2486,22 +2512,22 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
         [Test]
         public void PublicKeyRingWithX509Test()
         {
-            checkPublicKeyRingWithX509(pubWithX509);
+            CheckPublicKeyRingWithX509(pubWithX509);
 
             PgpPublicKeyRing pubRing = new PgpPublicKeyRing(pubWithX509);
 
-            checkPublicKeyRingWithX509(pubRing.GetEncoded());
+            CheckPublicKeyRingWithX509(pubRing.GetEncoded());
         }
 
         [Test]
         public void SecretKeyRingWithPersonalCertificateTest()
         {
-            checkSecretKeyRingWithPersonalCertificate(secWithPersonalCertificate);
+            CheckSecretKeyRingWithPersonalCertificate(secWithPersonalCertificate);
             PgpSecretKeyRingBundle secRing = new PgpSecretKeyRingBundle(secWithPersonalCertificate);
-            checkSecretKeyRingWithPersonalCertificate(secRing.GetEncoded());
+            CheckSecretKeyRingWithPersonalCertificate(secRing.GetEncoded());
         }
 
-        private void checkSecretKeyRingWithPersonalCertificate(
+        private void CheckSecretKeyRingWithPersonalCertificate(
             byte[] keyRing)
         {
             PgpSecretKeyRingBundle secCol = new PgpSecretKeyRingBundle(keyRing);
@@ -2523,21 +2549,20 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
             }
         }
 
-        private void checkPublicKeyRingWithX509(
-            byte[] keyRing)
+        private void CheckPublicKeyRingWithX509(byte[] keyRing)
         {
             PgpPublicKeyRing pubRing = new PgpPublicKeyRing(keyRing);
             var en = pubRing.GetPublicKeys().GetEnumerator();
 
             if (en.MoveNext())
             {
-                PgpPublicKey key = (PgpPublicKey) en.Current;
+                PgpPublicKey key = en.Current;
 
                 var sEn = key.GetSignatures().GetEnumerator();
 
                 if (sEn.MoveNext())
                 {
-                    PgpSignature sig = (PgpSignature) sEn.Current;
+                    PgpSignature sig = sEn.Current;
                     if (sig.KeyAlgorithm != PublicKeyAlgorithmTag.Experimental_1)
                     {
                         Fail("experimental signature not found");
@@ -2581,6 +2606,26 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
             }
         }
 
+        [Test]
+        public void TestEdDsaRing()
+        {
+            ArmoredInputStream aIn = new ArmoredInputStream(GetTestDataAsStream("openpgp.eddsa-pub-keyring.asc"));
+
+            // make sure we can parse it without falling over.
+            PgpPublicKeyRing rng = new PgpPublicKeyRing(aIn);
+            Assert.IsNotNull(rng);
+        }
+
+        [Test]
+        public void TestCurve25519Ring()
+        {
+            // make sure we can parse it without falling over.
+            PgpPublicKeyRing rng = new PgpPublicKeyRing(new MemoryStream(curve25519Pub));
+
+            PgpSecretKeyRing priv = new PgpSecretKeyRing(new MemoryStream(curve25519Priv));
+            Assert.IsNotNull(priv);
+        }
+
         public override void PerformTest()
         {
             TestExpiryDate();
diff --git a/crypto/test/src/openssl/test/ReaderTest.cs b/crypto/test/src/openssl/test/ReaderTest.cs
index 78b06abc2..8cb66d6a6 100644
--- a/crypto/test/src/openssl/test/ReaderTest.cs
+++ b/crypto/test/src/openssl/test/ReaderTest.cs
@@ -3,6 +3,7 @@ using System.IO;
 
 using NUnit.Framework;
 
+using Org.BouncyCastle.Asn1;
 using Org.BouncyCastle.Asn1.Cms;
 using Org.BouncyCastle.Crypto;
 using Org.BouncyCastle.Crypto.Generators;
@@ -42,6 +43,23 @@ namespace Org.BouncyCastle.OpenSsl.Tests
             get { return "PEMReaderTest"; }
         }
 
+        [Test]
+        public void TestGost3410_2012()
+        {
+            string data =
+                "-----BEGIN PRIVATE KEY-----" +
+                "MEMCAQAwHAYGKoUDAgITMBIGByqFAwICIwEGByqFAwICHgEEIIBidanaO5G6Go8A" +
+                "thlDjR9rk4hij/PpjAQvXJr+zTqz" +
+                "-----END PRIVATE KEY-----";
+
+            using (var textReader = new StringReader(data))
+            {
+                var pemReader = new PemReader(textReader);
+                var pemObj = pemReader.ReadPemObject();
+                PrivateKeyFactory.CreateKey(pemObj.Content);
+            }
+        }
+
         public override void PerformTest()
         {
             IPasswordFinder pGet = new Password("secret".ToCharArray());
diff --git a/crypto/test/src/security/test/TestDotNetUtil.cs b/crypto/test/src/security/test/TestDotNetUtil.cs
index b83a94a36..5d0177ead 100644
--- a/crypto/test/src/security/test/TestDotNetUtil.cs
+++ b/crypto/test/src/security/test/TestDotNetUtil.cs
@@ -22,6 +22,36 @@ namespace Org.BouncyCastle.Security.Tests
 	[TestFixture]
     public class TestDotNetUtilities
 	{
+//#if NETCOREAPP1_0_OR_GREATER || NET47_OR_GREATER || NETSTANDARD1_6_OR_GREATER
+#if NET6_0_OR_GREATER
+        [Test]
+		public void TestECDsaInterop()
+		{
+			byte[] data = new byte[1024];
+
+            for (int i = 0; i < 10; ++i)
+			{
+                var ecDsa = ECDsa.Create(ECCurve.NamedCurves.nistP256);
+				byte[] sig1 = ecDsa.SignData(data, HashAlgorithmName.SHA256);
+
+                AsymmetricCipherKeyPair kp = DotNetUtilities.GetECDsaKeyPair(ecDsa);
+                Assert.IsNotNull(kp.Private);
+                Assert.IsNotNull(kp.Public);
+                ISigner signer = SignerUtilities.GetSigner("SHA256withPLAIN-ECDSA");
+
+                signer.Init(false, kp.Public);
+                signer.BlockUpdate(data, 0, data.Length);
+                Assert.IsTrue(signer.VerifySignature(sig1));
+
+				signer.Init(true, kp.Private);
+				signer.BlockUpdate(data, 0, data.Length);
+				byte[] sig2 = signer.GenerateSignature();
+
+                Assert.IsTrue(ecDsa.VerifyData(data, sig2, HashAlgorithmName.SHA256));
+            }
+        }
+#endif
+
 //#if NET5_0_OR_GREATER
 #if NET6_0_OR_GREATER
         [SupportedOSPlatform("windows")]
@@ -29,7 +59,7 @@ namespace Org.BouncyCastle.Security.Tests
         [Test]
 		public void TestRsaInterop()
 		{
-			for (int i = 0; i < 100; ++i)
+			for (int i = 0; i < 10; ++i)
 			{
 				RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(512);
 				RSAParameters rp = rsa.ExportParameters(true);
diff --git a/crypto/test/src/tls/test/LoggingDatagramTransport.cs b/crypto/test/src/tls/test/LoggingDatagramTransport.cs
index f675b72fc..0ad15e065 100644
--- a/crypto/test/src/tls/test/LoggingDatagramTransport.cs
+++ b/crypto/test/src/tls/test/LoggingDatagramTransport.cs
@@ -34,25 +34,86 @@ namespace Org.BouncyCastle.Tls.Tests
 
         public virtual int Receive(byte[] buf, int off, int len, int waitMillis)
         {
+//#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+#if NET6_0_OR_GREATER
+            return Receive(buf.AsSpan(off, len), waitMillis);
+#else
             int length = m_transport.Receive(buf, off, len, waitMillis);
             if (length >= 0)
             {
                 DumpDatagram("Received", buf, off, length);
             }
             return length;
+#endif
         }
 
+//#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+#if NET6_0_OR_GREATER
+        public virtual int Receive(Span<byte> buffer, int waitMillis)
+        {
+            int length = m_transport.Receive(buffer, waitMillis);
+            if (length >= 0)
+            {
+                DumpDatagram("Received", buffer[..length]);
+            }
+            return length;
+        }
+#endif
+
         public virtual void Send(byte[] buf, int off, int len)
         {
+//#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+#if NET6_0_OR_GREATER
+            Send(buf.AsSpan(off, len));
+#else
             DumpDatagram("Sending", buf, off, len);
             m_transport.Send(buf, off, len);
+#endif
         }
 
+//#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+#if NET6_0_OR_GREATER
+        public virtual void Send(ReadOnlySpan<byte> buffer)
+        {
+            DumpDatagram("Sending", buffer);
+            m_transport.Send(buffer);
+        }
+#endif
+
         public virtual void Close()
         {
             m_transport.Close();
         }
 
+//#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+#if NET6_0_OR_GREATER
+        private void DumpDatagram(string verb, ReadOnlySpan<byte> buffer)
+        {
+            int len = buffer.Length;
+            long timestamp = DateTimeUtilities.CurrentUnixMs() - m_launchTimestamp;
+            StringBuilder sb = new StringBuilder("(+" + timestamp + "ms) " + verb + " " + len + " byte datagram:");
+            for (int pos = 0; pos < len; ++pos)
+            {
+                if (pos % 16 == 0)
+                {
+                    sb.Append(Environment.NewLine);
+                    sb.Append("    ");
+                }
+                else if (pos % 16 == 8)
+                {
+                    sb.Append('-');
+                }
+                else
+                {
+                    sb.Append(' ');
+                }
+                int val = buffer[pos] & 0xFF;
+                sb.Append(HEX_CHARS[val >> 4]);
+                sb.Append(HEX_CHARS[val & 0xF]);
+            }
+            Dump(sb.ToString());
+        }
+#else
         private void DumpDatagram(string verb, byte[] buf, int off, int len)
         {
             long timestamp = DateTimeUtilities.CurrentUnixMs() - m_launchTimestamp;
@@ -78,6 +139,7 @@ namespace Org.BouncyCastle.Tls.Tests
             }
             Dump(sb.ToString());
         }
+#endif
 
         private void Dump(string s)
         {
diff --git a/crypto/test/src/tls/test/MockDatagramAssociation.cs b/crypto/test/src/tls/test/MockDatagramAssociation.cs
index ef317c7b6..3612bec40 100644
--- a/crypto/test/src/tls/test/MockDatagramAssociation.cs
+++ b/crypto/test/src/tls/test/MockDatagramAssociation.cs
@@ -58,6 +58,10 @@ namespace Org.BouncyCastle.Tls.Tests
 
             public virtual int Receive(byte[] buf, int off, int len, int waitMillis)
             {
+//#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+#if NET6_0_OR_GREATER
+                return Receive(buf.AsSpan(off, len), waitMillis);
+#else
                 lock (m_receiveQueue)
                 {
                     if (m_receiveQueue.Count < 1)
@@ -81,10 +85,45 @@ namespace Org.BouncyCastle.Tls.Tests
                     Array.Copy(packet, 0, buf, off, copyLength);
                     return copyLength;
                 }
+#endif
             }
 
+//#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+#if NET6_0_OR_GREATER
+            public virtual int Receive(Span<byte> buffer, int waitMillis)
+            {
+                lock (m_receiveQueue)
+                {
+                    if (m_receiveQueue.Count < 1)
+                    {
+                        try
+                        {
+                            Monitor.Wait(m_receiveQueue, waitMillis);
+                        }
+                        catch (ThreadInterruptedException)
+                        {
+                            // TODO Keep waiting until full wait expired?
+                        }
+
+                        if (m_receiveQueue.Count < 1)
+                            return -1;
+                    }
+
+                    byte[] packet = m_receiveQueue[0];
+                    m_receiveQueue.RemoveAt(0);
+                    int copyLength = System.Math.Min(buffer.Length, packet.Length);
+                    packet.AsSpan(0, copyLength).CopyTo(buffer);
+                    return copyLength;
+                }
+            }
+#endif
+
             public virtual void Send(byte[] buf, int off, int len)
             {
+//#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+#if NET6_0_OR_GREATER
+                Send(buf.AsSpan(off, len));
+#else
                 if (len > m_outer.m_mtu)
                 {
                     // TODO Simulate rejection?
@@ -97,7 +136,27 @@ namespace Org.BouncyCastle.Tls.Tests
                     m_sendQueue.Add(packet);
                     Monitor.PulseAll(m_sendQueue);
                 }
+#endif
+            }
+
+//#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+#if NET6_0_OR_GREATER
+            public virtual void Send(ReadOnlySpan<byte> buffer)
+            {
+                if (buffer.Length > m_outer.m_mtu)
+                {
+                    // TODO Simulate rejection?
+                }
+
+                byte[] packet = buffer.ToArray();
+
+                lock (m_sendQueue)
+                {
+                    m_sendQueue.Add(packet);
+                    Monitor.PulseAll(m_sendQueue);
+                }
             }
+#endif
 
             public virtual void Close()
             {
diff --git a/crypto/test/src/tls/test/UnreliableDatagramTransport.cs b/crypto/test/src/tls/test/UnreliableDatagramTransport.cs
index bdbfd6e67..7769db9d1 100644
--- a/crypto/test/src/tls/test/UnreliableDatagramTransport.cs
+++ b/crypto/test/src/tls/test/UnreliableDatagramTransport.cs
@@ -37,6 +37,10 @@ namespace Org.BouncyCastle.Tls.Tests
 
         public virtual int Receive(byte[] buf, int off, int len, int waitMillis)
         {
+//#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+#if NET6_0_OR_GREATER
+            return Receive(buf.AsSpan(off, len), waitMillis);
+#else
             long endMillis = DateTimeUtilities.CurrentUnixMs() + waitMillis;
             for (;;)
             {
@@ -52,10 +56,37 @@ namespace Org.BouncyCastle.Tls.Tests
 
                 waitMillis = (int)(endMillis - now);
             }
+#endif
         }
 
+//#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+#if NET6_0_OR_GREATER
+        public virtual int Receive(Span<byte> buffer, int waitMillis)
+        {
+            long endMillis = DateTimeUtilities.CurrentUnixMs() + waitMillis;
+            for (;;)
+            {
+                int length = m_transport.Receive(buffer, waitMillis);
+                if (length < 0 || !LostPacket(m_percentPacketLossReceiving))
+                    return length;
+
+                Console.WriteLine("PACKET LOSS (" + length + " byte packet not received)");
+
+                long now = DateTimeUtilities.CurrentUnixMs();
+                if (now >= endMillis)
+                    return -1;
+
+                waitMillis = (int)(endMillis - now);
+            }
+        }
+#endif
+
         public virtual void Send(byte[] buf, int off, int len)
         {
+//#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+#if NET6_0_OR_GREATER
+            Send(buf.AsSpan(off, len));
+#else
             if (LostPacket(m_percentPacketLossSending))
             {
                 Console.WriteLine("PACKET LOSS (" + len + " byte packet not sent)");
@@ -64,7 +95,23 @@ namespace Org.BouncyCastle.Tls.Tests
             {
                 m_transport.Send(buf, off, len);
             }
+#endif
+        }
+
+//#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+#if NET6_0_OR_GREATER
+        public virtual void Send(ReadOnlySpan<byte> buffer)
+        {
+            if (LostPacket(m_percentPacketLossSending))
+            {
+                Console.WriteLine("PACKET LOSS (" + buffer.Length + " byte packet not sent)");
+            }
+            else
+            {
+                m_transport.Send(buffer);
+            }
         }
+#endif
 
         public virtual void Close()
         {
diff --git a/crypto/test/src/tsp/test/TSPTestUtil.cs b/crypto/test/src/tsp/test/TSPTestUtil.cs
index abe153ac1..4e08bd76d 100644
--- a/crypto/test/src/tsp/test/TSPTestUtil.cs
+++ b/crypto/test/src/tsp/test/TSPTestUtil.cs
@@ -347,7 +347,7 @@ namespace Org.BouncyCastle.Tsp.Tests
 			else
 			{
 				_v3CertGen.AddExtension(X509Extensions.ExtendedKeyUsage, true,
-					ExtendedKeyUsage.GetInstance(new DerSequence(KeyPurposeID.IdKPTimeStamping)));
+					ExtendedKeyUsage.GetInstance(new DerSequence(KeyPurposeID.id_kp_timeStamping)));
 			}
 
             X509Certificate _cert = _v3CertGen.Generate(
diff --git a/crypto/test/src/util/test/SimpleTest.cs b/crypto/test/src/util/test/SimpleTest.cs
index 0a2b5e991..21b4daabb 100644
--- a/crypto/test/src/util/test/SimpleTest.cs
+++ b/crypto/test/src/util/test/SimpleTest.cs
@@ -168,12 +168,12 @@ namespace Org.BouncyCastle.Utilities.Test
 
         private static string GetFullName(string name)
 		{
-            return "BouncyCastle.Crypto.Tests.data." + name;
+            return "Org.BouncyCastle.data." + name;
         }
 
         private static string GetShortName(string fullName)
 		{
-            return fullName.Substring("BouncyCastle.Crypto.Tests.data.".Length);
+            return fullName.Substring("Org.BouncyCastle.data.".Length);
 		}
 
 		private static string GetNewLine()