summary refs log tree commit diff
path: root/crypto/src/security
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2018-09-21 15:17:56 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2018-09-21 15:17:56 +0700
commitfbae27fb1edcea6b0924dba977a6d94f0a3655db (patch)
treeffea8216ac6125b574dcd05bed38fccd0fe10ba5 /crypto/src/security
parentRefactoring (diff)
downloadBouncyCastle.NET-ed25519-fbae27fb1edcea6b0924dba977a6d94f0a3655db.tar.xz
Higher-level API support for Ed25519/Ed448/X25519/X448
Diffstat (limited to 'crypto/src/security')
-rw-r--r--crypto/src/security/AgreementUtilities.cs55
-rw-r--r--crypto/src/security/GeneratorUtilities.cs34
-rw-r--r--crypto/src/security/PrivateKeyFactory.cs28
-rw-r--r--crypto/src/security/PublicKeyFactory.cs32
-rw-r--r--crypto/src/security/SignerUtilities.cs36
5 files changed, 159 insertions, 26 deletions
diff --git a/crypto/src/security/AgreementUtilities.cs b/crypto/src/security/AgreementUtilities.cs
index 12d427c8c..26d1628cc 100644
--- a/crypto/src/security/AgreementUtilities.cs
+++ b/crypto/src/security/AgreementUtilities.cs
@@ -1,6 +1,7 @@
 using System.Collections;
 
 using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.EdEC;
 using Org.BouncyCastle.Asn1.X9;
 using Org.BouncyCastle.Crypto;
 using Org.BouncyCastle.Crypto.Agreement;
@@ -27,7 +28,10 @@ namespace Org.BouncyCastle.Security
             algorithms[X9ObjectIdentifiers.DHSinglePassCofactorDHSha1KdfScheme.Id] = "ECCDHWITHSHA1KDF";
 			algorithms[X9ObjectIdentifiers.DHSinglePassStdDHSha1KdfScheme.Id] = "ECDHWITHSHA1KDF";
 			algorithms[X9ObjectIdentifiers.MqvSinglePassSha1KdfScheme.Id] = "ECMQVWITHSHA1KDF";
-		}
+
+            algorithms[EdECObjectIdentifiers.id_X25519.Id] = "X25519";
+            algorithms[EdECObjectIdentifiers.id_X448.Id] = "X448";
+        }
 
         public static IBasicAgreement GetBasicAgreement(
 			DerObjectIdentifier oid)
@@ -38,15 +42,9 @@ namespace Org.BouncyCastle.Security
 		public static IBasicAgreement GetBasicAgreement(
 			string algorithm)
 		{
-			string upper = Platform.ToUpperInvariant(algorithm);
-			string mechanism = (string) algorithms[upper];
-
-			if (mechanism == null)
-			{
-				mechanism = upper;
-			}
+            string mechanism = GetMechanism(algorithm);
 
-			if (mechanism == "DH" || mechanism == "DIFFIEHELLMAN")
+            if (mechanism == "DH" || mechanism == "DIFFIEHELLMAN")
 				return new DHBasicAgreement();
 
 			if (mechanism == "ECDH")
@@ -72,15 +70,9 @@ namespace Org.BouncyCastle.Security
 			string agreeAlgorithm,
 			string wrapAlgorithm)
 		{
-			string upper = Platform.ToUpperInvariant(agreeAlgorithm);
-			string mechanism = (string) algorithms[upper];
+            string mechanism = GetMechanism(agreeAlgorithm);
 
-			if (mechanism == null)
-			{
-				mechanism = upper;
-			}
-
-			// 'DHWITHSHA1KDF' retained for backward compatibility
+            // 'DHWITHSHA1KDF' retained for backward compatibility
 			if (mechanism == "DHWITHSHA1KDF" || mechanism == "ECDHWITHSHA1KDF")
 				return new ECDHWithKdfBasicAgreement(
 					wrapAlgorithm,
@@ -96,10 +88,37 @@ namespace Org.BouncyCastle.Security
 			throw new SecurityUtilityException("Basic Agreement (with KDF) " + agreeAlgorithm + " not recognised.");
 		}
 
+        public static IRawAgreement GetRawAgreement(
+            DerObjectIdentifier oid)
+        {
+            return GetRawAgreement(oid.Id);
+        }
+
+        public static IRawAgreement GetRawAgreement(
+            string algorithm)
+        {
+            string mechanism = GetMechanism(algorithm);
+
+            if (mechanism == "X25519")
+                return new X25519Agreement();
+
+            if (mechanism == "X448")
+                return new X448Agreement();
+
+            throw new SecurityUtilityException("Raw Agreement " + algorithm + " not recognised.");
+        }
+
 		public static string GetAlgorithmName(
 			DerObjectIdentifier oid)
 		{
-			return (string) algorithms[oid.Id];
+			return (string)algorithms[oid.Id];
 		}
+
+        private static string GetMechanism(string algorithm)
+        {
+            string upper = Platform.ToUpperInvariant(algorithm);
+            string mechanism = (string)algorithms[upper];
+            return mechanism == null ? upper : mechanism;
+        }
 	}
 }
