use of org.apache.poi.EncryptedDocumentException in project poi by apache.
the class DocumentFactoryHelper method getDecryptedStream.
/**
* Wrap the OLE2 data in the NPOIFSFileSystem into a decrypted stream by using
* the given password.
*
* @param fs The OLE2 stream for the document
* @param password The password, null if the default password should be used
* @return A stream for reading the decrypted data
* @throws IOException If an error occurs while decrypting or if the password does not match
*/
public static InputStream getDecryptedStream(final NPOIFSFileSystem fs, String password) throws IOException {
EncryptionInfo info = new EncryptionInfo(fs);
Decryptor d = Decryptor.getInstance(info);
try {
boolean passwordCorrect = false;
if (password != null && d.verifyPassword(password)) {
passwordCorrect = true;
}
if (!passwordCorrect && d.verifyPassword(Decryptor.DEFAULT_PASSWORD)) {
passwordCorrect = true;
}
if (passwordCorrect) {
// as well when the resulting OPCPackage is closed
return new FilterInputStream(d.getDataStream(fs.getRoot())) {
@Override
public void close() throws IOException {
fs.close();
super.close();
}
};
} else {
if (password != null)
throw new EncryptedDocumentException("Password incorrect");
else
throw new EncryptedDocumentException("The supplied spreadsheet is protected, but no password was supplied");
}
} catch (GeneralSecurityException e) {
throw new IOException(e);
}
}
use of org.apache.poi.EncryptedDocumentException in project poi by apache.
the class StandardEncryptor method confirmPassword.
/**
* Fills the fields of verifier and header with the calculated hashes based
* on the password and a random salt
*
* see [MS-OFFCRYPTO] - 2.3.4.7 ECMA-376 Document Encryption Key Generation
*/
@Override
public void confirmPassword(String password, byte[] keySpec, byte[] keySalt, byte[] verifier, byte[] verifierSalt, byte[] integritySalt) {
StandardEncryptionVerifier ver = (StandardEncryptionVerifier) getEncryptionInfo().getVerifier();
ver.setSalt(verifierSalt);
SecretKey secretKey = generateSecretKey(password, ver, getKeySizeInBytes());
setSecretKey(secretKey);
Cipher cipher = getCipher(secretKey, null);
try {
byte[] encryptedVerifier = cipher.doFinal(verifier);
MessageDigest hashAlgo = CryptoFunctions.getMessageDigest(ver.getHashAlgorithm());
byte[] calcVerifierHash = hashAlgo.digest(verifier);
// 2.3.3 EncryptionVerifier ...
// An array of bytes that contains the encrypted form of the
// hash of the randomly generated Verifier value. The length of the array MUST be the size of
// the encryption block size multiplied by the number of blocks needed to encrypt the hash of the
// Verifier. If the encryption algorithm is RC4, the length MUST be 20 bytes. If the encryption
// algorithm is AES, the length MUST be 32 bytes. After decrypting the EncryptedVerifierHash
// field, only the first VerifierHashSize bytes MUST be used.
int encVerHashSize = ver.getCipherAlgorithm().encryptedVerifierHashLength;
byte[] encryptedVerifierHash = cipher.doFinal(Arrays.copyOf(calcVerifierHash, encVerHashSize));
ver.setEncryptedVerifier(encryptedVerifier);
ver.setEncryptedVerifierHash(encryptedVerifierHash);
} catch (GeneralSecurityException e) {
throw new EncryptedDocumentException("Password confirmation failed", e);
}
}
use of org.apache.poi.EncryptedDocumentException 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);
}
}
use of org.apache.poi.EncryptedDocumentException in project poi by apache.
the class AgileEncryptor method createEncryptionDocument.
protected EncryptionDocument createEncryptionDocument() {
AgileEncryptionVerifier ver = (AgileEncryptionVerifier) getEncryptionInfo().getVerifier();
AgileEncryptionHeader header = (AgileEncryptionHeader) getEncryptionInfo().getHeader();
EncryptionDocument ed = EncryptionDocument.Factory.newInstance();
CTEncryption edRoot = ed.addNewEncryption();
CTKeyData keyData = edRoot.addNewKeyData();
CTKeyEncryptors keyEncList = edRoot.addNewKeyEncryptors();
CTKeyEncryptor keyEnc = keyEncList.addNewKeyEncryptor();
keyEnc.setUri(passwordUri);
CTPasswordKeyEncryptor keyPass = keyEnc.addNewEncryptedPasswordKey();
keyPass.setSpinCount(ver.getSpinCount());
keyData.setSaltSize(header.getBlockSize());
keyPass.setSaltSize(ver.getBlockSize());
keyData.setBlockSize(header.getBlockSize());
keyPass.setBlockSize(ver.getBlockSize());
keyData.setKeyBits(header.getKeySize());
keyPass.setKeyBits(ver.getKeySize());
keyData.setHashSize(header.getHashAlgorithm().hashSize);
keyPass.setHashSize(ver.getHashAlgorithm().hashSize);
// header and verifier have to have the same cipher algorithm
if (!header.getCipherAlgorithm().xmlId.equals(ver.getCipherAlgorithm().xmlId)) {
throw new EncryptedDocumentException("Cipher algorithm of header and verifier have to match");
}
STCipherAlgorithm.Enum xmlCipherAlgo = STCipherAlgorithm.Enum.forString(header.getCipherAlgorithm().xmlId);
if (xmlCipherAlgo == null) {
throw new EncryptedDocumentException("CipherAlgorithm " + header.getCipherAlgorithm() + " not supported.");
}
keyData.setCipherAlgorithm(xmlCipherAlgo);
keyPass.setCipherAlgorithm(xmlCipherAlgo);
switch(header.getChainingMode()) {
case cbc:
keyData.setCipherChaining(STCipherChaining.CHAINING_MODE_CBC);
keyPass.setCipherChaining(STCipherChaining.CHAINING_MODE_CBC);
break;
case cfb:
keyData.setCipherChaining(STCipherChaining.CHAINING_MODE_CFB);
keyPass.setCipherChaining(STCipherChaining.CHAINING_MODE_CFB);
break;
default:
throw new EncryptedDocumentException("ChainingMode " + header.getChainingMode() + " not supported.");
}
keyData.setHashAlgorithm(mapHashAlgorithm(header.getHashAlgorithm()));
keyPass.setHashAlgorithm(mapHashAlgorithm(ver.getHashAlgorithm()));
keyData.setSaltValue(header.getKeySalt());
keyPass.setSaltValue(ver.getSalt());
keyPass.setEncryptedVerifierHashInput(ver.getEncryptedVerifier());
keyPass.setEncryptedVerifierHashValue(ver.getEncryptedVerifierHash());
keyPass.setEncryptedKeyValue(ver.getEncryptedKey());
CTDataIntegrity hmacData = edRoot.addNewDataIntegrity();
hmacData.setEncryptedHmacKey(header.getEncryptedHmacKey());
hmacData.setEncryptedHmacValue(header.getEncryptedHmacValue());
for (AgileCertificateEntry ace : ver.getCertificates()) {
keyEnc = keyEncList.addNewKeyEncryptor();
keyEnc.setUri(certificateUri);
CTCertificateKeyEncryptor certData = keyEnc.addNewEncryptedCertificateKey();
try {
certData.setX509Certificate(ace.x509.getEncoded());
} catch (CertificateEncodingException e) {
throw new EncryptedDocumentException(e);
}
certData.setEncryptedKeyValue(ace.encryptedKey);
certData.setCertVerifier(ace.certVerifier);
}
return ed;
}
use of org.apache.poi.EncryptedDocumentException in project poi by apache.
the class AgileEncryptor method marshallEncryptionDocument.
protected void marshallEncryptionDocument(EncryptionDocument ed, LittleEndianByteArrayOutputStream os) {
XmlOptions xo = new XmlOptions();
xo.setCharacterEncoding("UTF-8");
Map<String, String> nsMap = new HashMap<String, String>();
nsMap.put(passwordUri.toString(), "p");
nsMap.put(certificateUri.toString(), "c");
xo.setUseDefaultNamespace();
xo.setSaveSuggestedPrefixes(nsMap);
xo.setSaveNamespacesFirst();
xo.setSaveAggressiveNamespaces();
// setting standalone doesn't work with xmlbeans-2.3 & 2.6
// ed.documentProperties().setStandalone(true);
xo.setSaveNoXmlDecl();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
bos.write("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\r\n".getBytes("UTF-8"));
ed.save(bos, xo);
bos.writeTo(os);
} catch (IOException e) {
throw new EncryptedDocumentException("error marshalling encryption info document", e);
}
}
Aggregations