Sample code for 30+ languages & platforms
SQL Server

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 SQL Server Downloads

SQL Server
-- Important: See this note about string length limitations for strings returned by sp_OAMethod calls.
--
CREATE PROCEDURE ChilkatSample
AS
BEGIN
    DECLARE @hr int
    DECLARE @sTmp0 nvarchar(4000)
    DECLARE @success int
    SELECT @success = 0

    --  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.

    DECLARE @pkcs11 int
    EXEC @hr = sp_OACreate 'Chilkat.Pkcs11', @pkcs11 OUT
    IF @hr <> 0
    BEGIN
        PRINT 'Failed to create ActiveX component'
        RETURN
    END

    --  The PKCS#11 driver supplied by your HSM vendor: a .dll on Windows, a .so on Linux, or a
    --  .dylib on macOS.
    EXEC sp_OASetProperty @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.
    DECLARE @pin nvarchar(4000)
    SELECT @pin = '0000'

    --  Normal user = 1
    DECLARE @userType int
    SELECT @userType = 1

    EXEC sp_OAMethod @pkcs11, 'QuickSession', @success OUT, @userType, @pin
    IF @success = 0
      BEGIN
        EXEC sp_OAGetProperty @pkcs11, 'LastErrorText', @sTmp0 OUT
        PRINT @sTmp0
        EXEC @hr = sp_OADestroy @pkcs11
        RETURN
      END

    --  Describe the private key object to be located on the HSM.
    DECLARE @json int
    EXEC @hr = sp_OACreate 'Chilkat.JsonObject', @json OUT

    EXEC sp_OAMethod @json, 'UpdateString', @success OUT, 'class', 'private_key'
    EXEC sp_OAMethod @json, 'UpdateString', @success OUT, 'label', 'MySshKey'

    DECLARE @priv_handle int
    EXEC sp_OAMethod @pkcs11, 'FindObject', @priv_handle OUT, @json
    IF @priv_handle = 0
      BEGIN
        EXEC sp_OAGetProperty @pkcs11, 'LastErrorText', @sTmp0 OUT
        PRINT @sTmp0
        EXEC @hr = sp_OADestroy @pkcs11
        EXEC @hr = sp_OADestroy @json
        RETURN
      END

    --  Find the corresponding public key by changing the class in the same template.
    EXEC sp_OAMethod @json, 'UpdateString', @success OUT, 'class', 'public_key'

    DECLARE @pub_handle int
    EXEC sp_OAMethod @pkcs11, 'FindObject', @pub_handle OUT, @json
    IF @pub_handle = 0
      BEGIN
        EXEC sp_OAGetProperty @pkcs11, 'LastErrorText', @sTmp0 OUT
        PRINT @sTmp0
        EXEC @hr = sp_OADestroy @pkcs11
        EXEC @hr = sp_OADestroy @json
        RETURN
      END

    --  Create an SSH key object that uses the HSM handles.  The key type may be "rsa" or "ec".
    DECLARE @key int
    EXEC @hr = sp_OACreate 'Chilkat.SshKey', @key OUT

    DECLARE @keyType nvarchar(4000)
    SELECT @keyType = 'rsa'
    EXEC sp_OAMethod @key, 'UsePkcs11', @success OUT, @pkcs11, @priv_handle, @pub_handle, @keyType
    IF @success = 0
      BEGIN
        EXEC sp_OAGetProperty @key, 'LastErrorText', @sTmp0 OUT
        PRINT @sTmp0
        EXEC @hr = sp_OADestroy @pkcs11
        EXEC @hr = sp_OADestroy @json
        EXEC @hr = sp_OADestroy @key
        RETURN
      END

    DECLARE @ssh int
    EXEC @hr = sp_OACreate 'Chilkat.Ssh', @ssh OUT

    DECLARE @port int
    SELECT @port = 22
    EXEC sp_OAMethod @ssh, 'Connect', @success OUT, 'ssh.example.com', @port
    IF @success = 0
      BEGIN
        EXEC sp_OAGetProperty @ssh, 'LastErrorText', @sTmp0 OUT
        PRINT @sTmp0
        EXEC @hr = sp_OADestroy @pkcs11
        EXEC @hr = sp_OADestroy @json
        EXEC @hr = sp_OADestroy @key
        EXEC @hr = sp_OADestroy @ssh
        RETURN
      END

    --  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.
    EXEC sp_OAMethod @ssh, 'AuthenticatePk', @success OUT, 'mySshLogin', @key
    IF @success = 0
      BEGIN
        EXEC sp_OAGetProperty @ssh, 'LastErrorText', @sTmp0 OUT
        PRINT @sTmp0
        EXEC @hr = sp_OADestroy @pkcs11
        EXEC @hr = sp_OADestroy @json
        EXEC @hr = sp_OADestroy @key
        EXEC @hr = sp_OADestroy @ssh
        RETURN
      END


    PRINT 'Public-key authentication successful.'

    EXEC sp_OAMethod @ssh, 'Disconnect', NULL

    EXEC sp_OAMethod @pkcs11, 'Logout', @success OUT
    EXEC sp_OAMethod @pkcs11, 'CloseSession', @success OUT

    EXEC @hr = sp_OADestroy @pkcs11
    EXEC @hr = sp_OADestroy @json
    EXEC @hr = sp_OADestroy @key
    EXEC @hr = sp_OADestroy @ssh


END
GO