Lines 19-28
Link Here
|
19 |
|
19 |
|
20 |
package org.apache.poi.xssf.streaming; |
20 |
package org.apache.poi.xssf.streaming; |
21 |
|
21 |
|
|
|
22 |
import static java.nio.charset.StandardCharsets.UTF_8; |
22 |
import static org.junit.Assert.assertEquals; |
23 |
import static org.junit.Assert.assertEquals; |
|
|
24 |
import static org.junit.Assert.assertFalse; |
25 |
import static org.junit.Assert.assertTrue; |
23 |
|
26 |
|
24 |
import java.io.ByteArrayInputStream; |
27 |
import java.io.ByteArrayInputStream; |
25 |
import java.io.ByteArrayOutputStream; |
28 |
import java.io.ByteArrayOutputStream; |
|
|
29 |
import java.io.File; |
26 |
import java.io.FileInputStream; |
30 |
import java.io.FileInputStream; |
27 |
import java.io.FileOutputStream; |
31 |
import java.io.FileOutputStream; |
28 |
import java.io.IOException; |
32 |
import java.io.IOException; |
Lines 30-48
import java.io.InputStream;
Link Here
|
30 |
import java.io.OutputStream; |
34 |
import java.io.OutputStream; |
31 |
import java.security.GeneralSecurityException; |
35 |
import java.security.GeneralSecurityException; |
32 |
import java.security.SecureRandom; |
36 |
import java.security.SecureRandom; |
|
|
37 |
import java.util.ArrayList; |
38 |
import java.util.List; |
33 |
|
39 |
|
34 |
import javax.crypto.Cipher; |
40 |
import javax.crypto.Cipher; |
35 |
import javax.crypto.CipherInputStream; |
41 |
import javax.crypto.CipherInputStream; |
36 |
import javax.crypto.CipherOutputStream; |
42 |
import javax.crypto.CipherOutputStream; |
37 |
import javax.crypto.spec.SecretKeySpec; |
43 |
import javax.crypto.spec.SecretKeySpec; |
38 |
|
44 |
|
|
|
45 |
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; |
46 |
import org.apache.poi.openxml4j.opc.OPCPackage; |
39 |
import org.apache.poi.openxml4j.util.ZipEntrySource; |
47 |
import org.apache.poi.openxml4j.util.ZipEntrySource; |
40 |
import org.apache.poi.poifs.crypt.AesZipFileZipEntrySource; |
48 |
import org.apache.poi.poifs.crypt.AesZipFileZipEntrySource; |
41 |
import org.apache.poi.poifs.crypt.ChainingMode; |
49 |
import org.apache.poi.poifs.crypt.ChainingMode; |
42 |
import org.apache.poi.poifs.crypt.CipherAlgorithm; |
50 |
import org.apache.poi.poifs.crypt.CipherAlgorithm; |
43 |
import org.apache.poi.poifs.crypt.CryptoFunctions; |
51 |
import org.apache.poi.poifs.crypt.CryptoFunctions; |
|
|
52 |
import org.apache.poi.util.IOUtils; |
44 |
import org.apache.poi.util.POILogFactory; |
53 |
import org.apache.poi.util.POILogFactory; |
45 |
import org.apache.poi.util.POILogger; |
54 |
import org.apache.poi.util.POILogger; |
|
|
55 |
import org.apache.poi.util.TempFile; |
46 |
import org.apache.poi.xssf.usermodel.XSSFCell; |
56 |
import org.apache.poi.xssf.usermodel.XSSFCell; |
47 |
import org.apache.poi.xssf.usermodel.XSSFRow; |
57 |
import org.apache.poi.xssf.usermodel.XSSFRow; |
48 |
import org.apache.poi.xssf.usermodel.XSSFSheet; |
58 |
import org.apache.poi.xssf.usermodel.XSSFSheet; |
Lines 54-64
import org.junit.Test;
Link Here
|
54 |
* is encrypted, but the final saved workbook is not encrypted |
64 |
* is encrypted, but the final saved workbook is not encrypted |
55 |
*/ |
65 |
*/ |
56 |
public final class TestSXSSFWorkbookWithCustomZipEntrySource { |
66 |
public final class TestSXSSFWorkbookWithCustomZipEntrySource { |
57 |
|
67 |
|
|
|
68 |
final String sheetName = "TestSheet1"; |
69 |
final String cellValue = "customZipEntrySource"; |
70 |
|
58 |
@Test |
71 |
@Test |
59 |
public void customZipEntrySource() throws IOException, GeneralSecurityException { |
72 |
public void customZipEntrySource() throws IOException { |
60 |
final String sheetName = "TestSheet1"; |
|
|
61 |
final String cellValue = "customZipEntrySource"; |
62 |
SXSSFWorkbookWithCustomZipEntrySource workbook = new SXSSFWorkbookWithCustomZipEntrySource(); |
73 |
SXSSFWorkbookWithCustomZipEntrySource workbook = new SXSSFWorkbookWithCustomZipEntrySource(); |
63 |
SXSSFSheet sheet1 = workbook.createSheet(sheetName); |
74 |
SXSSFSheet sheet1 = workbook.createSheet(sheetName); |
64 |
SXSSFRow row1 = sheet1.createRow(1); |
75 |
SXSSFRow row1 = sheet1.createRow(1); |
Lines 77-82
public final class TestSXSSFWorkbookWithCustomZipEntrySource {
Link Here
|
77 |
xwb.close(); |
88 |
xwb.close(); |
78 |
} |
89 |
} |
79 |
|
90 |
|
|
|
91 |
@Test |
92 |
public void customZipEntrySourceForWriteAndRead() throws IOException, GeneralSecurityException, InvalidFormatException { |
93 |
SXSSFWorkbookWithCustomZipEntrySource workbook = new SXSSFWorkbookWithCustomZipEntrySource(); |
94 |
SXSSFSheet sheet1 = workbook.createSheet(sheetName); |
95 |
SXSSFRow row1 = sheet1.createRow(1); |
96 |
SXSSFCell cell1 = row1.createCell(1); |
97 |
cell1.setCellValue(cellValue); |
98 |
EncryptedTempData tempData = new EncryptedTempData(); |
99 |
workbook.write(tempData.getOutputStream()); |
100 |
workbook.close(); |
101 |
workbook.dispose(); |
102 |
ZipEntrySource zipEntrySource = AesZipFileZipEntrySource.createZipEntrySource(tempData.getInputStream()); |
103 |
tempData.dispose(); |
104 |
OPCPackage opc = OPCPackage.open(zipEntrySource); |
105 |
XSSFWorkbook xwb = new XSSFWorkbook(opc); |
106 |
zipEntrySource.close(); |
107 |
XSSFSheet xs1 = xwb.getSheetAt(0); |
108 |
assertEquals(sheetName, xs1.getSheetName()); |
109 |
XSSFRow xr1 = xs1.getRow(1); |
110 |
XSSFCell xc1 = xr1.getCell(1); |
111 |
assertEquals(cellValue, xc1.getStringCellValue()); |
112 |
xwb.close(); |
113 |
opc.close(); |
114 |
} |
115 |
|
116 |
@Test |
117 |
public void validateTempFilesAreEncrypted() throws IOException { |
118 |
TempFileRecordingSXSSFWorkbookWithCustomZipEntrySource workbook = new TempFileRecordingSXSSFWorkbookWithCustomZipEntrySource(); |
119 |
SXSSFSheet sheet1 = workbook.createSheet(sheetName); |
120 |
SXSSFRow row1 = sheet1.createRow(1); |
121 |
SXSSFCell cell1 = row1.createCell(1); |
122 |
cell1.setCellValue(cellValue); |
123 |
ByteArrayOutputStream os = new ByteArrayOutputStream(8192); |
124 |
workbook.write(os); |
125 |
workbook.close(); |
126 |
List<File> tempFiles = workbook.getTempFiles(); |
127 |
assertEquals(1, tempFiles.size()); |
128 |
File tempFile = tempFiles.get(0); |
129 |
assertTrue("tempFile exists?", tempFile.exists()); |
130 |
byte[] data = IOUtils.toByteArray(new FileInputStream(tempFile)); |
131 |
String text = new String(data, UTF_8); |
132 |
assertFalse(text.contains(sheetName)); |
133 |
assertFalse(text.contains(cellValue)); |
134 |
workbook.dispose(); |
135 |
assertFalse("tempFile deleted after dispose?", tempFile.exists()); |
136 |
} |
137 |
|
80 |
static class SXSSFWorkbookWithCustomZipEntrySource extends SXSSFWorkbook { |
138 |
static class SXSSFWorkbookWithCustomZipEntrySource extends SXSSFWorkbook { |
81 |
|
139 |
|
82 |
private static final POILogger logger = POILogFactory.getLogger(SXSSFWorkbookWithCustomZipEntrySource.class); |
140 |
private static final POILogger logger = POILogFactory.getLogger(SXSSFWorkbookWithCustomZipEntrySource.class); |
Lines 84-100
public final class TestSXSSFWorkbookWithCustomZipEntrySource {
Link Here
|
84 |
@Override |
142 |
@Override |
85 |
public void write(OutputStream stream) throws IOException { |
143 |
public void write(OutputStream stream) throws IOException { |
86 |
flushSheets(); |
144 |
flushSheets(); |
87 |
ByteArrayOutputStream os = new ByteArrayOutputStream(); |
145 |
EncryptedTempData tempData = new EncryptedTempData(); |
|
|
146 |
OutputStream os = tempData.getOutputStream(); |
88 |
getXSSFWorkbook().write(os); |
147 |
getXSSFWorkbook().write(os); |
|
|
148 |
os.close(); |
89 |
ZipEntrySource source = null; |
149 |
ZipEntrySource source = null; |
90 |
try { |
150 |
try { |
91 |
// provide ZipEntrySource to poi which decrypts on the fly |
151 |
// provide ZipEntrySource to poi which decrypts on the fly |
92 |
source = AesZipFileZipEntrySource.createZipEntrySource(new ByteArrayInputStream(os.toByteArray())); |
152 |
source = AesZipFileZipEntrySource.createZipEntrySource(tempData.getInputStream()); |
93 |
injectData(source, stream); |
153 |
injectData(source, stream); |
94 |
} catch (GeneralSecurityException e) { |
154 |
} catch (GeneralSecurityException e) { |
95 |
throw new IOException(e); |
155 |
throw new IOException(e); |
96 |
} finally { |
156 |
} finally { |
97 |
source.close(); |
157 |
IOUtils.closeQuietly(source); |
98 |
} |
158 |
} |
99 |
} |
159 |
} |
100 |
|
160 |
|
Lines 141-144
public final class TestSXSSFWorkbookWithCustomZipEntrySource {
Link Here
|
141 |
} |
201 |
} |
142 |
|
202 |
|
143 |
} |
203 |
} |
|
|
204 |
|
205 |
static class TempFileRecordingSXSSFWorkbookWithCustomZipEntrySource extends SXSSFWorkbookWithCustomZipEntrySource { |
206 |
|
207 |
private final List<File> tempFiles = new ArrayList<File>(); |
208 |
|
209 |
List<File> getTempFiles() { |
210 |
return new ArrayList<File>(tempFiles); |
211 |
} |
212 |
|
213 |
@Override |
214 |
protected SheetDataWriter createSheetDataWriter() throws IOException { |
215 |
return new TempFileRecordingSheetDataWriterWithDecorator(); |
216 |
} |
217 |
|
218 |
class TempFileRecordingSheetDataWriterWithDecorator extends SheetDataWriterWithDecorator { |
219 |
|
220 |
TempFileRecordingSheetDataWriterWithDecorator() throws IOException { |
221 |
super(); |
222 |
tempFiles.add(getTempFile()); |
223 |
} |
224 |
} |
225 |
} |
226 |
|
227 |
static class EncryptedTempData { |
228 |
final static CipherAlgorithm cipherAlgorithm = CipherAlgorithm.aes128; |
229 |
final SecretKeySpec skeySpec; |
230 |
final byte[] ivBytes; |
231 |
final File tempFile; |
232 |
|
233 |
EncryptedTempData() throws IOException { |
234 |
SecureRandom sr = new SecureRandom(); |
235 |
ivBytes = new byte[16]; |
236 |
byte[] keyBytes = new byte[16]; |
237 |
sr.nextBytes(ivBytes); |
238 |
sr.nextBytes(keyBytes); |
239 |
skeySpec = new SecretKeySpec(keyBytes, cipherAlgorithm.jceId); |
240 |
tempFile = TempFile.createTempFile("poi-temp-data", ".tmp"); |
241 |
} |
242 |
|
243 |
OutputStream getOutputStream() throws IOException { |
244 |
Cipher ciEnc = CryptoFunctions.getCipher(skeySpec, cipherAlgorithm, ChainingMode.cbc, ivBytes, Cipher.ENCRYPT_MODE, null); |
245 |
return new CipherOutputStream(new FileOutputStream(tempFile), ciEnc); |
246 |
} |
247 |
|
248 |
InputStream getInputStream() throws IOException { |
249 |
Cipher ciDec = CryptoFunctions.getCipher(skeySpec, cipherAlgorithm, ChainingMode.cbc, ivBytes, Cipher.DECRYPT_MODE, null); |
250 |
return new CipherInputStream(new FileInputStream(tempFile), ciDec); |
251 |
} |
252 |
|
253 |
void dispose() { |
254 |
tempFile.delete(); |
255 |
} |
256 |
} |
257 |
|
144 |
} |
258 |
} |
145 |
- |
|
|