using System; using Renci.SshNet.Common; using Renci.SshNet.Security.Chaos.NaCl; 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() }; } } /// /// Gets the length of the key. /// /// /// The length of the key. /// public override int KeyLength { get { return PublicKey.Length * 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) { if (publicKeyData is null) { throw new ArgumentNullException(nameof(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().Reverse().TrimLeadingZeros().Pad(Ed25519.PublicKeySizeInBytes); PrivateKey = new byte[Ed25519.ExpandedPrivateKeySizeInBytes]; } /// /// Initializes a new instance of the class. /// /// /// The private key data k || ENC(A) as described in RFC 8032. /// public ED25519Key(byte[] privateKeyData) { var seed = new byte[Ed25519.PrivateKeySeedSizeInBytes]; Buffer.BlockCopy(privateKeyData, 0, seed, 0, seed.Length); Ed25519.KeyPairFromSeed(out var publicKey, out var privateKey, seed); PublicKey = publicKey; PrivateKey = privateKey; } /// /// 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; } } /// /// Finalizes an instance of the class. /// ~ED25519Key() { Dispose(disposing: false); } } }