001: package org.bouncycastle.openpgp.test;
002:
003: import org.bouncycastle.jce.provider.BouncyCastleProvider;
004: import org.bouncycastle.openpgp.PGPCompressedData;
005: import org.bouncycastle.openpgp.PGPCompressedDataGenerator;
006: import org.bouncycastle.openpgp.PGPEncryptedData;
007: import org.bouncycastle.openpgp.PGPEncryptedDataGenerator;
008: import org.bouncycastle.openpgp.PGPEncryptedDataList;
009: import org.bouncycastle.openpgp.PGPLiteralData;
010: import org.bouncycastle.openpgp.PGPLiteralDataGenerator;
011: import org.bouncycastle.openpgp.PGPObjectFactory;
012: import org.bouncycastle.openpgp.PGPPBEEncryptedData;
013: import org.bouncycastle.util.encoders.Base64;
014: import org.bouncycastle.util.encoders.Hex;
015: import org.bouncycastle.util.test.SimpleTest;
016: import org.bouncycastle.util.test.UncloseableOutputStream;
017:
018: import java.io.ByteArrayOutputStream;
019: import java.io.InputStream;
020: import java.io.OutputStream;
021: import java.security.SecureRandom;
022: import java.security.Security;
023: import java.util.Date;
024:
025: public class PGPPBETest extends SimpleTest {
026: private static final Date TEST_DATE = new Date(1062200111000L);
027:
028: byte[] enc1 = Base64
029: .decode("jA0EAwMC5M5wWBP2HBZgySvUwWFAmMRLn7dWiZN6AkQMvpE3b6qwN3SSun7zInw2"
030: + "hxxdgFzVGfbjuB8w");
031:
032: byte[] enc1crc = Base64.decode("H66L");
033:
034: char[] pass = { 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l',
035: 'd' };
036:
037: /**
038: * Message with both PBE and symmetric
039: */
040: byte[] testPBEAsym = Base64
041: .decode("hQIOA/ZlQEFWB5vuEAf/covEUaBve7NlWWdiO5NZubdtTHGElEXzG9hyBycp9At8"
042: + "nZGi27xOZtEGFQo7pfz4JySRc3O0s6w7PpjJSonFJyNSxuze2LuqRwFWBYYcbS8/"
043: + "7YcjB6PqutrT939OWsozfNqivI9/QyZCjBvFU89pp7dtUngiZ6MVv81ds2I+vcvk"
044: + "GlIFcxcE1XoCIB3EvbqWNaoOotgEPT60unnB2BeDV1KD3lDRouMIYHfZ3SzBwOOI"
045: + "6aK39sWnY5sAK7JjFvnDAMBdueOiI0Fy+gxbFD/zFDt4cWAVSAGTC4w371iqppmT"
046: + "25TM7zAtCgpiq5IsELPlUZZnXKmnYQ7OCeysF0eeVwf+OFB9fyvCEv/zVQocJCg8"
047: + "fWxfCBlIVFNeNQpeGygn/ZmRaILvB7IXDWP0oOw7/F2Ym66IdYYIp2HeEZv+jFwa"
048: + "l41w5W4BH/gtbwGjFQ6CvF/m+lfUv6ZZdzsMIeEOwhP5g7rXBxrbcnGBaU+PXbho"
049: + "gjDqaYzAWGlrmAd6aPSj51AGeYXkb2T1T/yoJ++M3GvhH4C4hvitamDkksh/qRnM"
050: + "M/s8Nku6z1+RXO3M6p5QC1nlAVqieU8esT43945eSoC77K8WyujDNbysDyUCUTzt"
051: + "p/aoQwe/HgkeOTJNelKR9y2W3xinZLFzep0SqpNI/e468yB/2/LGsykIyQa7JX6r"
052: + "BYwuBAIDAkOKfv5rK8v0YDfnN+eFqwhTcrfBj5rDH7hER6nW3lNWcMataUiHEaMg"
053: + "o6Q0OO1vptIGxW8jClTD4N1sCNwNu9vKny8dKYDDHbCjE06DNTv7XYVW3+JqTL5E"
054: + "BnidvGgOmA==");
055:
056: /**
057: * decrypt the passed in message stream
058: */
059: private byte[] decryptMessage(byte[] message, Date date)
060: throws Exception {
061: PGPObjectFactory pgpF = new PGPObjectFactory(message);
062: PGPEncryptedDataList enc = (PGPEncryptedDataList) pgpF
063: .nextObject();
064: PGPPBEEncryptedData pbe = (PGPPBEEncryptedData) enc.get(0);
065:
066: InputStream clear = pbe.getDataStream(pass, "BC");
067:
068: PGPObjectFactory pgpFact = new PGPObjectFactory(clear);
069: PGPCompressedData cData = (PGPCompressedData) pgpFact
070: .nextObject();
071:
072: pgpFact = new PGPObjectFactory(cData.getDataStream());
073:
074: PGPLiteralData ld = (PGPLiteralData) pgpFact.nextObject();
075:
076: ByteArrayOutputStream bOut = new ByteArrayOutputStream();
077: if (!ld.getFileName().equals("test.txt")
078: && !ld.getFileName().equals("_CONSOLE")) {
079: fail("wrong filename in packet");
080: }
081: if (!ld.getModificationTime().equals(date)) {
082: fail("wrong modification time in packet: "
083: + ld.getModificationTime().getTime() + " "
084: + date.getTime());
085: }
086:
087: InputStream unc = ld.getInputStream();
088: int ch;
089:
090: while ((ch = unc.read()) >= 0) {
091: bOut.write(ch);
092: }
093:
094: if (pbe.isIntegrityProtected() && !pbe.verify()) {
095: fail("integrity check failed");
096: }
097:
098: return bOut.toByteArray();
099: }
100:
101: private byte[] decryptMessageBuffered(byte[] message, Date date)
102: throws Exception {
103: PGPObjectFactory pgpF = new PGPObjectFactory(message);
104: PGPEncryptedDataList enc = (PGPEncryptedDataList) pgpF
105: .nextObject();
106: PGPPBEEncryptedData pbe = (PGPPBEEncryptedData) enc.get(0);
107:
108: InputStream clear = pbe.getDataStream(pass, "BC");
109:
110: PGPObjectFactory pgpFact = new PGPObjectFactory(clear);
111: PGPCompressedData cData = (PGPCompressedData) pgpFact
112: .nextObject();
113:
114: pgpFact = new PGPObjectFactory(cData.getDataStream());
115:
116: PGPLiteralData ld = (PGPLiteralData) pgpFact.nextObject();
117:
118: ByteArrayOutputStream bOut = new ByteArrayOutputStream();
119: if (!ld.getFileName().equals("test.txt")
120: && !ld.getFileName().equals("_CONSOLE")) {
121: fail("wrong filename in packet");
122: }
123: if (!ld.getModificationTime().equals(date)) {
124: fail("wrong modification time in packet: "
125: + ld.getModificationTime().getTime() + " "
126: + date.getTime());
127: }
128:
129: InputStream unc = ld.getInputStream();
130: byte[] buf = new byte[1024];
131: int len;
132:
133: while ((len = unc.read(buf)) >= 0) {
134: bOut.write(buf, 0, len);
135: }
136:
137: if (pbe.isIntegrityProtected() && !pbe.verify()) {
138: fail("integrity check failed");
139: }
140:
141: return bOut.toByteArray();
142: }
143:
144: public void performTest() throws Exception {
145: byte[] out = decryptMessage(enc1, TEST_DATE);
146:
147: if (out[0] != 'h' || out[1] != 'e' || out[2] != 'l') {
148: fail("wrong plain text in packet");
149: }
150:
151: //
152: // create a PBE encrypted message and read it back.
153: //
154: byte[] text = { (byte) 'h', (byte) 'e', (byte) 'l', (byte) 'l',
155: (byte) 'o', (byte) ' ', (byte) 'w', (byte) 'o',
156: (byte) 'r', (byte) 'l', (byte) 'd', (byte) '!',
157: (byte) '\n' };
158:
159: //
160: // encryption step - convert to literal data, compress, encode.
161: //
162: ByteArrayOutputStream bOut = new ByteArrayOutputStream();
163:
164: PGPCompressedDataGenerator comData = new PGPCompressedDataGenerator(
165: PGPCompressedData.ZIP);
166:
167: Date cDate = new Date(
168: (System.currentTimeMillis() / 1000) * 1000);
169: PGPLiteralDataGenerator lData = new PGPLiteralDataGenerator();
170: OutputStream comOut = comData.open(new UncloseableOutputStream(
171: bOut));
172: OutputStream ldOut = lData.open(new UncloseableOutputStream(
173: comOut), PGPLiteralData.BINARY, PGPLiteralData.CONSOLE,
174: text.length, cDate);
175:
176: ldOut.write(text);
177:
178: ldOut.close();
179:
180: comOut.close();
181:
182: //
183: // encrypt - with stream close
184: //
185: ByteArrayOutputStream cbOut = new ByteArrayOutputStream();
186: PGPEncryptedDataGenerator cPk = new PGPEncryptedDataGenerator(
187: PGPEncryptedData.CAST5, new SecureRandom(), "BC");
188:
189: cPk.addMethod(pass);
190:
191: OutputStream cOut = cPk.open(
192: new UncloseableOutputStream(cbOut),
193: bOut.toByteArray().length);
194:
195: cOut.write(bOut.toByteArray());
196:
197: cOut.close();
198:
199: out = decryptMessage(cbOut.toByteArray(), cDate);
200:
201: if (!areEqual(out, text)) {
202: fail("wrong plain text in generated packet");
203: }
204:
205: //
206: // encrypt - with generator close
207: //
208: cbOut = new ByteArrayOutputStream();
209: cPk = new PGPEncryptedDataGenerator(PGPEncryptedData.CAST5,
210: new SecureRandom(), "BC");
211:
212: cPk.addMethod(pass);
213:
214: cOut = cPk.open(new UncloseableOutputStream(cbOut), bOut
215: .toByteArray().length);
216:
217: cOut.write(bOut.toByteArray());
218:
219: cPk.close();
220:
221: out = decryptMessage(cbOut.toByteArray(), cDate);
222:
223: if (!areEqual(out, text)) {
224: fail("wrong plain text in generated packet");
225: }
226:
227: //
228: // encrypt - partial packet style.
229: //
230: SecureRandom rand = new SecureRandom();
231: byte[] test = new byte[1233];
232:
233: rand.nextBytes(test);
234:
235: bOut = new ByteArrayOutputStream();
236:
237: comData = new PGPCompressedDataGenerator(PGPCompressedData.ZIP);
238: comOut = comData.open(bOut);
239: lData = new PGPLiteralDataGenerator();
240:
241: ldOut = lData.open(new UncloseableOutputStream(comOut),
242: PGPLiteralData.BINARY, PGPLiteralData.CONSOLE,
243: TEST_DATE, new byte[16]);
244:
245: ldOut.write(test);
246:
247: ldOut.close();
248:
249: comOut.close();
250:
251: cbOut = new ByteArrayOutputStream();
252: cPk = new PGPEncryptedDataGenerator(PGPEncryptedData.CAST5,
253: rand, "BC");
254:
255: cPk.addMethod(pass);
256:
257: cOut = cPk.open(new UncloseableOutputStream(cbOut),
258: new byte[16]);
259:
260: cOut.write(bOut.toByteArray());
261:
262: cOut.close();
263:
264: out = decryptMessage(cbOut.toByteArray(), TEST_DATE);
265: if (!areEqual(out, test)) {
266: fail("wrong plain text in generated packet");
267: }
268:
269: //
270: // with integrity packet
271: //
272: cbOut = new ByteArrayOutputStream();
273: cPk = new PGPEncryptedDataGenerator(PGPEncryptedData.CAST5,
274: true, rand, "BC");
275:
276: cPk.addMethod(pass);
277:
278: cOut = cPk.open(new UncloseableOutputStream(cbOut),
279: new byte[16]);
280:
281: cOut.write(bOut.toByteArray());
282:
283: cOut.close();
284:
285: out = decryptMessage(cbOut.toByteArray(), TEST_DATE);
286: if (!areEqual(out, test)) {
287: fail("wrong plain text in generated packet");
288: }
289:
290: //
291: // decrypt with buffering
292: //
293: out = decryptMessageBuffered(cbOut.toByteArray(), TEST_DATE);
294: if (!areEqual(out, test)) {
295: fail("wrong plain text in buffer generated packet");
296: }
297:
298: //
299: // sample message
300: //
301: PGPObjectFactory pgpFact = new PGPObjectFactory(testPBEAsym);
302:
303: PGPEncryptedDataList enc = (PGPEncryptedDataList) pgpFact
304: .nextObject();
305:
306: PGPPBEEncryptedData pbe = (PGPPBEEncryptedData) enc.get(1);
307:
308: InputStream clear = pbe.getDataStream("password".toCharArray(),
309: "BC");
310:
311: pgpFact = new PGPObjectFactory(clear);
312:
313: PGPLiteralData ld = (PGPLiteralData) pgpFact.nextObject();
314:
315: bOut = new ByteArrayOutputStream();
316: InputStream unc = ld.getInputStream();
317: int ch;
318:
319: while ((ch = unc.read()) >= 0) {
320: bOut.write(ch);
321: }
322:
323: if (!areEqual(bOut.toByteArray(), Hex
324: .decode("5361742031302e30322e30370d0a"))) {
325: fail("data mismatch on combined PBE");
326: }
327:
328: //
329: // with integrity packet - one byte message
330: //
331: byte[] msg = new byte[1];
332: bOut = new ByteArrayOutputStream();
333:
334: comData = new PGPCompressedDataGenerator(PGPCompressedData.ZIP);
335:
336: lData = new PGPLiteralDataGenerator();
337: comOut = comData.open(new UncloseableOutputStream(bOut));
338: ldOut = lData.open(new UncloseableOutputStream(comOut),
339: PGPLiteralData.BINARY, PGPLiteralData.CONSOLE,
340: msg.length, cDate);
341:
342: ldOut.write(msg);
343:
344: ldOut.close();
345:
346: comOut.close();
347:
348: cbOut = new ByteArrayOutputStream();
349: cPk = new PGPEncryptedDataGenerator(PGPEncryptedData.CAST5,
350: true, rand, "BC");
351:
352: cPk.addMethod(pass);
353:
354: cOut = cPk.open(new UncloseableOutputStream(cbOut),
355: new byte[16]);
356:
357: cOut.write(bOut.toByteArray());
358:
359: cOut.close();
360:
361: out = decryptMessage(cbOut.toByteArray(), cDate);
362: if (!areEqual(out, msg)) {
363: fail("wrong plain text in generated packet");
364: }
365:
366: //
367: // decrypt with buffering
368: //
369: out = decryptMessageBuffered(cbOut.toByteArray(), cDate);
370: if (!areEqual(out, msg)) {
371: fail("wrong plain text in buffer generated packet");
372: }
373: }
374:
375: public String getName() {
376: return "PGPPBETest";
377: }
378:
379: public static void main(String[] args) {
380: Security.addProvider(new BouncyCastleProvider());
381:
382: runTest(new PGPPBETest());
383: }
384: }
|