Sample code for 30+ languages & platforms
React Native

SSH HSM Public Key Authentication

See more SSH Examples

Demonstrates SSH public-key authentication using a private key stored on an HSM — a USB token or smart card — accessed through PKCS#11. A session is opened with the vendor's driver, the key handles are located, and an SshKey object is bound to them with UsePkcs11.

Background: The point of an HSM is that the private key is generated on the device and cannot be exported: the signing operation happens on the hardware, so the key material never reaches your application's memory or disk. Even a fully compromised host cannot yield a copy of the key. PKCS#11 is the vendor-neutral interface to such devices, which is why the driver path and the object-finding template are the only vendor-specific parts of this example.

Chilkat React Native Downloads

React Native
import { JsonObject, Pkcs11, Ssh, SshKey } from '@chilkat/react-native'

async function chilkatExample() {
  // This example requires the Chilkat API to have been previously unlocked.
  // See Global Unlock Sample for sample code.

  // Demonstrates SSH public-key authentication using a private key stored on an HSM (a USB token
  // or smart card) accessed through PKCS#11.
  // 
  // Note: Chilkat's PKCS#11 implementation runs on Windows, Linux, macOS, and other supported
  // operating systems.

  const pkcs11 = new Pkcs11();

  // The PKCS#11 driver supplied by your HSM vendor: a .dll on Windows, a .so on Linux, or a
  // .dylib on macOS.
  pkcs11.sharedLibPath = 'C:/Program Files (x86)/Gemalto/IDGo 800 PKCS#11/IDPrimePKCS1164.dll';

  // The PIN should come from a secure source rather than being hard-coded.
  const pin = '0000';

  // Normal user = 1
  const userType = 1;

  try {
    pkcs11.quickSession(userType, pin);
  } catch {
    console.log(pkcs11.lastErrorText);
    return;
  }

  // Describe the private key object to be located on the HSM.
  const json = new JsonObject();
  json.updateString('class', 'private_key');
  json.updateString('label', 'MySshKey');

  const privHandle = pkcs11.findObject(json);
  if (privHandle === 0) {
    console.log(pkcs11.lastErrorText);
    return;
  }

  // Find the corresponding public key by changing the class in the same template.
  json.updateString('class', 'public_key');

  const pubHandle = pkcs11.findObject(json);
  if (pubHandle === 0) {
    console.log(pkcs11.lastErrorText);
    return;
  }

  // Create an SSH key object that uses the HSM handles.  The key type may be "rsa" or "ec".
  const key = new SshKey();
  const keyType = 'rsa';
  try {
    key.usePkcs11(pkcs11, privHandle, pubHandle, keyType);
  } catch {
    console.log(key.lastErrorText);
    return;
  }

  const ssh = new Ssh();

  const port = 22;
  try {
    await ssh.connectAsync('ssh.example.com', port);
  } catch {
    console.log(ssh.lastErrorText);
    return;
  }

  // The corresponding public key must already be installed on the SSH server for the account.
  // The signing operation happens on the HSM -- the private key never leaves the device.
  try {
    await ssh.authenticatePkAsync('mySshLogin', key);
  } catch {
    console.log(ssh.lastErrorText);
    return;
  }

  console.log('Public-key authentication successful.');

  ssh.disconnect();

  pkcs11.logout();
  pkcs11.closeSession();
}