| | | 1 | | using Renci.SshNet.Abstractions; |
| | | 2 | | using Renci.SshNet.Common; |
| | | 3 | | using Renci.SshNet.Messages.Transport; |
| | | 4 | | using Renci.SshNet.Security.Chaos.NaCl; |
| | | 5 | | using Renci.SshNet.Security.Chaos.NaCl.Internal.Ed25519Ref10; |
| | | 6 | | |
| | | 7 | | namespace Renci.SshNet.Security |
| | | 8 | | { |
| | | 9 | | internal sealed class KeyExchangeECCurve25519 : KeyExchangeEC |
| | | 10 | | { |
| | | 11 | | private byte[] _privateKey; |
| | | 12 | | |
| | | 13 | | /// <summary> |
| | | 14 | | /// Gets algorithm name. |
| | | 15 | | /// </summary> |
| | | 16 | | public override string Name |
| | | 17 | | { |
| | 3516 | 18 | | get { return "curve25519-sha256"; } |
| | | 19 | | } |
| | | 20 | | |
| | | 21 | | /// <summary> |
| | | 22 | | /// Gets the size, in bits, of the computed hash code. |
| | | 23 | | /// </summary> |
| | | 24 | | /// <value> |
| | | 25 | | /// The size, in bits, of the computed hash code. |
| | | 26 | | /// </value> |
| | | 27 | | protected override int HashSize |
| | | 28 | | { |
| | 0 | 29 | | get { return 256; } |
| | | 30 | | } |
| | | 31 | | |
| | | 32 | | /// <summary> |
| | | 33 | | /// Starts key exchange algorithm. |
| | | 34 | | /// </summary> |
| | | 35 | | /// <param name="session">The session.</param> |
| | | 36 | | /// <param name="message">Key exchange init message.</param> |
| | | 37 | | public override void Start(Session session, KeyExchangeInitMessage message) |
| | 1172 | 38 | | { |
| | 1172 | 39 | | base.Start(session, message); |
| | | 40 | | |
| | 1172 | 41 | | Session.RegisterMessage("SSH_MSG_KEX_ECDH_REPLY"); |
| | | 42 | | |
| | 1172 | 43 | | Session.KeyExchangeEcdhReplyMessageReceived += Session_KeyExchangeEcdhReplyMessageReceived; |
| | | 44 | | |
| | 1172 | 45 | | var basepoint = new byte[MontgomeryCurve25519.PublicKeySizeInBytes]; |
| | 1172 | 46 | | basepoint[0] = 9; |
| | | 47 | | |
| | 1172 | 48 | | _privateKey = CryptoAbstraction.GenerateRandom(MontgomeryCurve25519.PrivateKeySizeInBytes); |
| | | 49 | | |
| | 1172 | 50 | | _clientExchangeValue = new byte[MontgomeryCurve25519.PublicKeySizeInBytes]; |
| | 1172 | 51 | | MontgomeryOperations.scalarmult(_clientExchangeValue, 0, _privateKey, 0, basepoint, 0); |
| | | 52 | | |
| | 1172 | 53 | | SendMessage(new KeyExchangeEcdhInitMessage(_clientExchangeValue)); |
| | 1172 | 54 | | } |
| | | 55 | | |
| | | 56 | | /// <summary> |
| | | 57 | | /// Finishes key exchange algorithm. |
| | | 58 | | /// </summary> |
| | | 59 | | public override void Finish() |
| | 1172 | 60 | | { |
| | 1172 | 61 | | base.Finish(); |
| | | 62 | | |
| | 1171 | 63 | | Session.KeyExchangeEcdhReplyMessageReceived -= Session_KeyExchangeEcdhReplyMessageReceived; |
| | 1171 | 64 | | } |
| | | 65 | | |
| | | 66 | | /// <summary> |
| | | 67 | | /// Hashes the specified data bytes. |
| | | 68 | | /// </summary> |
| | | 69 | | /// <param name="hashData">The hash data.</param> |
| | | 70 | | /// <returns> |
| | | 71 | | /// The hash of the data. |
| | | 72 | | /// </returns> |
| | | 73 | | protected override byte[] Hash(byte[] hashData) |
| | 9375 | 74 | | { |
| | 9375 | 75 | | using (var sha256 = CryptoAbstraction.CreateSHA256()) |
| | 9375 | 76 | | { |
| | 9375 | 77 | | return sha256.ComputeHash(hashData, 0, hashData.Length); |
| | | 78 | | } |
| | 9375 | 79 | | } |
| | | 80 | | |
| | | 81 | | private void Session_KeyExchangeEcdhReplyMessageReceived(object sender, MessageEventArgs<KeyExchangeEcdhReplyMes |
| | 1172 | 82 | | { |
| | 1172 | 83 | | var message = e.Message; |
| | | 84 | | |
| | | 85 | | // Unregister message once received |
| | 1172 | 86 | | Session.UnRegisterMessage("SSH_MSG_KEX_ECDH_REPLY"); |
| | | 87 | | |
| | 1172 | 88 | | HandleServerEcdhReply(message.KS, message.QS, message.Signature); |
| | | 89 | | |
| | | 90 | | // When SSH_MSG_KEXDH_REPLY received key exchange is completed |
| | 1172 | 91 | | Finish(); |
| | 1171 | 92 | | } |
| | | 93 | | |
| | | 94 | | /// <summary> |
| | | 95 | | /// Handles the server DH reply message. |
| | | 96 | | /// </summary> |
| | | 97 | | /// <param name="hostKey">The host key.</param> |
| | | 98 | | /// <param name="serverExchangeValue">The server exchange value.</param> |
| | | 99 | | /// <param name="signature">The signature.</param> |
| | | 100 | | private void HandleServerEcdhReply(byte[] hostKey, byte[] serverExchangeValue, byte[] signature) |
| | 1172 | 101 | | { |
| | 1172 | 102 | | _serverExchangeValue = serverExchangeValue; |
| | 1172 | 103 | | _hostKey = hostKey; |
| | 1172 | 104 | | _signature = signature; |
| | | 105 | | |
| | 1172 | 106 | | var sharedKey = new byte[MontgomeryCurve25519.PublicKeySizeInBytes]; |
| | 1172 | 107 | | MontgomeryOperations.scalarmult(sharedKey, 0, _privateKey, 0, serverExchangeValue, 0); |
| | 1172 | 108 | | SharedKey = sharedKey.ToBigInteger2().ToByteArray().Reverse(); |
| | 1172 | 109 | | } |
| | | 110 | | } |
| | | 111 | | } |