Example code

SDKMS provides multiple interfaces to application developers. For C/C++ programmers, SDKMS provides a PKCS#11 interface through a library. For Java programmers, SDKMS can be accessed through the JCE interface. SDKMS can also be accessed through its RESTful interface, documented at {{ site.urls.docs }}

We provide examples for using SDKMS in 3 languages – a C++ program using the PKCS#11 interface, a Java program using the JCE interface, and a Python program using the REST interface.

The example programs can be downloaded in full at https://support.fortanix.com/sdkms/resources.html

Initialization and Login

C++


            CK_FUNCTION_LIST_PTR initialize() {
            CK_FUNCTION_LIST_PTR p11;
            void *pDynLib;

            pDynLib = dlopen("/opt/fortanix/pkcs11/sdkms-pkcs11.so", RTLD_NOW);
            if (!pDynLib) {
            cout << "Failed to load the PKCS#11 library" << endl;
            return NULL;
          }
          cout << "Successfully initialized PKCS#11 library to use Fortanix SDKMS" << endl;
          CK_C_GetFunctionList pGetFunctionList = (CK_C_GetFunctionList) dlsym(pDynLib, "C_GetFunctionList");
          (*pGetFunctionList)(&p11);
          return p11;
        }

        CK_RV login(CK_FUNCTION_LIST_PTR p11, CK_SESSION_HANDLE_PTR phSession, string pin) {
        CK_RV rv;
        CK_SLOT_ID slotId = 1;

        rv = p11->C_Initialize(NULL_PTR);
        if (rv == CKR_OK) {
        rv = p11->C_OpenSession(slotId, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, phSession);
        if (rv == CKR_OK) rv = p11->C_Login(*phSession, CKU_USER, (CK_UTF8CHAR_PTR)pin.c_str(), pin.length());
      }
      if (rv != CKR_OK) {
      cout << "Incorrect API Key. Error code = " << rv << endl;
    } else {
    cout << "Successfully logged in to Fortanix SDKMS" << endl << endl;
  }
  return rv;
}

C#


    public void initialize() {
    string apiKey = "";
    Configuration.Default.BasePath = "https://sdkms.fortanix.com";

    string decodedKey = Encoding.ASCII.GetString(Convert.FromBase64String(apiKey));
    string[] tokens = decodedKey.Split(':');
    Configuration.Default.Username = tokens[0];
    Configuration.Default.Password = tokens[1];

    // App Authentication
    AuthenticationApi authenticationApi = new AuthenticationApi();
    AuthResponse response = authenticationApi.Authorize();
    Configuration.Default.AddApiKey("Authorization", response.AccessToken);
    Configuration.Default.AddApiKeyPrefix("Authorization", "Bearer");
  } 

Golang


    func initialize() {
    API_KEY = `YOUR_API_KEY`
    API_END_POINT = `API_END_POINT`
    config := &sdkms.Configuration{
    BasePath: API_END_POINT,
  }
  client := sdkms.NewAPIClient(config)
  decodeKey, _ := base64.StdEncoding.DecodeString(API_KEY)
  parts := strings.Split(string(decodeKey), ":")
  ctx := context.WithValue(context.Background(), sdkms.ContextBasicAuth, sdkms.BasicAuth{
  UserName: parts[0],
  Password: parts[1],
})
authResponse, _, _ := client.AuthenticationApi.Authorize(ctx)
ctx = context.WithValue(context.Background(), sdkms.ContextAccessToken, authResponse.AccessToken)
}  

Java


    private static Provider initialize() {
    try {
    final Path tmpFile = Files.createTempFile("pkcs11", ".cfg");
    tmpFile.toFile().deleteOnExit();
    final List lines = Arrays.asList("name = fortanix", "library = /opt/fortanix/pkcs11/sdkms-pkcs11.so");
      Files.write(tmpFile, lines, Charset.defaultCharset(), StandardOpenOption.WRITE);

      Provider provider = new sun.security.pkcs11.SunPKCS11(tmpFile.toString());
      System.out.println("Successfully initialized JCE to use Fortanix SDKMS");
      return provider;
    } catch (Exception e) {
    System.out.println("Could not initialize: " + e);
    return null;
  }
}

