TStreamCipher

0

TForge 0.76 is released.

The release introduces a new class TStreamCipher. The name TStreamCipher does not mean that the class supports stream cipher algorithms only, such as Salsa20 or RC4 – it supports all cipher algorithms currently implemented in TForge, like TCipher class does; block ciphers are converted into stream ciphers using CTR mode of operation.

The initial motivation to write TStreamCipher class was to generate “solid” byte-wise keystream. TCipher class generates block-wise keystream; to obtain solid byte-wise keystream you need to maintain additional state, and that’s what the TStreamCipher class is doing. Here is the code sample illustrating the above:

const
  Nonce = 42;

var
  Cipher: TCipher;
  StreamCipher: TStreamCipher;
  Key: ByteArray;
  KeyStream, KeyStream1, KeyStream2: ByteArray;

begin
// create 128-bit AES key:
  Key:= ByteArray.AllocateRand(16);

// generate 16 bytes of keystream:
  KeyStream:= TCipher.AES.ExpandKey(Key, CTR_ENCRYPT, Nonce).KeyStream(16);
  Writeln(KeyStream.ToHex);

// generate 8 + 8 bytes of keystream:
  Cipher:= TCipher.AES.ExpandKey(Key, CTR_ENCRYPT, Nonce);
// Warning - KeyStream1:= Cipher.KeyStream(8) + Cipher.KeyStream(8) is wrong
//   because the compiler does not evaluate the summands in order
  KeyStream1:= Cipher.KeyStream(8);
  KeyStream1:= KeyStream1 + Cipher.KeyStream(8);
  Writeln(KeyStream1.ToHex);
  Assert(KeyStream <> KeyStream1);

// generate 8 + 8 bytes of keystream using TStreamCipher instance:
  StreamCipher:= TStreamCipher.AES.ExpandKey(Key, Nonce);
  KeyStream2:= StreamCipher.KeyStream(8);
  KeyStream2:= KeyStream2 + StreamCipher.KeyStream(8);
  Writeln(KeyStream2.ToHex);
  Assert(KeyStream = KeyStream2);
end;

The Cipher instance generates 8 + 8 bytes of keystream by taking the first 8 bytes from the first block and the second 8 bytes from the second block (AES block size is 16 bytes), that is why the generated keystream is different.

The code also illustrates the use of Nonce. The purpose of nonce is to encrypt multiple messages (ex files) with the same secret key – each message should be encrypted with unique non-secret nonce. Modern cryptoalgorithms such as Salsa20 have built-in support for nonce, and TForge supported the feature since version 0.71; old block cipher algorithms such as AES allow to implement the same feature using IV (initialization vector), and this is the second thing that TStreamCipher class is doing; TStreamCipher API does not expose IV of the underlying cryptoalgorithm, it exposes Nonce only.

Nonces are now supported by both TStreamCipher and TCipher classes, as the above code sample shows; there is a limitation though: the block size of an algorithm should be 128 bits at least; that means you can’t use nonces with legacy 64-bit block ciphers such as DES or Triple DES.

TForge 0.76 includes new demo project FileEncryptDemo (Demos\Ciphers folder) which shows how to use TStreamCipher. The idea of the project is to implement secure encryption of multiple files with a single key (and multiple non-secret nonces) and transparent reading of the encrypted files.