Salsa20 support explained

Salsa20 is a stream cipher; like any stream cipher Salsa20 encrypts/decrypts data by xor‘ing a plaintext/ciphertext with a pseudorandom keystream.

Salsa20 generates keystream by hashing 64-byte (512-bit) blocks; the block consists of 4 parts:

  • fixed “magic words” – 16 bytes
  • key – 32 bytes
  • nonce (message number) – 8 bytes
  • block number – 8 bytes

This simple structure allows to generate 64-byte blocks of keystream independently; to generate an arbitrary block of the keystream one need to set the block number in the cipher’s state and hash the 64-byte block.

TCipher class supports Salsa20 design by following methods:

function TCipher.SetIV(const AIV: ByteArray): TCipher;
function TCipher.SetNonce(Value: UInt64): TCipher;
function TCipher.Skip(Value: UInt64): TCipher;

TCipher class considers concatenated nonce and block number as initialization vector (IV). The TCipher.SetIV sets both the nonce and the block number in the cipher instance state. [Corrected – changed in ver 0.71]

The TCipher.SetIV  and TCipher.SetNonce methods do the same – set the nonce field in the the cipher instance state and clear the block number field; the difference is that TCipher.SetIV accepts the parameter as a byte array while TCipher.SetNonce as an integer.

The TCipher.SetIV method was introduced mainly for testing purposes.

The purpose of nonce is to serve as a unique message number; a nonce need not be kept secret, but it should never repeat during the lifetime of a secret key.

As an example suppose we want to encrypt several files by a single secret key; the right way to do it is to encrypt each file with a unique nonce value, like this:

procedure EncryptFiles(const Key: ByteArray; FileNames: array of string);
  Cipher: TCipher;
  Nonce: UInt64;
  I: Integer;

  Nonce:= 0;
  for I:= 0 to High(FileNames) do begin
    Cipher:= TCipher.Salsa20;
            .EncryptFile(FileNames[I], FileNames[I] + '.salsa20');

The try .. finally block ensures that the sensitive key data in the cipher instances’ states is destroyed.

The TCipher.Skip method increments the block number field in the cipher instance state; its purpose is to implement parallel encryption/decryption as was demonstrated in the previous post.


10 thoughts on “Salsa20 support explained

  1. What are a good value for ‘Nonce’? You uses Inc(Nonce) – what about to use a Guid for example as ‘Nonce’? Did this increase the security of salsa20?

    • You can speculate that randomized nonces may improve security, but if it is really so then it is considered as a weakness of the underlying cryptoalgorithm. A secure cryptoalgorithm does not require randomized nonces – anything that does not repeat is enough.

  2. Serg, thank you for your really interesting work.

    I have a problem trying to install TCiphers package in Delphi XE7 (no problems at all with others two packages).

    At this line (223) of Tfsalsa20.pas:

    PLongWord(Data)[N]:= PLongWord(Data)[N] + Inst.FExpandedKey[N];

    the compilation stops with this error

    [dcc32 Error] tfSalsa20.pas(233): E2016 Array type required

    (two times , one for each of the [N] , rejected, indexing.
    Any help?

    Thanks again.

  3. Hello Serg,

    I’ve tryed to set nonce on encryption to 5 and on decryption to 12 f.e.
    When I do this encryption didn’t work. Did this comply with the rules? When I use the same nonce for encryption/decryption then it works fine.

    Did I have to use the same nonce for a file for encryption/decryption?

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s