private static boolean login(Provider provider, String apiKey) {
try {
KeyStore ks = KeyStore.getInstance("PKCS11", provider);
ks.load(null, apiKey.toCharArray());
System.out.println("Successfully logged in to Fortanix SDKMS");
return true;
} catch (Exception e) {
System.out.println("Incorrect API Key: " + e);
return false;
}
}

Python


    def initialize_api_client():
    KEY = 'YOUR_API_KEY'
    API_END_PONT = 'API_END_POINT'
    api_keys = base64.b64decode(KEY).decode('ascii')
    parts = api_keys.split(':')
    if len(parts) != 2:
    print 'Invalid API key provided'
    exit(1)
    config = sdkms.v1.Configuration()
    config.host = API_END_POINT
    config.username = parts[0]
    config.password = parts[1]
    client = sdkms.v1.ApiClient(configuration=config)
    auth_instance = sdkms.v1.AuthenticationApi(api_client=client)
    try:
    auth = auth_instance.authorize()
    config.api_key['Authorization'] = auth.access_token
    config.api_key_prefix['Authorization'] = 'Bearer'
    return client
    except ApiException as e:
    print("Exception when calling AuthenticationApi->authorize: %s\n" % e)
    return None
  

Creating a key

C++


        CK_OBJECT_HANDLE generate_key(CK_FUNCTION_LIST_PTR p11, CK_SESSION_HANDLE hSession, CK_ULONG len) {
        CK_RV rv;
        CK_MECHANISM mechKeyGen = {
        CKM_AES_KEY_GEN, NULL_PTR, 0
      };
      CK_BBOOL _true = CK_TRUE;
      CK_OBJECT_HANDLE hKey;

      CK_ATTRIBUTE keyTemplate[] = {
      {CKA_VALUE_LEN, &len, sizeof(len)},
      {CKA_ENCRYPT, &_true, sizeof(_true)},
      {CKA_DECRYPT, &_true, sizeof(_true)}
    };

    rv = p11->C_GenerateKey(hSession, &mechKeyGen, keyTemplate, sizeof(keyTemplate)/sizeof(*keyTemplate), &hKey);
    if (rv == CKR_OK) return hKey; else return CK_INVALID_HANDLE;
  }

C#


    public void createKey() {
    SobjectRequest req = new SobjectRequest(Name: "Security Object name", ObjType: ObjectType, KeySize: keySize);
    SecurityObjectsApi api = new SecurityObjectsApi();
    KeyObject key = api.GenerateSecurityObject(req);
  } 

Golang


    func createSecurityKey() {
    securityObjectRequest := sdkms.SobjectRequest{
    Name:    "Your Security object name",
    KeySize: 128,
    ObjType: &sdkms.AES,
  }
  securityObjectResponse, _, _ := client.SecurityObjectsApi.GenerateSecurityObject(ctx, securityObjectRequest)
  fmt.Printf("Security Object Created with Key Id: %s", securityObjectResponse.Kid)
}

Java


    private static SecretKey generateKey(Provider provider, String type, int length) {
    try {
    KeyGenerator keyGen = KeyGenerator.getInstance(type, provider);
    keyGen.init(length);
    SecretKey key = keyGen.generateKey();
    System.out.println("Successfully generated secret key of type " + type + " and length " + length);
    return key;
  } catch (Exception e) {
  System.out.println("Can't generate secret key: " + e);
  return null;
}
}

Python


    def create_key(): 
    api_instance = sdkms.v1.SecurityObjectsApi(api_client=client)
    request = sdkms.v1.SobjectRequest(name='Security Object name',
    key_size=128, obj_type=ObjectType.AES)
    try:                
    key_id = api_instance.generate_security_object(request).kid
    return key_id
    except ApiException as e:
    print("Exception when calling SecurityObjectsApi->generate_security_object: %s\n" % e)
    return None
  

Encryption

