KeyExchangeECDH.BclImpl.cs 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. #if NET8_0_OR_GREATER
  2. using System;
  3. using System.Security.Cryptography;
  4. namespace Renci.SshNet.Security
  5. {
  6. internal abstract partial class KeyExchangeECDH
  7. {
  8. private sealed class BclImpl : Impl
  9. {
  10. private readonly ECCurve _curve;
  11. private readonly ECDiffieHellman _clientECDH;
  12. public BclImpl(ECCurve curve)
  13. {
  14. _curve = curve;
  15. _clientECDH = ECDiffieHellman.Create();
  16. }
  17. public override byte[] GenerateClientECPoint()
  18. {
  19. _clientECDH.GenerateKey(_curve);
  20. var q = _clientECDH.PublicKey.ExportParameters().Q;
  21. return EncodeECPoint(q);
  22. }
  23. public override byte[] CalculateAgreement(byte[] serverECPoint)
  24. {
  25. var q = DecodeECPoint(serverECPoint);
  26. var parameters = new ECParameters
  27. {
  28. Curve = _curve,
  29. Q = q,
  30. };
  31. using var serverECDH = ECDiffieHellman.Create(parameters);
  32. return _clientECDH.DeriveRawSecretAgreement(serverECDH.PublicKey);
  33. }
  34. private static byte[] EncodeECPoint(ECPoint point)
  35. {
  36. var q = new byte[1 + point.X.Length + point.Y.Length];
  37. q[0] = 0x04;
  38. Buffer.BlockCopy(point.X, 0, q, 1, point.X.Length);
  39. Buffer.BlockCopy(point.Y, 0, q, point.X.Length + 1, point.Y.Length);
  40. return q;
  41. }
  42. private static ECPoint DecodeECPoint(byte[] q)
  43. {
  44. var cordSize = (q.Length - 1) / 2;
  45. var x = new byte[cordSize];
  46. var y = new byte[cordSize];
  47. Buffer.BlockCopy(q, 1, x, 0, x.Length);
  48. Buffer.BlockCopy(q, cordSize + 1, y, 0, y.Length);
  49. return new ECPoint { X = x, Y = y };
  50. }
  51. protected override void Dispose(bool disposing)
  52. {
  53. base.Dispose(disposing);
  54. if (disposing)
  55. {
  56. _clientECDH.Dispose();
  57. }
  58. }
  59. }
  60. }
  61. }
  62. #endif