using System; using System.Numerics; using Org.BouncyCastle.Math.EC.Rfc8032; using Renci.SshNet.Common; using Renci.SshNet.Security.Cryptography; namespace Renci.SshNet.Security { /// /// Contains ED25519 private and public key. /// public class ED25519Key : Key, IDisposable { private ED25519DigitalSignature _digitalSignature; private bool _isDisposed; /// /// Gets the name of the key. /// /// /// The name of the key. /// public override string ToString() { return "ssh-ed25519"; } /// /// Gets the Ed25519 public key. /// /// /// An array with encoded at index 0. /// public override BigInteger[] Public { get { return new BigInteger[] { PublicKey.ToBigInteger2() }; } } /// public override int KeyLength { get { return Ed25519.PublicKeySize * 8; } } /// /// Gets the digital signature. /// protected internal override DigitalSignature DigitalSignature { get { _digitalSignature ??= new ED25519DigitalSignature(this); return _digitalSignature; } } /// /// Gets the PublicKey Bytes. /// public byte[] PublicKey { get; } /// /// Gets the PrivateKey Bytes. /// public byte[] PrivateKey { get; } /// /// Initializes a new instance of the class. /// /// The encoded public key data. public ED25519Key(SshKeyData publicKeyData) { ThrowHelper.ThrowIfNull(publicKeyData); if (publicKeyData.Name != "ssh-ed25519" || publicKeyData.Keys.Length != 1) { throw new ArgumentException($"Invalid Ed25519 public key data ({publicKeyData.Name}, {publicKeyData.Keys.Length}).", nameof(publicKeyData)); } PublicKey = publicKeyData.Keys[0].ToByteArray(isBigEndian: true).TrimLeadingZeros().Pad(Ed25519.PublicKeySize); PrivateKey = new byte[Ed25519.SecretKeySize]; } /// /// Initializes a new instance of the class. /// /// /// The private key data k || ENC(A) as described in RFC 8032. /// public ED25519Key(byte[] privateKeyData) { PrivateKey = new byte[Ed25519.SecretKeySize]; PublicKey = new byte[Ed25519.PublicKeySize]; Buffer.BlockCopy(privateKeyData, 0, PrivateKey, 0, Ed25519.SecretKeySize); Ed25519.GeneratePublicKey(privateKeyData, 0, PublicKey, 0); } /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } /// /// Releases unmanaged and - optionally - managed resources. /// /// to release both managed and unmanaged resources; to release only unmanaged resources. protected virtual void Dispose(bool disposing) { if (_isDisposed) { return; } if (disposing) { _isDisposed = true; } } } }