summary refs log tree commit diff
path: root/crypto/src/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/src/crypto')
-rw-r--r--crypto/src/crypto/IRawAgreement.cs13
-rw-r--r--crypto/src/crypto/agreement/X25519Agreement.cs27
-rw-r--r--crypto/src/crypto/agreement/X448Agreement.cs27
-rw-r--r--crypto/src/crypto/generators/Ed25519KeyPairGenerator.cs25
-rw-r--r--crypto/src/crypto/generators/Ed448KeyPairGenerator.cs25
-rw-r--r--crypto/src/crypto/generators/X25519KeyPairGenerator.cs25
-rw-r--r--crypto/src/crypto/generators/X448KeyPairGenerator.cs25
-rw-r--r--crypto/src/crypto/parameters/Ed25519KeyGenerationParameters.cs15
-rw-r--r--crypto/src/crypto/parameters/Ed25519PrivateKeyParameters.cs98
-rw-r--r--crypto/src/crypto/parameters/Ed25519PublicKeyParameters.cs40
-rw-r--r--crypto/src/crypto/parameters/Ed448KeyGenerationParameters.cs15
-rw-r--r--crypto/src/crypto/parameters/Ed448PrivateKeyParameters.cs90
-rw-r--r--crypto/src/crypto/parameters/Ed448PublicKeyParameters.cs40
-rw-r--r--crypto/src/crypto/parameters/X25519KeyGenerationParameters.cs15
-rw-r--r--crypto/src/crypto/parameters/X25519PrivateKeyParameters.cs62
-rw-r--r--crypto/src/crypto/parameters/X25519PublicKeyParameters.cs40
-rw-r--r--crypto/src/crypto/parameters/X448KeyGenerationParameters.cs15
-rw-r--r--crypto/src/crypto/parameters/X448PrivateKeyParameters.cs62
-rw-r--r--crypto/src/crypto/parameters/X448PublicKeyParameters.cs40
-rw-r--r--crypto/src/crypto/signers/Ed25519Signer.cs128
-rw-r--r--crypto/src/crypto/signers/Ed25519ctxSigner.cs130
-rw-r--r--crypto/src/crypto/signers/Ed25519phSigner.cs89
-rw-r--r--crypto/src/crypto/signers/Ed448Signer.cs130
-rw-r--r--crypto/src/crypto/signers/Ed448phSigner.cs89
24 files changed, 1265 insertions, 0 deletions
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(); + } + } +}