123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 |
- /* ====================================================================
- 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.hslf.record;
-
-
- import static org.junit.jupiter.api.Assertions.assertArrayEquals;
- import static org.junit.jupiter.api.Assertions.assertEquals;
- import static org.junit.jupiter.api.Assertions.assertNotNull;
- import static org.junit.jupiter.api.Assertions.assertTrue;
-
- import java.io.InputStream;
- import java.security.MessageDigest;
- import java.util.Base64;
- import java.util.List;
-
- import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
- import org.apache.poi.POIDataSamples;
- import org.apache.poi.hpsf.DocumentSummaryInformation;
- import org.apache.poi.hpsf.PropertySet;
- import org.apache.poi.hpsf.PropertySetFactory;
- import org.apache.poi.hpsf.SummaryInformation;
- import org.apache.poi.hslf.usermodel.HSLFPictureData;
- import org.apache.poi.hslf.usermodel.HSLFSlide;
- import org.apache.poi.hslf.usermodel.HSLFSlideShow;
- import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl;
- import org.apache.poi.hslf.usermodel.HSLFTextParagraph;
- import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
- import org.apache.poi.poifs.crypt.CryptoFunctions;
- import org.apache.poi.poifs.crypt.EncryptionInfo;
- import org.apache.poi.poifs.crypt.HashAlgorithm;
- import org.apache.poi.poifs.crypt.cryptoapi.CryptoAPIDecryptor;
- import org.apache.poi.poifs.filesystem.POIFSFileSystem;
- import org.junit.jupiter.api.Test;
- import org.junit.jupiter.params.ParameterizedTest;
- import org.junit.jupiter.params.provider.ValueSource;
-
- /**
- * Tests that DocumentEncryption works properly.
- */
- public class TestDocumentEncryption {
- private static final POIDataSamples slTests = POIDataSamples.getSlideShowInstance();
-
- @ParameterizedTest
- @ValueSource(strings = {
- "Password_Protected-56-hello.ppt",
- "Password_Protected-hello.ppt",
- "Password_Protected-np-hello.ppt"
- })
- void cryptoAPIDecryptionOther(String pptFile) throws Exception {
- Biff8EncryptionKey.setCurrentUserPassword("hello");
- try {
- try (POIFSFileSystem fs = new POIFSFileSystem(slTests.getFile(pptFile), true);
- HSLFSlideShow ppt = new HSLFSlideShow(fs)) {
- assertTrue(ppt.getSlides().size() > 0);
- }
- } finally {
- Biff8EncryptionKey.setCurrentUserPassword(null);
- }
- }
-
- @Test
- void cryptoAPIChangeKeySize() throws Exception {
- String pptFile = "cryptoapi-proc2356.ppt";
- Biff8EncryptionKey.setCurrentUserPassword("crypto");
- try (POIFSFileSystem fs = new POIFSFileSystem(slTests.getFile(pptFile), true);
- HSLFSlideShowImpl hss = new HSLFSlideShowImpl(fs)) {
- // need to cache data (i.e. read all data) before changing the key size
- List<HSLFPictureData> picsExpected = hss.getPictureData();
- hss.getDocumentSummaryInformation();
- DocumentEncryptionAtom documentEncryptionAtom = hss.getDocumentEncryptionAtom();
- assertNotNull(documentEncryptionAtom);
- EncryptionInfo ei = documentEncryptionAtom.getEncryptionInfo();
- ei.getHeader().setKeySize(0x78);
-
- UnsynchronizedByteArrayOutputStream bos = new UnsynchronizedByteArrayOutputStream();
- hss.write(bos);
-
- try (POIFSFileSystem fs2 = new POIFSFileSystem(bos.toInputStream());
- HSLFSlideShowImpl hss2 = new HSLFSlideShowImpl(fs2)) {
- List<HSLFPictureData> picsActual = hss2.getPictureData();
-
- assertEquals(picsExpected.size(), picsActual.size());
- for (int i = 0; i < picsExpected.size(); i++) {
- assertArrayEquals(picsExpected.get(i).getRawData(), picsActual.get(i).getRawData());
- }
- }
- } finally {
- Biff8EncryptionKey.setCurrentUserPassword(null);
- }
- }
-
- @Test
- void cryptoAPIEncryption() throws Exception {
- /* documents with multiple edits need to be normalized for encryption */
- String pptFile = "57272_corrupted_usereditatom.ppt";
- UnsynchronizedByteArrayOutputStream encrypted = new UnsynchronizedByteArrayOutputStream();
- UnsynchronizedByteArrayOutputStream expected = new UnsynchronizedByteArrayOutputStream();
- UnsynchronizedByteArrayOutputStream actual = new UnsynchronizedByteArrayOutputStream();
- try {
- try (POIFSFileSystem fs = new POIFSFileSystem(slTests.getFile(pptFile), true);
- HSLFSlideShowImpl hss = new HSLFSlideShowImpl(fs)) {
- hss.normalizeRecords();
-
- // normalized ppt
- hss.write(expected);
-
- // encrypted
- Biff8EncryptionKey.setCurrentUserPassword("hello");
- hss.write(encrypted);
- }
-
- // decrypted
-
- try (InputStream bis = encrypted.toInputStream();
- POIFSFileSystem fs = new POIFSFileSystem(bis);
- HSLFSlideShowImpl hss = new HSLFSlideShowImpl(fs)) {
- Biff8EncryptionKey.setCurrentUserPassword(null);
- hss.write(actual);
- }
- } finally {
- Biff8EncryptionKey.setCurrentUserPassword(null);
- }
-
- assertArrayEquals(expected.toByteArray(), actual.toByteArray());
- }
-
- @Test
- void cryptoAPIDecryption() throws Exception {
- // taken from a msdn blog:
- // http://blogs.msdn.com/b/openspecification/archive/2009/05/08/dominic-salemno.aspx
- Biff8EncryptionKey.setCurrentUserPassword("crypto");
- try (POIFSFileSystem fs = new POIFSFileSystem(slTests.getFile("cryptoapi-proc2356.ppt"));
- HSLFSlideShow ss = new HSLFSlideShow(fs)) {
-
- HSLFSlide slide = ss.getSlides().get(0);
- String rawText = HSLFTextParagraph.getRawText(slide.getTextParagraphs().get(0));
- assertEquals("Dominic Salemno", rawText);
-
- String[][] picCmp = {
- {"0", "nKsDTKqxTCR8LFkVVWlP9GSTvZ0="},
- {"95163", "SuNOR+9V1UVYZIoeD65l3VTaLoc="},
- {"100864", "Ql3IGrr4bNq07ZTp5iPg7b+pva8="},
- {"714114", "8pdst9NjBGSfWezSZE8+aVhIRe0="},
- {"723752", "go6xqW7lvkCtlOO5tYLiMfb4oxw="},
- {"770128", "gZUM8YqRNL5kGNfyyYvEEernvCc="},
- {"957958", "CNU2iiqUFAnk3TDXsXV1ihH9eRM="},
- };
-
- MessageDigest md = CryptoFunctions.getMessageDigest(HashAlgorithm.sha1);
- List<HSLFPictureData> pd = ss.getSlideShowImpl().getPictureData();
- int i = 0;
- for (HSLFPictureData p : pd) {
- byte[] hash = md.digest(p.getData());
- assertEquals(Integer.parseInt(picCmp[i][0]), p.getOffset());
- assertEquals(picCmp[i][1], Base64.getEncoder().encodeToString(hash));
- i++;
- }
-
- DocumentEncryptionAtom dea = ss.getSlideShowImpl().getDocumentEncryptionAtom();
- assertNotNull(dea);
-
- CryptoAPIDecryptor dec = (CryptoAPIDecryptor) dea.getEncryptionInfo().getDecryptor();
- try (POIFSFileSystem fs2 = dec.getSummaryEntries(fs.getRoot(), "EncryptedSummary")) {
- PropertySet ps = PropertySetFactory.create(fs2.getRoot(), SummaryInformation.DEFAULT_STREAM_NAME);
- assertNotNull(ps);
- assertTrue(ps.isSummaryInformation());
- assertEquals("RC4 CryptoAPI Encryption", ps.getProperties()[1].getValue());
- ps = PropertySetFactory.create(fs2.getRoot(), DocumentSummaryInformation.DEFAULT_STREAM_NAME);
- assertNotNull(ps);
- assertTrue(ps.isDocumentSummaryInformation());
- assertEquals("On-screen Show (4:3)", ps.getProperties()[1].getValue());
- }
- } finally {
- Biff8EncryptionKey.setCurrentUserPassword(null);
- }
- }
- }
|