summary refs log tree commit diff
path: root/crypto/test/src/openpgp
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2022-11-05 15:40:09 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2022-11-05 15:40:09 +0700
commit7f43ba84bd30b99d0e957920aa660a45f998c522 (patch)
tree7c6f4738d69ab3def1416c397752a3b63b66738f /crypto/test/src/openpgp
parentUpdate package icon (diff)
downloadBouncyCastle.NET-ed25519-7f43ba84bd30b99d0e957920aa660a45f998c522.tar.xz
Port OpenPGP support for XDH, EdDSA from bc-java
- see https://github.com/bcgit/bc-csharp/issues/345
Diffstat (limited to 'crypto/test/src/openpgp')
-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
4 files changed, 476 insertions, 25 deletions
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();