phpseclib

phpseclib

  • Docs
  • API
  • Support
  • GitHub

›SSH2

Introduction

  • Why phpseclib?
  • Installation
  • Speed
  • Versioning

SSH2

  • Connecting
  • Authenticating
  • Running Commands
  • SFTP
  • Diagnosing Issues

Public Keys

  • Overview
  • RSA
  • DSA
  • Elliptic Curves
  • (EC)DH
  • Example: JWT

Symmetric Keys

  • Overview

X.509

  • X.509
  • CSR
  • SPKAC
  • CRL

Interoperability

  • Overview
  • Python
  • Java
  • JavaScript
  • Node.js
  • Go
  • Ruby
  • C#
  • C
  • PHP

Authenticating

Password

use phpseclib3\Net\SSH2;

$ssh = new SSH2('localhost');
if (!$ssh->login('username', 'password')) {
    throw new \Exception('Login failed');
}

If you're absolutely certain that the password / username you've entered are correct it's possible the server isn't using SSH authentication and that what's prompting you for your credentials is the terminal itself. In this scenario you would want to authenticate in the manner demonstrated in the No Authentication example.

Public Key

use phpseclib3\Net\SSH2;
use phpseclib3\Crypt\PublicKeyLoader;

$key = PublicKeyLoader::load(file_get_contents('privatekey'));

$ssh = new SSH2('localhost');
if (!$ssh->login('username', $key)) {
    throw new \Exception('Login failed');
}

Public Key Authentication is one of the most secure ways to connect to a server. Even if the server is being "spoofed" or otherwise compromised the worst thing that'll happen is that the public key will be exposed to the attacker. The private key remains private and the hostile actor will be unable to login as you. This is in contrast to password authentication wherein supplying your password to a "spoofed" server means that the attacker could use that same password to login as you to the legit server.

RSA, DSA, ECDSA and EdDSA (Ed25519) keys are supported, in a myriad of different formats. Click the links for a more detailed breakdown.

Password Protected Public Key

use phpseclib3\Net\SSH2;
use phpseclib3\Crypt\PublicKeyLoader;

$key = PublicKeyLoader::load(file_get_contents('privatekey'), 'password');

$ssh = new SSH2('localhost');
if (!$ssh->login('username', $key)) {
    throw new \Exception('Login failed');
}

Keyboard-Interactive

use phpseclib3\Net\SSH2;

$ssh = new SSH2('localhost', 22);
$result = $ssh->login('username', [
    ['Password' => 'pass1'],
    ['Verification code' => 'code1']
]);

if (!$result) {
    throw new \Exception('Login failed');
}

When doing password authentication phpseclib tries keyboard-interactive if password auth fails. Only after both fail does $ssh->login() return false. The reason for this is that a lot of systems just prompt for the password via keyboard-interactive. So if your server only has one keyboard-interactive prompt using the password authentication method would be sufficient.

The method utilized in this example is mainly useful when you have multiple keyboard-interactive prompts and need to disambiguate between them. This example utilizes prompt-based disambiguation. One can also distinguish between the various keyboard-interactive prompts via order-based disambiguation. This method is demonstrated in the Multi-Factor example. What'll happen in that example is that password auth will be tried, will presumably fail and then when keyboard-interactive succeeds all subsequent authentications will utilize keyboard-interactive (unless you're trying to auth with a public key).

Multi Factor

use phpseclib3\Net\SSH2;

$ssh = new SSH2('localhost');
if (!$ssh->login('username', 'pass1', 'code1')) {
    throw new \Exception('Login failed');
}
// this does the same thing as the above
//if (!$ssh->login($username, 'pass1') && !$ssh->login('username', 'code1')) {
//    throw new \Exception('Login failed');
//}

SSH Agent

use phpseclib3\Net\SSH2;
use phpseclib3\System\SSH\Agent;

$agent = new Agent;

$ssh = new SSH2('localhost');
if (!$ssh->login('username', $agent)) {
    throw new \Exception('Login failed');
}

See ssh-agent for more information.

By default, the socket path is determined by looking at $_SERVER['SSH_AUTH_SOCK'] and (failing the former) $_ENV['SSH_AUTH_SOCK'].

If necessary, the socket path can be passed to the Agent constructor. eg. if, on the CLI, echo $SSH_AUTH_SOCK returns /run/user/1000/keyring/ssh you can do $agent = new Agent('/run/user/1000/keyring/ssh').

Agent Forwarding

Let's say you wanted to connect to another SSH server (hereinafter referred to as server B) from the server that you're already SSH'd into (hereinafter referred to as server A). Let's also say that you use the same private key to access both servers. Normally this would mean that you'd need to have your private key on server A to connect to server B from server A but with Agent Forwarding that ceases to be the case. Instead you can do something like this:

$agent->startSSHForwarding($ssh);
echo $ssh->exec('ssh user@domain.tld "ls -latr"');

No Authentication

use phpseclib3\Net\SSH2;

$ssh = new SSH2('localhost');
$ssh->login('username');
$ssh->read('User Name:');
$ssh->write("username\n");
$ssh->read('Password:');
$ssh->write("password\n");

$ssh->setTimeout(1);
$ssh->read();
$ssh->write("ls -la\n");
echo $ssh->read();

I would provide a better example but have never had direct access to an SSH server that did authentication in this manner nor do I know how to set one up.

← ConnectingRunning Commands →
  • Password
  • Public Key
  • Password Protected Public Key
  • Keyboard-Interactive
  • Multi Factor
  • SSH Agent
    • Agent Forwarding
  • No Authentication
phpseclib
Docs
IntroductionSSH2 / SFTPPublic Key CryptoSymmetric Key CryptoX.509 / CSR / SPKAC / CRLInteroperability
Support
Docs (1.0 / 2.0)Stack OverflowGitHubStar
Sponsor
PatreonGitHubPayPal
Copyright © 2025 Jim Wigginton