diff --git a/crypto/src/security/GeneratorUtilities.cs b/crypto/src/security/GeneratorUtilities.cs
index db1929c16..26ddb396b 100644
--- a/crypto/src/security/GeneratorUtilities.cs
+++ b/crypto/src/security/GeneratorUtilities.cs
@@ -2,6 +2,7 @@ using System.Collections;
 
 using Org.BouncyCastle.Asn1;
 using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.EdEC;
 using Org.BouncyCastle.Asn1.Iana;
 using Org.BouncyCastle.Asn1.Kisa;
 using Org.BouncyCastle.Asn1.Nist;
@@ -180,12 +181,23 @@ namespace Org.BouncyCastle.Security
             AddKpgAlgorithm("ECGOST3410",
                 "ECGOST-3410",
                 "GOST-3410-2001");
+            AddKpgAlgorithm("Ed25519",
+                "Ed25519ctx",
+                "Ed25519ph",
+                EdECObjectIdentifiers.id_Ed25519);
+            AddKpgAlgorithm("Ed448",
+                "Ed448ph",
+                EdECObjectIdentifiers.id_Ed448);
             AddKpgAlgorithm("ELGAMAL");
             AddKpgAlgorithm("GOST3410",
                 "GOST-3410",
                 "GOST-3410-94");
             AddKpgAlgorithm("RSA",
                 "1.2.840.113549.1.1.1");
+            AddKpgAlgorithm("X25519",
+                EdECObjectIdentifiers.id_X25519);
+            AddKpgAlgorithm("X448",
+                EdECObjectIdentifiers.id_X448);
 
             AddDefaultKeySizeEntries(64, "DES");
             AddDefaultKeySizeEntries(80, "SKIPJACK");
@@ -216,11 +228,11 @@ namespace Org.BouncyCastle.Security
             string			canonicalName,
             params object[] aliases)
         {
-            kgAlgorithms[canonicalName] = canonicalName;
+            kgAlgorithms[Platform.ToUpperInvariant(canonicalName)] = canonicalName;
 
             foreach (object alias in aliases)
             {
-                kgAlgorithms[alias.ToString()] = canonicalName;
+                kgAlgorithms[Platform.ToUpperInvariant(alias.ToString())] = canonicalName;
             }
         }
 
@@ -228,11 +240,11 @@ namespace Org.BouncyCastle.Security
             string			canonicalName,
             params object[] aliases)
         {
-            kpgAlgorithms[canonicalName] = canonicalName;
+            kpgAlgorithms[Platform.ToUpperInvariant(canonicalName)] = canonicalName;
 
             foreach (object alias in aliases)
             {
-                kpgAlgorithms[alias.ToString()] = canonicalName;
+                kpgAlgorithms[Platform.ToUpperInvariant(alias.ToString())] = canonicalName;
             }
         }
 
@@ -248,7 +260,7 @@ namespace Org.BouncyCastle.Security
 
             foreach (object alias in aliases)
             {
-                kgAlgorithms[alias.ToString()] = mainName;
+                kgAlgorithms[Platform.ToUpperInvariant(alias.ToString())] = mainName;
             }
         }
 
@@ -318,6 +330,12 @@ namespace Org.BouncyCastle.Security
             if (Platform.StartsWith(canonicalName, "EC"))
                 return new ECKeyPairGenerator(canonicalName);
 
+            if (canonicalName == "Ed25519")
+                return new Ed25519KeyPairGenerator();
+
+            if (canonicalName == "Ed448")
+                return new Ed448KeyPairGenerator();
+
             if (canonicalName == "ELGAMAL")
                 return new ElGamalKeyPairGenerator();
 
