Discuss this help topic in SecureBlackbox Forum

Decrypt data with asymmetric algorithm

With asymmetric, or public key, cryptography, you encrypt data with a recipient's public key. Upon receipt of the encrypted data the recipient decrypts it with his private key. This implies that everyone can encrypt data for a particular recipient. However, it is only the recipient who can decrypt this data. Often a public key of an entity is contained in its public X.509 certificates. The private key is typically contained in a separate file, or even on a hardware device.

Asymmetric algorithms operate with really small amounts of data (up to several hundred of bytes), and asymmetric cryptography is rarely used to encrypt the data itself. Instead, the data is encrypted with a random symmetric 'session' key, and the session key itself is encrypted with the recipient's public key.

The two most common asymmetric encryption algorithms are RSA and Elgamal, with RSA being the absolute leader in popularity. Both are supported in SecureBlackbox. Decrypting a piece of data with an RSA key contained in the certificate can be performed in the following way:
  1. Create a TElRSAPublicKeyCrypto object (SBPublicKeyCrypto namespace; SecureBlackbox.dll assembly): TElRSAPublicKeyCrypto crypto = new TElRSAPublicKeyCrypto();
  2. Load the certificate into a TElX509Certificate object (a standalone key may be loaded into TElRSAKeyMaterial): TElX509Certificate cert = new TElX509Certificate();
    int r = cert.LoadFromFileAuto("cert.pfx", "password");
    if (r != 0) throw new Exception("Failed to load certificate!");
    There are other ways to initialize the decrypting TElX509Certificate object. For instance, you can use the TElPKCS11CertStorage if the certificate and the private key are stored on a hardware token, or TElWinCertStorage if the certificate is accessible via Windows Personal system store. The specific way of initialization of the certificate object doesn't affect the main part of the decryption process. It is vital that the decrypting cert has its PrivateKeyExists property indicating true.
  3. Assign the certificate's key material object to the crypto's KeyMaterial property: crypto.KeyMaterial = cert.KeyMaterial; Note, that the cert.KeyMaterial property, being of an abstract TElPublicKeyMaterial type, should reference an instance of TElRSAKeyMaterial. This object will be automatically created and initialized if the certificate in the cert.pfx file contains an RSA key.
  4. Set InputEncoding and OutputEncoding properties of the crypto object: crypto.InputEncoding = TSBPublicKeyCryptoEncoding.pkeBinary;
    crypto.OutputEncoding = TSBPublicKeyCryptoEncoding.pkeBinary;
  5. Decrypt the data using the Decrypt() method. Two options, buffer-based and stream-based, are available. The buffer-based option supports output length request calls common in Windows API:
    
    byte[] encryptedSecretData = new byte[256] { ... };
    
    // output length request
    byte[] secretData = null;
    int secretLen = 0;
    crypto.Decrypt(encryptedSecretData, 0, encryptedSecretData.Length, ref secretData, 0, ref secretLen);
    
    // adjusting the output buffer length:
    secretData = new byte[secretLen];
    
    // decrypting the data with a 'real' call:
    crypto.Decrypt(encryptedSecretData, 0, encryptedSecretData.Length, ref secretData, 0, ref secretLen);
    
    // as the estimated length might be (and in most cases, will be) larger than the real output, we might need to adjust buffer to the new secretLen value:
    secretData = SBUtils.Unit.CloneArray(secretData, 0, secretLen);
    			
    That's it. The secretData array now contains the decrypted data.

How To articles related to low-level cryptography

Discuss this help topic in SecureBlackbox Forum