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;
}
}
}
}