use of javax.crypto.Cipher in project poi by apache.
the class StandardDecryptor method verifyPassword.
@Override
public boolean verifyPassword(String password) {
EncryptionVerifier ver = getEncryptionInfo().getVerifier();
SecretKey skey = generateSecretKey(password, ver, getKeySizeInBytes());
Cipher cipher = getCipher(skey);
try {
byte[] encryptedVerifier = ver.getEncryptedVerifier();
byte[] verifier = cipher.doFinal(encryptedVerifier);
setVerifier(verifier);
MessageDigest sha1 = CryptoFunctions.getMessageDigest(ver.getHashAlgorithm());
byte[] calcVerifierHash = sha1.digest(verifier);
byte[] encryptedVerifierHash = ver.getEncryptedVerifierHash();
byte[] decryptedVerifierHash = cipher.doFinal(encryptedVerifierHash);
// see 2.3.4.9 Password Verification (Standard Encryption)
// ... The number of bytes used by the encrypted Verifier hash MUST be 32 ...
// TODO: check and trim/pad the hashes to 32
byte[] verifierHash = Arrays.copyOf(decryptedVerifierHash, calcVerifierHash.length);
if (Arrays.equals(calcVerifierHash, verifierHash)) {
setSecretKey(skey);
return true;
} else {
return false;
}
} catch (GeneralSecurityException e) {
throw new EncryptedDocumentException(e);
}
}
use of javax.crypto.Cipher 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 javax.crypto.Cipher in project poi by apache.
the class AgileEncryptor method confirmPassword.
@Override
public void confirmPassword(String password, byte[] keySpec, byte[] keySalt, byte[] verifier, byte[] verifierSalt, byte[] integritySalt) {
AgileEncryptionVerifier ver = (AgileEncryptionVerifier) getEncryptionInfo().getVerifier();
AgileEncryptionHeader header = (AgileEncryptionHeader) getEncryptionInfo().getHeader();
ver.setSalt(verifierSalt);
header.setKeySalt(keySalt);
int blockSize = header.getBlockSize();
pwHash = hashPassword(password, ver.getHashAlgorithm(), verifierSalt, ver.getSpinCount());
/**
* encryptedVerifierHashInput: This attribute MUST be generated by using the following steps:
* 1. Generate a random array of bytes with the number of bytes used specified by the saltSize
* attribute.
* 2. Generate an encryption key as specified in section 2.3.4.11 by using the user-supplied password,
* the binary byte array used to create the saltValue attribute, and a blockKey byte array
* consisting of the following bytes: 0xfe, 0xa7, 0xd2, 0x76, 0x3b, 0x4b, 0x9e, and 0x79.
* 3. Encrypt the random array of bytes generated in step 1 by using the binary form of the saltValue
* attribute as an initialization vector as specified in section 2.3.4.12. If the array of bytes is not an
* integral multiple of blockSize bytes, pad the array with 0x00 to the next integral multiple of
* blockSize bytes.
* 4. Use base64 to encode the result of step 3.
*/
byte[] encryptedVerifier = hashInput(ver, pwHash, kVerifierInputBlock, verifier, Cipher.ENCRYPT_MODE);
ver.setEncryptedVerifier(encryptedVerifier);
/**
* encryptedVerifierHashValue: This attribute MUST be generated by using the following steps:
* 1. Obtain the hash value of the random array of bytes generated in step 1 of the steps for
* encryptedVerifierHashInput.
* 2. Generate an encryption key as specified in section 2.3.4.11 by using the user-supplied password,
* the binary byte array used to create the saltValue attribute, and a blockKey byte array
* consisting of the following bytes: 0xd7, 0xaa, 0x0f, 0x6d, 0x30, 0x61, 0x34, and 0x4e.
* 3. Encrypt the hash value obtained in step 1 by using the binary form of the saltValue attribute as
* an initialization vector as specified in section 2.3.4.12. If hashSize is not an integral multiple of
* blockSize bytes, pad the hash value with 0x00 to an integral multiple of blockSize bytes.
* 4. Use base64 to encode the result of step 3.
*/
MessageDigest hashMD = getMessageDigest(ver.getHashAlgorithm());
byte[] hashedVerifier = hashMD.digest(verifier);
byte[] encryptedVerifierHash = hashInput(ver, pwHash, kHashedVerifierBlock, hashedVerifier, Cipher.ENCRYPT_MODE);
ver.setEncryptedVerifierHash(encryptedVerifierHash);
/**
* encryptedKeyValue: This attribute MUST be generated by using the following steps:
* 1. Generate a random array of bytes that is the same size as specified by the
* Encryptor.KeyData.keyBits attribute of the parent element.
* 2. Generate an encryption key as specified in section 2.3.4.11, using the user-supplied password,
* the binary byte array used to create the saltValue attribute, and a blockKey byte array
* consisting of the following bytes: 0x14, 0x6e, 0x0b, 0xe7, 0xab, 0xac, 0xd0, and 0xd6.
* 3. Encrypt the random array of bytes generated in step 1 by using the binary form of the saltValue
* attribute as an initialization vector as specified in section 2.3.4.12. If the array of bytes is not an
* integral multiple of blockSize bytes, pad the array with 0x00 to an integral multiple of
* blockSize bytes.
* 4. Use base64 to encode the result of step 3.
*/
byte[] encryptedKey = hashInput(ver, pwHash, kCryptoKeyBlock, keySpec, Cipher.ENCRYPT_MODE);
ver.setEncryptedKey(encryptedKey);
SecretKey secretKey = new SecretKeySpec(keySpec, header.getCipherAlgorithm().jceId);
setSecretKey(secretKey);
/*
* 2.3.4.14 DataIntegrity Generation (Agile Encryption)
*
* The DataIntegrity element contained within an Encryption element MUST be generated by using
* the following steps:
* 1. Obtain the intermediate key by decrypting the encryptedKeyValue from a KeyEncryptor
* contained within the KeyEncryptors sequence. Use this key for encryption operations in the
* remaining steps of this section.
* 2. Generate a random array of bytes, known as Salt, of the same length as the value of the
* KeyData.hashSize attribute.
* 3. Encrypt the random array of bytes generated in step 2 by using the binary form of the
* KeyData.saltValue attribute and a blockKey byte array consisting of the following bytes:
* 0x5f, 0xb2, 0xad, 0x01, 0x0c, 0xb9, 0xe1, and 0xf6 used to form an initialization vector as
* specified in section 2.3.4.12. If the array of bytes is not an integral multiple of blockSize
* bytes, pad the array with 0x00 to the next integral multiple of blockSize bytes.
* 4. Assign the encryptedHmacKey attribute to the base64-encoded form of the result of step 3.
* 5. 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.
* 6. 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.
* 7. Assign the encryptedHmacValue attribute to the base64-encoded form of the result of step 6.
*/
this.integritySalt = integritySalt.clone();
try {
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 = Cipher.getInstance("RSA");
for (AgileCertificateEntry ace : ver.getCertificates()) {
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());
}
} catch (GeneralSecurityException e) {
throw new EncryptedDocumentException(e);
}
}
use of javax.crypto.Cipher in project poi by apache.
the class SignatureInfo method signDigest.
/**
* Sign (encrypt) the digest with the private key.
* Currently only rsa is supported.
*
* @param digest the hashed input
* @return the encrypted hash
*/
public byte[] signDigest(byte[] digest) {
Cipher cipher = CryptoFunctions.getCipher(signatureConfig.getKey(), CipherAlgorithm.rsa, ChainingMode.ecb, null, Cipher.ENCRYPT_MODE, "PKCS1Padding");
try {
ByteArrayOutputStream digestInfoValueBuf = new ByteArrayOutputStream();
digestInfoValueBuf.write(signatureConfig.getHashMagic());
digestInfoValueBuf.write(digest);
byte[] digestInfoValue = digestInfoValueBuf.toByteArray();
byte[] signatureValue = cipher.doFinal(digestInfoValue);
return signatureValue;
} catch (Exception e) {
throw new EncryptedDocumentException(e);
}
}
use of javax.crypto.Cipher in project poi by apache.
the class AesZipFileZipEntrySource method copyToFile.
private static void copyToFile(InputStream is, File tmpFile, CipherAlgorithm cipherAlgorithm, byte[] keyBytes, byte[] ivBytes) throws IOException, GeneralSecurityException {
SecretKeySpec skeySpec = new SecretKeySpec(keyBytes, cipherAlgorithm.jceId);
Cipher ciEnc = CryptoFunctions.getCipher(skeySpec, cipherAlgorithm, ChainingMode.cbc, ivBytes, Cipher.ENCRYPT_MODE, "PKCS5Padding");
ZipInputStream zis = new ZipInputStream(is);
FileOutputStream fos = new FileOutputStream(tmpFile);
ZipOutputStream zos = new ZipOutputStream(fos);
ZipEntry ze;
while ((ze = zis.getNextEntry()) != null) {
// the cipher output stream pads the data, therefore we can't reuse the ZipEntry with set sizes
// as those will be validated upon close()
ZipEntry zeNew = new ZipEntry(ze.getName());
zeNew.setComment(ze.getComment());
zeNew.setExtra(ze.getExtra());
zeNew.setTime(ze.getTime());
// zeNew.setMethod(ze.getMethod());
zos.putNextEntry(zeNew);
FilterOutputStream fos2 = new FilterOutputStream(zos) {
// don't close underlying ZipOutputStream
@Override
public void close() {
}
};
CipherOutputStream cos = new CipherOutputStream(fos2, ciEnc);
IOUtils.copy(zis, cos);
cos.close();
fos2.close();
zos.closeEntry();
zis.closeEntry();
}
zos.close();
fos.close();
zis.close();
}
Aggregations