C++


        string encrypt(CK_FUNCTION_LIST_PTR p11, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey, string plain) {
        CK_RV rv;
        CK_BYTE *iv;
        CK_ULONG iv_len;
        string iv_b64;
        CK_BYTE *cipher;
        CK_ULONG cipher_len;
        string cipher_b64;

        iv_len = (CK_ULONG) AES_KEYLENGTH/8;
        iv = (CK_BYTE *)malloc(iv_len * sizeof(CK_BYTE));
        CK_MECHANISM mechanism = {
        CKM_AES_CBC_PAD, iv, iv_len
      };
      Base64::Encode(string((char *)iv, iv_len), &iv_b64);

      rv = p11->C_EncryptInit(hSession, &mechanism, hKey);
      if (rv == CKR_OK) {
      rv = p11->C_Encrypt(hSession, (CK_BYTE_PTR) plain.c_str(), plain.length(), NULL, &cipher_len);
      if (rv == CKR_OK) {
      cipher = (CK_BYTE *)malloc(cipher_len * sizeof(CK_BYTE));
      rv = p11->C_Encrypt(hSession, (CK_BYTE_PTR) plain.c_str(), plain.length(), cipher, &cipher_len);
    }
  }
  if (rv != CKR_OK) {
  cout << "Encryption failed. Error code = " << rv << endl;
  return string();
}
Base64::Encode(string((char *)cipher, cipher_len), &cipher_b64);
return iv_b64 + ":" + cipher_b64;
}

C#


    public void encrypt() {
    EncryptRequest encReq = new EncryptRequest(Alg: ObjectType.AES, Mode: CryptMode.CBC, Plain: Encoding.ASCII.GetBytes("ABCD"));
    EncryptionAndDecryptionApi encApi = new EncryptionAndDecryptionApi();
    EncryptResponse encResp = encApi.Encrypt(key.Kid, encReq);
  } 

Golang


    func encrypt() {
    encryptionRequest := sdkms.EncryptRequest{
    Alg:   &sdkms.AES,
    Plain: plain,
    Mode:  &sdkms.CBC,
  }
  encryptionResponse, _, _ := client.EncryptionAndDecryptionApi.Encrypt(ctx, securityObjectResponse.Kid, encryptionRequest)
}

Java


    private static String encrypt(Provider provider, SecretKey key, String plain, String mode, int length) {
    byte[] iv = new byte[length / 8];
    SecureRandom prng = new SecureRandom();
    prng.nextBytes(iv);

    try {
    Cipher cipher = Cipher.getInstance(mode, provider);
    cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
    byte[] byteCipherText = cipher.doFinal(plain.getBytes());
    String cryptStruct = new Base64().encodeAsString(iv) + ":" + new Base64().encodeAsString(byteCipherText);
    return cryptStruct;
  } catch (Exception e) {
  System.out.println("Encryption failed: " + e);
  return null;
}
}

Python


    def encrypt_key():
    api_instance = sdkms.v1.EncryptionAndDecryptionApi(api_client=client)
    request = sdkms.v1.EncryptRequest(alg=ObjectType.AES, plain=plain, mode=CipherMode.CBC)
    try:
    encryption_response = api_instance.encrypt(key_id, request)
    return encryption_response
    except ApiException as e:
    print("Exception when calling EncryptionAndDecryptionApi->encrypt: %s\n" % e)
    return None

  

Decryption

C++


        string decrypt(CK_FUNCTION_LIST_PTR p11, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey, string iv_cipher) {
        CK_RV rv;
        CK_BYTE *plain;
        CK_ULONG plain_len;
        string iv;
        string cipher;

        Base64::Decode(iv_cipher.substr(0, iv_cipher.find(':')), &iv);
        CK_MECHANISM mechanism = {
        CKM_AES_CBC_PAD, (CK_BYTE_PTR) iv.c_str(), iv.length()
      };

      rv = p11->C_DecryptInit(hSession, &mechanism, hKey);
      if (rv == CKR_OK) {
      Base64::Decode(iv_cipher.substr(iv_cipher.find(':')+1, iv_cipher.length() - iv_cipher.find(':') + 1), &cipher);
      rv = p11->C_Decrypt(hSession, (CK_BYTE_PTR) cipher.c_str(), cipher.length(), NULL, &plain_len);
      if (rv == CKR_OK) {
      plain = (CK_BYTE *)malloc(plain_len * sizeof(CK_BYTE));
      rv = p11->C_Decrypt(hSession, (CK_BYTE_PTR) cipher.c_str(), cipher.length(), plain, &plain_len);
    }
  }
  if (rv != CKR_OK) {
  cout << "Decryption failed. Error code = " << rv << endl;
  return string();
}
return string((char*)plain, plain_len);
}

