mirror of https://github.com/apache/poi.git
bug 60321: add examples with encrypted temp data. Patch from PJ Fanning.
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1768744 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
0a7a454082
commit
776621c3bb
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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.crypt.examples;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FilterOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Enumeration;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipException;
|
||||
import java.util.zip.ZipFile;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.CipherInputStream;
|
||||
import javax.crypto.CipherOutputStream;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import org.apache.poi.openxml4j.util.ZipEntrySource;
|
||||
import org.apache.poi.poifs.crypt.ChainingMode;
|
||||
import org.apache.poi.poifs.crypt.CipherAlgorithm;
|
||||
import org.apache.poi.poifs.crypt.CryptoFunctions;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.TempFile;
|
||||
|
||||
/**
|
||||
* An example <code>ZipEntrySource</code> that has encrypted temp files to ensure that
|
||||
* sensitive data is not stored in raw format on disk.
|
||||
*/
|
||||
public class AesZipFileZipEntrySource implements ZipEntrySource {
|
||||
final File tmpFile;
|
||||
final ZipFile zipFile;
|
||||
final Cipher ci;
|
||||
boolean closed;
|
||||
|
||||
public AesZipFileZipEntrySource(File tmpFile, Cipher ci) throws IOException {
|
||||
this.tmpFile = tmpFile;
|
||||
this.zipFile = new ZipFile(tmpFile);
|
||||
this.ci = ci;
|
||||
this.closed = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Note: the file sizes are rounded up to the next cipher block size,
|
||||
* so don't rely on file sizes of these custom encrypted zip file entries!
|
||||
*/
|
||||
@Override
|
||||
public Enumeration<? extends ZipEntry> getEntries() {
|
||||
return zipFile.entries();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream(ZipEntry entry) throws IOException {
|
||||
InputStream is = zipFile.getInputStream(entry);
|
||||
return new CipherInputStream(is, ci);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if(!closed) {
|
||||
zipFile.close();
|
||||
tmpFile.delete();
|
||||
}
|
||||
closed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isClosed() {
|
||||
return closed;
|
||||
}
|
||||
|
||||
public static AesZipFileZipEntrySource createZipEntrySource(InputStream is) throws IOException, GeneralSecurityException {
|
||||
// generate session key
|
||||
SecureRandom sr = new SecureRandom();
|
||||
byte[] ivBytes = new byte[16], keyBytes = new byte[16];
|
||||
sr.nextBytes(ivBytes);
|
||||
sr.nextBytes(keyBytes);
|
||||
final File tmpFile = TempFile.createTempFile("protectedXlsx", ".zip");
|
||||
copyToFile(is, tmpFile, CipherAlgorithm.aes128, keyBytes, ivBytes);
|
||||
IOUtils.closeQuietly(is);
|
||||
return fileToSource(tmpFile, CipherAlgorithm.aes128, keyBytes, ivBytes);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
private static AesZipFileZipEntrySource fileToSource(File tmpFile, CipherAlgorithm cipherAlgorithm, byte keyBytes[], byte ivBytes[]) throws ZipException, IOException {
|
||||
SecretKeySpec skeySpec = new SecretKeySpec(keyBytes, cipherAlgorithm.jceId);
|
||||
Cipher ciDec = CryptoFunctions.getCipher(skeySpec, cipherAlgorithm, ChainingMode.cbc, ivBytes, Cipher.DECRYPT_MODE, "PKCS5Padding");
|
||||
return new AesZipFileZipEntrySource(tmpFile, ciDec);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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.crypt.examples;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.CipherInputStream;
|
||||
import javax.crypto.CipherOutputStream;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import org.apache.poi.poifs.crypt.ChainingMode;
|
||||
import org.apache.poi.poifs.crypt.CipherAlgorithm;
|
||||
import org.apache.poi.poifs.crypt.CryptoFunctions;
|
||||
import org.apache.poi.util.TempFile;
|
||||
|
||||
/**
|
||||
* EncryptedTempData can be used to buffer binary data in a secure way, by using encrypted temp files.
|
||||
*/
|
||||
public class EncryptedTempData {
|
||||
final static CipherAlgorithm cipherAlgorithm = CipherAlgorithm.aes128;
|
||||
final SecretKeySpec skeySpec;
|
||||
final byte[] ivBytes;
|
||||
final File tempFile;
|
||||
|
||||
public EncryptedTempData() throws IOException {
|
||||
SecureRandom sr = new SecureRandom();
|
||||
ivBytes = new byte[16];
|
||||
byte[] keyBytes = new byte[16];
|
||||
sr.nextBytes(ivBytes);
|
||||
sr.nextBytes(keyBytes);
|
||||
skeySpec = new SecretKeySpec(keyBytes, cipherAlgorithm.jceId);
|
||||
tempFile = TempFile.createTempFile("poi-temp-data", ".tmp");
|
||||
}
|
||||
|
||||
public OutputStream getOutputStream() throws IOException {
|
||||
Cipher ciEnc = CryptoFunctions.getCipher(skeySpec, cipherAlgorithm, ChainingMode.cbc, ivBytes, Cipher.ENCRYPT_MODE, null);
|
||||
return new CipherOutputStream(new FileOutputStream(tempFile), ciEnc);
|
||||
}
|
||||
|
||||
public InputStream getInputStream() throws IOException {
|
||||
Cipher ciDec = CryptoFunctions.getCipher(skeySpec, cipherAlgorithm, ChainingMode.cbc, ivBytes, Cipher.DECRYPT_MODE, null);
|
||||
return new CipherInputStream(new FileInputStream(tempFile), ciDec);
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
tempFile.delete();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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.crypt.examples;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.apache.poi.poifs.crypt.Decryptor;
|
||||
import org.apache.poi.poifs.crypt.EncryptionInfo;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
|
||||
public class EncryptionUtils {
|
||||
public static InputStream decrypt(final InputStream inputStream, final String pwd) throws Exception {
|
||||
try {
|
||||
POIFSFileSystem fs = new POIFSFileSystem(inputStream);
|
||||
EncryptionInfo info = new EncryptionInfo(fs);
|
||||
Decryptor d = Decryptor.getInstance(info);
|
||||
if (!d.verifyPassword(pwd)) {
|
||||
throw new RuntimeException("incorrect password");
|
||||
}
|
||||
return d.getDataStream(fs);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(inputStream);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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.examples.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.poi.util.TempFile;
|
||||
|
||||
public class TempFileUtils {
|
||||
public static void checkTempFiles() throws IOException {
|
||||
String tmpDir = System.getProperty(TempFile.JAVA_IO_TMPDIR) + "/poifiles";
|
||||
File tempDir = new File(tmpDir);
|
||||
if(tempDir.exists()) {
|
||||
String[] tempFiles = tempDir.list();
|
||||
if(tempFiles.length > 0) {
|
||||
System.out.println("found files in poi temp dir " + tempDir.getAbsolutePath());
|
||||
for(String filename : tempDir.list()) {
|
||||
System.out.println("file: " + filename);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
System.out.println("unable to find poi temp dir");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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.xssf.eventusermodel.examples;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.apache.poi.crypt.examples.AesZipFileZipEntrySource;
|
||||
import org.apache.poi.crypt.examples.EncryptionUtils;
|
||||
import org.apache.poi.examples.util.TempFileUtils;
|
||||
import org.apache.poi.openxml4j.opc.OPCPackage;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.xssf.eventusermodel.XSSFReader;
|
||||
import org.apache.poi.xssf.eventusermodel.XSSFReader.SheetIterator;
|
||||
|
||||
/**
|
||||
* An example that loads a password protected workbook and counts the sheets.
|
||||
* The example highlights how to do this in streaming way.
|
||||
* <p><ul>
|
||||
* <li>The example demonstrates that all temp files are removed.
|
||||
* <li><code>AesZipFileZipEntrySource</code> is used to ensure that temp files are encrypted.
|
||||
* </ul><p>
|
||||
*/
|
||||
public class LoadPasswordProtectedXlsxStreaming {
|
||||
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
if(args.length != 2) {
|
||||
throw new Exception("Expected 2 params: filename and password");
|
||||
}
|
||||
TempFileUtils.checkTempFiles();
|
||||
String filename = args[0];
|
||||
String password = args[1];
|
||||
FileInputStream fis = new FileInputStream(filename);
|
||||
try {
|
||||
InputStream unencryptedStream = EncryptionUtils.decrypt(fis, password);
|
||||
try {
|
||||
printSheetCount(unencryptedStream);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(unencryptedStream);
|
||||
}
|
||||
} finally {
|
||||
IOUtils.closeQuietly(fis);
|
||||
}
|
||||
TempFileUtils.checkTempFiles();
|
||||
} catch(Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void printSheetCount(final InputStream inputStream) throws Exception {
|
||||
AesZipFileZipEntrySource source = AesZipFileZipEntrySource.createZipEntrySource(inputStream);
|
||||
try {
|
||||
OPCPackage pkg = OPCPackage.open(source);
|
||||
try {
|
||||
XSSFReader reader = new XSSFReader(pkg);
|
||||
SheetIterator iter = (SheetIterator)reader.getSheetsData();
|
||||
int count = 0;
|
||||
while(iter.hasNext()) {
|
||||
iter.next();
|
||||
count++;
|
||||
}
|
||||
System.out.println("sheet count: " + count);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(pkg);
|
||||
}
|
||||
} finally {
|
||||
IOUtils.closeQuietly(source);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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.xssf.streaming.examples;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.CipherInputStream;
|
||||
import javax.crypto.CipherOutputStream;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import org.apache.poi.crypt.examples.AesZipFileZipEntrySource;
|
||||
import org.apache.poi.crypt.examples.EncryptedTempData;
|
||||
import org.apache.poi.openxml4j.util.ZipEntrySource;
|
||||
import org.apache.poi.poifs.crypt.ChainingMode;
|
||||
import org.apache.poi.poifs.crypt.CipherAlgorithm;
|
||||
import org.apache.poi.poifs.crypt.CryptoFunctions;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
|
||||
import org.apache.poi.xssf.streaming.SheetDataWriter;
|
||||
|
||||
public class SXSSFWorkbookWithCustomZipEntrySource extends SXSSFWorkbook {
|
||||
|
||||
public SXSSFWorkbookWithCustomZipEntrySource() {
|
||||
super(20);
|
||||
setCompressTempFiles(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(OutputStream stream) throws IOException {
|
||||
flushSheets();
|
||||
EncryptedTempData tempData = new EncryptedTempData();
|
||||
ZipEntrySource source = null;
|
||||
try {
|
||||
OutputStream os = tempData.getOutputStream();
|
||||
try {
|
||||
getXSSFWorkbook().write(os);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(os);
|
||||
}
|
||||
// provide ZipEntrySource to poi which decrypts on the fly
|
||||
source = AesZipFileZipEntrySource.createZipEntrySource(tempData.getInputStream());
|
||||
injectData(source, stream);
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw new IOException(e);
|
||||
} finally {
|
||||
tempData.dispose();
|
||||
IOUtils.closeQuietly(source);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SheetDataWriter createSheetDataWriter() throws IOException {
|
||||
return new SheetDataWriterWithDecorator();
|
||||
}
|
||||
|
||||
static class SheetDataWriterWithDecorator extends SheetDataWriter {
|
||||
final static CipherAlgorithm cipherAlgorithm = CipherAlgorithm.aes128;
|
||||
SecretKeySpec skeySpec;
|
||||
byte[] ivBytes;
|
||||
|
||||
public SheetDataWriterWithDecorator() throws IOException {
|
||||
super();
|
||||
}
|
||||
|
||||
void init() {
|
||||
if(skeySpec == null) {
|
||||
SecureRandom sr = new SecureRandom();
|
||||
ivBytes = new byte[16];
|
||||
byte[] keyBytes = new byte[16];
|
||||
sr.nextBytes(ivBytes);
|
||||
sr.nextBytes(keyBytes);
|
||||
skeySpec = new SecretKeySpec(keyBytes, cipherAlgorithm.jceId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected OutputStream decorateOutputStream(FileOutputStream fos) {
|
||||
init();
|
||||
Cipher ciEnc = CryptoFunctions.getCipher(skeySpec, cipherAlgorithm, ChainingMode.cbc, ivBytes, Cipher.ENCRYPT_MODE, "PKCS5Padding");
|
||||
return new CipherOutputStream(fos, ciEnc);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InputStream decorateInputStream(FileInputStream fis) {
|
||||
Cipher ciDec = CryptoFunctions.getCipher(skeySpec, cipherAlgorithm, ChainingMode.cbc, ivBytes, Cipher.DECRYPT_MODE, "PKCS5Padding");
|
||||
return new CipherInputStream(fis, ciDec);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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.xssf.streaming.examples;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
import org.apache.poi.crypt.examples.EncryptedTempData;
|
||||
import org.apache.poi.examples.util.TempFileUtils;
|
||||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
|
||||
import org.apache.poi.openxml4j.opc.OPCPackage;
|
||||
import org.apache.poi.poifs.crypt.EncryptionInfo;
|
||||
import org.apache.poi.poifs.crypt.EncryptionMode;
|
||||
import org.apache.poi.poifs.crypt.Encryptor;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.xssf.streaming.SXSSFCell;
|
||||
import org.apache.poi.xssf.streaming.SXSSFRow;
|
||||
import org.apache.poi.xssf.streaming.SXSSFSheet;
|
||||
|
||||
/**
|
||||
* An example that outputs a simple generated workbook that is password protected.
|
||||
* The example highlights how to do this in streaming way.
|
||||
* <p><ul>
|
||||
* <li>The example demonstrates that all temp files are removed.
|
||||
* <li><code>SXSSFWorkbookWithCustomZipEntrySource</code> extends SXSSFWorkbook to ensure temp files are encrypted.
|
||||
* </ul><p>
|
||||
*/
|
||||
public class SavePasswordProtectedXlsx {
|
||||
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
if(args.length != 2) {
|
||||
throw new Exception("Expected 2 params: filename and password");
|
||||
}
|
||||
TempFileUtils.checkTempFiles();
|
||||
String filename = args[0];
|
||||
String password = args[1];
|
||||
SXSSFWorkbookWithCustomZipEntrySource wb = new SXSSFWorkbookWithCustomZipEntrySource();
|
||||
try {
|
||||
for(int i = 0; i < 10; i++) {
|
||||
SXSSFSheet sheet = wb.createSheet("Sheet" + i);
|
||||
for(int r = 0; r < 1000; r++) {
|
||||
SXSSFRow row = sheet.createRow(r);
|
||||
for(int c = 0; c < 100; c++) {
|
||||
SXSSFCell cell = row.createCell(c);
|
||||
cell.setCellValue("abcd");
|
||||
}
|
||||
}
|
||||
}
|
||||
EncryptedTempData tempData = new EncryptedTempData();
|
||||
try {
|
||||
wb.write(tempData.getOutputStream());
|
||||
save(tempData.getInputStream(), filename, password);
|
||||
System.out.println("Saved " + filename);
|
||||
} finally {
|
||||
tempData.dispose();
|
||||
}
|
||||
} finally {
|
||||
wb.close();
|
||||
wb.dispose();
|
||||
}
|
||||
TempFileUtils.checkTempFiles();
|
||||
} catch(Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void save(final InputStream inputStream, final String filename, final String pwd)
|
||||
throws InvalidFormatException, IOException, GeneralSecurityException {
|
||||
try {
|
||||
POIFSFileSystem fs = new POIFSFileSystem();
|
||||
EncryptionInfo info = new EncryptionInfo(EncryptionMode.agile);
|
||||
Encryptor enc = Encryptor.getInstance(info);
|
||||
enc.confirmPassword(pwd);
|
||||
OPCPackage opc = OPCPackage.open(inputStream);
|
||||
try {
|
||||
FileOutputStream fos = new FileOutputStream(filename);
|
||||
try {
|
||||
opc.save(enc.getDataStream(fs));
|
||||
fs.writeFilesystem(fos);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(fos);
|
||||
}
|
||||
} finally {
|
||||
IOUtils.closeQuietly(opc);
|
||||
}
|
||||
} finally {
|
||||
IOUtils.closeQuietly(inputStream);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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.xssf.usermodel.examples;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.apache.poi.crypt.examples.AesZipFileZipEntrySource;
|
||||
import org.apache.poi.crypt.examples.EncryptionUtils;
|
||||
import org.apache.poi.examples.util.TempFileUtils;
|
||||
import org.apache.poi.openxml4j.opc.OPCPackage;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
|
||||
/**
|
||||
* An example that loads a password protected workbook and counts the sheets.
|
||||
* <p><ul>
|
||||
* <li>The example demonstrates that all temp files are removed.
|
||||
* <li><code>AesZipFileZipEntrySource</code> is used to ensure that temp files are encrypted.
|
||||
* </ul><p>
|
||||
*/
|
||||
public class LoadPasswordProtectedXlsx {
|
||||
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
if(args.length != 2) {
|
||||
throw new Exception("Expected 2 params: filename and password");
|
||||
}
|
||||
TempFileUtils.checkTempFiles();
|
||||
String filename = args[0];
|
||||
String password = args[1];
|
||||
FileInputStream fis = new FileInputStream(filename);
|
||||
try {
|
||||
InputStream unencryptedStream = EncryptionUtils.decrypt(fis, password);
|
||||
try {
|
||||
printSheetCount(unencryptedStream);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(unencryptedStream);
|
||||
}
|
||||
} finally {
|
||||
IOUtils.closeQuietly(fis);
|
||||
}
|
||||
TempFileUtils.checkTempFiles();
|
||||
} catch(Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void printSheetCount(final InputStream inputStream) throws Exception {
|
||||
AesZipFileZipEntrySource source = AesZipFileZipEntrySource.createZipEntrySource(inputStream);
|
||||
try {
|
||||
OPCPackage pkg = OPCPackage.open(source);
|
||||
try {
|
||||
XSSFWorkbook workbook = new XSSFWorkbook(pkg);
|
||||
try {
|
||||
System.out.println("sheet count: " + workbook.getNumberOfSheets());
|
||||
} finally {
|
||||
IOUtils.closeQuietly(workbook);
|
||||
}
|
||||
} finally {
|
||||
IOUtils.closeQuietly(pkg);
|
||||
}
|
||||
} finally {
|
||||
IOUtils.closeQuietly(source);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue