From 39ab347d996a35be999add6c673e7085b7e9975c Mon Sep 17 00:00:00 2001 From: Andreas Beeker Date: Sat, 22 Feb 2020 00:36:32 +0000 Subject: [PATCH] Remove invalid agile certificate encryption git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1874351 13f79535-47bb-0310-9956-ffa450edef68 --- .../poi/poifs/crypt/agile/AgileDecryptor.java | 77 +------ .../crypt/agile/AgileEncryptionVerifier.java | 52 +---- .../poi/poifs/crypt/agile/AgileEncryptor.java | 79 ++----- .../poi/poifs/crypt/AllPOIFSCryptoTests.java | 1 - .../crypt/TestCertificateEncryption.java | 197 ------------------ 5 files changed, 27 insertions(+), 379 deletions(-) delete mode 100644 src/ooxml/testcases/org/apache/poi/poifs/crypt/TestCertificateEncryption.java diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileDecryptor.java b/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileDecryptor.java index 39d3d8f0ee..f8efe0d201 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileDecryptor.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileDecryptor.java @@ -27,14 +27,11 @@ import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; import java.security.GeneralSecurityException; -import java.security.KeyPair; import java.security.MessageDigest; -import java.security.cert.X509Certificate; import java.security.spec.AlgorithmParameterSpec; import java.util.Arrays; import javax.crypto.Cipher; -import javax.crypto.Mac; import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.RC2ParameterSpec; @@ -49,7 +46,6 @@ import org.apache.poi.poifs.crypt.Decryptor; import org.apache.poi.poifs.crypt.EncryptionHeader; import org.apache.poi.poifs.crypt.EncryptionInfo; import org.apache.poi.poifs.crypt.HashAlgorithm; -import org.apache.poi.poifs.crypt.agile.AgileEncryptionVerifier.AgileCertificateEntry; import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.poifs.filesystem.DocumentInputStream; import org.apache.poi.util.LittleEndian; @@ -90,7 +86,7 @@ public class AgileDecryptor extends Decryptor { byte[] pwHash = hashPassword(password, ver.getHashAlgorithm(), ver.getSalt(), 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. @@ -108,7 +104,7 @@ public class AgileDecryptor extends Decryptor { MessageDigest hashMD = getMessageDigest(ver.getHashAlgorithm()); byte[] verifierHash = hashMD.digest(verfierInputEnc); - /** + /* * 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. @@ -123,7 +119,7 @@ public class AgileDecryptor extends Decryptor { byte[] verifierHashDec = hashInput(ver, pwHash, kHashedVerifierBlock, ver.getEncryptedVerifierHash(), Cipher.DECRYPT_MODE); verifierHashDec = getBlock0(verifierHashDec, ver.getHashAlgorithm().hashSize); - /** + /* * 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. @@ -140,7 +136,7 @@ public class AgileDecryptor extends Decryptor { keyspec = getBlock0(keyspec, header.getKeySize()/8); SecretKeySpec secretKey = new SecretKeySpec(keyspec, header.getCipherAlgorithm().jceId); - /** + /* * 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. @@ -159,7 +155,7 @@ public class AgileDecryptor extends Decryptor { byte[] hmacKey = cipher.doFinal(header.getEncryptedHmacKey()); hmacKey = getBlock0(hmacKey, header.getHashAlgorithm().hashSize); - /** + /* * 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 @@ -183,69 +179,8 @@ public class AgileDecryptor extends Decryptor { } } - /** - * instead of a password, it's also possible to decrypt via certificate. - * Warning: this code is experimental and hasn't been validated - * - * @see Agile encryption with certificates - * - * @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; - } - } - protected static int getNextBlockSize(int inputLen, int blockSize) { - int fillSize; - for (fillSize=blockSize; fillSize certList = new ArrayList<>(); private int keyBits = -1; private int blockSize = -1; + @SuppressWarnings("unused") public AgileEncryptionVerifier(String descriptor) { this(AgileEncryptionInfoBuilder.parseDescriptor(descriptor)); } @@ -114,24 +93,6 @@ public class AgileEncryptionVerifier extends EncryptionVerifier { default: throw new EncryptedDocumentException("Unsupported chaining mode - "+ keyData.getCipherChaining()); } - - if (!encList.hasNext()) { - return; - } - - try { - CertificateFactory cf = CertificateFactory.getInstance("X.509"); - while (encList.hasNext()) { - CTCertificateKeyEncryptor certKey = encList.next().getEncryptedCertificateKey(); - AgileCertificateEntry ace = new AgileCertificateEntry(); - ace.certVerifier = certKey.getCertVerifier(); - ace.encryptedKey = certKey.getEncryptedKeyValue(); - ace.x509 = (X509Certificate)cf.generateCertificate(new ByteArrayInputStream(certKey.getX509Certificate())); - certList.add(ace); - } - } catch (GeneralSecurityException e) { - throw new EncryptedDocumentException("can't parse X509 certificate", e); - } } public AgileEncryptionVerifier(CipherAlgorithm cipherAlgorithm, HashAlgorithm hashAlgorithm, int keyBits, int blockSize, ChainingMode chainingMode) { @@ -147,7 +108,6 @@ public class AgileEncryptionVerifier extends EncryptionVerifier { super(other); keyBits = other.keyBits; blockSize = other.blockSize; - other.certList.stream().map(AgileCertificateEntry::new).forEach(certList::add); } @Override @@ -176,16 +136,6 @@ public class AgileEncryptionVerifier extends EncryptionVerifier { super.setEncryptedKey(encryptedKey); } - public void addCertificate(X509Certificate x509) { - AgileCertificateEntry ace = new AgileCertificateEntry(); - ace.x509 = x509; - certList.add(ace); - } - - public List getCertificates() { - return certList; - } - @Override public AgileEncryptionVerifier copy() { return new AgileEncryptionVerifier(this); diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptor.java b/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptor.java index 4c9b10d49b..05ab2755a1 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptor.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptor.java @@ -39,7 +39,6 @@ import java.nio.charset.StandardCharsets; import java.security.GeneralSecurityException; import java.security.MessageDigest; import java.security.SecureRandom; -import java.security.cert.CertificateEncodingException; import java.util.HashMap; import java.util.Map; import java.util.Random; @@ -58,7 +57,6 @@ import com.microsoft.schemas.office.x2006.encryption.EncryptionDocument; import com.microsoft.schemas.office.x2006.encryption.STCipherAlgorithm; import com.microsoft.schemas.office.x2006.encryption.STCipherChaining; import com.microsoft.schemas.office.x2006.encryption.STHashAlgorithm; -import com.microsoft.schemas.office.x2006.keyEncryptor.certificate.CTCertificateKeyEncryptor; import com.microsoft.schemas.office.x2006.keyEncryptor.password.CTPasswordKeyEncryptor; import org.apache.poi.EncryptedDocumentException; import org.apache.poi.poifs.crypt.ChunkedCipherOutputStream; @@ -67,8 +65,6 @@ import org.apache.poi.poifs.crypt.DataSpaceMapUtils; import org.apache.poi.poifs.crypt.EncryptionInfo; import org.apache.poi.poifs.crypt.Encryptor; import org.apache.poi.poifs.crypt.HashAlgorithm; -import org.apache.poi.poifs.crypt.agile.AgileEncryptionVerifier.AgileCertificateEntry; -import org.apache.poi.poifs.crypt.standard.EncryptionRecord; import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.util.IOUtils; import org.apache.poi.util.LittleEndian; @@ -127,7 +123,7 @@ public class AgileEncryptor extends Encryptor { 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. @@ -144,7 +140,7 @@ public class AgileEncryptor extends Encryptor { 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. @@ -161,7 +157,7 @@ public class AgileEncryptor extends Encryptor { 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. @@ -212,15 +208,6 @@ public class AgileEncryptor extends Encryptor { 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); } @@ -276,8 +263,6 @@ public class AgileEncryptor extends Encryptor { private final CTKeyEncryptor.Uri.Enum passwordUri = CTKeyEncryptor.Uri.HTTP_SCHEMAS_MICROSOFT_COM_OFFICE_2006_KEY_ENCRYPTOR_PASSWORD; - private final CTKeyEncryptor.Uri.Enum certificateUri = - CTKeyEncryptor.Uri.HTTP_SCHEMAS_MICROSOFT_COM_OFFICE_2006_KEY_ENCRYPTOR_CERTIFICATE; protected EncryptionDocument createEncryptionDocument() { AgileEncryptionVerifier ver = (AgileEncryptionVerifier)getEncryptionInfo().getVerifier(); @@ -343,19 +328,6 @@ public class AgileEncryptor extends Encryptor { 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; } @@ -372,7 +344,6 @@ public class AgileEncryptor extends Encryptor { xo.setCharacterEncoding("UTF-8"); Map nsMap = new HashMap<>(); nsMap.put(passwordUri.toString(),"p"); - nsMap.put(certificateUri.toString(), "c"); xo.setUseDefaultNamespace(); xo.setSaveSuggestedPrefixes(nsMap); xo.setSaveNamespacesFirst(); @@ -391,31 +362,6 @@ public class AgileEncryptor extends Encryptor { } } - protected void createEncryptionInfoEntry(DirectoryNode dir, File tmpFile) - throws IOException, GeneralSecurityException { - DataSpaceMapUtils.addDefaultDataSpace(dir); - - final EncryptionInfo info = getEncryptionInfo(); - - EncryptionRecord er = new EncryptionRecord(){ - @Override - public void write(LittleEndianByteArrayOutputStream bos) { - // EncryptionVersionInfo (4 bytes): A Version structure (section 2.1.4), where - // Version.vMajor MUST be 0x0004 and Version.vMinor MUST be 0x0004 - bos.writeShort(info.getVersionMajor()); - bos.writeShort(info.getVersionMinor()); - // Reserved (4 bytes): A value that MUST be 0x00000040 - bos.writeInt(info.getEncryptionFlags()); - - EncryptionDocument ed = createEncryptionDocument(); - marshallEncryptionDocument(ed, bos); - } - }; - - createEncryptionEntry(dir, "EncryptionInfo", er); - } - - /** * 2.3.4.15 Data Encryption (Agile Encryption) * @@ -451,8 +397,23 @@ public class AgileEncryptor extends Encryptor { @Override protected void createEncryptionInfoEntry(DirectoryNode dir, File tmpFile) - throws IOException, GeneralSecurityException { - AgileEncryptor.this.createEncryptionInfoEntry(dir, tmpFile); + throws IOException { + DataSpaceMapUtils.addDefaultDataSpace(dir); + createEncryptionEntry(dir, "EncryptionInfo", this::marshallEncryptionRecord); + } + + private void marshallEncryptionRecord(LittleEndianByteArrayOutputStream bos) { + final EncryptionInfo info = getEncryptionInfo(); + + // EncryptionVersionInfo (4 bytes): A Version structure (section 2.1.4), where + // Version.vMajor MUST be 0x0004 and Version.vMinor MUST be 0x0004 + bos.writeShort(info.getVersionMajor()); + bos.writeShort(info.getVersionMinor()); + // Reserved (4 bytes): A value that MUST be 0x00000040 + bos.writeInt(info.getEncryptionFlags()); + + EncryptionDocument ed = createEncryptionDocument(); + marshallEncryptionDocument(ed, bos); } } diff --git a/src/ooxml/testcases/org/apache/poi/poifs/crypt/AllPOIFSCryptoTests.java b/src/ooxml/testcases/org/apache/poi/poifs/crypt/AllPOIFSCryptoTests.java index 90bc4ceb36..ffdbdff9f9 100644 --- a/src/ooxml/testcases/org/apache/poi/poifs/crypt/AllPOIFSCryptoTests.java +++ b/src/ooxml/testcases/org/apache/poi/poifs/crypt/AllPOIFSCryptoTests.java @@ -30,7 +30,6 @@ import org.junit.runners.Suite; , TestDecryptor.class , TestEncryptor.class , TestAgileEncryptionParameters.class - , TestCertificateEncryption.class }) public final class AllPOIFSCryptoTests { } \ No newline at end of file diff --git a/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestCertificateEncryption.java b/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestCertificateEncryption.java deleted file mode 100644 index f556513ed0..0000000000 --- a/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestCertificateEncryption.java +++ /dev/null @@ -1,197 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.poifs.crypt; - -import static org.hamcrest.core.IsEqual.equalTo; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.security.GeneralSecurityException; -import java.security.KeyPair; -import java.security.KeyStore; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.security.cert.X509Certificate; - -import org.apache.poi.POIDataSamples; -import org.apache.poi.poifs.crypt.agile.AgileDecryptor; -import org.apache.poi.poifs.crypt.agile.AgileEncryptionVerifier; -import org.apache.poi.poifs.filesystem.POIFSFileSystem; -import org.apache.poi.util.IOUtils; -import org.junit.Test; - -/* -import org.junit.BeforeClass; -import java.util.Date; -import java.math.BigInteger; -import java.security.KeyPairGenerator; -import java.security.SecureRandom; -import java.security.cert.Certificate; -import sun.security.x509.AlgorithmId; -import sun.security.x509.CertificateAlgorithmId; -import sun.security.x509.CertificateIssuerName; -import sun.security.x509.CertificateSerialNumber; -import sun.security.x509.CertificateSubjectName; -import sun.security.x509.CertificateValidity; -import sun.security.x509.CertificateVersion; -import sun.security.x509.CertificateX509Key; -import sun.security.x509.X500Name; -import sun.security.x509.X509CertImpl; -import sun.security.x509.X509CertInfo; -*/ - -/** - * @see creating a self-signed certificate - */ -public class TestCertificateEncryption { - /** - * how many days from now the Certificate is valid for - */ - static final int days = 1000; - /** - * the signing algorithm, eg "SHA1withRSA" - */ - static final String algorithm = "SHA1withRSA"; - static final String password = "foobaa"; - static final String certAlias = "poitest"; - /** - * the X.509 Distinguished Name, eg "CN=Test, L=London, C=GB" - */ - static final String certDN = "CN=poitest"; - // static final File pfxFile = TempFile.createTempFile("poitest", ".pfx"); - static byte[] pfxFileBytes; - - static class CertData { - KeyPair keypair; - X509Certificate x509; - } - - /** - * Create a self-signed X.509 Certificate - * - * The keystore generation / loading is split, because normally the keystore would - * already exist. - */ - /* @BeforeClass - public static void initKeystore() throws GeneralSecurityException, IOException { - CertData certData = new CertData(); - - KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); - keyGen.initialize(1024); - certData.keypair = keyGen.generateKeyPair(); - PrivateKey privkey = certData.keypair.getPrivate(); - PublicKey publkey = certData.keypair.getPublic(); - - X509CertInfo info = new X509CertInfo(); - Date from = new Date(); - Date to = new Date(from.getTime() + days * 86400000l); - CertificateValidity interval = new CertificateValidity(from, to); - BigInteger sn = new BigInteger(64, new SecureRandom()); - X500Name owner = new X500Name(certDN); - - info.set(X509CertInfo.VALIDITY, interval); - info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(sn)); - info.set(X509CertInfo.SUBJECT, new CertificateSubjectName(owner)); - info.set(X509CertInfo.ISSUER, new CertificateIssuerName(owner)); - info.set(X509CertInfo.KEY, new CertificateX509Key(publkey)); - info.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V3)); - AlgorithmId algo = new AlgorithmId(AlgorithmId.md5WithRSAEncryption_oid); - info.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId(algo)); - - // Sign the cert to identify the algorithm that's used. - X509CertImpl cert = new X509CertImpl(info); - cert.sign(privkey, algorithm); - - // Update the algorith, and resign. - algo = (AlgorithmId)cert.get(X509CertImpl.SIG_ALG); - info.set(CertificateAlgorithmId.NAME + "." + CertificateAlgorithmId.ALGORITHM, algo); - cert = new X509CertImpl(info); - cert.sign(privkey, algorithm); - certData.x509 = cert; - - KeyStore keystore = KeyStore.getInstance("PKCS12"); - keystore.load(null, password.toCharArray()); - keystore.setKeyEntry(certAlias, certData.keypair.getPrivate(), password.toCharArray(), new Certificate[]{certData.x509}); - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - keystore.store(bos, password.toCharArray()); - pfxFileBytes = bos.toByteArray(); - } */ - - public CertData loadKeystore() - throws GeneralSecurityException, IOException { - KeyStore keystore = KeyStore.getInstance("PKCS12"); - - // InputStream fis = new ByteArrayInputStream(pfxFileBytes); - InputStream fis = POIDataSamples.getPOIFSInstance().openResourceAsStream("poitest.pfx"); - keystore.load(fis, password.toCharArray()); - fis.close(); - - X509Certificate x509 = (X509Certificate)keystore.getCertificate(certAlias); - PrivateKey privateKey = (PrivateKey)keystore.getKey(certAlias, password.toCharArray()); - PublicKey publicKey = x509.getPublicKey(); - - CertData certData = new CertData(); - certData.keypair = new KeyPair(publicKey, privateKey); - certData.x509 = x509; - - return certData; - } - - @Test - public void testCertificateEncryption() throws Exception { - POIFSFileSystem fs = new POIFSFileSystem(); - EncryptionInfo info = new EncryptionInfo(EncryptionMode.agile, CipherAlgorithm.aes128, HashAlgorithm.sha1, -1, -1, ChainingMode.cbc); - AgileEncryptionVerifier aev = (AgileEncryptionVerifier)info.getVerifier(); - CertData certData = loadKeystore(); - aev.addCertificate(certData.x509); - - Encryptor enc = info.getEncryptor(); - enc.confirmPassword("foobaa"); - - File file = POIDataSamples.getDocumentInstance().getFile("VariousPictures.docx"); - InputStream fis = new FileInputStream(file); - byte[] byteExpected = IOUtils.toByteArray(fis); - fis.close(); - - OutputStream os = enc.getDataStream(fs); - IOUtils.copy(new ByteArrayInputStream(byteExpected), os); - os.close(); - - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - fs.writeFilesystem(bos); - bos.close(); - - fs = new POIFSFileSystem(new ByteArrayInputStream(bos.toByteArray())); - info = new EncryptionInfo(fs); - AgileDecryptor agDec = (AgileDecryptor)info.getDecryptor(); - boolean passed = agDec.verifyPassword(certData.keypair, certData.x509); - assertTrue("certificate verification failed", passed); - - fis = agDec.getDataStream(fs); - byte[] byteActual = IOUtils.toByteArray(fis); - fis.close(); - - assertThat(byteExpected, equalTo(byteActual)); - } -}