int blockSize = header.getBlockSize(); HashAlgorithm hashAlgo = header.getHashAlgorithm(); Mac integrityMD = CryptoFunctions.getMac(hashAlgo); byte hmacKey[] = getBlock0(this.integritySalt, getNextBlockSize(this.integritySalt.length, blockSize)); integrityMD.init(new SecretKeySpec(hmacKey, hashAlgo.jceHmacId)); byte hmacValueFilled[] = getBlock0(hmacValue, getNextBlockSize(hmacValue.length, blockSize)); byte iv[] = CryptoFunctions.generateIv(header.getHashAlgorithm(), header.getKeySalt(), kIntegrityValueBlock, blockSize); Cipher cipher = CryptoFunctions.getCipher(getSecretKey(), header.getCipherAlgorithm(), header.getChainingMode(), iv, Cipher.ENCRYPT_MODE); byte encryptedHmacValue[] = cipher.doFinal(hmacValueFilled);
@Override public void confirmPassword(String password) { int keyComp = CryptoFunctions.createXorKey1(password); int verifierComp = CryptoFunctions.createXorVerifier1(password); byte xorArray[] = CryptoFunctions.createXorArray1(password); byte shortBuf[] = new byte[2]; XOREncryptionVerifier ver = (XOREncryptionVerifier)getEncryptionInfo().getVerifier(); LittleEndian.putUShort(shortBuf, 0, keyComp); ver.setEncryptedKey(shortBuf); LittleEndian.putUShort(shortBuf, 0, verifierComp); ver.setEncryptedVerifier(shortBuf); setSecretKey(new SecretKeySpec(xorArray, "XOR")); }
/* package */ static byte[] hashInput(AgileEncryptionVerifier ver, byte pwHash[], byte blockKey[], byte inputKey[], int cipherMode) { CipherAlgorithm cipherAlgo = ver.getCipherAlgorithm(); ChainingMode chainMode = ver.getChainingMode(); int keySize = ver.getKeySize()/8; int blockSize = ver.getBlockSize(); HashAlgorithm hashAlgo = ver.getHashAlgorithm(); byte intermedKey[] = generateKey(pwHash, hashAlgo, blockKey, keySize); SecretKey skey = new SecretKeySpec(intermedKey, cipherAlgo.jceId); byte[] iv = generateIv(hashAlgo, ver.getSalt(), null, blockSize); Cipher cipher = getCipher(skey, cipherAlgo, chainMode, iv, cipherMode); byte[] hashFinal; try { inputKey = getBlock0(inputKey, getNextBlockSize(inputKey.length, blockSize)); hashFinal = cipher.doFinal(inputKey); return hashFinal; } catch (GeneralSecurityException e) { throw new EncryptedDocumentException(e); } }
/** * <p><cite>2.3.4.12 Initialization Vector Generation (Agile Encryption)</cite></p> * * <p>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:</p> * <ul> * <li>If a blockKey is provided, let IV be a hash of the KeySalt and the following value:<br> * {@code blockKey: IV = H(KeySalt + blockKey)}</li> * <li>If a blockKey is not provided, let IV be equal to the following value:<br> * {@code KeySalt:IV = KeySalt}</li> * <li>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.</li> * </ul> **/ public static byte[] generateIv(HashAlgorithm hashAlgorithm, byte[] salt, byte[] blockKey, int blockSize) { byte iv[] = salt; if (blockKey != null) { MessageDigest hashAlgo = getMessageDigest(hashAlgorithm); hashAlgo.update(salt); iv = hashAlgo.digest(blockKey); } return getBlock36(iv, blockSize); }
System.arraycopy(PAD_ARRAY, 0, obfuscationArray, passBytes.length, PAD_ARRAY.length-passBytes.length+1); int xorKey = createXorKey1(password); for (int i=0; i<obfuscationArray.length; i++) { obfuscationArray[i] ^= baseKeyLE[i&1]; obfuscationArray[i] = rotateLeft(obfuscationArray[i], nRotateSize);
byte[] pwHash = hashPassword(password, ver.getHashAlgorithm(), ver.getSalt(), ver.getSpinCount()); MessageDigest hashMD = getMessageDigest(ver.getHashAlgorithm()); byte[] verifierHash = hashMD.digest(verfierInputEnc); verifierHashDec = getBlock0(verifierHashDec, ver.getHashAlgorithm().hashSize); keyspec = getBlock0(keyspec, header.getKeySize()/8); SecretKeySpec secretKey = new SecretKeySpec(keyspec, header.getCipherAlgorithm().jceId); byte vec[] = CryptoFunctions.generateIv(header.getHashAlgorithm(), header.getKeySalt(), kIntegrityKeyBlock, blockSize); CipherAlgorithm cipherAlgo = header.getCipherAlgorithm(); Cipher cipher = getCipher(secretKey, cipherAlgo, header.getChainingMode(), vec, Cipher.DECRYPT_MODE); byte hmacKey[] = cipher.doFinal(header.getEncryptedHmacKey()); hmacKey = getBlock0(hmacKey, header.getHashAlgorithm().hashSize); vec = CryptoFunctions.generateIv(header.getHashAlgorithm(), header.getKeySalt(), kIntegrityValueBlock, blockSize); cipher = getCipher(secretKey, cipherAlgo, ver.getChainingMode(), vec, Cipher.DECRYPT_MODE); byte hmacValue[] = cipher.doFinal(header.getEncryptedHmacValue()); hmacValue = getBlock0(hmacValue, header.getHashAlgorithm().hashSize);
/** * 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. * * @param key the secret key * @param cipherAlgorithm the cipher algorithm * @param chain the chaining mode * @param vec the initialization vector (IV), can be null * @param cipherMode Cipher.DECRYPT_MODE or Cipher.ENCRYPT_MODE * @return the requested cipher * @throws GeneralSecurityException * @throws EncryptedDocumentException if the initialization failed or if an algorithm was specified, * which depends on a missing bouncy castle provider */ public static Cipher getCipher(SecretKey key, CipherAlgorithm cipherAlgorithm, ChainingMode chain, byte[] vec, int cipherMode) { return getCipher(key, cipherAlgorithm, chain, vec, cipherMode, null); }
protected static byte[] fillAndXor(byte hash[], byte fillByte) { byte[] buff = new byte[64]; Arrays.fill(buff, fillByte); for (int i=0; i<hash.length; i++) { buff[i] = (byte) (buff[i] ^ hash[i]); } MessageDigest sha1 = CryptoFunctions.getMessageDigest(HashAlgorithm.sha1); return sha1.digest(buff); }
protected static Cipher initCipherForBlock(Cipher cipher, int block, EncryptionInfo encryptionInfo, SecretKey skey, int encryptMode) throws GeneralSecurityException { EncryptionVerifier ver = encryptionInfo.getVerifier(); HashAlgorithm hashAlgo = ver.getHashAlgorithm(); byte blockKey[] = new byte[4]; LittleEndian.putUInt(blockKey, 0, block); MessageDigest hashAlg = CryptoFunctions.getMessageDigest(hashAlgo); hashAlg.update(skey.getEncoded()); byte encKey[] = hashAlg.digest(blockKey); EncryptionHeader header = encryptionInfo.getHeader(); int keyBits = header.getKeySize(); encKey = CryptoFunctions.getBlock0(encKey, keyBits / 8); if (keyBits == 40) { encKey = CryptoFunctions.getBlock0(encKey, 16); } SecretKey key = new SecretKeySpec(encKey, skey.getAlgorithm()); if (cipher == null) { cipher = CryptoFunctions.getCipher(key, header.getCipherAlgorithm(), null, null, encryptMode); } else { cipher.init(encryptMode, key); } return cipher; }
int hash2 = CryptoFunctions.createXorVerifier1(password); return hash1 == hash2; } else { byte salt[] = DatatypeConverter.parseBase64Binary(saltVal); int spinCnt = Integer.parseInt(spinCount); byte hash2[] = CryptoFunctions.hashPassword(password, hashAlgo, salt, spinCnt, false); return Arrays.equals(hash1, hash2);
String legacyHash = CryptoFunctions.xorHashPasswordReversed(password); byte hash2[] = CryptoFunctions.hashPassword(legacyHash, hashAlgo, salt, spinCount.intValue(), false);
protected static Cipher initCipherForBlock(Cipher cipher, int block, EncryptionInfo encryptionInfo, SecretKey skey, int encryptMode) throws GeneralSecurityException { EncryptionVerifier ver = encryptionInfo.getVerifier(); HashAlgorithm hashAlgo = ver.getHashAlgorithm(); byte blockKey[] = new byte[4]; LittleEndian.putUInt(blockKey, 0, block); byte encKey[] = CryptoFunctions.generateKey(skey.getEncoded(), hashAlgo, blockKey, 16); SecretKey key = new SecretKeySpec(encKey, skey.getAlgorithm()); if (cipher == null) { EncryptionHeader em = encryptionInfo.getHeader(); cipher = CryptoFunctions.getCipher(key, em.getCipherAlgorithm(), null, null, encryptMode); } else { cipher.init(encryptMode, key); } return cipher; }
public static MessageDigest getMessageDigest(HashAlgorithm hashAlgorithm) { try { if (hashAlgorithm.needsBouncyCastle) { registerBouncyCastle(); return MessageDigest.getInstance(hashAlgorithm.jceId, "BC"); } else { return MessageDigest.getInstance(hashAlgorithm.jceId); } } catch (GeneralSecurityException e) { throw new EncryptedDocumentException("hash algo not supported", e); } }
protected static SecretKey generateSecretKey(String password, EncryptionVerifier ver, int keySize) { HashAlgorithm hashAlgo = ver.getHashAlgorithm(); byte pwHash[] = hashPassword(password, hashAlgo, ver.getSalt(), ver.getSpinCount()); byte[] blockKey = new byte[4]; LittleEndian.putInt(blockKey, 0, 0); byte[] finalHash = CryptoFunctions.generateKey(pwHash, hashAlgo, blockKey, hashAlgo.hashSize); byte x1[] = fillAndXor(finalHash, (byte) 0x36); byte x2[] = fillAndXor(finalHash, (byte) 0x5c); byte[] x3 = new byte[x1.length + x2.length]; System.arraycopy(x1, 0, x3, 0, x1.length); System.arraycopy(x2, 0, x3, x1.length, x2.length); byte[] key = Arrays.copyOf(x3, keySize); return new SecretKeySpec(key, ver.getCipherAlgorithm().jceId); }
protected static Cipher initCipherForBlock(Cipher existing, int block, boolean lastChunk, EncryptionInfo encryptionInfo, SecretKey skey, int encryptionMode) throws GeneralSecurityException { EncryptionHeader header = encryptionInfo.getHeader(); String padding = (lastChunk ? "PKCS5Padding" : "NoPadding"); if (existing == null || !existing.getAlgorithm().endsWith(padding)) { existing = getCipher(skey, header.getCipherAlgorithm(), header.getChainingMode(), header.getKeySalt(), encryptionMode, padding); } byte[] blockKey = new byte[4]; LittleEndian.putInt(blockKey, 0, block); byte[] iv = generateIv(header.getHashAlgorithm(), header.getKeySalt(), blockKey, header.getBlockSize()); AlgorithmParameterSpec aps; if (header.getCipherAlgorithm() == CipherAlgorithm.rc2) { aps = new RC2ParameterSpec(skey.getEncoded().length*8, iv); } else { aps = new IvParameterSpec(iv); } existing.init(encryptionMode, skey, aps); return existing; }
byte[] arrByteChars = toAnsiPassword(password); int verifier = createXorVerifier1(password);
/** * protect a workbook with a password (not encypted, just sets writeprotect * flags and the password. * * @param password the password * @param username the username */ public void writeProtectWorkbook( String password, String username ) { FileSharingRecord frec = getFileSharing(); WriteAccessRecord waccess = getWriteAccess(); /* WriteProtectRecord wprotect =*/ getWriteProtect(); frec.setReadOnly((short)1); frec.setPassword((short)CryptoFunctions.createXorVerifier1(password)); frec.setUsername(username); waccess.setUsername(username); }
/** * Create the xor key for xor obfuscation, which is used to create the xor array (method 1) * * @see <a href="http://msdn.microsoft.com/en-us/library/dd924704.aspx">2.3.7.2 Binary Document XOR Array Initialization Method 1</a> * @see <a href="http://msdn.microsoft.com/en-us/library/dd905229.aspx">2.3.7.4 Binary Document Password Verifier Derivation Method 2</a> * * @param password the password * @return the xor key */ public static int createXorKey1(String password) { // the xor key for method 1 is part of the verifier for method 2 // so we simply chop it from there return createXorVerifier2(password) >>> 16; }
return hashPassword(password, hashAlgorithm, salt, spinCount, true);
pwHash = hashPassword(password, ver.getHashAlgorithm(), verifierSalt, ver.getSpinCount()); MessageDigest hashMD = getMessageDigest(ver.getHashAlgorithm()); byte[] hashedVerifier = hashMD.digest(verifier); byte encryptedVerifierHash[] = hashInput(ver, pwHash, kHashedVerifierBlock, hashedVerifier, Cipher.ENCRYPT_MODE); byte vec[] = CryptoFunctions.generateIv(header.getHashAlgorithm(), header.getKeySalt(), kIntegrityKeyBlock, header.getBlockSize()); Cipher cipher = getCipher(secretKey, header.getCipherAlgorithm(), header.getChainingMode(), vec, Cipher.ENCRYPT_MODE); byte hmacKey[] = getBlock0(this.integritySalt, getNextBlockSize(this.integritySalt.length, blockSize)); byte encryptedHmacKey[] = cipher.doFinal(hmacKey); header.setEncryptedHmacKey(encryptedHmacKey); cipher.init(Cipher.ENCRYPT_MODE, ace.x509.getPublicKey()); ace.encryptedKey = cipher.doFinal(getSecretKey().getEncoded()); Mac x509Hmac = CryptoFunctions.getMac(header.getHashAlgorithm()); x509Hmac.init(getSecretKey()); ace.certVerifier = x509Hmac.doFinal(ace.x509.getEncoded());