SshKeyData.cs 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. using System.Collections.Generic;
  2. using System.Text;
  3. using Org.BouncyCastle.Math.EC.Rfc8032;
  4. using Renci.SshNet.Common;
  5. namespace Renci.SshNet.Security
  6. {
  7. /// <summary>
  8. /// Facilitates (de)serializing encoded public key data in the format
  9. /// specified by RFC 4253 section 6.6.
  10. /// </summary>
  11. /// <remarks>
  12. /// See https://datatracker.ietf.org/doc/html/rfc4253#section-6.6.
  13. /// </remarks>
  14. public sealed class SshKeyData : SshData
  15. {
  16. /// <summary>
  17. /// Gets the public key format identifier.
  18. /// </summary>
  19. public string Name { get; private set; }
  20. /// <summary>
  21. /// Gets the public key constituents.
  22. /// </summary>
  23. public BigInteger[] Keys { get; private set; }
  24. /// <inheritdoc/>
  25. protected override int BufferCapacity
  26. {
  27. get
  28. {
  29. var capacity = base.BufferCapacity;
  30. capacity += 4; // Name length
  31. capacity += Encoding.UTF8.GetByteCount(Name); // Name
  32. foreach (var key in Keys)
  33. {
  34. capacity += 4; // Key length
  35. capacity += key.BitLength / 8; // Key
  36. }
  37. return capacity;
  38. }
  39. }
  40. /// <summary>
  41. /// Initializes a new instance of the <see cref="SshKeyData"/> class.
  42. /// </summary>
  43. /// <param name="data">The encoded public key data.</param>
  44. public SshKeyData(byte[] data)
  45. {
  46. Load(data);
  47. }
  48. /// <summary>
  49. /// Initializes a new instance of the <see cref="SshKeyData"/> class.
  50. /// </summary>
  51. /// <param name="name">The public key format identifer.</param>
  52. /// <param name="keys">The public key constituents.</param>
  53. public SshKeyData(string name, BigInteger[] keys)
  54. {
  55. Name = name;
  56. Keys = keys;
  57. }
  58. /// <inheritdoc/>
  59. protected override void LoadData()
  60. {
  61. Name = ReadString();
  62. var keys = new List<BigInteger>();
  63. while (!IsEndOfData)
  64. {
  65. keys.Add(ReadBinary().ToBigInteger2());
  66. }
  67. Keys = keys.ToArray();
  68. }
  69. /// <inheritdoc/>
  70. protected override void SaveData()
  71. {
  72. Write(Name);
  73. foreach (var key in Keys)
  74. {
  75. var keyData = key.ToByteArray().Reverse();
  76. if (Name == "ssh-ed25519")
  77. {
  78. keyData = keyData.TrimLeadingZeros().Pad(Ed25519.PublicKeySize);
  79. }
  80. WriteBinaryString(keyData);
  81. }
  82. }
  83. }
  84. }