ED25519Key.cs 4.0 KB

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