KeyHostAlgorithm
Implements key support for host algorithm.
using Renci.SshNet.Common;
using Renci.SshNet.Security.Chaos.NaCl;
using Renci.SshNet.Security.Cryptography;
using System.Collections.Generic;
using System.Text;
namespace Renci.SshNet.Security
{
public class KeyHostAlgorithm : HostAlgorithm
{
private sealed class SshKeyData : SshData
{
private byte[] _name;
private List<byte[]> _keys;
public BigInteger[] Keys {
get {
BigInteger[] array = new BigInteger[_keys.Count];
for (int i = 0; i < _keys.Count; i++) {
byte[] data = _keys[i];
array[i] = data.ToBigInteger2();
}
return array;
}
private set {
_keys = new List<byte[]>(value.Length);
for (int i = 0; i < value.Length; i++) {
BigInteger bigInteger = value[i];
byte[] array = bigInteger.ToByteArray().Reverse();
if (Name == "ssh-ed25519")
array = array.TrimLeadingZeros().Pad(Ed25519.PublicKeySizeInBytes);
_keys.Add(array);
}
}
}
private string Name {
get {
return SshData.Utf8.GetString(_name, 0, _name.Length);
}
set {
_name = SshData.Utf8.GetBytes(value);
}
}
protected override int BufferCapacity {
get {
int bufferCapacity = base.BufferCapacity;
bufferCapacity += 4;
bufferCapacity += _name.Length;
foreach (byte[] key in _keys) {
bufferCapacity += 4;
bufferCapacity += key.Length;
}
return bufferCapacity;
}
}
public SshKeyData()
{
}
public SshKeyData(string name, params BigInteger[] keys)
{
Name = name;
Keys = keys;
}
protected override void LoadData()
{
_name = ReadBinary();
_keys = new List<byte[]>();
while (!base.IsEndOfData) {
_keys.Add(ReadBinary());
}
}
protected override void SaveData()
{
WriteBinaryString(_name);
foreach (byte[] key in _keys) {
WriteBinaryString(key);
}
}
}
internal sealed class SignatureKeyData : SshData
{
public string AlgorithmName { get; set; }
public byte[] Signature { get; set; }
protected override int BufferCapacity => base.BufferCapacity + 4 + Encoding.UTF8.GetByteCount(AlgorithmName) + 4 + Signature.Length;
public SignatureKeyData()
{
}
public SignatureKeyData(string name, byte[] signature)
{
AlgorithmName = name;
Signature = signature;
}
protected override void LoadData()
{
AlgorithmName = Encoding.UTF8.GetString(ReadBinary());
Signature = ReadBinary();
}
protected override void SaveData()
{
WriteBinaryString(Encoding.UTF8.GetBytes(AlgorithmName));
WriteBinaryString(Signature);
}
}
public Key Key { get; set; }
public DigitalSignature DigitalSignature { get; set; }
public override byte[] Data => new SshKeyData((Key is RsaKey) ? "ssh-rsa" : base.Name, Key.Public).GetBytes();
public KeyHostAlgorithm(string name, Key key)
: base(name)
{
Key = key;
DigitalSignature = key.DigitalSignature;
}
public KeyHostAlgorithm(string name, Key key, DigitalSignature digitalSignature)
: base(name)
{
Key = key;
DigitalSignature = digitalSignature;
}
public KeyHostAlgorithm(string name, Key key, byte[] data)
: base(name)
{
Key = key;
SshKeyData sshKeyData = new SshKeyData();
sshKeyData.Load(data);
Key.Public = sshKeyData.Keys;
DigitalSignature = key.DigitalSignature;
}
public KeyHostAlgorithm(string name, Key key, byte[] data, DigitalSignature digitalSignature)
: base(name)
{
Key = key;
SshKeyData sshKeyData = new SshKeyData();
sshKeyData.Load(data);
Key.Public = sshKeyData.Keys;
DigitalSignature = digitalSignature;
}
public override byte[] Sign(byte[] data)
{
return new SignatureKeyData(base.Name, DigitalSignature.Sign(data)).GetBytes();
}
public override bool VerifySignature(byte[] data, byte[] signature)
{
SignatureKeyData signatureKeyData = new SignatureKeyData();
signatureKeyData.Load(signature);
return DigitalSignature.Verify(data, signatureKeyData.Signature);
}
}
}