@@ -327,6 +345,12 @@ namespace Org.BouncyCastle.Security
             if (canonicalName == "RSA")
                 return new RsaKeyPairGenerator();
 
+            if (canonicalName == "X25519")
+                return new X25519KeyPairGenerator();
+
+            if (canonicalName == "X448")
+                return new X448KeyPairGenerator();
+
             throw new SecurityUtilityException("KeyPairGenerator " + algorithm
                 + " (" + canonicalName + ") not supported.");
         }
diff --git a/crypto/src/security/PrivateKeyFactory.cs b/crypto/src/security/PrivateKeyFactory.cs
index c9e19cc7d..0b07d0659 100644
--- a/crypto/src/security/PrivateKeyFactory.cs
+++ b/crypto/src/security/PrivateKeyFactory.cs
@@ -5,6 +5,7 @@ using System.Text;
 
 using Org.BouncyCastle.Asn1;
 using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.EdEC;
 using Org.BouncyCastle.Asn1.Oiw;
 using Org.BouncyCastle.Asn1.Pkcs;
 using Org.BouncyCastle.Asn1.Sec;
@@ -170,12 +171,37 @@ namespace Org.BouncyCastle.Security
 
 				return new Gost3410PrivateKeyParameters(x, gostParams.PublicKeyParamSet);
 			}
+            else if (algOid.Equals(EdECObjectIdentifiers.id_X25519))
+            {
+                return new X25519PrivateKeyParameters(GetRawKey(keyInfo, X25519PrivateKeyParameters.KeySize), 0);
+            }
+            else if (algOid.Equals(EdECObjectIdentifiers.id_X448))
+            {
+                return new X448PrivateKeyParameters(GetRawKey(keyInfo, X448PrivateKeyParameters.KeySize), 0);
+            }
+            else if (algOid.Equals(EdECObjectIdentifiers.id_Ed25519))
+            {
+                return new Ed25519PrivateKeyParameters(GetRawKey(keyInfo, Ed25519PrivateKeyParameters.KeySize), 0);
+            }
+            else if (algOid.Equals(EdECObjectIdentifiers.id_Ed448))
+            {
+                return new Ed448PrivateKeyParameters(GetRawKey(keyInfo, Ed448PrivateKeyParameters.KeySize), 0);
+            }
             else
             {
-                throw new SecurityUtilityException("algorithm identifier in key not recognised");
+                throw new SecurityUtilityException("algorithm identifier in private key not recognised");
             }
         }
 
+        private static byte[] GetRawKey(PrivateKeyInfo keyInfo, int expectedSize)
+        {
+            byte[] result = Asn1OctetString.GetInstance(keyInfo.ParsePrivateKey()).GetOctets();
+            if (expectedSize != result.Length)
+                throw new SecurityUtilityException("private key encoding has incorrect length");
+
+            return result;
+        }
+
         public static AsymmetricKeyParameter DecryptKey(
             char[]					passPhrase,
             EncryptedPrivateKeyInfo	encInfo)
diff --git a/crypto/src/security/PublicKeyFactory.cs b/crypto/src/security/PublicKeyFactory.cs
index f1b28b774..e39748e45 100644
--- a/crypto/src/security/PublicKeyFactory.cs
+++ b/crypto/src/security/PublicKeyFactory.cs
@@ -5,6 +5,7 @@ using System.Text;
 
 using Org.BouncyCastle.Asn1;
 using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.EdEC;
 using Org.BouncyCastle.Asn1.Oiw;
 using Org.BouncyCastle.Asn1.Pkcs;
 using Org.BouncyCastle.Asn1.Sec;
@@ -218,12 +219,41 @@ namespace Org.BouncyCastle.Security
 
                 return new Gost3410PublicKeyParameters(y, algParams.PublicKeyParamSet);
             }
