Discuss this help topic in SecureBlackbox Forum

Encrypting data with symmetric algorithm

Symmetric encryption is normally used where you need to encrypt large amounts of data with a secret key known to both encrypting and decrypting parties. With SecureBlackbox you use a dedicated TElSymmetricCrypto class to perform encryption and decryption.

To encrypt data:

  1. Create a symmetric crypto factory object: TElSymmetricCryptoFactory factory = new TElSymmetricCryptoFactory();
  2. Use the factory to create a crypto object of the appropriate algorithm: TElSymmetricCrypto crypto = factory.CreateInstance(SBConstants.Unit.SB_ALGORITHM_CNT_AES256, TSBSymmetricCryptoMode.cmDefault); By default, encryption is performed in cipher block chaining (CBC) mode. This is the most common encryption mode used in a huge variety of security environments. If you need to encrypt your data in specific encryption mode (such as CFB, CTR or ECB), you can specify that via the second parameter of the factory's CreateInstance() call.
  3. Create a key material object and assign the values of the secret key and the IV (if any chaining mode is used) to the Key and IV properties of the new object: TElSymmetricKeyMaterial km = new TElSymmetricKeyMaterial(null);
    km.Key = keyBuf; // for AES256, keyBuf should contain a 32-element byte array containing the secret key value
    km.IV = ivBuf; // for AES256, which has a block of 16 bytes, ivBuf should contain a 16-element byte array containing the IV value
  4. Assign your key material object to the crypto object's KeyMaterial property: crypto.KeyMaterial = km;
  5. You're all set now and can proceed with data encryption. You can encrypt data stored in byte arrays or streams. Note, that the output data will be longer than the input data by up to two blocks, depending on the encryption mode.
    Buffer-based encryption supports preliminary 'length calls' approach used in a variety of environments: byte[] inBuf = Encoding.UTF8.GetBytes("My very secret message");

    // Setting outBuf and outSize to null/zero to indicate that our first call is a length getting call
    byte[] outBuf = null;
    int outSize = 0;

    // Finding out about the output length - this may be approximate
    crypto.Encrypt(inBuf, 0, inBuf.Length, ref outBuf, 0, ref outSize);

    // Allocating an array for the output data
    outBuf = new byte[outSize];

    // Encrypting the data
    crypto.Encrypt(inBuf, 0, inBuf.Length, ref outBuf, 0, ref outSize);

    // Copying the encrypted data to a dedicated buffer. Note that outSize returned by this call may be smaller than that of the first length getting call
    outBuf = SBUtils.Unit.CloneArray(outBuf, 0, outSize);

    Stream-based approach is much simpler: crypto.Encrypt(inStream, outStream);

In certain complicated scenarios you might need to encrypt data chunk-by-chunk. If this is the case, do the following:

  1. Set up the crypto object as above.
  2. Before encrypting, call the InitializeEncryption method of the crypto object: crypto.InitializeEncryption();
  3. Pass as much data as needed via a series of EncryptUpdate() calls. Concatenate the pieces of encrypted data returned by each call. crypto.EncryptUpdate(inBuf, 0, inBuf.Length, ref outBuf, 0, ref outSize);
    outBuf = SBUtils.Unit.CloneArray(outBuf, 0, outSize);
  4. When you've finished feeding the data to EncryptUpdate(), finalize the encryption by calling FinalizeEncryption(): crypto.FinalizeEncryption(ref outBuf, 0, ref outSize);
    outBuf = SBUtils.Unit.CloneArray(outBuf, 0, outSize);
    Note that, depending on the encryption mode used, FinalizeEncryption() may return the trailing piece of encrypted data. Remember to append it to the encrypted data you have received from the EncryptUpdate() calls. If you don't do so, the decrypting party might be unable to decrypt your content.

How To articles related to low-level cryptography

Discuss this help topic in SecureBlackbox Forum