001: package org.bouncycastle.openpgp.test;
002:
003: import org.bouncycastle.bcpg.CompressionAlgorithmTags;
004: import org.bouncycastle.bcpg.HashAlgorithmTags;
005: import org.bouncycastle.bcpg.PublicKeyAlgorithmTags;
006: import org.bouncycastle.bcpg.SignatureSubpacketTags;
007: import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags;
008: import org.bouncycastle.jce.provider.BouncyCastleProvider;
009: import org.bouncycastle.openpgp.PGPException;
010: import org.bouncycastle.openpgp.PGPLiteralData;
011: import org.bouncycastle.openpgp.PGPLiteralDataGenerator;
012: import org.bouncycastle.openpgp.PGPObjectFactory;
013: import org.bouncycastle.openpgp.PGPOnePassSignature;
014: import org.bouncycastle.openpgp.PGPOnePassSignatureList;
015: import org.bouncycastle.openpgp.PGPPrivateKey;
016: import org.bouncycastle.openpgp.PGPPublicKey;
017: import org.bouncycastle.openpgp.PGPSecretKey;
018: import org.bouncycastle.openpgp.PGPSecretKeyRing;
019: import org.bouncycastle.openpgp.PGPSignature;
020: import org.bouncycastle.openpgp.PGPSignatureGenerator;
021: import org.bouncycastle.openpgp.PGPSignatureList;
022: import org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator;
023: import org.bouncycastle.openpgp.PGPSignatureSubpacketVector;
024: import org.bouncycastle.openpgp.PGPV3SignatureGenerator;
025: import org.bouncycastle.util.encoders.Base64;
026: import org.bouncycastle.util.test.SimpleTest;
027: import org.bouncycastle.util.test.UncloseableOutputStream;
028:
029: import java.io.ByteArrayInputStream;
030: import java.io.ByteArrayOutputStream;
031: import java.io.IOException;
032: import java.io.InputStream;
033: import java.io.OutputStream;
034: import java.security.NoSuchProviderException;
035: import java.security.Security;
036: import java.security.SignatureException;
037: import java.util.Date;
038:
039: public class PGPSignatureTest extends SimpleTest {
040: private static final int[] NO_PREFERENCES = null;
041: private static final int[] PREFERRED_SYMMETRIC_ALGORITHMS = new int[] {
042: SymmetricKeyAlgorithmTags.AES_128,
043: SymmetricKeyAlgorithmTags.TRIPLE_DES };
044: private static final int[] PREFERRED_HASH_ALGORITHMS = new int[] {
045: HashAlgorithmTags.SHA1, HashAlgorithmTags.SHA256 };
046: private static final int[] PREFERRED_COMPRESSION_ALGORITHMS = new int[] { CompressionAlgorithmTags.ZLIB };
047:
048: private static final int TEST_EXPIRATION_TIME = 10000;
049: private static final String TEST_USER_ID = "test user id";
050: private static final byte[] TEST_DATA = "hello world!\nhello world!\n"
051: .getBytes();
052: private static final byte[] TEST_DATA_WITH_CRLF = "hello world!\r\nhello world!\r\n"
053: .getBytes();
054:
055: byte[] dsaKeyRing = Base64
056: .decode("lQHhBD9HBzURBACzkxRCVGJg5+Ld9DU4Xpnd4LCKgMq7YOY7Gi0EgK92gbaa6+zQ"
057: + "oQFqz1tt3QUmpz3YVkm/zLESBBtC1ACIXGggUdFMUr5I87+1Cb6vzefAtGt8N5VV"
058: + "1F/MXv1gJz4Bu6HyxL/ncfe71jsNhav0i4yAjf2etWFj53zK6R+Ojg5H6wCgpL9/"
059: + "tXVfGP8SqFvyrN/437MlFSUEAIN3V6j/MUllyrZglrtr2+RWIwRrG/ACmrF6hTug"
060: + "Ol4cQxaDYNcntXbhlTlJs9MxjTH3xxzylyirCyq7HzGJxZzSt6FTeh1DFYzhJ7Qu"
061: + "YR1xrSdA6Y0mUv0ixD5A4nPHjupQ5QCqHGeRfFD/oHzD4zqBnJp/BJ3LvQ66bERJ"
062: + "mKl5A/4uj3HoVxpb0vvyENfRqKMmGBISycY4MoH5uWfb23FffsT9r9KL6nJ4syLz"
063: + "aRR0gvcbcjkc9Z3epI7gr3jTrb4d8WPxsDbT/W1tv9bG/EHawomLcihtuUU68Uej"
064: + "6/wZot1XJqu2nQlku57+M/V2X1y26VKsipolPfja4uyBOOyvbP4DAwIDIBTxWjkC"
065: + "GGAWQO2jy9CTvLHJEoTO7moHrp1FxOVpQ8iJHyRqZzLllO26OzgohbiPYz8u9qCu"
066: + "lZ9Xn7QzRXJpYyBFY2hpZG5hIChEU0EgVGVzdCBLZXkpIDxlcmljQGJvdW5jeWNh"
067: + "c3RsZS5vcmc+iFkEExECABkFAj9HBzUECwcDAgMVAgMDFgIBAh4BAheAAAoJEM0j"
068: + "9enEyjRDAlwAnjTjjt57NKIgyym7OTCwzIU3xgFpAJ0VO5m5PfQKmGJRhaewLSZD"
069: + "4nXkHg==");
070:
071: char[] dsaPass = "hello world".toCharArray();
072:
073: byte[] rsaKeyRing = Base64
074: .decode("lQIEBEBXUNMBBADScQczBibewnbCzCswc/9ut8R0fwlltBRxMW0NMdKJY2LF"
075: + "7k2COeLOCIU95loJGV6ulbpDCXEO2Jyq8/qGw1qD3SCZNXxKs3GS8Iyh9Uwd"
076: + "VL07nMMYl5NiQRsFB7wOb86+94tYWgvikVA5BRP5y3+O3GItnXnpWSJyREUy"
077: + "6WI2QQAGKf4JAwIVmnRs4jtTX2DD05zy2mepEQ8bsqVAKIx7lEwvMVNcvg4Y"
078: + "8vFLh9Mf/uNciwL4Se/ehfKQ/AT0JmBZduYMqRU2zhiBmxj4cXUQ0s36ysj7"
079: + "fyDngGocDnM3cwPxaTF1ZRBQHSLewP7dqE7M73usFSz8vwD/0xNOHFRLKbsO"
080: + "RqDlLA1Cg2Yd0wWPS0o7+qqk9ndqrjjSwMM8ftnzFGjShAdg4Ca7fFkcNePP"
081: + "/rrwIH472FuRb7RbWzwXA4+4ZBdl8D4An0dwtfvAO+jCZSrLjmSpxEOveJxY"
082: + "GduyR4IA4lemvAG51YHTHd4NXheuEqsIkn1yarwaaj47lFPnxNOElOREMdZb"
083: + "nkWQb1jfgqO24imEZgrLMkK9bJfoDnlF4k6r6hZOp5FSFvc5kJB4cVo1QJl4"
084: + "pwCSdoU6luwCggrlZhDnkGCSuQUUW45NE7Br22NGqn4/gHs0KCsWbAezApGj"
085: + "qYUCfX1bcpPzUMzUlBaD5rz2vPeO58CDtBJ0ZXN0ZXIgPHRlc3RAdGVzdD6I"
086: + "sgQTAQIAHAUCQFdQ0wIbAwQLBwMCAxUCAwMWAgECHgECF4AACgkQs8JyyQfH"
087: + "97I1QgP8Cd+35maM2cbWV9iVRO+c5456KDi3oIUSNdPf1NQrCAtJqEUhmMSt"
088: + "QbdiaFEkPrORISI/2htXruYn0aIpkCfbUheHOu0sef7s6pHmI2kOQPzR+C/j"
089: + "8D9QvWsPOOso81KU2axUY8zIer64Uzqc4szMIlLw06c8vea27RfgjBpSCryw"
090: + "AgAA");
091:
092: char[] rsaPass = "2002 Buffalo Sabres".toCharArray();
093:
094: byte[] nullPacketsSubKeyBinding = Base64
095: .decode("iDYEGBECAAAAACp9AJ9PlJCrFpi+INwG7z61eku2Wg1HaQCgl33X5Egj+Kf7F9CXIWj2iFCvQDo=");
096:
097: public void performTest() throws Exception {
098: //
099: // RSA tests
100: //
101: PGPSecretKeyRing pgpPriv = new PGPSecretKeyRing(rsaKeyRing);
102: PGPSecretKey secretKey = pgpPriv.getSecretKey();
103: PGPPrivateKey pgpPrivKey = secretKey.extractPrivateKey(rsaPass,
104: "BC");
105:
106: try {
107: testSig(PublicKeyAlgorithmTags.DSA, HashAlgorithmTags.SHA1,
108: secretKey.getPublicKey(), pgpPrivKey);
109:
110: fail("RSA wrong key test failed.");
111: } catch (PGPException e) {
112: // expected
113: }
114:
115: try {
116: testSigV3(PublicKeyAlgorithmTags.DSA,
117: HashAlgorithmTags.SHA1, secretKey.getPublicKey(),
118: pgpPrivKey);
119:
120: fail("RSA V3 wrong key test failed.");
121: } catch (PGPException e) {
122: // expected
123: }
124:
125: //
126: // certifications
127: //
128: PGPSignatureGenerator sGen = new PGPSignatureGenerator(
129: PublicKeyAlgorithmTags.RSA_GENERAL,
130: HashAlgorithmTags.SHA1, "BC");
131:
132: sGen.initSign(PGPSignature.KEY_REVOCATION, pgpPrivKey);
133:
134: PGPSignature sig = sGen.generateCertification(secretKey
135: .getPublicKey());
136:
137: sig.initVerify(secretKey.getPublicKey(), "BC");
138:
139: if (!sig.verifyCertification(secretKey.getPublicKey())) {
140: fail("revocation verification failed.");
141: }
142:
143: PGPSecretKeyRing pgpDSAPriv = new PGPSecretKeyRing(dsaKeyRing);
144: PGPSecretKey secretDSAKey = pgpDSAPriv.getSecretKey();
145: PGPPrivateKey pgpPrivDSAKey = secretDSAKey.extractPrivateKey(
146: dsaPass, "BC");
147:
148: sGen = new PGPSignatureGenerator(PublicKeyAlgorithmTags.DSA,
149: HashAlgorithmTags.SHA1, "BC");
150:
151: sGen.initSign(PGPSignature.SUBKEY_BINDING, pgpPrivDSAKey);
152:
153: PGPSignatureSubpacketGenerator unhashedGen = new PGPSignatureSubpacketGenerator();
154: PGPSignatureSubpacketGenerator hashedGen = new PGPSignatureSubpacketGenerator();
155:
156: hashedGen.setSignatureExpirationTime(false,
157: TEST_EXPIRATION_TIME);
158: hashedGen.setSignerUserID(true, TEST_USER_ID);
159: hashedGen.setPreferredCompressionAlgorithms(false,
160: PREFERRED_COMPRESSION_ALGORITHMS);
161: hashedGen.setPreferredHashAlgorithms(false,
162: PREFERRED_HASH_ALGORITHMS);
163: hashedGen.setPreferredSymmetricAlgorithms(false,
164: PREFERRED_SYMMETRIC_ALGORITHMS);
165:
166: sGen.setHashedSubpackets(hashedGen.generate());
167: sGen.setUnhashedSubpackets(unhashedGen.generate());
168:
169: sig = sGen.generateCertification(secretDSAKey.getPublicKey(),
170: secretKey.getPublicKey());
171:
172: byte[] sigBytes = sig.getEncoded();
173:
174: PGPObjectFactory f = new PGPObjectFactory(sigBytes);
175:
176: sig = ((PGPSignatureList) f.nextObject()).get(0);
177:
178: sig.initVerify(secretDSAKey.getPublicKey(), "BC");
179:
180: if (!sig.verifyCertification(secretDSAKey.getPublicKey(),
181: secretKey.getPublicKey())) {
182: fail("subkey binding verification failed.");
183: }
184:
185: PGPSignatureSubpacketVector hashedPcks = sig
186: .getHashedSubPackets();
187: PGPSignatureSubpacketVector unhashedPcks = sig
188: .getUnhashedSubPackets();
189:
190: if (hashedPcks.size() != 6) {
191: fail("wrong number of hashed packets found.");
192: }
193:
194: if (unhashedPcks.size() != 1) {
195: fail("wrong number of unhashed packets found.");
196: }
197:
198: if (!hashedPcks.getSignerUserID().equals(TEST_USER_ID)) {
199: fail("test userid not matching");
200: }
201:
202: if (hashedPcks.getSignatureExpirationTime() != TEST_EXPIRATION_TIME) {
203: fail("test signature expiration time not matching");
204: }
205:
206: if (unhashedPcks.getIssuerKeyID() != secretDSAKey.getKeyID()) {
207: fail("wrong issuer key ID found in certification");
208: }
209:
210: int[] prefAlgs = hashedPcks.getPreferredCompressionAlgorithms();
211: preferredAlgorithmCheck("compression",
212: PREFERRED_COMPRESSION_ALGORITHMS, prefAlgs);
213:
214: prefAlgs = hashedPcks.getPreferredHashAlgorithms();
215: preferredAlgorithmCheck("hash", PREFERRED_HASH_ALGORITHMS,
216: prefAlgs);
217:
218: prefAlgs = hashedPcks.getPreferredSymmetricAlgorithms();
219: preferredAlgorithmCheck("symmetric",
220: PREFERRED_SYMMETRIC_ALGORITHMS, prefAlgs);
221:
222: int[] criticalHashed = hashedPcks.getCriticalTags();
223:
224: if (criticalHashed.length != 1) {
225: fail("wrong number of critical packets found.");
226: }
227:
228: if (criticalHashed[0] != SignatureSubpacketTags.SIGNER_USER_ID) {
229: fail("wrong critical packet found in tag list.");
230: }
231:
232: //
233: // no packets passed
234: //
235: sGen = new PGPSignatureGenerator(PublicKeyAlgorithmTags.DSA,
236: HashAlgorithmTags.SHA1, "BC");
237:
238: sGen.initSign(PGPSignature.SUBKEY_BINDING, pgpPrivDSAKey);
239:
240: sGen.setHashedSubpackets(null);
241: sGen.setUnhashedSubpackets(null);
242:
243: sig = sGen.generateCertification(TEST_USER_ID, secretKey
244: .getPublicKey());
245:
246: sig.initVerify(secretDSAKey.getPublicKey(), "BC");
247:
248: if (!sig.verifyCertification(TEST_USER_ID, secretKey
249: .getPublicKey())) {
250: fail("subkey binding verification failed.");
251: }
252:
253: hashedPcks = sig.getHashedSubPackets();
254:
255: if (hashedPcks.size() != 1) {
256: fail("found wrong number of hashed packets");
257: }
258:
259: unhashedPcks = sig.getUnhashedSubPackets();
260:
261: if (unhashedPcks.size() != 1) {
262: fail("found wrong number of unhashed packets");
263: }
264:
265: try {
266: sig.verifyCertification(secretKey.getPublicKey());
267:
268: fail("failed to detect non-key signature.");
269: } catch (IllegalStateException e) {
270: // expected
271: }
272:
273: //
274: // override hash packets
275: //
276: sGen = new PGPSignatureGenerator(PublicKeyAlgorithmTags.DSA,
277: HashAlgorithmTags.SHA1, "BC");
278:
279: sGen.initSign(PGPSignature.SUBKEY_BINDING, pgpPrivDSAKey);
280:
281: hashedGen = new PGPSignatureSubpacketGenerator();
282:
283: hashedGen.setSignatureCreationTime(false, new Date(0L));
284:
285: sGen.setHashedSubpackets(hashedGen.generate());
286:
287: sGen.setUnhashedSubpackets(null);
288:
289: sig = sGen.generateCertification(TEST_USER_ID, secretKey
290: .getPublicKey());
291:
292: sig.initVerify(secretDSAKey.getPublicKey(), "BC");
293:
294: if (!sig.verifyCertification(TEST_USER_ID, secretKey
295: .getPublicKey())) {
296: fail("subkey binding verification failed.");
297: }
298:
299: hashedPcks = sig.getHashedSubPackets();
300:
301: if (hashedPcks.size() != 1) {
302: fail("found wrong number of hashed packets in override test");
303: }
304:
305: if (!hashedPcks.getSignatureCreationTime().equals(new Date(0L))) {
306: fail("creation of overriden date failed.");
307: }
308:
309: prefAlgs = hashedPcks.getPreferredCompressionAlgorithms();
310: preferredAlgorithmCheck("compression", NO_PREFERENCES, prefAlgs);
311:
312: prefAlgs = hashedPcks.getPreferredHashAlgorithms();
313: preferredAlgorithmCheck("hash", NO_PREFERENCES, prefAlgs);
314:
315: prefAlgs = hashedPcks.getPreferredSymmetricAlgorithms();
316: preferredAlgorithmCheck("symmetric", NO_PREFERENCES, prefAlgs);
317:
318: if (hashedPcks.getKeyExpirationTime() != 0) {
319: fail("unexpected key expiration time found");
320: }
321:
322: if (hashedPcks.getSignatureExpirationTime() != 0) {
323: fail("unexpected signature expiration time found");
324: }
325:
326: if (hashedPcks.getSignerUserID() != null) {
327: fail("unexpected signer user ID found");
328: }
329:
330: criticalHashed = hashedPcks.getCriticalTags();
331:
332: if (criticalHashed.length != 0) {
333: fail("critical packets found when none expected");
334: }
335:
336: unhashedPcks = sig.getUnhashedSubPackets();
337:
338: if (unhashedPcks.size() != 1) {
339: fail("found wrong number of unhashed packets in override test");
340: }
341:
342: //
343: // general signatures
344: //
345: testSig(PublicKeyAlgorithmTags.RSA_GENERAL,
346: HashAlgorithmTags.SHA256, secretKey.getPublicKey(),
347: pgpPrivKey);
348: testSig(PublicKeyAlgorithmTags.RSA_GENERAL,
349: HashAlgorithmTags.SHA384, secretKey.getPublicKey(),
350: pgpPrivKey);
351: testSig(PublicKeyAlgorithmTags.RSA_GENERAL,
352: HashAlgorithmTags.SHA512, secretKey.getPublicKey(),
353: pgpPrivKey);
354: testSigV3(PublicKeyAlgorithmTags.RSA_GENERAL,
355: HashAlgorithmTags.SHA1, secretKey.getPublicKey(),
356: pgpPrivKey);
357: testTextSig(PublicKeyAlgorithmTags.RSA_GENERAL,
358: HashAlgorithmTags.SHA1, secretKey.getPublicKey(),
359: pgpPrivKey, TEST_DATA_WITH_CRLF, TEST_DATA_WITH_CRLF);
360: testTextSig(PublicKeyAlgorithmTags.RSA_GENERAL,
361: HashAlgorithmTags.SHA1, secretKey.getPublicKey(),
362: pgpPrivKey, TEST_DATA, TEST_DATA_WITH_CRLF);
363: testTextSigV3(PublicKeyAlgorithmTags.RSA_GENERAL,
364: HashAlgorithmTags.SHA1, secretKey.getPublicKey(),
365: pgpPrivKey, TEST_DATA_WITH_CRLF, TEST_DATA_WITH_CRLF);
366: testTextSigV3(PublicKeyAlgorithmTags.RSA_GENERAL,
367: HashAlgorithmTags.SHA1, secretKey.getPublicKey(),
368: pgpPrivKey, TEST_DATA, TEST_DATA_WITH_CRLF);
369:
370: //
371: // DSA Tests
372: //
373: pgpPriv = new PGPSecretKeyRing(dsaKeyRing);
374: secretKey = pgpPriv.getSecretKey();
375: pgpPrivKey = secretKey.extractPrivateKey(dsaPass, "BC");
376:
377: try {
378: testSig(PublicKeyAlgorithmTags.RSA_GENERAL,
379: HashAlgorithmTags.SHA1, secretKey.getPublicKey(),
380: pgpPrivKey);
381:
382: fail("DSA wrong key test failed.");
383: } catch (PGPException e) {
384: // expected
385: }
386:
387: try {
388: testSigV3(PublicKeyAlgorithmTags.RSA_GENERAL,
389: HashAlgorithmTags.SHA1, secretKey.getPublicKey(),
390: pgpPrivKey);
391:
392: fail("DSA V3 wrong key test failed.");
393: } catch (PGPException e) {
394: // expected
395: }
396:
397: testSig(PublicKeyAlgorithmTags.DSA, HashAlgorithmTags.SHA1,
398: secretKey.getPublicKey(), pgpPrivKey);
399: testSigV3(PublicKeyAlgorithmTags.DSA, HashAlgorithmTags.SHA1,
400: secretKey.getPublicKey(), pgpPrivKey);
401: testTextSig(PublicKeyAlgorithmTags.DSA, HashAlgorithmTags.SHA1,
402: secretKey.getPublicKey(), pgpPrivKey,
403: TEST_DATA_WITH_CRLF, TEST_DATA_WITH_CRLF);
404: testTextSig(PublicKeyAlgorithmTags.DSA, HashAlgorithmTags.SHA1,
405: secretKey.getPublicKey(), pgpPrivKey, TEST_DATA,
406: TEST_DATA_WITH_CRLF);
407: testTextSigV3(PublicKeyAlgorithmTags.DSA,
408: HashAlgorithmTags.SHA1, secretKey.getPublicKey(),
409: pgpPrivKey, TEST_DATA_WITH_CRLF, TEST_DATA_WITH_CRLF);
410: testTextSigV3(PublicKeyAlgorithmTags.DSA,
411: HashAlgorithmTags.SHA1, secretKey.getPublicKey(),
412: pgpPrivKey, TEST_DATA, TEST_DATA_WITH_CRLF);
413:
414: // special cases
415: //
416: testMissingSubpackets(nullPacketsSubKeyBinding);
417:
418: testMissingSubpackets(generateV3BinarySig(pgpPrivKey,
419: PublicKeyAlgorithmTags.DSA, HashAlgorithmTags.SHA1));
420: }
421:
422: private void testMissingSubpackets(byte[] signature)
423: throws IOException {
424: PGPObjectFactory f = new PGPObjectFactory(signature);
425: Object obj = f.nextObject();
426:
427: while (!(obj instanceof PGPSignatureList)) {
428: obj = f.nextObject();
429: if (obj instanceof PGPLiteralData) {
430: InputStream in = ((PGPLiteralData) obj).getDataStream();
431: while (in.read() >= 0) {
432: // do nothing
433: }
434: }
435: }
436:
437: PGPSignature sig = ((PGPSignatureList) obj).get(0);
438:
439: if (sig.getVersion() > 3) {
440: PGPSignatureSubpacketVector v = sig.getHashedSubPackets();
441:
442: if (v.getKeyExpirationTime() != 0) {
443: fail("key expiration time not zero for missing subpackets");
444: }
445: } else {
446: if (sig.getHashedSubPackets() != null) {
447: fail("hashed sub packets found when none expected");
448: }
449: if (sig.getUnhashedSubPackets() != null) {
450: fail("unhashed sub packets found when none expected");
451: }
452: }
453: }
454:
455: private void preferredAlgorithmCheck(String type, int[] expected,
456: int[] prefAlgs) {
457: if (expected == null) {
458: if (prefAlgs != null) {
459: fail("preferences for " + type
460: + " found when none expected");
461: }
462: } else {
463: if (prefAlgs.length != expected.length) {
464: fail("wrong number of preferred " + type
465: + " algorithms found");
466: }
467:
468: for (int i = 0; i != expected.length; i++) {
469: if (expected[i] != prefAlgs[i]) {
470: fail("wrong algorithm found for " + type
471: + ": expected " + expected[i] + " got "
472: + prefAlgs);
473: }
474: }
475: }
476: }
477:
478: private void testSig(int encAlgorithm, int hashAlgorithm,
479: PGPPublicKey pubKey, PGPPrivateKey privKey)
480: throws Exception {
481: ByteArrayOutputStream bOut = new ByteArrayOutputStream();
482: ByteArrayInputStream testIn = new ByteArrayInputStream(
483: TEST_DATA);
484: PGPSignatureGenerator sGen = new PGPSignatureGenerator(
485: encAlgorithm, hashAlgorithm, "BC");
486:
487: sGen.initSign(PGPSignature.BINARY_DOCUMENT, privKey);
488: sGen.generateOnePassVersion(false).encode(bOut);
489:
490: PGPLiteralDataGenerator lGen = new PGPLiteralDataGenerator();
491: OutputStream lOut = lGen.open(
492: new UncloseableOutputStream(bOut),
493: PGPLiteralData.BINARY, "_CONSOLE",
494: TEST_DATA.length * 2, new Date());
495:
496: int ch;
497: while ((ch = testIn.read()) >= 0) {
498: lOut.write(ch);
499: sGen.update((byte) ch);
500: }
501:
502: lOut.write(TEST_DATA);
503: sGen.update(TEST_DATA);
504:
505: lGen.close();
506:
507: sGen.generate().encode(bOut);
508:
509: verifySignature(bOut.toByteArray(), hashAlgorithm, pubKey,
510: TEST_DATA);
511: }
512:
513: private void testTextSig(int encAlgorithm, int hashAlgorithm,
514: PGPPublicKey pubKey, PGPPrivateKey privKey, byte[] data,
515: byte[] canonicalData) throws Exception {
516: PGPSignatureGenerator sGen = new PGPSignatureGenerator(
517: encAlgorithm, HashAlgorithmTags.SHA1, "BC");
518: ByteArrayOutputStream bOut = new ByteArrayOutputStream();
519: ByteArrayInputStream testIn = new ByteArrayInputStream(data);
520: Date creationTime = new Date();
521:
522: sGen.initSign(PGPSignature.CANONICAL_TEXT_DOCUMENT, privKey);
523: sGen.generateOnePassVersion(false).encode(bOut);
524:
525: PGPLiteralDataGenerator lGen = new PGPLiteralDataGenerator();
526: OutputStream lOut = lGen.open(
527: new UncloseableOutputStream(bOut), PGPLiteralData.TEXT,
528: "_CONSOLE", data.length * 2, creationTime);
529:
530: int ch;
531: while ((ch = testIn.read()) >= 0) {
532: lOut.write(ch);
533: sGen.update((byte) ch);
534: }
535:
536: lOut.write(data);
537: sGen.update(data);
538:
539: lGen.close();
540:
541: sGen.generate().encode(bOut);
542:
543: verifySignature(bOut.toByteArray(), hashAlgorithm, pubKey,
544: canonicalData);
545: }
546:
547: private void testSigV3(int encAlgorithm, int hashAlgorithm,
548: PGPPublicKey pubKey, PGPPrivateKey privKey)
549: throws Exception {
550: byte[] bytes = generateV3BinarySig(privKey, encAlgorithm,
551: hashAlgorithm);
552:
553: verifySignature(bytes, hashAlgorithm, pubKey, TEST_DATA);
554: }
555:
556: private byte[] generateV3BinarySig(PGPPrivateKey privKey,
557: int encAlgorithm, int hashAlgorithm) throws Exception {
558: ByteArrayOutputStream bOut = new ByteArrayOutputStream();
559: ByteArrayInputStream testIn = new ByteArrayInputStream(
560: TEST_DATA);
561: PGPV3SignatureGenerator sGen = new PGPV3SignatureGenerator(
562: encAlgorithm, hashAlgorithm, "BC");
563:
564: sGen.initSign(PGPSignature.BINARY_DOCUMENT, privKey);
565: sGen.generateOnePassVersion(false).encode(bOut);
566:
567: PGPLiteralDataGenerator lGen = new PGPLiteralDataGenerator();
568: OutputStream lOut = lGen.open(
569: new UncloseableOutputStream(bOut),
570: PGPLiteralData.BINARY, "_CONSOLE",
571: TEST_DATA.length * 2, new Date());
572:
573: int ch;
574: while ((ch = testIn.read()) >= 0) {
575: lOut.write(ch);
576: sGen.update((byte) ch);
577: }
578:
579: lOut.write(TEST_DATA);
580: sGen.update(TEST_DATA);
581:
582: lGen.close();
583:
584: sGen.generate().encode(bOut);
585:
586: return bOut.toByteArray();
587: }
588:
589: private void testTextSigV3(int encAlgorithm, int hashAlgorithm,
590: PGPPublicKey pubKey, PGPPrivateKey privKey, byte[] data,
591: byte[] canonicalData) throws Exception {
592: PGPV3SignatureGenerator sGen = new PGPV3SignatureGenerator(
593: encAlgorithm, HashAlgorithmTags.SHA1, "BC");
594: ByteArrayOutputStream bOut = new ByteArrayOutputStream();
595: ByteArrayInputStream testIn = new ByteArrayInputStream(data);
596:
597: sGen.initSign(PGPSignature.CANONICAL_TEXT_DOCUMENT, privKey);
598: sGen.generateOnePassVersion(false).encode(bOut);
599:
600: PGPLiteralDataGenerator lGen = new PGPLiteralDataGenerator();
601: OutputStream lOut = lGen.open(
602: new UncloseableOutputStream(bOut), PGPLiteralData.TEXT,
603: "_CONSOLE", data.length * 2, new Date());
604:
605: int ch;
606: while ((ch = testIn.read()) >= 0) {
607: lOut.write(ch);
608: sGen.update((byte) ch);
609: }
610:
611: lOut.write(data);
612: sGen.update(data);
613:
614: lGen.close();
615:
616: sGen.generate().encode(bOut);
617:
618: verifySignature(bOut.toByteArray(), hashAlgorithm, pubKey,
619: canonicalData);
620: }
621:
622: private void verifySignature(byte[] encodedSig, int hashAlgorithm,
623: PGPPublicKey pubKey, byte[] original) throws IOException,
624: PGPException, NoSuchProviderException, SignatureException {
625: PGPObjectFactory pgpFact = new PGPObjectFactory(encodedSig);
626: PGPOnePassSignatureList p1 = (PGPOnePassSignatureList) pgpFact
627: .nextObject();
628: PGPOnePassSignature ops = p1.get(0);
629: PGPLiteralData p2 = (PGPLiteralData) pgpFact.nextObject();
630: InputStream dIn = p2.getInputStream();
631:
632: ops.initVerify(pubKey, "BC");
633:
634: int ch;
635:
636: while ((ch = dIn.read()) >= 0) {
637: ops.update((byte) ch);
638: }
639:
640: PGPSignatureList p3 = (PGPSignatureList) pgpFact.nextObject();
641: PGPSignature sig = p3.get(0);
642:
643: Date creationTime = sig.getCreationTime();
644: Date now = new Date();
645:
646: // Check creationTime is recent
647: if (creationTime.after(now)
648: || creationTime.before(new Date(
649: now.getTime() - 10 * 60 * 1000))) {
650: fail("bad creation time in signature: " + creationTime);
651: }
652:
653: if (sig.getKeyID() != pubKey.getKeyID()) {
654: fail("key id mismatch in signature");
655: }
656:
657: if (!ops.verify(sig)) {
658: fail("Failed generated signature check - " + hashAlgorithm);
659: }
660:
661: sig.initVerify(pubKey, "BC");
662:
663: for (int i = 0; i != original.length; i++) {
664: sig.update(original[i]);
665: }
666:
667: sig.update(original);
668:
669: if (!sig.verify()) {
670: fail("Failed generated signature check against original data");
671: }
672: }
673:
674: public String getName() {
675: return "PGPSignatureTest";
676: }
677:
678: public static void main(String[] args) {
679: Security.addProvider(new BouncyCastleProvider());
680:
681: runTest(new PGPSignatureTest());
682: }
683: }
|