| | | 1 | | using System; |
| | | 2 | | |
| | | 3 | | using Renci.SshNet.Abstractions; |
| | | 4 | | using Renci.SshNet.Security; |
| | | 5 | | |
| | | 6 | | namespace Renci.SshNet.Common |
| | | 7 | | { |
| | | 8 | | /// <summary> |
| | | 9 | | /// Provides data for the HostKeyReceived event. |
| | | 10 | | /// </summary> |
| | | 11 | | public class HostKeyEventArgs : EventArgs |
| | | 12 | | { |
| | | 13 | | private readonly Lazy<byte[]> _lazyFingerPrint; |
| | | 14 | | private readonly Lazy<string> _lazyFingerPrintSHA256; |
| | | 15 | | private readonly Lazy<string> _lazyFingerPrintMD5; |
| | | 16 | | |
| | | 17 | | /// <summary> |
| | | 18 | | /// Gets or sets a value indicating whether host key can be trusted. |
| | | 19 | | /// </summary> |
| | | 20 | | /// <value> |
| | | 21 | | /// <see langword="true"/> if host key can be trusted; otherwise, <see langword="false"/>. |
| | | 22 | | /// </value> |
| | 2432 | 23 | | public bool CanTrust { get; set; } |
| | | 24 | | |
| | | 25 | | /// <summary> |
| | | 26 | | /// Gets the host key. |
| | | 27 | | /// </summary> |
| | 1237 | 28 | | public byte[] HostKey { get; private set; } |
| | | 29 | | |
| | | 30 | | /// <summary> |
| | | 31 | | /// Gets the host key name. |
| | | 32 | | /// </summary> |
| | 1228 | 33 | | public string HostKeyName { get; private set; } |
| | | 34 | | |
| | | 35 | | /// <summary> |
| | | 36 | | /// Gets the MD5 fingerprint. |
| | | 37 | | /// </summary> |
| | | 38 | | /// <value> |
| | | 39 | | /// MD5 fingerprint as byte array. |
| | | 40 | | /// </value> |
| | | 41 | | public byte[] FingerPrint |
| | | 42 | | { |
| | | 43 | | get |
| | 29 | 44 | | { |
| | 29 | 45 | | return _lazyFingerPrint.Value; |
| | 29 | 46 | | } |
| | | 47 | | } |
| | | 48 | | |
| | | 49 | | /// <summary> |
| | | 50 | | /// Gets the SHA256 fingerprint of the host key in the same format as the ssh command, |
| | | 51 | | /// i.e. non-padded base64, but without the <c>SHA256:</c> prefix. |
| | | 52 | | /// </summary> |
| | | 53 | | /// <example><c>ohD8VZEXGWo6Ez8GSEJQ9WpafgLFsOfLOtGGQCQo6Og</c>.</example> |
| | | 54 | | /// <value> |
| | | 55 | | /// Base64 encoded SHA256 fingerprint with padding (equals sign) removed. |
| | | 56 | | /// </value> |
| | | 57 | | public string FingerPrintSHA256 |
| | | 58 | | { |
| | | 59 | | get |
| | 4 | 60 | | { |
| | 4 | 61 | | return _lazyFingerPrintSHA256.Value; |
| | 4 | 62 | | } |
| | | 63 | | } |
| | | 64 | | |
| | | 65 | | /// <summary> |
| | | 66 | | /// Gets the MD5 fingerprint of the host key in the same format as the ssh command, |
| | | 67 | | /// i.e. hexadecimal bytes separated by colons, but without the <c>MD5:</c> prefix. |
| | | 68 | | /// </summary> |
| | | 69 | | /// <example><c>97:70:33:82:fd:29:3a:73:39:af:6a:07:ad:f8:80:49</c>.</example> |
| | | 70 | | public string FingerPrintMD5 |
| | | 71 | | { |
| | | 72 | | get |
| | 4 | 73 | | { |
| | 4 | 74 | | return _lazyFingerPrintMD5.Value; |
| | 4 | 75 | | } |
| | | 76 | | } |
| | | 77 | | |
| | | 78 | | /// <summary> |
| | | 79 | | /// Gets the length of the key in bits. |
| | | 80 | | /// </summary> |
| | | 81 | | /// <value> |
| | | 82 | | /// The length of the key in bits. |
| | | 83 | | /// </value> |
| | 1228 | 84 | | public int KeyLength { get; private set; } |
| | | 85 | | |
| | | 86 | | /// <summary> |
| | | 87 | | /// Initializes a new instance of the <see cref="HostKeyEventArgs"/> class. |
| | | 88 | | /// </summary> |
| | | 89 | | /// <param name="host">The host.</param> |
| | | 90 | | /// <exception cref="ArgumentNullException"><paramref name="host"/> is <see langword="null"/>.</exception> |
| | 1220 | 91 | | public HostKeyEventArgs(KeyHostAlgorithm host) |
| | 1220 | 92 | | { |
| | 1220 | 93 | | if (host is null) |
| | 0 | 94 | | { |
| | 0 | 95 | | throw new ArgumentNullException(nameof(host)); |
| | | 96 | | } |
| | | 97 | | |
| | 1220 | 98 | | CanTrust = true; |
| | 1220 | 99 | | HostKey = host.Data; |
| | 1220 | 100 | | HostKeyName = host.Name; |
| | 1220 | 101 | | KeyLength = host.Key.KeyLength; |
| | | 102 | | |
| | 1220 | 103 | | _lazyFingerPrint = new Lazy<byte[]>(() => |
| | 10 | 104 | | { |
| | 10 | 105 | | using var md5 = CryptoAbstraction.CreateMD5(); |
| | 10 | 106 | | return md5.ComputeHash(HostKey); |
| | 1230 | 107 | | }); |
| | | 108 | | |
| | 1220 | 109 | | _lazyFingerPrintSHA256 = new Lazy<string>(() => |
| | 4 | 110 | | { |
| | 4 | 111 | | using var sha256 = CryptoAbstraction.CreateSHA256(); |
| | 1220 | 112 | | |
| | 4 | 113 | | return Convert.ToBase64String(sha256.ComputeHash(HostKey)) |
| | 4 | 114 | | #if NET || NETSTANDARD2_1_OR_GREATER |
| | 4 | 115 | | .Replace("=", string.Empty, StringComparison.Ordinal); |
| | 1214 | 116 | | #else |
| | 1214 | 117 | | .Replace("=", string.Empty); |
| | 1220 | 118 | | #endif // NET || NETSTANDARD2_1_OR_GREATER |
| | 1224 | 119 | | }); |
| | | 120 | | |
| | 1220 | 121 | | _lazyFingerPrintMD5 = new Lazy<string>(() => |
| | 4 | 122 | | { |
| | 1220 | 123 | | #pragma warning disable CA1308 // Normalize strings to uppercase |
| | 4 | 124 | | return BitConverter.ToString(FingerPrint).Replace('-', ':').ToLowerInvariant(); |
| | 1220 | 125 | | #pragma warning restore CA1308 // Normalize strings to uppercase |
| | 1224 | 126 | | }); |
| | 1220 | 127 | | } |
| | | 128 | | } |
| | | 129 | | } |