2.3.4.11 Encryption Key Generation (Agile Encryption)

The encryption key for ECMA-376 document encryption [ECMA-376] using agile encryption MUST be generated by using the following method, which is derived from PKCS #5: Password-Based Cryptography Version 2.0 [RFC2898].

Let H() be a hashing algorithm as determined by the PasswordKeyEncryptor.hashAlgorithm element, Hn be the hash data of the nth iteration, and a plus sign (+) represent concatenation. The password MUST be provided as an array of Unicode characters. Limitations on the length of the password and the characters used by the password are implementation-dependent. The initial password hash is generated as follows:

  • H0 = H(salt + password)

The salt used MUST be generated randomly. The salt MUST be stored in the PasswordKeyEncryptor.saltValue element contained within the \EncryptionInfo stream as specified in section 2.3.4.10. The hash is then iterated by using the following approach:

  • Hn = H(iterator + Hn-1)

where iterator is an unsigned 32-bit value that is initially set to 0x00000000 and then incremented monotonically on each iteration until PasswordKey.spinCount iterations have been performed. The value of iterator on the last iteration MUST be one less than PasswordKey.spinCount.

The final hash data that is used for an encryption key is then generated by using the following method:

  • Hfinal = H(Hn + blockKey)

where blockKey represents an array of bytes used to prevent two different blocks from encrypting to the same cipher text.

If the size of the resulting Hfinal is smaller than that of PasswordKeyEncryptor.keyBits, the key MUST be padded by appending bytes with a value of 0x36. If the hash value is larger in size than PasswordKeyEncryptor.keyBits, the key is obtained by truncating the hash value.