ED25519Key.cs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. using System;
  2. using Renci.SshNet.Common;
  3. using Renci.SshNet.Security.Chaos.NaCl;
  4. using Renci.SshNet.Security.Cryptography;
  5. namespace Renci.SshNet.Security
  6. {
  7. /// <summary>
  8. /// Contains ED25519 private and public key.
  9. /// </summary>
  10. public class ED25519Key : Key, IDisposable
  11. {
  12. private ED25519DigitalSignature _digitalSignature;
  13. private bool _isDisposed;
  14. /// <summary>
  15. /// Gets the name of the key.
  16. /// </summary>
  17. /// <returns>
  18. /// The name of the key.
  19. /// </returns>
  20. public override string ToString()
  21. {
  22. return "ssh-ed25519";
  23. }
  24. /// <summary>
  25. /// Gets the Ed25519 public key.
  26. /// </summary>
  27. /// <value>
  28. /// An array with <see cref="PublicKey"/> encoded at index 0.
  29. /// </value>
  30. public override BigInteger[] Public
  31. {
  32. get
  33. {
  34. return new BigInteger[] { PublicKey.ToBigInteger2() };
  35. }
  36. }
  37. /// <summary>
  38. /// Gets the length of the key.
  39. /// </summary>
  40. /// <value>
  41. /// The length of the key.
  42. /// </value>
  43. public override int KeyLength
  44. {
  45. get
  46. {
  47. return PublicKey.Length * 8;
  48. }
  49. }
  50. /// <summary>
  51. /// Gets the digital signature.
  52. /// </summary>
  53. protected internal override DigitalSignature DigitalSignature
  54. {
  55. get
  56. {
  57. _digitalSignature ??= new ED25519DigitalSignature(this);
  58. return _digitalSignature;
  59. }
  60. }
  61. /// <summary>
  62. /// Gets the PublicKey Bytes.
  63. /// </summary>
  64. public byte[] PublicKey { get; }
  65. /// <summary>
  66. /// Gets the PrivateKey Bytes.
  67. /// </summary>
  68. public byte[] PrivateKey { get; }
  69. /// <summary>
  70. /// Initializes a new instance of the <see cref="ED25519Key"/> class.
  71. /// </summary>
  72. /// <param name="publicKeyData">The encoded public key data.</param>
  73. public ED25519Key(SshKeyData publicKeyData)
  74. {
  75. if (publicKeyData is null)
  76. {
  77. throw new ArgumentNullException(nameof(publicKeyData));
  78. }
  79. if (publicKeyData.Name != "ssh-ed25519" || publicKeyData.Keys.Length != 1)
  80. {
  81. throw new ArgumentException($"Invalid Ed25519 public key data ({publicKeyData.Name}, {publicKeyData.Keys.Length}).", nameof(publicKeyData));
  82. }
  83. PublicKey = publicKeyData.Keys[0].ToByteArray().Reverse().TrimLeadingZeros().Pad(Ed25519.PublicKeySizeInBytes);
  84. PrivateKey = new byte[Ed25519.ExpandedPrivateKeySizeInBytes];
  85. }
  86. /// <summary>
  87. /// Initializes a new instance of the <see cref="ED25519Key"/> class.
  88. /// </summary>
  89. /// <param name="privateKeyData">
  90. /// The private key data <c>k || ENC(A)</c> as described in RFC 8032.
  91. /// </param>
  92. public ED25519Key(byte[] privateKeyData)
  93. {
  94. var seed = new byte[Ed25519.PrivateKeySeedSizeInBytes];
  95. Buffer.BlockCopy(privateKeyData, 0, seed, 0, seed.Length);
  96. Ed25519.KeyPairFromSeed(out var publicKey, out var privateKey, seed);
  97. PublicKey = publicKey;
  98. PrivateKey = privateKey;
  99. }
  100. /// <summary>
  101. /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
  102. /// </summary>
  103. public void Dispose()
  104. {
  105. Dispose(disposing: true);
  106. GC.SuppressFinalize(this);
  107. }
  108. /// <summary>
  109. /// Releases unmanaged and - optionally - managed resources.
  110. /// </summary>
  111. /// <param name="disposing"><see langword="true"/> to release both managed and unmanaged resources; <see langword="false"/> to release only unmanaged resources.</param>
  112. protected virtual void Dispose(bool disposing)
  113. {
  114. if (_isDisposed)
  115. {
  116. return;
  117. }
  118. if (disposing)
  119. {
  120. _isDisposed = true;
  121. }
  122. }
  123. /// <summary>
  124. /// Finalizes an instance of the <see cref="ED25519Key"/> class.
  125. /// </summary>
  126. ~ED25519Key()
  127. {
  128. Dispose(disposing: false);
  129. }
  130. }
  131. }