Sample code for 30+ languages & platforms
Xbase++

SSH Authenticate using a Smart Card Private Key

See more SSH Examples

Demonstrates using a private key stored on an HSM (smart card or token) for SSH public-key authentication. A JSON template locates the private and public key objects by class, key type, and label, and the returned handles are bound to an SshKey object.

Background: PKCS#11 objects are found by attribute rather than by name alone, which is why a template describing the class, key type, and label is used. An important practical detail is that the returned handles are valid only for the lifetime of the PKCS#11 session — they cannot be cached and reused later, so a subsequent session must locate the objects again. Logging out and closing the session when finished releases the device for other applications.

Chilkat Xbase++ Downloads

Xbase++
LOCAL nSuccess
LOCAL oPkcs11
LOCAL cPin
LOCAL nUserType
LOCAL oJsonTemplate
LOCAL nPrivKeyHandle
LOCAL nPubKeyHandle
LOCAL oSshKey
LOCAL oSsh
LOCAL nPort

nSuccess := 0

//  This example requires the Chilkat API to have been previously unlocked.
//  See Global Unlock Sample for sample code.

//  Demonstrates using a private key stored on an HSM (smart card or token) for SSH public-key
//  authentication.  Public-key authentication means the client uses the private key, while the
//  corresponding public key is installed on the server under the SSH account.
//  
//  Note: Chilkat's PKCS#11 implementation runs on Windows, Linux, macOS, and other supported
//  operating systems.

oPkcs11 := CreateObject("Chilkat.Pkcs11")

//  Use the PKCS#11 driver (.dll, .so, or .dylib) for your particular HSM.
oPkcs11:SharedLibPath := "C:/Program Files (x86)/Gemalto/IDGo 800 PKCS#11/IDPrimePKCS11.dll"

//  The HSM PIN should come from a secure source rather than being hard-coded.
cPin := "0000"

//  Normal user = 1
nUserType := 1

nSuccess := oPkcs11:QuickSession(nUserType, cPin)
IF (nSuccess == 0)
    ? oPkcs11:LastErrorText
    oPkcs11:destroy()
    RETURN
ENDIF

//  Provide a template describing the PKCS#11 object to find: an RSA private key labeled
//  "MySshKey".  For how such a key is originally imported, see
//  PKCS11 Import SSH Key
oJsonTemplate := CreateObject("Chilkat.JsonObject")
oJsonTemplate:UpdateString("class", "private_key")
oJsonTemplate:UpdateString("key_type", "rsa")
oJsonTemplate:UpdateString("label", "MySshKey")

nPrivKeyHandle := oPkcs11:FindObject(oJsonTemplate)
IF (nPrivKeyHandle == 0)
    ? oPkcs11:LastErrorText
    oPkcs11:destroy()
    oJsonTemplate:destroy()
    RETURN
ENDIF

//  The handle is only valid for the duration of this PKCS#11 session.  To use the key in a
//  later session, find it again.
? "private key handle: " + Str(nPrivKeyHandle)

//  Find the corresponding public key by changing the class in the same template.
oJsonTemplate:UpdateString("class", "public_key")

nPubKeyHandle := oPkcs11:FindObject(oJsonTemplate)
IF (nPubKeyHandle == 0)
    ? oPkcs11:LastErrorText
    oPkcs11:destroy()
    oJsonTemplate:destroy()
    RETURN
ENDIF

? "public key handle: " + Str(nPubKeyHandle)

//  Create an empty SSH key object and tell it to use the PKCS#11 handles, indicating the key type.
oSshKey := CreateObject("Chilkat.SshKey")
nSuccess := oSshKey:UsePkcs11(oPkcs11, nPrivKeyHandle, nPubKeyHandle, "rsa")
IF (nSuccess == 0)
    ? oSshKey:LastErrorText
    oPkcs11:destroy()
    oJsonTemplate:destroy()
    oSshKey:destroy()
    RETURN
ENDIF

oSsh := CreateObject("Chilkat.Ssh")

nPort := 22
nSuccess := oSsh:Connect("ssh.example.com", nPort)
IF (nSuccess == 0)
    ? oSsh:LastErrorText
    oPkcs11:destroy()
    oJsonTemplate:destroy()
    oSshKey:destroy()
    oSsh:destroy()
    RETURN
ENDIF

//  Authentication uses the existing PKCS#11 session.  The signing happens on the smart card --
//  the private key never leaves the device.
nSuccess := oSsh:AuthenticatePk("mySshLogin", oSshKey)
IF (nSuccess == 0)
    ? oSsh:LastErrorText
    oPkcs11:destroy()
    oJsonTemplate:destroy()
    oSshKey:destroy()
    oSsh:destroy()
    RETURN
ENDIF

? "Public-key authentication successful."

//  ... use the authenticated SSH session ...

oSsh:Disconnect()

oPkcs11:Logout()
oPkcs11:CloseSession()

oPkcs11:destroy()
oJsonTemplate:destroy()
oSshKey:destroy()
oSsh:destroy()