<PackageReference Include="SSH.NET" Version="2020.0.1" />

PrivateKeyAuthenticationMethod

Provides functionality to perform private key authentication.
using Renci.SshNet.Common; using Renci.SshNet.Messages; using Renci.SshNet.Messages.Authentication; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Threading; namespace Renci.SshNet { public class PrivateKeyAuthenticationMethod : AuthenticationMethod, IDisposable { private class SignatureData : SshData { private readonly RequestMessagePublicKey _message; private readonly byte[] _sessionId; private readonly byte[] _serviceName; private readonly byte[] _authenticationMethod; protected override int BufferCapacity => base.BufferCapacity + 4 + _sessionId.Length + 1 + 4 + _message.Username.Length + 4 + _serviceName.Length + 4 + _authenticationMethod.Length + 1 + 4 + _message.PublicKeyAlgorithmName.Length + 4 + _message.PublicKeyData.Length; public SignatureData(RequestMessagePublicKey message, byte[] sessionId) { _message = message; _sessionId = sessionId; _serviceName = ServiceName.Connection.ToArray(); _authenticationMethod = SshData.Ascii.GetBytes("publickey"); } protected override void LoadData() { throw new NotImplementedException(); } protected override void SaveData() { WriteBinaryString(_sessionId); Write(50); WriteBinaryString(_message.Username); WriteBinaryString(_serviceName); WriteBinaryString(_authenticationMethod); Write(1); WriteBinaryString(_message.PublicKeyAlgorithmName); WriteBinaryString(_message.PublicKeyData); } } private AuthenticationResult _authenticationResult = AuthenticationResult.Failure; private EventWaitHandle _authenticationCompleted = new ManualResetEvent(false); private bool _isSignatureRequired; private bool _isDisposed; public override string Name => "publickey"; public ICollection<PrivateKeyFile> KeyFiles { get; set; } public PrivateKeyAuthenticationMethod(string username, params PrivateKeyFile[] keyFiles) : base(username) { if (keyFiles == null) throw new ArgumentNullException("keyFiles"); KeyFiles = new Collection<PrivateKeyFile>(keyFiles); } public override AuthenticationResult Authenticate(Session session) { session.UserAuthenticationSuccessReceived += Session_UserAuthenticationSuccessReceived; session.UserAuthenticationFailureReceived += Session_UserAuthenticationFailureReceived; session.UserAuthenticationPublicKeyReceived += Session_UserAuthenticationPublicKeyReceived; session.RegisterMessage("SSH_MSG_USERAUTH_PK_OK"); try { foreach (PrivateKeyFile keyFile in KeyFiles) { _authenticationCompleted.Reset(); _isSignatureRequired = false; RequestMessagePublicKey requestMessagePublicKey = new RequestMessagePublicKey(ServiceName.Connection, base.Username, keyFile.HostKey.Name, keyFile.HostKey.Data); if (KeyFiles.Count < 2) { byte[] bytes = new SignatureData(requestMessagePublicKey, session.SessionId).GetBytes(); requestMessagePublicKey.Signature = keyFile.HostKey.Sign(bytes); } session.SendMessage(requestMessagePublicKey); session.WaitOnHandle(_authenticationCompleted); if (_isSignatureRequired) { _authenticationCompleted.Reset(); RequestMessagePublicKey requestMessagePublicKey2 = new RequestMessagePublicKey(ServiceName.Connection, base.Username, keyFile.HostKey.Name, keyFile.HostKey.Data); byte[] bytes2 = new SignatureData(requestMessagePublicKey, session.SessionId).GetBytes(); requestMessagePublicKey2.Signature = keyFile.HostKey.Sign(bytes2); session.SendMessage(requestMessagePublicKey2); } session.WaitOnHandle(_authenticationCompleted); if (_authenticationResult == AuthenticationResult.Success) break; } return _authenticationResult; } finally { session.UserAuthenticationSuccessReceived -= Session_UserAuthenticationSuccessReceived; session.UserAuthenticationFailureReceived -= Session_UserAuthenticationFailureReceived; session.UserAuthenticationPublicKeyReceived -= Session_UserAuthenticationPublicKeyReceived; session.UnRegisterMessage("SSH_MSG_USERAUTH_PK_OK"); } } private void Session_UserAuthenticationSuccessReceived(object sender, MessageEventArgs<SuccessMessage> e) { _authenticationResult = AuthenticationResult.Success; _authenticationCompleted.Set(); } private void Session_UserAuthenticationFailureReceived(object sender, MessageEventArgs<FailureMessage> e) { if (e.Message.PartialSuccess) _authenticationResult = AuthenticationResult.PartialSuccess; else _authenticationResult = AuthenticationResult.Failure; base.AllowedAuthentications = e.Message.AllowedAuthentications; _authenticationCompleted.Set(); } private void Session_UserAuthenticationPublicKeyReceived(object sender, MessageEventArgs<PublicKeyMessage> e) { _isSignatureRequired = true; _authenticationCompleted.Set(); } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (!_isDisposed && disposing) { EventWaitHandle authenticationCompleted = _authenticationCompleted; if (authenticationCompleted != null) { _authenticationCompleted = null; authenticationCompleted.Dispose(); } _isDisposed = true; } } ~PrivateKeyAuthenticationMethod() { Dispose(false); } } }