use of org.apache.poi.poifs.crypt.HashAlgorithm in project poi by apache.
the class AgileEncryptor method updateIntegrityHMAC.
/**
* Generate an HMAC, as specified in [RFC2104], of the encrypted form of the data (message),
* which the DataIntegrity element will verify by using the Salt generated in step 2 as the key.
* Note that the entire EncryptedPackage stream (1), including the StreamSize field, MUST be
* used as the message.
*
* Encrypt the HMAC as in step 3 by using a blockKey byte array consisting of the following bytes:
* 0xa0, 0x67, 0x7f, 0x02, 0xb2, 0x2c, 0x84, and 0x33.
**/
protected void updateIntegrityHMAC(File tmpFile, int oleStreamSize) throws GeneralSecurityException, IOException {
// as the integrity hmac needs to contain the StreamSize,
// it's not possible to calculate it on-the-fly while buffering
// TODO: add stream size parameter to getDataStream()
AgileEncryptionHeader header = (AgileEncryptionHeader) getEncryptionInfo().getHeader();
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[] buf = new byte[1024];
LittleEndian.putLong(buf, 0, oleStreamSize);
integrityMD.update(buf, 0, LittleEndianConsts.LONG_SIZE);
InputStream fis = new FileInputStream(tmpFile);
try {
int readBytes;
while ((readBytes = fis.read(buf)) != -1) {
integrityMD.update(buf, 0, readBytes);
}
} finally {
fis.close();
}
byte[] hmacValue = integrityMD.doFinal();
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);
header.setEncryptedHmacValue(encryptedHmacValue);
}
use of org.apache.poi.poifs.crypt.HashAlgorithm in project poi by apache.
the class AgileDecryptor method verifyPassword.
/**
* instead of a password, it's also possible to decrypt via certificate.
* Warning: this code is experimental and hasn't been validated
*
* @see <a href="http://social.msdn.microsoft.com/Forums/en-US/cc9092bb-0c82-4b5b-ae21-abf643bdb37c/agile-encryption-with-certificates">Agile encryption with certificates</a>
*
* @param keyPair
* @param x509
* @return true, when the data can be successfully decrypted with the given private key
* @throws GeneralSecurityException
*/
public boolean verifyPassword(KeyPair keyPair, X509Certificate x509) throws GeneralSecurityException {
AgileEncryptionVerifier ver = (AgileEncryptionVerifier) getEncryptionInfo().getVerifier();
AgileEncryptionHeader header = (AgileEncryptionHeader) getEncryptionInfo().getHeader();
HashAlgorithm hashAlgo = header.getHashAlgorithm();
CipherAlgorithm cipherAlgo = header.getCipherAlgorithm();
int blockSize = header.getBlockSize();
AgileCertificateEntry ace = null;
for (AgileCertificateEntry aceEntry : ver.getCertificates()) {
if (x509.equals(aceEntry.x509)) {
ace = aceEntry;
break;
}
}
if (ace == null) {
return false;
}
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivate());
byte[] keyspec = cipher.doFinal(ace.encryptedKey);
SecretKeySpec secretKey = new SecretKeySpec(keyspec, ver.getCipherAlgorithm().jceId);
Mac x509Hmac = CryptoFunctions.getMac(hashAlgo);
x509Hmac.init(secretKey);
byte[] certVerifier = x509Hmac.doFinal(ace.x509.getEncoded());
byte[] vec = CryptoFunctions.generateIv(hashAlgo, header.getKeySalt(), kIntegrityKeyBlock, blockSize);
cipher = getCipher(secretKey, cipherAlgo, header.getChainingMode(), vec, Cipher.DECRYPT_MODE);
byte[] hmacKey = cipher.doFinal(header.getEncryptedHmacKey());
hmacKey = getBlock0(hmacKey, hashAlgo.hashSize);
vec = CryptoFunctions.generateIv(hashAlgo, header.getKeySalt(), kIntegrityValueBlock, blockSize);
cipher = getCipher(secretKey, cipherAlgo, header.getChainingMode(), vec, Cipher.DECRYPT_MODE);
byte[] hmacValue = cipher.doFinal(header.getEncryptedHmacValue());
hmacValue = getBlock0(hmacValue, hashAlgo.hashSize);
if (Arrays.equals(ace.certVerifier, certVerifier)) {
setSecretKey(secretKey);
setIntegrityHmacKey(hmacKey);
setIntegrityHmacValue(hmacValue);
return true;
} else {
return false;
}
}
use of org.apache.poi.poifs.crypt.HashAlgorithm in project poi by apache.
the class XSSFPasswordHelper method validatePassword.
/**
* Validates the password, i.e.
* calculates the hash of the given password and compares it against the stored hash
*
* @param xobj the xmlbeans object which contains the password attributes
* @param password the password, if null the method will always return false,
* even if there's no password set
* @param prefix the prefix of the password attributes, may be null
*
* @return true, if the hashes match
*/
public static boolean validatePassword(XmlObject xobj, String password, String prefix) {
// TODO: is "velvetSweatshop" the default password?
if (password == null)
return false;
XmlCursor cur = xobj.newCursor();
String xorHashVal = cur.getAttributeText(getAttrName(prefix, "password"));
String algoName = cur.getAttributeText(getAttrName(prefix, "algorithmName"));
String hashVal = cur.getAttributeText(getAttrName(prefix, "hashValue"));
String saltVal = cur.getAttributeText(getAttrName(prefix, "saltValue"));
String spinCount = cur.getAttributeText(getAttrName(prefix, "spinCount"));
cur.dispose();
if (xorHashVal != null) {
int hash1 = Integer.parseInt(xorHashVal, 16);
int hash2 = CryptoFunctions.createXorVerifier1(password);
return hash1 == hash2;
} else {
if (hashVal == null || algoName == null || saltVal == null || spinCount == null) {
return false;
}
byte[] hash1 = DatatypeConverter.parseBase64Binary(hashVal);
HashAlgorithm hashAlgo = HashAlgorithm.fromString(algoName);
byte[] salt = DatatypeConverter.parseBase64Binary(saltVal);
int spinCnt = Integer.parseInt(spinCount);
byte[] hash2 = CryptoFunctions.hashPassword(password, hashAlgo, salt, spinCnt, false);
return Arrays.equals(hash1, hash2);
}
}
use of org.apache.poi.poifs.crypt.HashAlgorithm in project poi by apache.
the class StandardDecryptor method generateSecretKey.
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);
SecretKey skey = new SecretKeySpec(key, ver.getCipherAlgorithm().jceId);
return skey;
}
use of org.apache.poi.poifs.crypt.HashAlgorithm in project poi by apache.
the class AgileDecryptor method hashInput.
/* 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);
}
}
Aggregations