using System.Collections.Generic; using System.Text; using Org.BouncyCastle.Math.EC.Rfc8032; using Renci.SshNet.Common; namespace Renci.SshNet.Security { /// /// Facilitates (de)serializing encoded public key data in the format /// specified by RFC 4253 section 6.6. /// /// /// See https://datatracker.ietf.org/doc/html/rfc4253#section-6.6. /// public sealed class SshKeyData : SshData { /// /// Gets the public key format identifier. /// public string Name { get; private set; } /// /// Gets the public key constituents. /// public BigInteger[] Keys { get; private set; } /// protected override int BufferCapacity { get { var capacity = base.BufferCapacity; capacity += 4; // Name length capacity += Encoding.UTF8.GetByteCount(Name); // Name foreach (var key in Keys) { capacity += 4; // Key length capacity += key.BitLength / 8; // Key } return capacity; } } /// /// Initializes a new instance of the class. /// /// The encoded public key data. public SshKeyData(byte[] data) { Load(data); } /// /// Initializes a new instance of the class. /// /// The public key format identifer. /// The public key constituents. public SshKeyData(string name, BigInteger[] keys) { Name = name; Keys = keys; } /// protected override void LoadData() { Name = ReadString(); var keys = new List(); while (!IsEndOfData) { keys.Add(ReadBinary().ToBigInteger2()); } Keys = keys.ToArray(); } /// protected override void SaveData() { Write(Name); foreach (var key in Keys) { var keyData = key.ToByteArray().Reverse(); if (Name == "ssh-ed25519") { keyData = keyData.TrimLeadingZeros().Pad(Ed25519.PublicKeySize); } WriteBinaryString(keyData); } } } }