mirror of https://github.com/apache/poi.git
Some encryption fixes:
- don't rely on SecretKey object having the right algorithm set - leave encryption-description parsing of string/stream to xmlbeans and refactor it to one location - use namespaces of schema instead of hard-coded strings - use CryptoFunctions.getMessageDigest() instead of code duplication git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1588874 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
740c46ef84
commit
f566b57be0
|
@ -195,16 +195,18 @@ public class CryptoFunctions {
|
|||
|
||||
try {
|
||||
// Ensure the JCE policies files allow for this sized key
|
||||
if (Cipher.getMaxAllowedKeyLength(key.getAlgorithm()) < keySizeInBytes*8) {
|
||||
if (Cipher.getMaxAllowedKeyLength(cipherAlgorithm.jceId) < keySizeInBytes*8) {
|
||||
throw new EncryptedDocumentException("Export Restrictions in place - please install JCE Unlimited Strength Jurisdiction Policy files");
|
||||
}
|
||||
|
||||
Cipher cipher;
|
||||
if (cipherAlgorithm.needsBouncyCastle) {
|
||||
if (cipherAlgorithm == CipherAlgorithm.rc4) {
|
||||
cipher = Cipher.getInstance(cipherAlgorithm.jceId);
|
||||
} else if (cipherAlgorithm.needsBouncyCastle) {
|
||||
registerBouncyCastle();
|
||||
cipher = Cipher.getInstance(key.getAlgorithm() + "/" + chain.jceId + "/" + padding, "BC");
|
||||
cipher = Cipher.getInstance(cipherAlgorithm.jceId + "/" + chain.jceId + "/" + padding, "BC");
|
||||
} else {
|
||||
cipher = Cipher.getInstance(key.getAlgorithm() + "/" + chain.jceId + "/" + padding);
|
||||
cipher = Cipher.getInstance(cipherAlgorithm.jceId + "/" + chain.jceId + "/" + padding);
|
||||
}
|
||||
|
||||
if (vec == null) {
|
||||
|
@ -282,7 +284,6 @@ public class CryptoFunctions {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private static final int InitialCodeArray[] = {
|
||||
0xE1F0, 0x1D0F, 0xCC9C, 0x84C0, 0x110C, 0x0E10, 0xF1CE,
|
||||
0x313E, 0x1872, 0xE139, 0xD40F, 0x84F9, 0x280C, 0xA96A,
|
||||
|
|
|
@ -16,14 +16,11 @@
|
|||
==================================================================== */
|
||||
package org.apache.poi.poifs.crypt.agile;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.poi.EncryptedDocumentException;
|
||||
import org.apache.poi.poifs.crypt.ChainingMode;
|
||||
import org.apache.poi.poifs.crypt.CipherAlgorithm;
|
||||
import org.apache.poi.poifs.crypt.EncryptionHeader;
|
||||
import org.apache.poi.poifs.crypt.HashAlgorithm;
|
||||
import org.apache.xmlbeans.XmlException;
|
||||
|
||||
import com.microsoft.schemas.office.x2006.encryption.CTDataIntegrity;
|
||||
import com.microsoft.schemas.office.x2006.encryption.CTKeyData;
|
||||
|
@ -33,14 +30,11 @@ import com.microsoft.schemas.office.x2006.encryption.STCipherChaining;
|
|||
public class AgileEncryptionHeader extends EncryptionHeader {
|
||||
private byte encryptedHmacKey[], encryptedHmacValue[];
|
||||
|
||||
public AgileEncryptionHeader(String descriptor) throws IOException {
|
||||
EncryptionDocument ed;
|
||||
try {
|
||||
ed = EncryptionDocument.Factory.parse(descriptor);
|
||||
} catch (XmlException e) {
|
||||
throw new EncryptedDocumentException("Unable to parse encryption descriptor", e);
|
||||
}
|
||||
|
||||
public AgileEncryptionHeader(String descriptor) {
|
||||
this(AgileEncryptionInfoBuilder.parseDescriptor(descriptor));
|
||||
}
|
||||
|
||||
protected AgileEncryptionHeader(EncryptionDocument ed) {
|
||||
CTKeyData keyData;
|
||||
try {
|
||||
keyData = ed.getEncryption().getKeyData();
|
||||
|
|
|
@ -17,14 +17,19 @@
|
|||
package org.apache.poi.poifs.crypt.agile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.apache.poi.EncryptedDocumentException;
|
||||
import org.apache.poi.poifs.crypt.ChainingMode;
|
||||
import org.apache.poi.poifs.crypt.CipherAlgorithm;
|
||||
import org.apache.poi.poifs.crypt.EncryptionInfo;
|
||||
import org.apache.poi.poifs.crypt.EncryptionInfoBuilder;
|
||||
import org.apache.poi.poifs.crypt.EncryptionMode;
|
||||
import org.apache.poi.poifs.crypt.HashAlgorithm;
|
||||
import org.apache.poi.poifs.filesystem.DocumentInputStream;
|
||||
import org.apache.xmlbeans.XmlException;
|
||||
|
||||
import com.microsoft.schemas.office.x2006.encryption.EncryptionDocument;
|
||||
|
||||
public class AgileEncryptionInfoBuilder implements EncryptionInfoBuilder {
|
||||
|
||||
|
@ -37,15 +42,11 @@ public class AgileEncryptionInfoBuilder implements EncryptionInfoBuilder {
|
|||
public void initialize(EncryptionInfo info, DocumentInputStream dis) throws IOException {
|
||||
this.info = info;
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
byte[] xmlDescriptor = new byte[dis.available()];
|
||||
dis.read(xmlDescriptor);
|
||||
for (byte b : xmlDescriptor)
|
||||
builder.append((char)b);
|
||||
String descriptor = builder.toString();
|
||||
header = new AgileEncryptionHeader(descriptor);
|
||||
verifier = new AgileEncryptionVerifier(descriptor);
|
||||
if (info.getVersionMajor() == 4 && info.getVersionMinor() == 4) {
|
||||
EncryptionDocument ed = parseDescriptor(dis);
|
||||
header = new AgileEncryptionHeader(ed);
|
||||
verifier = new AgileEncryptionVerifier(ed);
|
||||
if (info.getVersionMajor() == EncryptionMode.agile.versionMajor
|
||||
&& info.getVersionMinor() == EncryptionMode.agile.versionMinor) {
|
||||
decryptor = new AgileDecryptor(this);
|
||||
}
|
||||
}
|
||||
|
@ -107,5 +108,19 @@ public class AgileEncryptionInfoBuilder implements EncryptionInfoBuilder {
|
|||
return info;
|
||||
}
|
||||
|
||||
|
||||
protected static EncryptionDocument parseDescriptor(String descriptor) {
|
||||
try {
|
||||
return EncryptionDocument.Factory.parse(descriptor);
|
||||
} catch (XmlException e) {
|
||||
throw new EncryptedDocumentException("Unable to parse encryption descriptor", e);
|
||||
}
|
||||
}
|
||||
|
||||
protected static EncryptionDocument parseDescriptor(InputStream descriptor) {
|
||||
try {
|
||||
return EncryptionDocument.Factory.parse(descriptor);
|
||||
} catch (Exception e) {
|
||||
throw new EncryptedDocumentException("Unable to parse encryption descriptor", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@ import org.apache.poi.poifs.crypt.ChainingMode;
|
|||
import org.apache.poi.poifs.crypt.CipherAlgorithm;
|
||||
import org.apache.poi.poifs.crypt.EncryptionVerifier;
|
||||
import org.apache.poi.poifs.crypt.HashAlgorithm;
|
||||
import org.apache.xmlbeans.XmlException;
|
||||
|
||||
import com.microsoft.schemas.office.x2006.encryption.CTKeyEncryptor;
|
||||
import com.microsoft.schemas.office.x2006.encryption.EncryptionDocument;
|
||||
|
@ -50,15 +49,11 @@ public class AgileEncryptionVerifier extends EncryptionVerifier {
|
|||
|
||||
private List<AgileCertificateEntry> certList = new ArrayList<AgileCertificateEntry>();
|
||||
|
||||
|
||||
public AgileEncryptionVerifier(String descriptor) {
|
||||
EncryptionDocument ed;
|
||||
try {
|
||||
ed = EncryptionDocument.Factory.parse(descriptor);
|
||||
} catch (XmlException e) {
|
||||
throw new EncryptedDocumentException("Unable to parse encryption descriptor", e);
|
||||
}
|
||||
|
||||
this(AgileEncryptionInfoBuilder.parseDescriptor(descriptor));
|
||||
}
|
||||
|
||||
protected AgileEncryptionVerifier(EncryptionDocument ed) {
|
||||
Iterator<CTKeyEncryptor> encList = ed.getEncryption().getKeyEncryptors().getKeyEncryptorList().iterator();
|
||||
CTPasswordKeyEncryptor keyData;
|
||||
try {
|
||||
|
|
|
@ -403,6 +403,11 @@ public class AgileEncryptor extends Encryptor {
|
|||
}
|
||||
|
||||
protected void createEncryptionInfoEntry(DirectoryNode dir) throws IOException {
|
||||
final CTKeyEncryptor.Uri.Enum passwordUri =
|
||||
CTKeyEncryptor.Uri.HTTP_SCHEMAS_MICROSOFT_COM_OFFICE_2006_KEY_ENCRYPTOR_PASSWORD;
|
||||
final CTKeyEncryptor.Uri.Enum certificateUri =
|
||||
CTKeyEncryptor.Uri.HTTP_SCHEMAS_MICROSOFT_COM_OFFICE_2006_KEY_ENCRYPTOR_CERTIFICATE;
|
||||
|
||||
AgileEncryptionVerifier ver = builder.getVerifier();
|
||||
AgileEncryptionHeader header = builder.getHeader();
|
||||
|
||||
|
@ -412,7 +417,7 @@ public class AgileEncryptor extends Encryptor {
|
|||
CTKeyData keyData = edRoot.addNewKeyData();
|
||||
CTKeyEncryptors keyEncList = edRoot.addNewKeyEncryptors();
|
||||
CTKeyEncryptor keyEnc = keyEncList.addNewKeyEncryptor();
|
||||
keyEnc.setUri(CTKeyEncryptor.Uri.HTTP_SCHEMAS_MICROSOFT_COM_OFFICE_2006_KEY_ENCRYPTOR_PASSWORD);
|
||||
keyEnc.setUri(passwordUri);
|
||||
CTPasswordKeyEncryptor keyPass = keyEnc.addNewEncryptedPasswordKey();
|
||||
|
||||
keyPass.setSpinCount(ver.getSpinCount());
|
||||
|
@ -469,7 +474,7 @@ public class AgileEncryptor extends Encryptor {
|
|||
|
||||
for (AgileCertificateEntry ace : ver.getCertificates()) {
|
||||
keyEnc = keyEncList.addNewKeyEncryptor();
|
||||
keyEnc.setUri(CTKeyEncryptor.Uri.HTTP_SCHEMAS_MICROSOFT_COM_OFFICE_2006_KEY_ENCRYPTOR_CERTIFICATE);
|
||||
keyEnc.setUri(certificateUri);
|
||||
CTCertificateKeyEncryptor certData = keyEnc.addNewEncryptedCertificateKey();
|
||||
try {
|
||||
certData.setX509Certificate(ace.x509.getEncoded());
|
||||
|
@ -479,13 +484,13 @@ public class AgileEncryptor extends Encryptor {
|
|||
certData.setEncryptedKeyValue(ace.encryptedKey);
|
||||
certData.setCertVerifier(ace.certVerifier);
|
||||
}
|
||||
|
||||
|
||||
XmlOptions xo = new XmlOptions();
|
||||
xo.setCharacterEncoding("UTF-8");
|
||||
Map<String,String> nsMap = new HashMap<String,String>();
|
||||
nsMap.put("http://schemas.microsoft.com/office/2006/keyEncryptor/password","p");
|
||||
nsMap.put("http://schemas.microsoft.com/office/2006/keyEncryptor/certificate", "c");
|
||||
nsMap.put("http://schemas.microsoft.com/office/2006/encryption","");
|
||||
nsMap.put(passwordUri.toString(),"p");
|
||||
nsMap.put(certificateUri.toString(), "c");
|
||||
xo.setUseDefaultNamespace();
|
||||
xo.setSaveSuggestedPrefixes(nsMap);
|
||||
xo.setSaveNamespacesFirst();
|
||||
xo.setSaveAggressiveNamespaces();
|
||||
|
@ -505,7 +510,7 @@ public class AgileEncryptor extends Encryptor {
|
|||
leos.writeShort(info.getVersionMajor());
|
||||
leos.writeShort(info.getVersionMinor());
|
||||
// Reserved (4 bytes): A value that MUST be 0x00000040
|
||||
leos.writeInt(0x40);
|
||||
leos.writeInt(info.getEncryptionFlags());
|
||||
leos.write(bos.toByteArray());
|
||||
|
||||
dir.createDocument("EncryptionInfo", leos.getWriteIndex(), new POIFSWriterListener() {
|
||||
|
|
|
@ -21,7 +21,6 @@ import java.awt.Graphics2D;
|
|||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import org.apache.poi.hslf.blip.BitmapPainter;
|
||||
import org.apache.poi.hslf.blip.DIB;
|
||||
|
@ -31,8 +30,9 @@ import org.apache.poi.hslf.blip.JPEG;
|
|||
import org.apache.poi.hslf.blip.PICT;
|
||||
import org.apache.poi.hslf.blip.PNG;
|
||||
import org.apache.poi.hslf.blip.WMF;
|
||||
import org.apache.poi.hslf.exceptions.HSLFException;
|
||||
import org.apache.poi.hslf.model.Picture;
|
||||
import org.apache.poi.poifs.crypt.CryptoFunctions;
|
||||
import org.apache.poi.poifs.crypt.HashAlgorithm;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.util.POILogFactory;
|
||||
import org.apache.poi.util.POILogger;
|
||||
|
@ -138,14 +138,9 @@ public abstract class PictureData {
|
|||
* Compute 16-byte checksum of this picture using MD5 algorithm.
|
||||
*/
|
||||
public static byte[] getChecksum(byte[] data) {
|
||||
MessageDigest sha;
|
||||
try {
|
||||
sha = MessageDigest.getInstance("MD5");
|
||||
} catch (NoSuchAlgorithmException e){
|
||||
throw new HSLFException(e.getMessage());
|
||||
}
|
||||
sha.update(data);
|
||||
return sha.digest();
|
||||
MessageDigest md5 = CryptoFunctions.getMessageDigest(HashAlgorithm.md5);
|
||||
md5.update(data);
|
||||
return md5.digest();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -31,7 +31,6 @@ import java.net.MalformedURLException;
|
|||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
|
@ -43,6 +42,8 @@ import java.util.Stack;
|
|||
import java.util.zip.ZipException;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import org.apache.poi.poifs.crypt.CryptoFunctions;
|
||||
import org.apache.poi.poifs.crypt.HashAlgorithm;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.ContentHandler;
|
||||
import org.xml.sax.InputSource;
|
||||
|
@ -542,12 +543,7 @@ public final class ExcelFileFormatDocFunctionExtractor {
|
|||
* Helps identify the source file
|
||||
*/
|
||||
private static String getFileMD5(File f) {
|
||||
MessageDigest m;
|
||||
try {
|
||||
m = MessageDigest.getInstance("MD5");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
MessageDigest m = CryptoFunctions.getMessageDigest(HashAlgorithm.md5);
|
||||
|
||||
byte[]buf = new byte[2048];
|
||||
try {
|
||||
|
|
Loading…
Reference in New Issue