diff --git a/crypto/src/asn1/edec/EdECObjectIdentifiers.cs b/crypto/src/asn1/edec/EdECObjectIdentifiers.cs
new file mode 100644
index 000000000..f8c5713d8
--- /dev/null
+++ b/crypto/src/asn1/edec/EdECObjectIdentifiers.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.EdEC
+{
+ /**
+ * Edwards Elliptic Curve Object Identifiers (RFC 8410)
+ */
+ public abstract class EdECObjectIdentifiers
+ {
+ public static readonly DerObjectIdentifier id_edwards_curve_algs = new DerObjectIdentifier("1.3.101");
+
+ public static readonly DerObjectIdentifier id_X25519 = id_edwards_curve_algs.Branch("110");
+ public static readonly DerObjectIdentifier id_X448 = id_edwards_curve_algs.Branch("111");
+ public static readonly DerObjectIdentifier id_Ed25519 = id_edwards_curve_algs.Branch("112");
+ public static readonly DerObjectIdentifier id_Ed448 = id_edwards_curve_algs.Branch("113");
+ }
+}
diff --git a/crypto/src/crypto/IRawAgreement.cs b/crypto/src/crypto/IRawAgreement.cs
new file mode 100644
index 000000000..63e664888
--- /dev/null
+++ b/crypto/src/crypto/IRawAgreement.cs
@@ -0,0 +1,13 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto
+{
+ public interface IRawAgreement
+ {
+ void Init(ICipherParameters parameters);
+
+ int AgreementSize { get; }
+
+ void CalculateAgreement(ICipherParameters publicKey, byte[] buf, int off);
+ }
+}
diff --git a/crypto/src/crypto/agreement/X25519Agreement.cs b/crypto/src/crypto/agreement/X25519Agreement.cs
new file mode 100644
index 000000000..7e5890c16
--- /dev/null
+++ b/crypto/src/crypto/agreement/X25519Agreement.cs
@@ -0,0 +1,27 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Agreement
+{
+ public sealed class X25519Agreement
+ : IRawAgreement
+ {
+ private X25519PrivateKeyParameters privateKey;
+
+ public void Init(ICipherParameters parameters)
+ {
+ this.privateKey = (X25519PrivateKeyParameters)parameters;
+ }
+
+ public int AgreementSize
+ {
+ get { return X25519PrivateKeyParameters.SecretSize; }
+ }
+
+ public void CalculateAgreement(ICipherParameters publicKey, byte[] buf, int off)
+ {
+ privateKey.GenerateSecret((X25519PublicKeyParameters)publicKey, buf, off);
+ }
+ }
+}
diff --git a/crypto/src/crypto/agreement/X448Agreement.cs b/crypto/src/crypto/agreement/X448Agreement.cs
new file mode 100644
index 000000000..26f608c26
--- /dev/null
+++ b/crypto/src/crypto/agreement/X448Agreement.cs
@@ -0,0 +1,27 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Agreement
+{
+ public sealed class X448Agreement
+ : IRawAgreement
+ {
+ private X448PrivateKeyParameters privateKey;
+
+ public void Init(ICipherParameters parameters)
+ {
+ this.privateKey = (X448PrivateKeyParameters)parameters;
+ }
+
+ public int AgreementSize
+ {
+ get { return X448PrivateKeyParameters.SecretSize; }
+ }
+
+ public void CalculateAgreement(ICipherParameters publicKey, byte[] buf, int off)
+ {
+ privateKey.GenerateSecret((X448PublicKeyParameters)publicKey, buf, off);
+ }
+ }
+}
diff --git a/crypto/src/crypto/generators/Ed25519KeyPairGenerator.cs b/crypto/src/crypto/generators/Ed25519KeyPairGenerator.cs
new file mode 100644
index 000000000..266d111cf
--- /dev/null
+++ b/crypto/src/crypto/generators/Ed25519KeyPairGenerator.cs
@@ -0,0 +1,25 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Generators
+{
+ public class Ed25519KeyPairGenerator
+ : IAsymmetricCipherKeyPairGenerator
+ {
+ private SecureRandom random;
+
+ public virtual void Init(KeyGenerationParameters parameters)
+ {
+ this.random = parameters.Random;
+ }
+
+ public virtual AsymmetricCipherKeyPair GenerateKeyPair()
+ {
+ Ed25519PrivateKeyParameters privateKey = new Ed25519PrivateKeyParameters(random);
+ Ed25519PublicKeyParameters publicKey = privateKey.GeneratePublicKey();
+ return new AsymmetricCipherKeyPair(publicKey, privateKey);
+ }
+ }
+}
diff --git a/crypto/src/crypto/generators/Ed448KeyPairGenerator.cs b/crypto/src/crypto/generators/Ed448KeyPairGenerator.cs
new file mode 100644
index 000000000..50aee631e
--- /dev/null
+++ b/crypto/src/crypto/generators/Ed448KeyPairGenerator.cs
@@ -0,0 +1,25 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Generators
+{
+ public class Ed448KeyPairGenerator
+ : IAsymmetricCipherKeyPairGenerator
+ {
+ private SecureRandom random;
+
+ public virtual void Init(KeyGenerationParameters parameters)
+ {
+ this.random = parameters.Random;
+ }
+
+ public virtual AsymmetricCipherKeyPair GenerateKeyPair()
+ {
+ Ed448PrivateKeyParameters privateKey = new Ed448PrivateKeyParameters(random);
+ Ed448PublicKeyParameters publicKey = privateKey.GeneratePublicKey();
+ return new AsymmetricCipherKeyPair(publicKey, privateKey);
+ }
+ }
+}
diff --git a/crypto/src/crypto/generators/X25519KeyPairGenerator.cs b/crypto/src/crypto/generators/X25519KeyPairGenerator.cs
new file mode 100644
index 000000000..94378448b
--- /dev/null
+++ b/crypto/src/crypto/generators/X25519KeyPairGenerator.cs
@@ -0,0 +1,25 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Generators
+{
+ public class X25519KeyPairGenerator
+ : IAsymmetricCipherKeyPairGenerator
+ {
+ private SecureRandom random;
+
+ public virtual void Init(KeyGenerationParameters parameters)
+ {
+ this.random = parameters.Random;
+ }
+
+ public virtual AsymmetricCipherKeyPair GenerateKeyPair()
+ {
+ X25519PrivateKeyParameters privateKey = new X25519PrivateKeyParameters(random);
+ X25519PublicKeyParameters publicKey = privateKey.GeneratePublicKey();
+ return new AsymmetricCipherKeyPair(publicKey, privateKey);
+ }
+ }
+}
diff --git a/crypto/src/crypto/generators/X448KeyPairGenerator.cs b/crypto/src/crypto/generators/X448KeyPairGenerator.cs
new file mode 100644
index 000000000..4a203e4f1
--- /dev/null
+++ b/crypto/src/crypto/generators/X448KeyPairGenerator.cs
@@ -0,0 +1,25 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Generators
+{
+ public class X448KeyPairGenerator
+ : IAsymmetricCipherKeyPairGenerator
+ {
+ private SecureRandom random;
+
+ public virtual void Init(KeyGenerationParameters parameters)
+ {
+ this.random = parameters.Random;
+ }
+
+ public virtual AsymmetricCipherKeyPair GenerateKeyPair()
+ {
+ X448PrivateKeyParameters privateKey = new X448PrivateKeyParameters(random);
+ X448PublicKeyParameters publicKey = privateKey.GeneratePublicKey();
+ return new AsymmetricCipherKeyPair(publicKey, privateKey);
+ }
+ }
+}
diff --git a/crypto/src/crypto/parameters/Ed25519KeyGenerationParameters.cs b/crypto/src/crypto/parameters/Ed25519KeyGenerationParameters.cs
new file mode 100644
index 000000000..daf3856c3
--- /dev/null
+++ b/crypto/src/crypto/parameters/Ed25519KeyGenerationParameters.cs
@@ -0,0 +1,15 @@
+using System;
+
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+ public class Ed25519KeyGenerationParameters
+ : KeyGenerationParameters
+ {
+ public Ed25519KeyGenerationParameters(SecureRandom random)
+ : base(random, 256)
+ {
+ }
+ }
+}
diff --git a/crypto/src/crypto/parameters/Ed25519PrivateKeyParameters.cs b/crypto/src/crypto/parameters/Ed25519PrivateKeyParameters.cs
new file mode 100644
index 000000000..97902e093
--- /dev/null
+++ b/crypto/src/crypto/parameters/Ed25519PrivateKeyParameters.cs
@@ -0,0 +1,98 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Math.EC.Rfc8032;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+ public sealed class Ed25519PrivateKeyParameters
+ : AsymmetricKeyParameter
+ {
+ public static readonly int KeySize = Ed25519.SecretKeySize;
+ public static readonly int SignatureSize = Ed25519.SignatureSize;
+
+ private readonly byte[] data = new byte[KeySize];
+
+ public Ed25519PrivateKeyParameters(SecureRandom random)
+ : base(true)
+ {
+ random.NextBytes(data);
+ }
+
+ public Ed25519PrivateKeyParameters(byte[] buf, int off)
+ : base(true)
+ {
+ Array.Copy(buf, off, data, 0, KeySize);
+ }
+
+ public Ed25519PrivateKeyParameters(Stream input)
+ : base(true)
+ {
+ if (KeySize != Streams.ReadFully(input, data))
+ throw new EndOfStreamException("EOF encountered in middle of Ed25519 private key");
+ }
+
+ public void Encode(byte[] buf, int off)
+ {
+ Array.Copy(data, 0, buf, off, KeySize);
+ }
+
+ public byte[] GetEncoded()
+ {
+ return Arrays.Clone(data);
+ }
+
+ public Ed25519PublicKeyParameters GeneratePublicKey()
+ {
+ byte[] publicKey = new byte[Ed25519.PublicKeySize];
+ Ed25519.GeneratePublicKey(data, 0, publicKey, 0);
+ return new Ed25519PublicKeyParameters(publicKey, 0);
+ }
+
+ public void Sign(Ed25519.Algorithm algorithm, Ed25519PublicKeyParameters publicKey, byte[] ctx, byte[] msg, int msgOff, int msgLen,
+ byte[] sig, int sigOff)
+ {
+ byte[] pk = new byte[Ed25519.PublicKeySize];
+ if (null == publicKey)
+ {
+ Ed25519.GeneratePublicKey(data, 0, pk, 0);
+ }
+ else
+ {
+ publicKey.Encode(pk, 0);
+ }
+
+ switch (algorithm)
+ {
+ case Ed25519.Algorithm.Ed25519:
+ {
+ if (null != ctx)
+ throw new ArgumentException("ctx");
+
+ Ed25519.Sign(data, 0, pk, 0, msg, msgOff, msgLen, sig, sigOff);
+ break;
+ }
+ case Ed25519.Algorithm.Ed25519ctx:
+ {
+ Ed25519.Sign(data, 0, pk, 0, ctx, msg, msgOff, msgLen, sig, sigOff);
+ break;
+ }
+ case Ed25519.Algorithm.Ed25519ph:
+ {
+ if (Ed25519.PrehashSize != msgLen)
+ throw new ArgumentException("msgLen");
+
+ Ed25519.SignPrehash(data, 0, pk, 0, ctx, msg, msgOff, sig, sigOff);
+ break;
+ }
+ default:
+ {
+ throw new ArgumentException("algorithm");
+ }
+ }
+ }
+ }
+}
diff --git a/crypto/src/crypto/parameters/Ed25519PublicKeyParameters.cs b/crypto/src/crypto/parameters/Ed25519PublicKeyParameters.cs
new file mode 100644
index 000000000..96e9ec21f
--- /dev/null
+++ b/crypto/src/crypto/parameters/Ed25519PublicKeyParameters.cs
@@ -0,0 +1,40 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Math.EC.Rfc8032;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+ public sealed class Ed25519PublicKeyParameters
+ : AsymmetricKeyParameter
+ {
+ public static readonly int KeySize = Ed25519.PublicKeySize;
+
+ private readonly byte[] data = new byte[KeySize];
+
+ public Ed25519PublicKeyParameters(byte[] buf, int off)
+ : base(false)
+ {
+ Array.Copy(buf, off, data, 0, KeySize);
+ }
+
+ public Ed25519PublicKeyParameters(Stream input)
+ : base(false)
+ {
+ if (KeySize != Streams.ReadFully(input, data))
+ throw new EndOfStreamException("EOF encountered in middle of Ed25519 public key");
+ }
+
+ public void Encode(byte[] buf, int off)
+ {
+ Array.Copy(data, 0, buf, off, KeySize);
+ }
+
+ public byte[] GetEncoded()
+ {
+ return Arrays.Clone(data);
+ }
+ }
+}
diff --git a/crypto/src/crypto/parameters/Ed448KeyGenerationParameters.cs b/crypto/src/crypto/parameters/Ed448KeyGenerationParameters.cs
new file mode 100644
index 000000000..830d15a04
--- /dev/null
+++ b/crypto/src/crypto/parameters/Ed448KeyGenerationParameters.cs
@@ -0,0 +1,15 @@
+using System;
+
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+ public class Ed448KeyGenerationParameters
+ : KeyGenerationParameters
+ {
+ public Ed448KeyGenerationParameters(SecureRandom random)
+ : base(random, 448)
+ {
+ }
+ }
+}
diff --git a/crypto/src/crypto/parameters/Ed448PrivateKeyParameters.cs b/crypto/src/crypto/parameters/Ed448PrivateKeyParameters.cs
new file mode 100644
index 000000000..74b5d63f3
--- /dev/null
+++ b/crypto/src/crypto/parameters/Ed448PrivateKeyParameters.cs
@@ -0,0 +1,90 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Math.EC.Rfc8032;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+ public sealed class Ed448PrivateKeyParameters
+ : AsymmetricKeyParameter
+ {
+ public static readonly int KeySize = Ed448.SecretKeySize;
+ public static readonly int SignatureSize = Ed448.SignatureSize;
+
+ private readonly byte[] data = new byte[KeySize];
+
+ public Ed448PrivateKeyParameters(SecureRandom random)
+ : base(true)
+ {
+ random.NextBytes(data);
+ }
+
+ public Ed448PrivateKeyParameters(byte[] buf, int off)
+ : base(true)
+ {
+ Array.Copy(buf, off, data, 0, KeySize);
+ }
+
+ public Ed448PrivateKeyParameters(Stream input)
+ : base(true)
+ {
+ if (KeySize != Streams.ReadFully(input, data))
+ throw new EndOfStreamException("EOF encountered in middle of Ed448 private key");
+ }
+
+ public void Encode(byte[] buf, int off)
+ {
+ Array.Copy(data, 0, buf, off, KeySize);
+ }
+
+ public byte[] GetEncoded()
+ {
+ return Arrays.Clone(data);
+ }
+
+ public Ed448PublicKeyParameters GeneratePublicKey()
+ {
+ byte[] publicKey = new byte[Ed448.PublicKeySize];
+ Ed448.GeneratePublicKey(data, 0, publicKey, 0);
+ return new Ed448PublicKeyParameters(publicKey, 0);
+ }
+
+ public void Sign(Ed448.Algorithm algorithm, Ed448PublicKeyParameters publicKey, byte[] ctx, byte[] msg, int msgOff, int msgLen,
+ byte[] sig, int sigOff)
+ {
+ byte[] pk = new byte[Ed448.PublicKeySize];
+ if (null == publicKey)
+ {
+ Ed448.GeneratePublicKey(data, 0, pk, 0);
+ }
+ else
+ {
+ publicKey.Encode(pk, 0);
+ }
+
+ switch (algorithm)
+ {
+ case Ed448.Algorithm.Ed448:
+ {
+ Ed448.Sign(data, 0, pk, 0, ctx, msg, msgOff, msgLen, sig, sigOff);
+ break;
+ }
+ case Ed448.Algorithm.Ed448ph:
+ {
+ if (Ed448.PrehashSize != msgLen)
+ throw new ArgumentException("msgLen");
+
+ Ed448.SignPrehash(data, 0, pk, 0, ctx, msg, msgOff, sig, sigOff);
+ break;
+ }
+ default:
+ {
+ throw new ArgumentException("algorithm");
+ }
+ }
+ }
+ }
+}
diff --git a/crypto/src/crypto/parameters/Ed448PublicKeyParameters.cs b/crypto/src/crypto/parameters/Ed448PublicKeyParameters.cs
new file mode 100644
index 000000000..d7faac246
--- /dev/null
+++ b/crypto/src/crypto/parameters/Ed448PublicKeyParameters.cs
@@ -0,0 +1,40 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Math.EC.Rfc8032;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+ public sealed class Ed448PublicKeyParameters
+ : AsymmetricKeyParameter
+ {
+ public static readonly int KeySize = Ed448.PublicKeySize;
+
+ private readonly byte[] data = new byte[KeySize];
+
+ public Ed448PublicKeyParameters(byte[] buf, int off)
+ : base(false)
+ {
+ Array.Copy(buf, off, data, 0, KeySize);
+ }
+
+ public Ed448PublicKeyParameters(Stream input)
+ : base(false)
+ {
+ if (KeySize != Streams.ReadFully(input, data))
+ throw new EndOfStreamException("EOF encountered in middle of Ed448 public key");
+ }
+
+ public void Encode(byte[] buf, int off)
+ {
+ Array.Copy(data, 0, buf, off, KeySize);
+ }
+
+ public byte[] GetEncoded()
+ {
+ return Arrays.Clone(data);
+ }
+ }
+}
diff --git a/crypto/src/crypto/parameters/X25519KeyGenerationParameters.cs b/crypto/src/crypto/parameters/X25519KeyGenerationParameters.cs
new file mode 100644
index 000000000..09972c7a2
--- /dev/null
+++ b/crypto/src/crypto/parameters/X25519KeyGenerationParameters.cs
@@ -0,0 +1,15 @@
+using System;
+
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+ public class X25519KeyGenerationParameters
+ : KeyGenerationParameters
+ {
+ public X25519KeyGenerationParameters(SecureRandom random)
+ : base(random, 256)
+ {
+ }
+ }
+}
diff --git a/crypto/src/crypto/parameters/X25519PrivateKeyParameters.cs b/crypto/src/crypto/parameters/X25519PrivateKeyParameters.cs
new file mode 100644
index 000000000..c25ab9364
--- /dev/null
+++ b/crypto/src/crypto/parameters/X25519PrivateKeyParameters.cs
@@ -0,0 +1,62 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Math.EC.Rfc7748;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+ public sealed class X25519PrivateKeyParameters
+ : AsymmetricKeyParameter
+ {
+ public static readonly int KeySize = X25519.ScalarSize;
+ public static readonly int SecretSize = X25519.PointSize;
+
+ private readonly byte[] data = new byte[KeySize];
+
+ public X25519PrivateKeyParameters(SecureRandom random)
+ : base(true)
+ {
+ random.NextBytes(data);
+ }
+
+ public X25519PrivateKeyParameters(byte[] buf, int off)
+ : base(true)
+ {
+ Array.Copy(buf, off, data, 0, KeySize);
+ }
+
+ public X25519PrivateKeyParameters(Stream input)
+ : base(true)
+ {
+ if (KeySize != Streams.ReadFully(input, data))
+ throw new EndOfStreamException("EOF encountered in middle of X25519 private key");
+ }
+
+ public void Encode(byte[] buf, int off)
+ {
+ Array.Copy(data, 0, buf, off, KeySize);
+ }
+
+ public byte[] GetEncoded()
+ {
+ return Arrays.Clone(data);
+ }
+
+ public X25519PublicKeyParameters GeneratePublicKey()
+ {
+ byte[] publicKey = new byte[X25519.PointSize];
+ X25519.ScalarMultBase(data, 0, publicKey, 0);
+ return new X25519PublicKeyParameters(publicKey, 0);
+ }
+
+ public void GenerateSecret(X25519PublicKeyParameters publicKey, byte[] buf, int off)
+ {
+ byte[] encoded = new byte[X25519.PointSize];
+ publicKey.Encode(encoded, 0);
+ X25519.ScalarMult(data, 0, encoded, 0, buf, off);
+ }
+ }
+}
diff --git a/crypto/src/crypto/parameters/X25519PublicKeyParameters.cs b/crypto/src/crypto/parameters/X25519PublicKeyParameters.cs
new file mode 100644
index 000000000..7df5f624d
--- /dev/null
+++ b/crypto/src/crypto/parameters/X25519PublicKeyParameters.cs
@@ -0,0 +1,40 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Math.EC.Rfc7748;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+ public sealed class X25519PublicKeyParameters
+ : AsymmetricKeyParameter
+ {
+ public static readonly int KeySize = X25519.PointSize;
+
+ private readonly byte[] data = new byte[KeySize];
+
+ public X25519PublicKeyParameters(byte[] buf, int off)
+ : base(false)
+ {
+ Array.Copy(buf, off, data, 0, KeySize);
+ }
+
+ public X25519PublicKeyParameters(Stream input)
+ : base(false)
+ {
+ if (KeySize != Streams.ReadFully(input, data))
+ throw new EndOfStreamException("EOF encountered in middle of X25519 public key");
+ }
+
+ public void Encode(byte[] buf, int off)
+ {
+ Array.Copy(data, 0, buf, off, KeySize);
+ }
+
+ public byte[] GetEncoded()
+ {
+ return Arrays.Clone(data);
+ }
+ }
+}
diff --git a/crypto/src/crypto/parameters/X448KeyGenerationParameters.cs b/crypto/src/crypto/parameters/X448KeyGenerationParameters.cs
new file mode 100644
index 000000000..a7cb55844
--- /dev/null
+++ b/crypto/src/crypto/parameters/X448KeyGenerationParameters.cs
@@ -0,0 +1,15 @@
+using System;
+
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+ public class X448KeyGenerationParameters
+ : KeyGenerationParameters
+ {
+ public X448KeyGenerationParameters(SecureRandom random)
+ : base(random, 448)
+ {
+ }
+ }
+}
diff --git a/crypto/src/crypto/parameters/X448PrivateKeyParameters.cs b/crypto/src/crypto/parameters/X448PrivateKeyParameters.cs
new file mode 100644
index 000000000..291eac10f
--- /dev/null
+++ b/crypto/src/crypto/parameters/X448PrivateKeyParameters.cs
@@ -0,0 +1,62 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Math.EC.Rfc7748;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+ public sealed class X448PrivateKeyParameters
+ : AsymmetricKeyParameter
+ {
+ public static readonly int KeySize = X448.ScalarSize;
+ public static readonly int SecretSize = X448.PointSize;
+
+ private readonly byte[] data = new byte[KeySize];
+
+ public X448PrivateKeyParameters(SecureRandom random)
+ : base(true)
+ {
+ random.NextBytes(data);
+ }
+
+ public X448PrivateKeyParameters(byte[] buf, int off)
+ : base(true)
+ {
+ Array.Copy(buf, off, data, 0, KeySize);
+ }
+
+ public X448PrivateKeyParameters(Stream input)
+ : base(true)
+ {
+ if (KeySize != Streams.ReadFully(input, data))
+ throw new EndOfStreamException("EOF encountered in middle of X448 private key");
+ }
+
+ public void Encode(byte[] buf, int off)
+ {
+ Array.Copy(data, 0, buf, off, KeySize);
+ }
+
+ public byte[] GetEncoded()
+ {
+ return Arrays.Clone(data);
+ }
+
+ public X448PublicKeyParameters GeneratePublicKey()
+ {
+ byte[] publicKey = new byte[X448.PointSize];
+ X448.ScalarMultBase(data, 0, publicKey, 0);
+ return new X448PublicKeyParameters(publicKey, 0);
+ }
+
+ public void GenerateSecret(X448PublicKeyParameters publicKey, byte[] buf, int off)
+ {
+ byte[] encoded = new byte[X448.PointSize];
+ publicKey.Encode(encoded, 0);
+ X448.ScalarMult(data, 0, encoded, 0, buf, off);
+ }
+ }
+}
diff --git a/crypto/src/crypto/parameters/X448PublicKeyParameters.cs b/crypto/src/crypto/parameters/X448PublicKeyParameters.cs
new file mode 100644
index 000000000..6c566ddf2
--- /dev/null
+++ b/crypto/src/crypto/parameters/X448PublicKeyParameters.cs
@@ -0,0 +1,40 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Math.EC.Rfc7748;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+ public sealed class X448PublicKeyParameters
+ : AsymmetricKeyParameter
+ {
+ public static readonly int KeySize = X448.PointSize;
+
+ private readonly byte[] data = new byte[KeySize];
+
+ public X448PublicKeyParameters(byte[] buf, int off)
+ : base(false)
+ {
+ Array.Copy(buf, off, data, 0, KeySize);
+ }
+
+ public X448PublicKeyParameters(Stream input)
+ : base(false)
+ {
+ if (KeySize != Streams.ReadFully(input, data))
+ throw new EndOfStreamException("EOF encountered in middle of X448 public key");
+ }
+
+ public void Encode(byte[] buf, int off)
+ {
+ Array.Copy(data, 0, buf, off, KeySize);
+ }
+
+ public byte[] GetEncoded()
+ {
+ return Arrays.Clone(data);
+ }
+ }
+}
diff --git a/crypto/src/crypto/signers/Ed25519Signer.cs b/crypto/src/crypto/signers/Ed25519Signer.cs
new file mode 100644
index 000000000..904450ed1
--- /dev/null
+++ b/crypto/src/crypto/signers/Ed25519Signer.cs
@@ -0,0 +1,128 @@
+using System;
+using System.IO;
+using System.Runtime.CompilerServices;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math.EC.Rfc8032;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Signers
+{
+ public class Ed25519Signer
+ : ISigner
+ {
+ private readonly Buffer buffer = new Buffer();
+
+ private bool forSigning;
+ private Ed25519PrivateKeyParameters privateKey;
+ private Ed25519PublicKeyParameters publicKey;
+
+ public Ed25519Signer()
+ {
+ }
+
+ public virtual string AlgorithmName
+ {
+ get { return "Ed25519"; }
+ }
+
+ public virtual void Init(bool forSigning, ICipherParameters parameters)
+ {
+ this.forSigning = forSigning;
+
+ if (forSigning)
+ {
+ // TODO Allow IAsymmetricCipherKeyPair to be an ICipherParameters?
+
+ this.privateKey = (Ed25519PrivateKeyParameters)parameters;
+ this.publicKey = privateKey.GeneratePublicKey();
+ }
+ else
+ {
+ this.privateKey = null;
+ this.publicKey = (Ed25519PublicKeyParameters)parameters;
+ }
+
+ Reset();
+ }
+
+ public virtual void Update(byte b)
+ {
+ buffer.WriteByte(b);
+ }
+
+ public virtual void BlockUpdate(byte[] buf, int off, int len)
+ {
+ buffer.Write(buf, off, len);
+ }
+
+ public virtual byte[] GenerateSignature()
+ {
+ if (!forSigning)
+ throw new InvalidOperationException("Ed25519Signer not initialised for signature generation.");
+
+ return buffer.GenerateSignature(privateKey, publicKey);
+ }
+
+ public virtual bool VerifySignature(byte[] signature)
+ {
+ if (forSigning)
+ throw new InvalidOperationException("Ed25519Signer not initialised for verification");
+
+ return buffer.VerifySignature(publicKey, signature);
+ }
+
+ public virtual void Reset()
+ {
+ buffer.Reset();
+ }
+
+ private class Buffer : MemoryStream
+ {
+ [MethodImpl(MethodImplOptions.Synchronized)]
+ internal byte[] GenerateSignature(Ed25519PrivateKeyParameters privateKey, Ed25519PublicKeyParameters publicKey)
+ {
+#if PORTABLE
+ byte[] buf = ToArray();
+ int count = buf.Length;
+#else
+ byte[] buf = GetBuffer();
+ int count = (int)Position;
+#endif
+ byte[] signature = new byte[Ed25519PrivateKeyParameters.SignatureSize];
+ privateKey.Sign(Ed25519.Algorithm.Ed25519, publicKey, null, buf, 0, count, signature, 0);
+ Reset();
+ return signature;
+ }
+
+ [MethodImpl(MethodImplOptions.Synchronized)]
+ internal bool VerifySignature(Ed25519PublicKeyParameters publicKey, byte[] signature)
+ {
+#if PORTABLE
+ byte[] buf = ToArray();
+ int count = buf.Length;
+#else
+ byte[] buf = GetBuffer();
+ int count = (int)Position;
+#endif
+ byte[] pk = publicKey.GetEncoded();
+ bool result = Ed25519.Verify(signature, 0, pk, 0, buf, 0, count);
+ Reset();
+ return result;
+ }
+
+ [MethodImpl(MethodImplOptions.Synchronized)]
+ internal void Reset()
+ {
+#if PORTABLE
+ this.Position = 0L;
+
+ // TODO Clear using Write method
+#else
+ Array.Clear(GetBuffer(), 0, (int)Position);
+#endif
+ this.Position = 0L;
+ }
+ }
+ }
+}
diff --git a/crypto/src/crypto/signers/Ed25519ctxSigner.cs b/crypto/src/crypto/signers/Ed25519ctxSigner.cs
new file mode 100644
index 000000000..e9c2eca44
--- /dev/null
+++ b/crypto/src/crypto/signers/Ed25519ctxSigner.cs
@@ -0,0 +1,130 @@
+using System;
+using System.IO;
+using System.Runtime.CompilerServices;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math.EC.Rfc8032;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Signers
+{
+ public class Ed25519ctxSigner
+ : ISigner
+ {
+ private readonly Buffer buffer = new Buffer();
+ private readonly byte[] context;
+
+ private bool forSigning;
+ private Ed25519PrivateKeyParameters privateKey;
+ private Ed25519PublicKeyParameters publicKey;
+
+ public Ed25519ctxSigner(byte[] context)
+ {
+ this.context = Arrays.Clone(context);
+ }
+
+ public virtual string AlgorithmName
+ {
+ get { return "Ed25519ctx"; }
+ }
+
+ public virtual void Init(bool forSigning, ICipherParameters parameters)
+ {
+ this.forSigning = forSigning;
+
+ if (forSigning)
+ {
+ // TODO Allow IAsymmetricCipherKeyPair to be an ICipherParameters?
+
+ this.privateKey = (Ed25519PrivateKeyParameters)parameters;
+ this.publicKey = privateKey.GeneratePublicKey();
+ }
+ else
+ {
+ this.privateKey = null;
+ this.publicKey = (Ed25519PublicKeyParameters)parameters;
+ }
+
+ Reset();
+ }
+
+ public virtual void Update(byte b)
+ {
+ buffer.WriteByte(b);
+ }
+
+ public virtual void BlockUpdate(byte[] buf, int off, int len)
+ {
+ buffer.Write(buf, off, len);
+ }
+
+ public virtual byte[] GenerateSignature()
+ {
+ if (!forSigning)
+ throw new InvalidOperationException("Ed25519ctxSigner not initialised for signature generation.");
+
+ return buffer.GenerateSignature(privateKey, publicKey, context);
+ }
+
+ public virtual bool VerifySignature(byte[] signature)
+ {
+ if (forSigning)
+ throw new InvalidOperationException("Ed25519ctxSigner not initialised for verification");
+
+ return buffer.VerifySignature(publicKey, context, signature);
+ }
+
+ public virtual void Reset()
+ {
+ buffer.Reset();
+ }
+
+ private class Buffer : MemoryStream
+ {
+ [MethodImpl(MethodImplOptions.Synchronized)]
+ internal byte[] GenerateSignature(Ed25519PrivateKeyParameters privateKey, Ed25519PublicKeyParameters publicKey, byte[] ctx)
+ {
+#if PORTABLE
+ byte[] buf = ToArray();
+ int count = buf.Length;
+#else
+ byte[] buf = GetBuffer();
+ int count = (int)Position;
+#endif
+ byte[] signature = new byte[Ed25519PrivateKeyParameters.SignatureSize];
+ privateKey.Sign(Ed25519.Algorithm.Ed25519ctx, publicKey, ctx, buf, 0, count, signature, 0);
+ Reset();
+ return signature;
+ }
+
+ [MethodImpl(MethodImplOptions.Synchronized)]
+ internal bool VerifySignature(Ed25519PublicKeyParameters publicKey, byte[] ctx, byte[] signature)
+ {
+#if PORTABLE
+ byte[] buf = ToArray();
+ int count = buf.Length;
+#else
+ byte[] buf = GetBuffer();
+ int count = (int)Position;
+#endif
+ byte[] pk = publicKey.GetEncoded();
+ bool result = Ed25519.Verify(signature, 0, pk, 0, ctx, buf, 0, count);
+ Reset();
+ return result;
+ }
+
+ [MethodImpl(MethodImplOptions.Synchronized)]
+ internal void Reset()
+ {
+#if PORTABLE
+ this.Position = 0L;
+
+ // TODO Clear using Write method
+#else
+ Array.Clear(GetBuffer(), 0, (int)Position);
+#endif
+ this.Position = 0L;
+ }
+ }
+ }
+}
diff --git a/crypto/src/crypto/signers/Ed25519phSigner.cs b/crypto/src/crypto/signers/Ed25519phSigner.cs
new file mode 100644
index 000000000..0d3de96f3
--- /dev/null
+++ b/crypto/src/crypto/signers/Ed25519phSigner.cs
@@ -0,0 +1,89 @@
+using System;
+using System.IO;
+using System.Runtime.CompilerServices;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math.EC.Rfc8032;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Signers
+{
+ public class Ed25519phSigner
+ : ISigner
+ {
+ private readonly IDigest prehash = Ed25519.CreatePrehash();
+ private readonly byte[] context;
+
+ private bool forSigning;
+ private Ed25519PrivateKeyParameters privateKey;
+ private Ed25519PublicKeyParameters publicKey;
+
+ public Ed25519phSigner(byte[] context)
+ {
+ this.context = Arrays.Clone(context);
+ }
+
+ public virtual string AlgorithmName
+ {
+ get { return "Ed25519ph"; }
+ }
+
+ public virtual void Init(bool forSigning, ICipherParameters parameters)
+ {
+ this.forSigning = forSigning;
+
+ if (forSigning)
+ {
+ // TODO Allow AsymmetricCipherKeyPair to be a CipherParameters?
+
+ this.privateKey = (Ed25519PrivateKeyParameters)parameters;
+ this.publicKey = privateKey.GeneratePublicKey();
+ }
+ else
+ {
+ this.privateKey = null;
+ this.publicKey = (Ed25519PublicKeyParameters)parameters;
+ }
+
+ Reset();
+ }
+
+ public virtual void Update(byte b)
+ {
+ prehash.Update(b);
+ }
+
+ public virtual void BlockUpdate(byte[] buf, int off, int len)
+ {
+ prehash.BlockUpdate(buf, off, len);
+ }
+
+ public virtual byte[] GenerateSignature()
+ {
+ if (!forSigning)
+ throw new InvalidOperationException("Ed25519phSigner not initialised for signature generation.");
+
+ byte[] msg = new byte[Ed25519.PrehashSize];
+ if (Ed25519.PrehashSize != prehash.DoFinal(msg, 0))
+ throw new InvalidOperationException("Prehash digest failed");
+
+ byte[] signature = new byte[Ed25519PrivateKeyParameters.SignatureSize];
+ privateKey.Sign(Ed25519.Algorithm.Ed25519ph, publicKey, context, msg, 0, Ed25519.PrehashSize, signature, 0);
+ return signature;
+ }
+
+ public virtual bool VerifySignature(byte[] signature)
+ {
+ if (forSigning)
+ throw new InvalidOperationException("Ed25519phSigner not initialised for verification");
+
+ byte[] pk = publicKey.GetEncoded();
+ return Ed25519.VerifyPrehash(signature, 0, pk, 0, context, prehash);
+ }
+
+ public void Reset()
+ {
+ prehash.Reset();
+ }
+ }
+}
diff --git a/crypto/src/crypto/signers/Ed448Signer.cs b/crypto/src/crypto/signers/Ed448Signer.cs
new file mode 100644
index 000000000..c01d84b4d
--- /dev/null
+++ b/crypto/src/crypto/signers/Ed448Signer.cs
@@ -0,0 +1,130 @@
+using System;
+using System.IO;
+using System.Runtime.CompilerServices;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math.EC.Rfc8032;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Signers
+{
+ public class Ed448Signer
+ : ISigner
+ {
+ private readonly Buffer buffer = new Buffer();
+ private readonly byte[] context;
+
+ private bool forSigning;
+ private Ed448PrivateKeyParameters privateKey;
+ private Ed448PublicKeyParameters publicKey;
+
+ public Ed448Signer(byte[] context)
+ {
+ this.context = Arrays.Clone(context);
+ }
+
+ public virtual string AlgorithmName
+ {
+ get { return "Ed448"; }
+ }
+
+ public virtual void Init(bool forSigning, ICipherParameters parameters)
+ {
+ this.forSigning = forSigning;
+
+ if (forSigning)
+ {
+ // TODO Allow IAsymmetricCipherKeyPair to be an ICipherParameters?
+
+ this.privateKey = (Ed448PrivateKeyParameters)parameters;
+ this.publicKey = privateKey.GeneratePublicKey();
+ }
+ else
+ {
+ this.privateKey = null;
+ this.publicKey = (Ed448PublicKeyParameters)parameters;
+ }
+
+ Reset();
+ }
+
+ public virtual void Update(byte b)
+ {
+ buffer.WriteByte(b);
+ }
+
+ public virtual void BlockUpdate(byte[] buf, int off, int len)
+ {
+ buffer.Write(buf, off, len);
+ }
+
+ public virtual byte[] GenerateSignature()
+ {
+ if (!forSigning)
+ throw new InvalidOperationException("Ed448Signer not initialised for signature generation.");
+
+ return buffer.GenerateSignature(privateKey, publicKey, context);
+ }
+
+ public virtual bool VerifySignature(byte[] signature)
+ {
+ if (forSigning)
+ throw new InvalidOperationException("Ed448Signer not initialised for verification");
+
+ return buffer.VerifySignature(publicKey, context, signature);
+ }
+
+ public virtual void Reset()
+ {
+ buffer.Reset();
+ }
+
+ private class Buffer : MemoryStream
+ {
+ [MethodImpl(MethodImplOptions.Synchronized)]
+ internal byte[] GenerateSignature(Ed448PrivateKeyParameters privateKey, Ed448PublicKeyParameters publicKey, byte[] ctx)
+ {
+#if PORTABLE
+ byte[] buf = ToArray();
+ int count = buf.Length;
+#else
+ byte[] buf = GetBuffer();
+ int count = (int)Position;
+#endif
+ byte[] signature = new byte[Ed448PrivateKeyParameters.SignatureSize];
+ privateKey.Sign(Ed448.Algorithm.Ed448, publicKey, ctx, buf, 0, count, signature, 0);
+ Reset();
+ return signature;
+ }
+
+ [MethodImpl(MethodImplOptions.Synchronized)]
+ internal bool VerifySignature(Ed448PublicKeyParameters publicKey, byte[] ctx, byte[] signature)
+ {
+#if PORTABLE
+ byte[] buf = ToArray();
+ int count = buf.Length;
+#else
+ byte[] buf = GetBuffer();
+ int count = (int)Position;
+#endif
+ byte[] pk = publicKey.GetEncoded();
+ bool result = Ed448.Verify(signature, 0, pk, 0, ctx, buf, 0, count);
+ Reset();
+ return result;
+ }
+
+ [MethodImpl(MethodImplOptions.Synchronized)]
+ internal void Reset()
+ {
+#if PORTABLE
+ this.Position = 0L;
+
+ // TODO Clear using Write method
+#else
+ Array.Clear(GetBuffer(), 0, (int)Position);
+#endif
+ this.Position = 0L;
+ }
+ }
+ }
+}
diff --git a/crypto/src/crypto/signers/Ed448phSigner.cs b/crypto/src/crypto/signers/Ed448phSigner.cs
new file mode 100644
index 000000000..50d0a0154
--- /dev/null
+++ b/crypto/src/crypto/signers/Ed448phSigner.cs
@@ -0,0 +1,89 @@
+using System;
+using System.IO;
+using System.Runtime.CompilerServices;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math.EC.Rfc8032;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Signers
+{
+ public class Ed448phSigner
+ : ISigner
+ {
+ private readonly IXof prehash = Ed448.CreatePrehash();
+ private readonly byte[] context;
+
+ private bool forSigning;
+ private Ed448PrivateKeyParameters privateKey;
+ private Ed448PublicKeyParameters publicKey;
+
+ public Ed448phSigner(byte[] context)
+ {
+ this.context = Arrays.Clone(context);
+ }
+
+ public virtual string AlgorithmName
+ {
+ get { return "Ed448ph"; }
+ }
+
+ public virtual void Init(bool forSigning, ICipherParameters parameters)
+ {
+ this.forSigning = forSigning;
+
+ if (forSigning)
+ {
+ // TODO Allow AsymmetricCipherKeyPair to be a CipherParameters?
+
+ this.privateKey = (Ed448PrivateKeyParameters)parameters;
+ this.publicKey = privateKey.GeneratePublicKey();
+ }
+ else
+ {
+ this.privateKey = null;
+ this.publicKey = (Ed448PublicKeyParameters)parameters;
+ }
+
+ Reset();
+ }
+
+ public virtual void Update(byte b)
+ {
+ prehash.Update(b);
+ }
+
+ public virtual void BlockUpdate(byte[] buf, int off, int len)
+ {
+ prehash.BlockUpdate(buf, off, len);
+ }
+
+ public virtual byte[] GenerateSignature()
+ {
+ if (!forSigning)
+ throw new InvalidOperationException("Ed448phSigner not initialised for signature generation.");
+
+ byte[] msg = new byte[Ed448.PrehashSize];
+ if (Ed448.PrehashSize != prehash.DoFinal(msg, 0, Ed448.PrehashSize))
+ throw new InvalidOperationException("Prehash digest failed");
+
+ byte[] signature = new byte[Ed448PrivateKeyParameters.SignatureSize];
+ privateKey.Sign(Ed448.Algorithm.Ed448ph, publicKey, context, msg, 0, Ed448.PrehashSize, signature, 0);
+ return signature;
+ }
+
+ public virtual bool VerifySignature(byte[] signature)
+ {
+ if (forSigning)
+ throw new InvalidOperationException("Ed448phSigner not initialised for verification");
+
+ byte[] pk = publicKey.GetEncoded();
+ return Ed448.VerifyPrehash(signature, 0, pk, 0, context, prehash);
+ }
+
+ public void Reset()
+ {
+ prehash.Reset();
+ }
+ }
+}
diff --git a/crypto/src/math/ec/rfc8032/Ed25519.cs b/crypto/src/math/ec/rfc8032/Ed25519.cs
index adb56ca9b..0b0e649d7 100644
--- a/crypto/src/math/ec/rfc8032/Ed25519.cs
+++ b/crypto/src/math/ec/rfc8032/Ed25519.cs
@@ -12,6 +12,13 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
{
public abstract class Ed25519
{
+ public enum Algorithm
+ {
+ Ed25519 = 0,
+ Ed25519ctx = 1,
+ Ed25519ph = 2,
+ }
+
private const long M28L = 0x0FFFFFFFL;
private const long M32L = 0xFFFFFFFFL;
diff --git a/crypto/src/math/ec/rfc8032/Ed448.cs b/crypto/src/math/ec/rfc8032/Ed448.cs
index c1c0788a7..f12aa0807 100644
--- a/crypto/src/math/ec/rfc8032/Ed448.cs
+++ b/crypto/src/math/ec/rfc8032/Ed448.cs
@@ -12,6 +12,12 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
{
public abstract class Ed448
{
+ public enum Algorithm
+ {
+ Ed448 = 0,
+ Ed448ph = 1,
+ }
+
private const ulong M26UL = 0x03FFFFFFUL;
private const ulong M28UL = 0x0FFFFFFFUL;
diff --git a/crypto/src/pkcs/PrivateKeyInfoFactory.cs b/crypto/src/pkcs/PrivateKeyInfoFactory.cs
index a349a11d2..69eb3fa67 100644
--- a/crypto/src/pkcs/PrivateKeyInfoFactory.cs
+++ b/crypto/src/pkcs/PrivateKeyInfoFactory.cs
@@ -2,6 +2,7 @@ using System;
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;
@@ -22,59 +23,68 @@ namespace Org.BouncyCastle.Pkcs
}
public static PrivateKeyInfo CreatePrivateKeyInfo(
- AsymmetricKeyParameter key)
+ AsymmetricKeyParameter privateKey)
{
- if (key == null)
- throw new ArgumentNullException("key");
- if (!key.IsPrivate)
- throw new ArgumentException("Public key passed - private key expected", "key");
+ return CreatePrivateKeyInfo(privateKey, null);
+ }
+
+ /**
+ * Create a PrivateKeyInfo representation of a private key with attributes.
+ *
+ * @param privateKey the key to be encoded into the info object.
+ * @param attributes the set of attributes to be included.
+ * @return the appropriate PrivateKeyInfo
+ * @throws java.io.IOException on an error encoding the key
+ */
+ public static PrivateKeyInfo CreatePrivateKeyInfo(AsymmetricKeyParameter privateKey, Asn1Set attributes)
+ {
+ if (privateKey == null)
+ throw new ArgumentNullException("privateKey");
+ if (!privateKey.IsPrivate)
+ throw new ArgumentException("Public key passed - private key expected", "privateKey");
- if (key is ElGamalPrivateKeyParameters)
+ if (privateKey is ElGamalPrivateKeyParameters)
{
- ElGamalPrivateKeyParameters _key = (ElGamalPrivateKeyParameters)key;
+ ElGamalPrivateKeyParameters _key = (ElGamalPrivateKeyParameters)privateKey;
+ ElGamalParameters egp = _key.Parameters;
return new PrivateKeyInfo(
- new AlgorithmIdentifier(
- OiwObjectIdentifiers.ElGamalAlgorithm,
- new ElGamalParameter(
- _key.Parameters.P,
- _key.Parameters.G).ToAsn1Object()),
- new DerInteger(_key.X));
+ new AlgorithmIdentifier(OiwObjectIdentifiers.ElGamalAlgorithm, new ElGamalParameter(egp.P, egp.G).ToAsn1Object()),
+ new DerInteger(_key.X),
+ attributes);
}
- if (key is DsaPrivateKeyParameters)
+ if (privateKey is DsaPrivateKeyParameters)
{
- DsaPrivateKeyParameters _key = (DsaPrivateKeyParameters)key;
+ DsaPrivateKeyParameters _key = (DsaPrivateKeyParameters)privateKey;
+ DsaParameters dp = _key.Parameters;
return new PrivateKeyInfo(
- new AlgorithmIdentifier(
- X9ObjectIdentifiers.IdDsa,
- new DsaParameter(
- _key.Parameters.P,
- _key.Parameters.Q,
- _key.Parameters.G).ToAsn1Object()),
- new DerInteger(_key.X));
+ new AlgorithmIdentifier(X9ObjectIdentifiers.IdDsa, new DsaParameter(dp.P, dp.Q, dp.G).ToAsn1Object()),
+ new DerInteger(_key.X),
+ attributes);
}
- if (key is DHPrivateKeyParameters)
+ if (privateKey is DHPrivateKeyParameters)
{
- DHPrivateKeyParameters _key = (DHPrivateKeyParameters)key;
+ DHPrivateKeyParameters _key = (DHPrivateKeyParameters)privateKey;
DHParameter p = new DHParameter(
_key.Parameters.P, _key.Parameters.G, _key.Parameters.L);
return new PrivateKeyInfo(
new AlgorithmIdentifier(_key.AlgorithmOid, p.ToAsn1Object()),
- new DerInteger(_key.X));
+ new DerInteger(_key.X),
+ attributes);
}
- if (key is RsaKeyParameters)
+ if (privateKey is RsaKeyParameters)
{
AlgorithmIdentifier algID = new AlgorithmIdentifier(
PkcsObjectIdentifiers.RsaEncryption, DerNull.Instance);
RsaPrivateKeyStructure keyStruct;
- if (key is RsaPrivateCrtKeyParameters)
+ if (privateKey is RsaPrivateCrtKeyParameters)
{
- RsaPrivateCrtKeyParameters _key = (RsaPrivateCrtKeyParameters)key;
+ RsaPrivateCrtKeyParameters _key = (RsaPrivateCrtKeyParameters)privateKey;
keyStruct = new RsaPrivateKeyStructure(
_key.Modulus,
@@ -88,7 +98,7 @@ namespace Org.BouncyCastle.Pkcs
}
else
{
- RsaKeyParameters _key = (RsaKeyParameters) key;
+ RsaKeyParameters _key = (RsaKeyParameters) privateKey;
keyStruct = new RsaPrivateKeyStructure(
_key.Modulus,
@@ -101,12 +111,12 @@ namespace Org.BouncyCastle.Pkcs
BigInteger.Zero);
}
- return new PrivateKeyInfo(algID, keyStruct.ToAsn1Object());
+ return new PrivateKeyInfo(algID, keyStruct.ToAsn1Object(), attributes);
}
- if (key is ECPrivateKeyParameters)
+ if (privateKey is ECPrivateKeyParameters)
{
- ECPrivateKeyParameters priv = (ECPrivateKeyParameters)key;
+ ECPrivateKeyParameters priv = (ECPrivateKeyParameters)privateKey;
ECDomainParameters dp = priv.Parameters;
int orderBitLength = dp.N.BitLength;
@@ -145,12 +155,12 @@ namespace Org.BouncyCastle.Pkcs
algID = new AlgorithmIdentifier(X9ObjectIdentifiers.IdECPublicKey, x962);
}
- return new PrivateKeyInfo(algID, ec);
+ return new PrivateKeyInfo(algID, ec, attributes);
}
- if (key is Gost3410PrivateKeyParameters)
+ if (privateKey is Gost3410PrivateKeyParameters)
{
- Gost3410PrivateKeyParameters _key = (Gost3410PrivateKeyParameters)key;
+ Gost3410PrivateKeyParameters _key = (Gost3410PrivateKeyParameters)privateKey;
if (_key.PublicKeyParamSet == null)
throw Platform.CreateNotImplementedException("Not a CryptoPro parameter set");
@@ -170,10 +180,42 @@ namespace Org.BouncyCastle.Pkcs
CryptoProObjectIdentifiers.GostR3410x94,
algParams.ToAsn1Object());
- return new PrivateKeyInfo(algID, new DerOctetString(keyBytes));
+ return new PrivateKeyInfo(algID, new DerOctetString(keyBytes), attributes);
+ }
+
+ if (privateKey is X448PrivateKeyParameters)
+ {
+ X448PrivateKeyParameters key = (X448PrivateKeyParameters)privateKey;
+
+ return new PrivateKeyInfo(new AlgorithmIdentifier(EdECObjectIdentifiers.id_X448),
+ new DerOctetString(key.GetEncoded()), attributes, key.GeneratePublicKey().GetEncoded());
+ }
+
+ if (privateKey is X25519PrivateKeyParameters)
+ {
+ X25519PrivateKeyParameters key = (X25519PrivateKeyParameters)privateKey;
+
+ return new PrivateKeyInfo(new AlgorithmIdentifier(EdECObjectIdentifiers.id_X25519),
+ new DerOctetString(key.GetEncoded()), attributes, key.GeneratePublicKey().GetEncoded());
+ }
+
+ if (privateKey is Ed448PrivateKeyParameters)
+ {
+ Ed448PrivateKeyParameters key = (Ed448PrivateKeyParameters)privateKey;
+
+ return new PrivateKeyInfo(new AlgorithmIdentifier(EdECObjectIdentifiers.id_Ed448),
+ new DerOctetString(key.GetEncoded()), attributes, key.GeneratePublicKey().GetEncoded());
+ }
+
+ if (privateKey is Ed25519PrivateKeyParameters)
+ {
+ Ed25519PrivateKeyParameters key = (Ed25519PrivateKeyParameters)privateKey;
+
+ return new PrivateKeyInfo(new AlgorithmIdentifier(EdECObjectIdentifiers.id_Ed25519),
+ new DerOctetString(key.GetEncoded()), attributes, key.GeneratePublicKey().GetEncoded());
}
- throw new ArgumentException("Class provided is not convertible: " + Platform.GetTypeName(key));
+ throw new ArgumentException("Class provided is not convertible: " + Platform.GetTypeName(privateKey));
}
public static PrivateKeyInfo CreatePrivateKeyInfo(
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));
diff --git a/crypto/src/x509/SubjectPublicKeyInfoFactory.cs b/crypto/src/x509/SubjectPublicKeyInfoFactory.cs
index 7614321d4..fca5da3f5 100644
--- a/crypto/src/x509/SubjectPublicKeyInfoFactory.cs
+++ b/crypto/src/x509/SubjectPublicKeyInfoFactory.cs
@@ -3,6 +3,7 @@ using System;
using Org.BouncyCastle.Crypto.Parameters;
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.X509;
@@ -26,20 +27,20 @@ namespace Org.BouncyCastle.X509
/// <summary>
/// Create a Subject Public Key Info object for a given public key.
/// </summary>
- /// <param name="key">One of ElGammalPublicKeyParameters, DSAPublicKeyParameter, DHPublicKeyParameters, RsaKeyParameters or ECPublicKeyParameters</param>
+ /// <param name="publicKey">One of ElGammalPublicKeyParameters, DSAPublicKeyParameter, DHPublicKeyParameters, RsaKeyParameters or ECPublicKeyParameters</param>
/// <returns>A subject public key info object.</returns>
/// <exception cref="Exception">Throw exception if object provided is not one of the above.</exception>
public static SubjectPublicKeyInfo CreateSubjectPublicKeyInfo(
- AsymmetricKeyParameter key)
+ AsymmetricKeyParameter publicKey)
{
- if (key == null)
- throw new ArgumentNullException("key");
- if (key.IsPrivate)
- throw new ArgumentException("Private key passed - public key expected.", "key");
+ if (publicKey == null)
+ throw new ArgumentNullException("publicKey");
+ if (publicKey.IsPrivate)
+ throw new ArgumentException("Private key passed - public key expected.", "publicKey");
- if (key is ElGamalPublicKeyParameters)
+ if (publicKey is ElGamalPublicKeyParameters)
{
- ElGamalPublicKeyParameters _key = (ElGamalPublicKeyParameters)key;
+ ElGamalPublicKeyParameters _key = (ElGamalPublicKeyParameters)publicKey;
ElGamalParameters kp = _key.Parameters;
SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(
@@ -51,9 +52,9 @@ namespace Org.BouncyCastle.X509
return info;
}
- if (key is DsaPublicKeyParameters)
+ if (publicKey is DsaPublicKeyParameters)
{
- DsaPublicKeyParameters _key = (DsaPublicKeyParameters) key;
+ DsaPublicKeyParameters _key = (DsaPublicKeyParameters) publicKey;
DsaParameters kp = _key.Parameters;
Asn1Encodable ae = kp == null
? null
@@ -64,9 +65,9 @@ namespace Org.BouncyCastle.X509
new DerInteger(_key.Y));
}
- if (key is DHPublicKeyParameters)
+ if (publicKey is DHPublicKeyParameters)
{
- DHPublicKeyParameters _key = (DHPublicKeyParameters) key;
+ DHPublicKeyParameters _key = (DHPublicKeyParameters) publicKey;
DHParameters kp = _key.Parameters;
SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(
@@ -78,9 +79,9 @@ namespace Org.BouncyCastle.X509
return info;
} // End of DH
- if (key is RsaKeyParameters)
+ if (publicKey is RsaKeyParameters)
{
- RsaKeyParameters _key = (RsaKeyParameters) key;
+ RsaKeyParameters _key = (RsaKeyParameters) publicKey;
SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(
new AlgorithmIdentifier(PkcsObjectIdentifiers.RsaEncryption, DerNull.Instance),
@@ -89,9 +90,9 @@ namespace Org.BouncyCastle.X509
return info;
} // End of RSA.
- if (key is ECPublicKeyParameters)
+ if (publicKey is ECPublicKeyParameters)
{
- ECPublicKeyParameters _key = (ECPublicKeyParameters) key;
+ ECPublicKeyParameters _key = (ECPublicKeyParameters) publicKey;
if (_key.AlgorithmName == "ECGOST3410")
{
@@ -139,9 +140,9 @@ namespace Org.BouncyCastle.X509
}
} // End of EC
- if (key is Gost3410PublicKeyParameters)
+ if (publicKey is Gost3410PublicKeyParameters)
{
- Gost3410PublicKeyParameters _key = (Gost3410PublicKeyParameters) key;
+ Gost3410PublicKeyParameters _key = (Gost3410PublicKeyParameters) publicKey;
if (_key.PublicKeyParamSet == null)
throw Platform.CreateNotImplementedException("Not a CryptoPro parameter set");
@@ -164,7 +165,35 @@ namespace Org.BouncyCastle.X509
return new SubjectPublicKeyInfo(algID, new DerOctetString(keyBytes));
}
- throw new ArgumentException("Class provided no convertible: " + Platform.GetTypeName(key));
+ if (publicKey is X448PublicKeyParameters)
+ {
+ X448PublicKeyParameters key = (X448PublicKeyParameters)publicKey;
+
+ return new SubjectPublicKeyInfo(new AlgorithmIdentifier(EdECObjectIdentifiers.id_X448), key.GetEncoded());
+ }
+
+ if (publicKey is X25519PublicKeyParameters)
+ {
+ X25519PublicKeyParameters key = (X25519PublicKeyParameters)publicKey;
+
+ return new SubjectPublicKeyInfo(new AlgorithmIdentifier(EdECObjectIdentifiers.id_X25519), key.GetEncoded());
+ }
+
+ if (publicKey is Ed448PublicKeyParameters)
+ {
+ Ed448PublicKeyParameters key = (Ed448PublicKeyParameters)publicKey;
+
+ return new SubjectPublicKeyInfo(new AlgorithmIdentifier(EdECObjectIdentifiers.id_Ed448), key.GetEncoded());
+ }
+
+ if (publicKey is Ed25519PublicKeyParameters)
+ {
+ Ed25519PublicKeyParameters key = (Ed25519PublicKeyParameters)publicKey;
+
+ return new SubjectPublicKeyInfo(new AlgorithmIdentifier(EdECObjectIdentifiers.id_Ed25519), key.GetEncoded());
+ }
+
+ throw new ArgumentException("Class provided no convertible: " + Platform.GetTypeName(publicKey));
}
private static void ExtractBytes(
|