You want to use an algorithm that requires a salt, a nonce or aninitialization vector (IV). You need to understand the differencesamong these three things and figure out how to select good specimensof each.
There’s a lot of terminology confusion, and the followingSection 4.9.3 contains our take on it. Basically, salts and IVs should be random,and nonces are usually sequential, potentially with a random salt asa component, if there is room. With sequential nonces, you need toensure that you never repeat a single {key, nonce} pairing.
To get good random values, use a well-seeded, cryptographicallystrong pseudo-random number generator (see the appropriate recipes inChapter 11). Using that, get the necessary numberof bits. For salt, 64 bits is sufficient. For an IV, get one of therequisite size.
Salts, nonces, and IVs are all one-time values used incryptography thatdon’t need to be secret, but still lead toadditional security. It is generally assumed that these values arevisible to attackers, even if it is sometimes possible to hide them.At the very least, the security of cryptographic algorithms andprotocols should not depend on the secrecy of such values.
Tip
We try to be consistent with respect to this terminology in the book.However, in the real world, even among cryptographersthere’s a lot of inconsistency. Therefore, be sureto follow the directions in the documentation for whatever primitiveyou’re using.
Salt is random data that helps protect against dictionaryand other precomputation attacks. Generally, salt is used inpassword-based systems and is concatenated to the front of a passwordbefore processing. Password systems often use a one-way hash functionto turn a password into an“authenticator.” In the simplestsuch system, if there were no salt, an attacker could build adictionary of common passwords and just look up the original passwordby authenticator.
The use of salt means that the attacker would have to produce atotally separate dictionary for every possible salt value. If thesalt is big enough, it essentially makes dictionary attacksinfeasible. However, the attacker can generally still try to guessevery password without using a stronger protocol. For a discussion ofvarious password-based authentication technologies, see Recipe 8.1.
If the salt isn’t chosen at random, certaindictionaries will be more likely than others. For this reason, saltis generally expected to be random.
Salt can be generated using the techniques discussed in Chapter 11.
Nonces [2] are bits ofdata often input to cryptographic protocols and algorithms, includingmany message authentication codes and some encryption modes. Suchvalues should only be used a single time with any particularcryptographic key. In fact, reuse generally isn’tprohibited, but the odds of reuse need to be exceptionally low. Thatis, if you have a nonce that is very large compared to the number oftimes you expect to use it (e.g., the nonce is 128 bits, and youdon’t expect to use it more than232 times), it is sufficient to choosenonces using a cryptographically strong pseudo-random numbergenerator.
Sequential nonces have a fewadvantages over random nonces:
You can easily guarantee that nonces are not repeated. Note, though,that if the possible nonce space is large, this is not a big concern.
Many protocols already send a unique sequence number for each packet,so one can save space in transmitted messages.
The sequential ordering of nonces can be used to prevent replayattacks, but only if you actually check to ensure that the nonce isalways incrementing. That is, if each message has a nonce attached toit, you can tell whether the message came in the right order, bylooking at the nonce and making sure its value is alwaysincrementing.
However, randomness in a nonce helps prevent against classes ofattacks that amortize work across multiple keys in the same system.
We recommend that nonces have both a random portion and a sequentialportion. Generally, the most significant bytes should be random, andthe final 6 to 8 bytes should be sequential. An 8-byte counter canaccommodate 264 messages without thecounter’s repeating, which should be more than bigenough for any system.
If you use both a nonce and a salt, you can select a single randompart for each key you use. The nonce on the whole has to be unique,but the salt can remain fixed for the lifetime of the key; thecounter ensures that the nonce is always unique. In such a nonce, therandom part is said to be a “salt.”Generally, it’s good to have four or more bytes ofsalt in a nonce.
If you decide to use only a random nonce, remember that the nonceneeds to be changed after each message, and you lose the ability toprevent against capture-replay attacks.
The random portion of a nonce can be generated using the techniquesdiscussed in Chapter 11. Generally, you will have afixed-size buffer into which you place the nonce, and you will thenset the remaining bytes to zero, incrementing them after each messageis sent. For example, if you have a 16-byte nonce with an 8-bytecounter in the least significant bytes, you might use the followingcode:
/* This assumes a 16-byte nonce where the last 8 bytes represent the counter! */void increment_nonce(unsigned char *nonce) { if (!++nonce[15]) if (!++nonce[14]) if (!++nonce[13]) if (!++nonce[12]) if (!++nonce[11]) if (!++nonce[10]) if (!++nonce[9]) if (!++nonce[8]) { /* If you get here, you're out of nonces. This really shouldn't happen * with an 8-byte nonce, so often you'll see: if (!++nonce[9]) ++nonce[8]; */ }}
Note that the this code can be more efficient if we do a 32-bitincrement, but then there are endian-ness issues that makeportability more difficult.
The term initializationvector (IV) is the mostwidely used and abused of the three terms we’ve beendiscussing. IV and nonce are often used interchangeably. However, acareful definition does differentiate between these two concepts. Forour purposes, an IV is a nonce with an additional requirement: itmust be selected in a nonpredictable way. That is, the IVcan’t be sequential; it must be random. One popularexample in which a real IV is required for maximizing security iswhen using the CBC encryption mode (see Recipe 5.6).
The big downside to an IV, as compared to a nonce, is that an IV does notafford protection against capture-replay attacks—unlessyou’re willing to remember every IV that has everbeen used, which is not a good solution. To ensure protection againstsuch attacks when using an IV, the higher-level protocol must haveits own notion of sequence numbers that get checked in order.
Another downside is that there is generally more data to send.Systems that use sequential nonces can often avoid sending the nonce,as it can be calculated from the sequence number already sent withthe message.
Initialization vectors can be generated using the techniquesdiscussed in Chapter 11.
[2] In the UK, “nonce” is slangfor a child sex offender. However, this term is widespread in thecryptographic world, so we use it.
Get Secure Programming Cookbook for C and C++ now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.
Start your free trial