C#


    public void decrypt() {
    DecryptRequest decReq = new DecryptRequest(Alg: ObjectType.AES, Mode: CryptMode.CBC, Cipher: cipher, Iv: encResp.Iv);
    DecryptResponse decResp = encApi.Decrypt(key.Kid, decReq);
  } 

Golang


    func decrypt() {
    decryptionRequest := sdkms.DecryptRequest{
    Alg:    &sdkms.AES,
    Mode:   &sdkms.CBC,
    Cipher: encryptionResponse.Cipher,
    Iv:     encryptionResponse.Iv,
  }
  decryptionResponse, _, _ := client.EncryptionAndDecryptionApi.Decrypt(ctx, securityObjectResponse.Kid, decryptionRequest)
}

Java


    private static String decrypt(Provider provider, SecretKey key, String cipherStruct, String mode) {
    try {
    String[] ivAndCipherText = cipherStruct.split(":");
    byte[] iv = new Base64().decode(ivAndCipherText[0]);
    byte[] cipherText = new Base64().decode(ivAndCipherText[1]);
    Cipher cipher = Cipher.getInstance(mode, provider);
    cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
    byte[] bytePlainText = cipher.doFinal(cipherText);

    return new String(bytePlainText);
  } catch (Exception e) {
  System.out.println("Decryption failed: " + e);
  return null;
}
}

Python


    def decrypt_key():
    api_instance = sdkms.v1.EncryptionAndDecryptionApi(api_client=client)
    decryption_request = sdkms.v1.DecryptRequest(alg=ObjectType.AES,
    mode=CipherMode.CBC, cipher=encryption_response.cipher,
    iv=encryption_response.iv)
    try:
    decryption_response = api_instance.decrypt(key_id, decryption_request)
    except ApiException as e:
    print 'Exception when calling EncryptionAndDecryptionApi->decrypt: %s\n' % e)
  

Deleting a key

C++


        CK_RV delete_key(CK_FUNCTION_LIST_PTR p11, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey) {
        return p11->C_DestroyObject(hSession, hKey);
      }
    

C#


      public void deleteKey() {
      api.DeleteSecurityObject(key.Kid);
    } 
  

Golang


    func deleteKey() {
    client.SecurityObjectsApi.DeleteSecurityObject(ctx, securityObjectResponse.Kid)
  } 

Java


    private static boolean delete_key(KeyStore ks, String alias) {
    try {
    ks.deleteEntry(alias);
    return true;
  } catch (Exception e) {
  System.out.println("Can't delete key " + alias + ": " + e);
  return false;
}
}

Python


    def delete_key():
    api_instance = sdkms.v1.SecurityObjectsApi(api_client=client)
    try:
    api_instance.delete_security_object(key_id)
    except ApiException as e:
    print("Exception when calling SecurityObjectsApi->delete_security_object: %s\n" % e)
  

Log out

C++


        CK_RV delete_key(CK_FUNCTION_LIST_PTR p11, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey) {
        return p11->C_DestroyObject(hSession, hKey);
      }
    

C#


      public void logout() {
      authenticationApi.Terminate();
    } 
  

Golang


    func logout(){
    response, _ := client.AuthenticationApi.Terminate(ctx)
  }

Java


    private static boolean delete_key(KeyStore ks, String alias) {
    try {
    ks.deleteEntry(alias);
    return true;
  } catch (Exception e) {
  System.out.println("Can't delete key " + alias + ": " + e);
  return false;
}
}

Python


    def logout():
    api_instance = sdkms.v1.AuthenticationApi(api_client=client)
    try:
    api_instance.terminate()
    except ApiException as e:
    print("Exception when calling AuthenticationApi->terminate: %s\n" % e)

  
Was this article helpful?
0 out of 0 found this helpful