Top Description Fields Constructors Methods
org.apache.poi.poifs.crypt

public final Class CryptoFunctions

extends Object
Class Inheritance
Annotations
@Internal
Imports
java.nio.charset.StandardCharsets, java.security.DigestException, .GeneralSecurityException, .Key, .MessageDigest, .Provider, .Security, java.security.spec.AlgorithmParameterSpec, java.util.Arrays, .Locale, javax.crypto.Cipher, .Mac, .SecretKey, javax.crypto.spec.IvParameterSpec, .RC2ParameterSpec, org.apache.poi.EncryptedDocumentException, org.apache.poi.util.IOUtils, .Internal, .LittleEndian, .LittleEndianConsts, .StringUtil

Helper functions used for standard and agile encryption

Field Summary

Modifier and TypeField and Description
private static final int
private static final int[][]
private static final int[]
pack-priv static int
private static final byte[]

Constructor Summary

AccessConstructor and Description
private

Method Summary

Modifier and TypeMethod and Description
public static byte[]

Returns:

the byte array for xor obfuscation
createXorArray1
(String
the password
password
)

Creates an byte array for xor obfuscation (method 1)

public static int

Returns:

the xor key
createXorKey1
(String
the password
password
)

Create the xor key for xor obfuscation, which is used to create the xor array (method 1)

public static int

Returns:

the verifier (actually a short value)
createXorVerifier1
(String
the password
password
)

Create the verifier for xor obfuscation (method 1)

public static int

Returns:

the hashed password
createXorVerifier2
(String
the password
password
)

This method generates the xor verifier for word documents < 2007 (method 2).

public static byte[]
generateIv(HashAlgorithm hashAlgorithm, byte[] salt, byte[] blockKey, int blockSize)

2.3.4.12 Initialization Vector Generation (Agile Encryption)

Initialization vectors are used in all cases for agile encryption.

public static byte[]

Returns:

intermediate key
generateKey
(byte[]
the hashed password byte
passwordHash
,
HashAlgorithm
the hash algorithm
hashAlgorithm
,
byte[]
the block key
blockKey
,
int
the key size
keySize
)

2.3.4.11 Encryption Key Generation (Agile Encryption)

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

H_final = H(H_n + blockKey)
public static byte[]

Returns:

the padded hash
getBlock0
(byte[]
the to be truncated/filled hash byte array
hash
,
int
the size of the returned byte array
size
)

Returns a new byte array with a truncated to the given size.

private static byte[]

Returns:

the padded hash
getBlock36
(byte[]
the to be truncated/filled hash byte array
hash
,
int
the size of the returned byte array
size
)

Returns a new byte array with a truncated to the given size.

private static byte[]
getBlockX(byte[] hash, int size, byte fill)

public static Cipher

Returns:

the requested cipher
getCipher
(SecretKey
the secret key
key
,
CipherAlgorithm
the cipher algorithm
cipherAlgorithm
,
ChainingMode
the chaining mode
chain
,
byte[]
the initialization vector (IV), can be null
vec
,
int
Cipher.DECRYPT_MODE or Cipher.ENCRYPT_MODE
cipherMode
)

Initialize a new cipher object with the given cipher properties and no padding If the given algorithm is not implemented in the JCE, it will try to load it from the bouncy castle provider.

public static Cipher

Returns:

the requested cipher
getCipher
(Key
the secret key
key
,
CipherAlgorithm
the cipher algorithm
cipherAlgorithm
,
ChainingMode
the chaining mode
chain
,
byte[]
the initialization vector (IV), can be null
vec
,
int
Cipher.DECRYPT_MODE or Cipher.ENCRYPT_MODE
cipherMode
,
String
the padding (null = NOPADDING, ANSIX923Padding, PKCS5Padding, PKCS7Padding, ISO10126Padding, ...)
padding
)

Initialize a new cipher object with the given cipher properties If the given algorithm is not implemented in the JCE, it will try to load it from the bouncy castle provider.

public static Mac
getMac(HashAlgorithm hashAlgorithm)

public static int

Returns:

the max record length allowed for CryptoFunctions
getMaxRecordLength
()

public static MessageDigest
public static byte[]

Returns:

the hashed password
hashPassword
(String
the password
password
,
HashAlgorithm
the hash algorithm
hashAlgorithm
,
byte[]
the initial salt value
salt
,
int
the repetition count
spinCount
)

2.3.4.7 ECMA-376 Document Encryption Key Generation (Standard Encryption) 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].

public static byte[]

Returns:

the hashed password
hashPassword
(String
the pasword
password
,
HashAlgorithm
the hash algorighm
hashAlgorithm
,
byte[]
the initial salt value
salt
,
int
the repetition count
spinCount
,
boolean
if true, the iterator is hashed before the n-1 hash value, if false the n-1 hash value is applied first
iteratorFirst
)

Generalized method for read and write protection hash generation.