+            else if (algOid.Equals(EdECObjectIdentifiers.id_X25519))
+            {
+                return new X25519PublicKeyParameters(GetRawKey(keyInfo, X25519PublicKeyParameters.KeySize), 0);
+            }
+            else if (algOid.Equals(EdECObjectIdentifiers.id_X448))
+            {
+                return new X448PublicKeyParameters(GetRawKey(keyInfo, X448PublicKeyParameters.KeySize), 0);
+            }
+            else if (algOid.Equals(EdECObjectIdentifiers.id_Ed25519))
+            {
+                return new Ed25519PublicKeyParameters(GetRawKey(keyInfo, Ed25519PublicKeyParameters.KeySize), 0);
+            }
+            else if (algOid.Equals(EdECObjectIdentifiers.id_Ed448))
+            {
+                return new Ed448PublicKeyParameters(GetRawKey(keyInfo, Ed448PublicKeyParameters.KeySize), 0);
+            }
             else
             {
-                throw new SecurityUtilityException("algorithm identifier in key not recognised: " + algOid);
+                throw new SecurityUtilityException("algorithm identifier in public key not recognised: " + algOid);
             }
         }
 
+        private static byte[] GetRawKey(SubjectPublicKeyInfo keyInfo, int expectedSize)
+        {
+            /*
+             * TODO[RFC 8422]
+             * - Require keyInfo.Algorithm.Parameters == null?
+             */
+            byte[] result = keyInfo.PublicKeyData.GetOctets();
+            if (expectedSize != result.Length)
+                throw new SecurityUtilityException("public key encoding has incorrect length");
+
+            return result;
+        }
+
         private static bool IsPkcsDHParam(Asn1Sequence seq)
         {
             if (seq.Count == 2)
diff --git a/crypto/src/security/SignerUtilities.cs b/crypto/src/security/SignerUtilities.cs
index 44281503a..a9045ae6e 100644
--- a/crypto/src/security/SignerUtilities.cs
+++ b/crypto/src/security/SignerUtilities.cs
@@ -4,6 +4,7 @@ using System.IO;
 
 using Org.BouncyCastle.Asn1;
 using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.EdEC;
 using Org.BouncyCastle.Asn1.Nist;
 using Org.BouncyCastle.Asn1.Oiw;
 using Org.BouncyCastle.Asn1.Pkcs;
@@ -231,7 +232,13 @@ namespace Org.BouncyCastle.Security
             algorithms["GOST3411WITHECGOST3410"] = "ECGOST3410";
             algorithms[CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001.Id] = "ECGOST3410";
 
-
+            algorithms["ED25519"] = "Ed25519";
+            algorithms[EdECObjectIdentifiers.id_Ed25519.Id] = "Ed25519";
+            algorithms["ED25519CTX"] = "Ed25519ctx";
+            algorithms["ED25519PH"] = "Ed25519ph";
+            algorithms["ED448"] = "Ed448";
+            algorithms[EdECObjectIdentifiers.id_Ed448.Id] = "Ed448";
+            algorithms["ED448PH"] = "Ed448ph";
 
             oids["MD2withRSA"] = PkcsObjectIdentifiers.MD2WithRsaEncryption;
             oids["MD4withRSA"] = PkcsObjectIdentifiers.MD4WithRsaEncryption;
@@ -264,6 +271,9 @@ namespace Org.BouncyCastle.Security
 
             oids["GOST3410"] = CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94;
             oids["ECGOST3410"] = CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001;
+
+            oids["Ed25519"] = EdECObjectIdentifiers.id_Ed25519;
+            oids["Ed448"] = EdECObjectIdentifiers.id_Ed448;
         }
 
         /// <summary>
@@ -361,6 +371,30 @@ namespace Org.BouncyCastle.Security
             if (mechanism == null)
                 mechanism = algorithm;
 
+            if (Platform.StartsWith(mechanism, "Ed"))
+            {
+                if (mechanism.Equals("Ed25519"))
+                {
+                    return new Ed25519Signer();
+                }
+                if (mechanism.Equals("Ed25519ctx"))
+                {
+                    return new Ed25519ctxSigner(Arrays.EmptyBytes);
+                }
+                if (mechanism.Equals("Ed25519ph"))
+                {
+                    return new Ed25519phSigner(Arrays.EmptyBytes);
+                }
+                if (mechanism.Equals("Ed448"))
+                {
+                    return new Ed448Signer(Arrays.EmptyBytes);
+                }
+                if (mechanism.Equals("Ed448ph"))
+                {
+                    return new Ed448phSigner(Arrays.EmptyBytes);
+                }
+            }
+
             if (mechanism.Equals("RSA"))
             {
                 return (new RsaDigestSigner(new NullDigest(), (AlgorithmIdentifier)null));