# Intro to PKCS #5: Password-Based Cryptography Specification

Our third post in our PKCS series, we will be looking at PKCS  #5. PKCS #5 is the Password-Based Cryptography Specification and is currently defined by version 2.0 of the specification. It is defined in RFC 2898 http://tools.ietf.org/html/rfc2898. It applies a pseudorandom function, such as a cryptographic hash, cipher, or HMAC to the input password or passphrase along with a salt value and repeats the process many times to produce a derived key, which can then be used as a cryptographic key in subsequent operations. The added computational work makes password cracking much more difficult, and is known as key stretching.

#### A. Key Derivation Functions

A key derivation function produces a derived key from a based key and other parameters. In a password-based key derivation function, the base key is a password and the other parameters are a salt value and an iteration count.

Two functions are specified below: PBKDF1 and PBKDF2. PBKDF2 is recommended for new applications; PBKDF1 is included only for compatibility with existing applications, and is not recommended for new applications.

#### B. PBKDF1

PBKDF1 applies a hash function, which shall be MD2, MD5 or SHA-1, to derive keys. The lengths of the derived keying bounded by the length of the hash function output, which is 16 octets from MD2 and MD5 and 20 octets from SHA-1.

Steps:

1. If dkLen > 16 for MD2 and MD5, or dkLen > 20 for SHA-1, output “derived key too long” and stop.

2. Apply the underlying hash function Hash for c iterations to the concatenation of the password P and

the salt S, then extract the first dkLen octets to produce a derived key DK:

T_1 = Hash (P || S) ,

T_2 = Hash (T_1) ,

T_c = Hash (T_{c-1}) ,

DK = Tc<0..dkLen-1>

3. Output the derived key DK.

#### C. PBKDF2

PBKDF2 applies a pseudorandom function to derive keys. The length of the derived key is essentially unbounded. However, the maximum effective search space for the derived key may be limited by the structure of the underlying pseudorandom function.

Steps:

1. If dkLen > (2^32 – 1) * hLen, output “derived key too long” and stop.

2. Let l be the number of hLen-octet blocks in the derived key, rounding up, and let r be the number of octets

in the last block:

l = CEIL (dkLen / hLen) ,

r = dkLen – (l – 1) * hLen .

Here, CEIL (x) is the “ceiling” function, i.e. the smallest integer greater than, or equal to, x.

3. For each block of the derived key apply the function F defined below to the password P, the salt S, the

iteration count c, and the block index to compute the block:

T_1 = F (P, S, c, 1) ,

T_2 = F (P, S, c, 2) ,

T_l = F (P, S, c, l) ,

where the function F is defined as the exclusive-or sum of the first c iterates of the underlying pseudorandom  function PRF applied to the password P and the concatenation of the salt S and the block index i:

F (P, S, c, i) = U_1 \xor U_2 \xor … \xor U_c

where

U_1 = PRF (P, S || INT (i)) ,

U_2 = PRF (P, U_1) ,

U_c = PRF (P, U_{c-1}) .

Here, INT (i) is a four-octet encoding of the integer i, most significant octet first.

4. Concatenate the blocks and extract the first dkLen octets to produce a derived key DK:

DK = T_1 || T_2 ||  …  || T_l<0..r-1>

5. Output the derived key DK.

http://tools.ietf.org/html/rfc2898

D. CyaSSL Support

CyaSSL supports both PBKDF1 and PBKDF2. The header file can be found in <cyassl_root>/cyassl/ctaocrypt/pwdbased.h and the source file can be found in <cyassl_root>/ctaocrypt/src/pwdbased.c of the CyaSSL library. When using these functions, they must be enabled when CyaSSL is configured. This is done by:

./configure –enable-pwdbased

The functions:

```int PBKDF1(byte* output, const byte* passwd, int pLen,
const byte* salt, int sLen, int iterations, int kLen,
int hashType);
int PBKDF2(byte* output, const byte* passwd, int pLen,
const byte* salt, int sLen, int iterations, int kLen,
int hashType);
```

CyaSSL also supports PKCS12

```int PKCS12_PBKDF(byte* output, const byte* passwd, int pLen,
const byte* salt, int sLen, int iterations,
int kLen, int hashType, int purpose);
```