public static void
private static byte
rotateLeft(byte bits, int shift)

private static short
rotateLeftBase15Bit(short verifier)

public static void
setMaxRecordLength(int
the max record length allowed for CryptoFunctions
length
)

private static byte[]

Returns:

the ansi bytes
toAnsiPassword
(String
the password
password
)

The provided Unicode password string is converted to a ANSI string

public static String
xorHashPassword(String password)

This method generates the xored-hashed password for word documents < 2007.

public static String
xorHashPasswordReversed(String password)

Convenience function which returns the reversed xored-hashed password for further processing in word documents 2007 and newer, which utilize a real hashing algorithm like sha1.

Inherited from java.lang.Object:
cloneequalsfinalizegetClasshashCodenotifynotifyAlltoStringwaitwaitwait

Field Detail

DEFAULT_MAX_RECORD_LENGTHback to summary
private static final int DEFAULT_MAX_RECORD_LENGTH
ENCRYPTION_MATRIXback to summary
private static final int[][] ENCRYPTION_MATRIX
INITIAL_CODE_ARRAYback to summary
private static final int[] INITIAL_CODE_ARRAY
MAX_RECORD_LENGTHback to summary
pack-priv static int MAX_RECORD_LENGTH
PAD_ARRAYback to summary
private static final byte[] PAD_ARRAY

Constructor Detail

CryptoFunctionsback to summary
private CryptoFunctions()

Method Detail

createXorArray1back to summary
public static byte[] createXorArray1(String password)

Creates an byte array for xor obfuscation (method 1)

Parameters
password:String

the password

Returns:byte[]

the byte array for xor obfuscation

See Also
2.3.7.2 Binary Document XOR Array Initialization Method 1, Libre Office implementation
createXorKey1back to summary
public static int createXorKey1(String password)

Create the xor key for xor obfuscation, which is used to create the xor array (method 1)

Parameters
password:String

the password

Returns:int

the xor key

See Also
2.3.7.2 Binary Document XOR Array Initialization Method 1, 2.3.7.4 Binary Document Password Verifier Derivation Method 2
createXorVerifier1back to summary
public static int createXorVerifier1(String password)

Create the verifier for xor obfuscation (method 1)

Parameters
password:String

the password

Returns:int

the verifier (actually a short value)

See Also
2.3.7.1 Binary Document Password Verifier Derivation Method 1, 2.3.7.4 Binary Document Password Verifier Derivation Method 2, Part 4 - Markup Language Reference - Ecma International - 3.2.12 fileSharing
createXorVerifier2back to summary
public static int createXorVerifier2(String password)

This method generates the xor verifier for word documents < 2007 (method 2). Its output will be used as password input for the newer word generations which utilize a real hashing algorithm like sha1.

Parameters
password:String

the password

Returns:int

the hashed password

See Also
2.3.7.4 Binary Document Password Verifier Derivation Method 2, How to set the editing restrictions in Word using Open XML SDK 2.0, Funny: How the new powerful cryptography implemented in Word 2007 turns it into a perfect tool for document password removal.
generateIvback to summary
public static byte[] generateIv(HashAlgorithm hashAlgorithm, byte[] salt, byte[] blockKey, int blockSize)

2.3.4.12 Initialization Vector Generation (Agile Encryption)

Initialization vectors are used in all cases for agile encryption. An initialization vector MUST be generated by using the following method, where H() is a hash function that MUST be the same as specified in section 2.3.4.11 and a plus sign (+) represents concatenation:

  • If a blockKey is provided, let IV be a hash of the KeySalt and the following value:
    blockKey: IV = H(KeySalt + blockKey)
  • If a blockKey is not provided, let IV be equal to the following value:
    KeySalt:IV = KeySalt
  • If the number of bytes in the value of IV is less than the value of the blockSize attribute corresponding to the cipherAlgorithm attribute, pad the array of bytes by appending 0x36 until the array is blockSize bytes. If the array of bytes is larger than blockSize bytes, truncate the array to blockSize bytes.
generateKeyback to summary
public static byte[] generateKey(byte[] passwordHash, HashAlgorithm hashAlgorithm, byte[] blockKey, int keySize)

2.3.4.11 Encryption Key Generation (Agile Encryption)

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

