<PackageReference Include="BouncyCastle.Cryptography" Version="2.3.0" />

X25519PrivateKeyParameters

using Org.BouncyCastle.Math.EC.Rfc7748; using Org.BouncyCastle.Security; using Org.BouncyCastle.Utilities; using Org.BouncyCastle.Utilities.IO; using System; using System.IO; namespace Org.BouncyCastle.Crypto.Parameters { public sealed class X25519PrivateKeyParameters : AsymmetricKeyParameter { public static readonly int KeySize = 32; public static readonly int SecretSize = 32; private readonly byte[] data = new byte[KeySize]; internal ReadOnlySpan<byte> DataSpan => data; internal ReadOnlyMemory<byte> DataMemory => data; public X25519PrivateKeyParameters(SecureRandom random) : base(true) { X25519.GeneratePrivateKey(random, data); } public X25519PrivateKeyParameters(byte[] buf) : this(Validate(buf), 0) { } public X25519PrivateKeyParameters(byte[] buf, int off) : base(true) { Array.Copy(buf, off, data, 0, KeySize); } public X25519PrivateKeyParameters(ReadOnlySpan<byte> buf) : base(true) { if (buf.Length != KeySize) throw new ArgumentException("must have length " + KeySize.ToString(), "buf"); buf.CopyTo(data); } 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 void Encode(Span<byte> buf) { data.CopyTo(buf); } public byte[] GetEncoded() { return Arrays.Clone(data); } public unsafe X25519PublicKeyParameters GeneratePublicKey() { Span<byte> span = new Span<byte>(stackalloc byte[32], 32); X25519.GeneratePublicKey(data, span); return new X25519PublicKeyParameters(span); } public void GenerateSecret(X25519PublicKeyParameters publicKey, byte[] buf, int off) { GenerateSecret(publicKey, buf.AsSpan(off)); } public unsafe void GenerateSecret(X25519PublicKeyParameters publicKey, Span<byte> buf) { Span<byte> span = new Span<byte>(stackalloc byte[32], 32); publicKey.Encode(span); if (!X25519.CalculateAgreement(data, span, buf)) throw new InvalidOperationException("X25519 agreement failed"); } private static byte[] Validate(byte[] buf) { if (buf.Length != KeySize) throw new ArgumentException("must have length " + KeySize.ToString(), "buf"); return buf; } } }