Sample code for 30+ languages & platforms
Dart

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 Dart Downloads

Dart
import 'package:chilkat/chilkat.dart';

void main() {
  // 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.

  final pkcs11 = CkPkcs11();

  // 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.
  final pin = '0000';

  // Normal user = 1
  final userType = 1;

  try {
    pkcs11.quickSession(userType, pin);
  } on ChilkatException catch (e) {
    print(e.lastErrorText);
    return;
  }

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

  final privHandle = pkcs11.findObject(json);
  if (privHandle == 0) {
    print(pkcs11.lastErrorText);
    return;
  }

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

  final pubHandle = pkcs11.findObject(json);
  if (pubHandle == 0) {
    print(pkcs11.lastErrorText);
    return;
  }

  // Create an SSH key object that uses the HSM handles.  The key type may be "rsa" or "ec".
  final key = CkSshKey();
  final keyType = 'rsa';
  try {
    key.usePkcs11(pkcs11, privHandle, pubHandle, keyType);
  } on ChilkatException catch (e) {
    print(e.lastErrorText);
    return;
  }

  final ssh = CkSsh();

  final port = 22;
  try {
    ssh.connect('ssh.example.com', port);
  } on ChilkatException catch (e) {
    print(e.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 {
    ssh.authenticatePk('mySshLogin', key);
  } on ChilkatException catch (e) {
    print(e.lastErrorText);
    return;
  }

  print('Public-key authentication successful.');

  ssh.disconnect();

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