H_final = H(H_n + 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 H_final 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.

Parameters
passwordHash:byte[]

the hashed password byte

hashAlgorithm:HashAlgorithm

the hash algorithm

blockKey:byte[]

the block key

keySize:int

the key size

Returns:byte[]

intermediate key

getBlock0back to summary
public static byte[] getBlock0(byte[] hash, int size)

Returns a new byte array with a truncated to the given size. If the hash has less than size bytes, it will be filled with 0-bytes

Parameters
hash:byte[]

the to be truncated/filled hash byte array

size:int

the size of the returned byte array

Returns:byte[]

the padded hash

getBlock36back to summary
private static byte[] getBlock36(byte[] hash, int size)

Returns a new byte array with a truncated to the given size. If the hash has less than size bytes, it will be filled with 0x36-bytes

Parameters
hash:byte[]

the to be truncated/filled hash byte array

size:int

the size of the returned byte array

Returns:byte[]

the padded hash

getBlockXback to summary
private static byte[] getBlockX(byte[] hash, int size, byte fill)
getCipherback to summary
public static Cipher getCipher(SecretKey key, CipherAlgorithm cipherAlgorithm, ChainingMode chain, byte[] vec, int cipherMode)

Initialize a new cipher object with the given cipher properties and no padding If the given algorithm is not implemented in the JCE, it will try to load it from the bouncy castle provider.

Parameters
key:SecretKey

the secret key

cipherAlgorithm:CipherAlgorithm

the cipher algorithm

chain:ChainingMode

the chaining mode

vec:byte[]

the initialization vector (IV), can be null

cipherMode:int

Cipher.DECRYPT_MODE or Cipher.ENCRYPT_MODE

Returns:Cipher

the requested cipher

Exceptions
EncryptedDocumentException:
if the initialization failed or if an algorithm was specified, which depends on a missing bouncy castle provider
getCipherback to summary
public static Cipher getCipher(Key key, CipherAlgorithm cipherAlgorithm, ChainingMode chain, byte[] vec, int cipherMode, String padding)

Initialize a new cipher object with the given cipher properties If the given algorithm is not implemented in the JCE, it will try to load it from the bouncy castle provider.

Parameters
key:Key

the secret key

cipherAlgorithm:CipherAlgorithm

the cipher algorithm

chain:ChainingMode

the chaining mode

vec:byte[]

the initialization vector (IV), can be null

cipherMode:int

Cipher.DECRYPT_MODE or Cipher.ENCRYPT_MODE

padding:String

the padding (null = NOPADDING, ANSIX923Padding, PKCS5Padding, PKCS7Padding, ISO10126Padding, ...)

Returns:Cipher

the requested cipher

Exceptions
EncryptedDocumentException:
if the initialization failed or if an algorithm was specified, which depends on a missing bouncy castle provider
getMacback to summary
public static Mac getMac(HashAlgorithm hashAlgorithm)
getMaxRecordLengthback to summary
public static int getMaxRecordLength()
Returns:int

the max record length allowed for CryptoFunctions

getMessageDigestback to summary
public static MessageDigest getMessageDigest(HashAlgorithm hashAlgorithm)
hashPasswordback to summary
public static byte[] hashPassword(String password, HashAlgorithm hashAlgorithm, byte[] salt, int spinCount)

2.3.4.7 ECMA-376 Document Encryption Key Generation (Standard Encryption)
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, H_n be the hash data of the n-th 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:

H_0 = 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:

H_n = H(iterator + H_n-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.

For POI, H_final will be calculated by generateKey(byte[], HashAlgorithm, byte[], int)

Parameters
password:String

the password

hashAlgorithm:HashAlgorithm

the hash algorithm

salt:byte[]

the initial salt value

spinCount:int

the repetition count

Returns:byte[]

the hashed password

hashPasswordback to summary
public static byte[] hashPassword(String password, HashAlgorithm hashAlgorithm, byte[] salt, int spinCount, boolean iteratorFirst)

Generalized method for read and write protection hash generation. The difference is, read protection uses the order iterator then hash in the hash loop, whereas write protection uses first the last hash value and then the current iterator value

Parameters
password:String

the pasword

hashAlgorithm:HashAlgorithm

the hash algorighm

salt:byte[]

the initial salt value

spinCount:int

the repetition count

iteratorFirst:boolean

if true, the iterator is hashed before the n-1 hash value, if false the n-1 hash value is applied first

Returns:byte[]

the hashed password

Annotations
@SuppressWarnings:squid:S2068
registerBouncyCastleback to summary
public static void registerBouncyCastle()
Annotations
@SuppressWarnings:unchecked
rotateLeftback to summary
private static byte rotateLeft(byte bits, int shift)
rotateLeftBase15Bitback to summary
private static short rotateLeftBase15Bit(short verifier)
setMaxRecordLengthback to summary
public static void setMaxRecordLength(int length)
Parameters
length:int

the max record length allowed for CryptoFunctions

toAnsiPasswordback to summary
private static byte[] toAnsiPassword(String password)

The provided Unicode password string is converted to a ANSI string

Parameters
password:String

the password

Returns:byte[]

the ansi bytes

See Also
Part 4 - Markup Language Reference - Ecma International - section 3.2.29 (workbookProtection)
xorHashPasswordback to summary
public static String xorHashPassword(String password)

This method generates the xored-hashed password for word documents < 2007.

xorHashPasswordReversedback to summary
public static String xorHashPasswordReversed(String password)

Convenience function which returns the reversed xored-hashed password for further processing in word documents 2007 and newer, which utilize a real hashing algorithm like sha1.