Sample code for 30+ languages & platforms
PureBasic

RSA Decrypt using Private Key on Smartcard or USB Token via Apple Keychain

See more Apple Keychain Examples

RSA decryption using a certificate's private key located on a hardware token or smartcard via the Apple Keychain.

Note: This example requires Chilkat v10.1.2 or greater.

Chilkat PureBasic Downloads

PureBasic
IncludeFile "CkBinData.pb"
IncludeFile "CkCert.pb"
IncludeFile "CkRsa.pb"

Procedure ChilkatExample()

    success.i = 0

    ; Beforehand, we generated a 256-bit AES key, RSA encrypted, and saved to a file as in this example:
    ; Generate a Random 256-bit AES Key and RSA Encrypt

    ; The RSA public key used to encrypt in the above example was obtained from the Apple Keychain
    ; like this:
    ; Export a Public Key from USB Token or Smartcard using the Apple Keychain

    ; This example will load the encrypted data and will RSA decrypt using the 
    ; private key of a certificate on a USB token (or smart card) via the Keychain.
    ; You can list the Keychain certificates on hardware tokens using the following example:
    ; Apple Keychain - List Certs on Smartcards and USB Tokens

    ; Get the RSA encrypted data to be decrypted.
    bd.i = CkBinData::ckCreate()
    If bd.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    ; In all Chilkat methods expecting a path, you can pass either absolute or relative paths.
    success = CkBinData::ckLoadFile(bd,"rsaEncrypted/myAes.key")
    If success = 0
        Debug "Failed to load the encrypted AES key."
        CkBinData::ckDispose(bd)
        ProcedureReturn
    EndIf

    ; Load the certificate having the private key from the Apple Keychain
    ; On MacOS and iOS, the LoadByCommonName function will search the Apple Keychain for the matching certificate.
    cert.i = CkCert::ckCreate()
    If cert.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    ; To potentially prevent the PIN dialog from being displayed,
    ; we'll need to provide the USB token (or smart card) PIN
    ; Note: It might not be possible to prevent the PIN dialog from being displayed
    ; 
    CkCert::setCkSmartCardPin(cert, "123456")

    success = CkCert::ckLoadByCommonName(cert,"Test 2048 bit RSA")
    If success = 0
        Debug CkCert::ckLastErrorText(cert)
        CkBinData::ckDispose(bd)
        CkCert::ckDispose(cert)
        ProcedureReturn
    EndIf

    rsa.i = CkRsa::ckCreate()
    If rsa.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    ; Specify we wish to use the certificate's private key for decryption.
    success = CkRsa::ckSetX509Cert(rsa,cert,1)
    If success = 0
        Debug CkRsa::ckLastErrorText(rsa)
        CkBinData::ckDispose(bd)
        CkCert::ckDispose(cert)
        CkRsa::ckDispose(rsa)
        ProcedureReturn
    EndIf

    ; RSA Decrypt
    CkRsa::setCkVerboseLogging(rsa, 1)
    success = CkRsa::ckDecryptBd(rsa,bd,1)
    If success = 0
        Debug CkRsa::ckLastErrorText(rsa)
        CkBinData::ckDispose(bd)
        CkCert::ckDispose(cert)
        CkRsa::ckDispose(rsa)
        ProcedureReturn
    EndIf

    ; The contents of bd are now decrypted.
    Debug "Num bytes after decryption: " + Str(CkBinData::ckNumBytes(bd))

    ; Some additional notes:
    ; 
    ; If using a Yubikey token, the certificate must be installed in the Key Management slot.
    ; The Digital Signature slot is for RSA keys to be used for signing, 
    ; and the Key Management slot is for RSA keys to be used for decrypting.
    ; image

    ; If you try to use the RSA key from the Digital Signature slot, you'll get an error such as this:

    ; The operation couldn't be completed. 
    ; (OSStatus error -50 - algid:encrypt:RSA:PKCS1: algorithm not supported by the key 
    ; <SecKeyRef:('com.apple.pivtoken:AF7172EB60DDCBF1D28459AE24398E11') 0x600001ecca90>)


    CkBinData::ckDispose(bd)
    CkCert::ckDispose(cert)
    CkRsa::ckDispose(rsa)


    ProcedureReturn
EndProcedure