001: package org.bouncycastle.openpgp.examples;
002:
003: import java.io.FileInputStream;
004: import java.io.FileOutputStream;
005: import java.io.IOException;
006: import java.io.InputStream;
007: import java.io.OutputStream;
008: import java.security.NoSuchAlgorithmException;
009: import java.security.NoSuchProviderException;
010: import java.security.Security;
011: import java.security.SignatureException;
012: import java.util.Iterator;
013:
014: import org.bouncycastle.bcpg.ArmoredOutputStream;
015: import org.bouncycastle.bcpg.BCPGOutputStream;
016:
017: import org.bouncycastle.jce.provider.BouncyCastleProvider;
018: import org.bouncycastle.openpgp.PGPException;
019: import org.bouncycastle.openpgp.PGPCompressedData;
020: import org.bouncycastle.openpgp.PGPObjectFactory;
021: import org.bouncycastle.openpgp.PGPPrivateKey;
022: import org.bouncycastle.openpgp.PGPPublicKey;
023: import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
024: import org.bouncycastle.openpgp.PGPSecretKey;
025: import org.bouncycastle.openpgp.PGPSecretKeyRing;
026: import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
027: import org.bouncycastle.openpgp.PGPSignature;
028: import org.bouncycastle.openpgp.PGPSignatureGenerator;
029: import org.bouncycastle.openpgp.PGPSignatureList;
030: import org.bouncycastle.openpgp.PGPUtil;
031:
032: /**
033: * A simple utility class that creates seperate signatures for files and verifies them.
034: * <p>
035: * To sign a file: DetachedSignatureProcessor -s [-a] fileName secretKey passPhrase.<br>
036: * If -a is specified the output file will be "ascii-armored".
037: * <p>
038: * To decrypt: DetachedSignatureProcessor -v fileName signatureFile publicKeyFile.
039: * <p>
040: * Note: this example will silently overwrite files.
041: * It also expects that a single pass phrase
042: * will have been used.
043: */
044: public class DetachedSignatureProcessor {
045: /**
046: * A simple routine that opens a key ring file and loads the first available key suitable for
047: * signature generation.
048: *
049: * @param in
050: * @return
051: * @throws IOException
052: * @throws PGPException
053: */
054: private static PGPSecretKey readSecretKey(InputStream in)
055: throws IOException, PGPException {
056: in = PGPUtil.getDecoderStream(in);
057:
058: PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(
059: in);
060:
061: //
062: // we just loop through the collection till we find a key suitable for encryption, in the real
063: // world you would probably want to be a bit smarter about this.
064: //
065: PGPSecretKey key = null;
066:
067: //
068: // iterate through the key rings.
069: //
070: Iterator rIt = pgpSec.getKeyRings();
071:
072: while (key == null && rIt.hasNext()) {
073: PGPSecretKeyRing kRing = (PGPSecretKeyRing) rIt.next();
074: Iterator kIt = kRing.getSecretKeys();
075:
076: while (key == null && kIt.hasNext()) {
077: PGPSecretKey k = (PGPSecretKey) kIt.next();
078:
079: if (k.isSigningKey()) {
080: key = k;
081: }
082: }
083: }
084:
085: if (key == null) {
086: throw new IllegalArgumentException(
087: "Can't find encryption key in key ring.");
088: }
089:
090: return key;
091: }
092:
093: /**
094: * verify the signature in in against the file fileName.
095: */
096: private static void verifySignature(String fileName,
097: InputStream in, InputStream keyIn) throws Exception {
098: in = PGPUtil.getDecoderStream(in);
099:
100: PGPObjectFactory pgpFact = new PGPObjectFactory(in);
101: PGPSignatureList p3 = null;
102:
103: Object o = pgpFact.nextObject();
104: if (o instanceof PGPCompressedData) {
105: PGPCompressedData c1 = (PGPCompressedData) o;
106:
107: pgpFact = new PGPObjectFactory(c1.getDataStream());
108:
109: p3 = (PGPSignatureList) pgpFact.nextObject();
110: } else {
111: p3 = (PGPSignatureList) o;
112: }
113:
114: PGPPublicKeyRingCollection pgpPubRingCollection = new PGPPublicKeyRingCollection(
115: PGPUtil.getDecoderStream(keyIn));
116:
117: InputStream dIn = new FileInputStream(fileName);
118: int ch;
119:
120: PGPSignature sig = p3.get(0);
121: PGPPublicKey key = pgpPubRingCollection.getPublicKey(sig
122: .getKeyID());
123:
124: sig.initVerify(key, "BC");
125:
126: while ((ch = dIn.read()) >= 0) {
127: sig.update((byte) ch);
128: }
129:
130: if (sig.verify()) {
131: System.out.println("signature verified.");
132: } else {
133: System.out.println("signature verification failed.");
134: }
135: }
136:
137: private static void createSignature(String fileName,
138: InputStream keyIn, OutputStream out, char[] pass,
139: boolean armor) throws IOException,
140: NoSuchAlgorithmException, NoSuchProviderException,
141: PGPException, SignatureException {
142: if (armor) {
143: out = new ArmoredOutputStream(out);
144: }
145:
146: PGPSecretKey pgpSec = readSecretKey(keyIn);
147: PGPPrivateKey pgpPrivKey = pgpSec.extractPrivateKey(pass, "BC");
148: PGPSignatureGenerator sGen = new PGPSignatureGenerator(pgpSec
149: .getPublicKey().getAlgorithm(), PGPUtil.SHA1, "BC");
150:
151: sGen.initSign(PGPSignature.BINARY_DOCUMENT, pgpPrivKey);
152:
153: BCPGOutputStream bOut = new BCPGOutputStream(out);
154:
155: FileInputStream fIn = new FileInputStream(fileName);
156: int ch = 0;
157:
158: while ((ch = fIn.read()) >= 0) {
159: sGen.update((byte) ch);
160: }
161:
162: sGen.generate().encode(bOut);
163:
164: out.close();
165: }
166:
167: public static void main(String[] args) throws Exception {
168: Security.addProvider(new BouncyCastleProvider());
169:
170: if (args[0].equals("-s")) {
171: if (args[1].equals("-a")) {
172: FileInputStream keyIn = new FileInputStream(args[3]);
173: FileOutputStream out = new FileOutputStream(args[2]
174: + ".asc");
175:
176: createSignature(args[2], keyIn, out, args[4]
177: .toCharArray(), true);
178: } else {
179: FileInputStream keyIn = new FileInputStream(args[2]);
180: FileOutputStream out = new FileOutputStream(args[1]
181: + ".bpg");
182:
183: createSignature(args[1], keyIn, out, args[3]
184: .toCharArray(), false);
185: }
186: } else if (args[0].equals("-v")) {
187: FileInputStream in = new FileInputStream(args[2]);
188: FileInputStream keyIn = new FileInputStream(args[3]);
189:
190: verifySignature(args[1], in, keyIn);
191: } else {
192: System.err
193: .println("usage: DetachedSignatureProcessor [-s [-a] file keyfile passPhrase]|[-v file sigFile keyFile]");
194: }
195: }
196: }
|