Class CryptoFunctions

java.lang.Object
org.docx4j.org.apache.poi.poifs.crypt.CryptoFunctions

public class CryptoFunctions
extends java.lang.Object
Helper functions used for standard and agile encryption
  • Constructor Summary

    Constructors 
    Constructor Description
    CryptoFunctions()  
  • Method Summary

    Modifier and Type Method Description
    static byte[] createXorArray1​(java.lang.String password)
    Creates an byte array for xor obfuscation (method 1)
    static int createXorKey1​(java.lang.String password)
    Create the xor key for xor obfuscation, which is used to create the xor array (method 1)
    static int createXorVerifier1​(java.lang.String password)
    Create the verifier for xor obfuscation (method 1)
    static int createXorVerifier2​(java.lang.String password)
    This method generates the xor verifier for word documents < 2007 (method 2).
    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.
    static byte[] generateKey​(byte[] passwordHash, HashAlgorithm hashAlgorithm, byte[] blockKey, int keySize)
    2.3.4.11 Encryption Key Generation (Agile Encryption) ...
    static byte[] getBlock0​(byte[] hash, int size)
    Returns a new byte array with a truncated to the given size.
    static byte[] getBlock36​(byte[] hash, int size)
    Returns a new byte array with a truncated to the given size.
    static javax.crypto.Cipher getCipher​(java.security.Key key, CipherAlgorithm cipherAlgorithm, ChainingMode chain, byte[] vec, int cipherMode, java.lang.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.
    static javax.crypto.Cipher getCipher​(javax.crypto.SecretKey key, CipherAlgorithm cipherAlgorithm, ChainingMode chain, byte[] vec, int cipherMode)  
    static javax.crypto.Mac getMac​(HashAlgorithm hashAlgorithm)  
    static java.security.MessageDigest getMessageDigest​(HashAlgorithm hashAlgorithm)  
    static byte[] hashPassword​(java.lang.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].
    static byte[] hashPassword​(java.lang.String password, HashAlgorithm hashAlgorithm, byte[] salt, int spinCount, boolean iteratorFirst)
    Generalized method for read and write protection hash generation.
    static void registerBouncyCastle()  
    static java.lang.String xorHashPassword​(java.lang.String password)
    This method generates the xored-hashed password for word documents < 2007.
    static java.lang.String xorHashPasswordReversed​(java.lang.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.

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Constructor Details

  • Method Details

    • hashPassword

      public static byte[] hashPassword​(java.lang.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 (1) 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 -
      hashAlgorithm -
      salt -
      spinCount -
      Returns:
      the hashed password
    • hashPassword

      public static byte[] hashPassword​(java.lang.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 -
      hashAlgorithm -
      salt -
      spinCount -
      iteratorFirst - if true, the iterator is hashed before the n-1 hash value, if false the n-1 hash value is applied first
      Returns:
      the hashed password
    • generateIv

      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: 1. If a blockKey is provided, let IV be a hash of the KeySalt and the following value: blockKey: IV = H(KeySalt + blockKey) 2. If a blockKey is not provided, let IV be equal to the following value: KeySalt:IV = KeySalt. 3. If the number of bytes in the value of IV is less than the 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.
    • generateKey

      public static byte[] generateKey​(byte[] passwordHash, HashAlgorithm hashAlgorithm, byte[] blockKey, int keySize)
      2.3.4.11 Encryption Key Generation (Agile Encryption) ... continued ... 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 -
      hashAlgorithm -
      blockKey -
      keySize -
      Returns:
      intermediate key
    • getCipher

      public static javax.crypto.Cipher getCipher​(javax.crypto.SecretKey key, CipherAlgorithm cipherAlgorithm, ChainingMode chain, byte[] vec, int cipherMode)
    • getCipher

      public static javax.crypto.Cipher getCipher​(java.security.Key key, CipherAlgorithm cipherAlgorithm, ChainingMode chain, byte[] vec, int cipherMode, java.lang.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 - the secrect key
      cipherAlgorithm - the cipher algorithm
      chain - the chaining mode
      vec - the initialization vector (IV), can be null
      cipherMode - Cipher.DECRYPT_MODE or Cipher.ENCRYPT_MODE
      padding -
      Returns:
      the requested cipher
      Throws:
      java.security.GeneralSecurityException
      EncryptedDocumentException - if the initialization failed or if an algorithm was specified, which depends on a missing bouncy castle provider
    • getBlock36

      public static byte[] getBlock36​(byte[] hash, int size)
      Returns a new byte array with a truncated to the given size. If the hash has less then size bytes, it will be filled with 0x36-bytes
      Parameters:
      hash - the to be truncated/filled hash byte array
      size - the size of the returned byte array
      Returns:
      the padded hash
    • getBlock0

      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 then size bytes, it will be filled with 0-bytes
      Parameters:
      hash - the to be truncated/filled hash byte array
      size - the size of the returned byte array
      Returns:
      the padded hash
    • getMessageDigest

      public static java.security.MessageDigest getMessageDigest​(HashAlgorithm hashAlgorithm)
    • getMac

      public static javax.crypto.Mac getMac​(HashAlgorithm hashAlgorithm)
    • registerBouncyCastle

      public static void registerBouncyCastle()
    • createXorVerifier2

      public static int createXorVerifier2​(java.lang.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 - the password
      Returns:
      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.
    • xorHashPassword

      public static java.lang.String xorHashPassword​(java.lang.String password)
      This method generates the xored-hashed password for word documents < 2007.
    • xorHashPasswordReversed

      public static java.lang.String xorHashPasswordReversed​(java.lang.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.
    • createXorVerifier1

      public static int createXorVerifier1​(java.lang.String password)
      Create the verifier for xor obfuscation (method 1)
      Parameters:
      password - the password
      Returns:
      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
    • createXorKey1

      public static int createXorKey1​(java.lang.String password)
      Create the xor key for xor obfuscation, which is used to create the xor array (method 1)
      Parameters:
      password - the password
      Returns:
      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
    • createXorArray1

      public static byte[] createXorArray1​(java.lang.String password)
      Creates an byte array for xor obfuscation (method 1)
      Parameters:
      password - the password
      Returns:
      the byte array for xor obfuscation
      See Also:
      2.3.7.2 Binary Document XOR Array Initialization Method 1, Libre Office implementation