diff options
Diffstat (limited to 'libraries/spongycastle/pg/src/main/java/org/spongycastle/openpgp/examples/KeyBasedLargeFileProcessor.java')
-rw-r--r-- | libraries/spongycastle/pg/src/main/java/org/spongycastle/openpgp/examples/KeyBasedLargeFileProcessor.java | 283 |
1 files changed, 283 insertions, 0 deletions
diff --git a/libraries/spongycastle/pg/src/main/java/org/spongycastle/openpgp/examples/KeyBasedLargeFileProcessor.java b/libraries/spongycastle/pg/src/main/java/org/spongycastle/openpgp/examples/KeyBasedLargeFileProcessor.java new file mode 100644 index 000000000..8bcc9049c --- /dev/null +++ b/libraries/spongycastle/pg/src/main/java/org/spongycastle/openpgp/examples/KeyBasedLargeFileProcessor.java @@ -0,0 +1,283 @@ +package org.spongycastle.openpgp.examples; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +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.NoSuchProviderException; +import java.security.SecureRandom; +import java.security.Security; +import java.util.Iterator; + +import org.spongycastle.bcpg.ArmoredOutputStream; +import org.spongycastle.jce.provider.BouncyCastleProvider; +import org.spongycastle.openpgp.PGPCompressedData; +import org.spongycastle.openpgp.PGPCompressedDataGenerator; +import org.spongycastle.openpgp.PGPEncryptedData; +import org.spongycastle.openpgp.PGPEncryptedDataGenerator; +import org.spongycastle.openpgp.PGPEncryptedDataList; +import org.spongycastle.openpgp.PGPException; +import org.spongycastle.openpgp.PGPLiteralData; +import org.spongycastle.openpgp.PGPObjectFactory; +import org.spongycastle.openpgp.PGPOnePassSignatureList; +import org.spongycastle.openpgp.PGPPrivateKey; +import org.spongycastle.openpgp.PGPPublicKey; +import org.spongycastle.openpgp.PGPPublicKeyEncryptedData; +import org.spongycastle.openpgp.PGPSecretKeyRingCollection; +import org.spongycastle.openpgp.PGPUtil; +import org.spongycastle.openpgp.operator.jcajce.JcePGPDataEncryptorBuilder; +import org.spongycastle.openpgp.operator.jcajce.JcePublicKeyDataDecryptorFactoryBuilder; +import org.spongycastle.openpgp.operator.jcajce.JcePublicKeyKeyEncryptionMethodGenerator; +import org.spongycastle.util.io.Streams; + +/** + * A simple utility class that encrypts/decrypts public key based + * encryption large files. + * <p> + * To encrypt a file: KeyBasedLargeFileProcessor -e [-a|-ai] fileName publicKeyFile.<br> + * If -a is specified the output file will be "ascii-armored". + * If -i is specified the output file will be have integrity checking added. + * <p> + * To decrypt: KeyBasedLargeFileProcessor -d fileName secretKeyFile passPhrase. + * <p> + * Note 1: this example will silently overwrite files, nor does it pay any attention to + * the specification of "_CONSOLE" in the filename. It also expects that a single pass phrase + * will have been used. + * <p> + * Note 2: this example generates partial packets to encode the file, the output it generates + * will not be readable by older PGP products or products that don't support partial packet + * encoding. + * <p> + * Note 3: if an empty file name has been specified in the literal data object contained in the + * encrypted packet a file with the name filename.out will be generated in the current working directory. + */ +public class KeyBasedLargeFileProcessor +{ + private static void decryptFile( + String inputFileName, + String keyFileName, + char[] passwd, + String defaultFileName) + throws IOException, NoSuchProviderException + { + InputStream in = new BufferedInputStream(new FileInputStream(inputFileName)); + InputStream keyIn = new BufferedInputStream(new FileInputStream(keyFileName)); + decryptFile(in, keyIn, passwd, defaultFileName); + keyIn.close(); + in.close(); + } + + /** + * decrypt the passed in message stream + */ + private static void decryptFile( + InputStream in, + InputStream keyIn, + char[] passwd, + String defaultFileName) + throws IOException, NoSuchProviderException + { + in = PGPUtil.getDecoderStream(in); + + try + { + PGPObjectFactory pgpF = new PGPObjectFactory(in); + PGPEncryptedDataList enc; + + Object o = pgpF.nextObject(); + // + // the first object might be a PGP marker packet. + // + if (o instanceof PGPEncryptedDataList) + { + enc = (PGPEncryptedDataList)o; + } + else + { + enc = (PGPEncryptedDataList)pgpF.nextObject(); + } + + // + // find the secret key + // + Iterator it = enc.getEncryptedDataObjects(); + PGPPrivateKey sKey = null; + PGPPublicKeyEncryptedData pbe = null; + PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection( + PGPUtil.getDecoderStream(keyIn)); + + while (sKey == null && it.hasNext()) + { + pbe = (PGPPublicKeyEncryptedData)it.next(); + + sKey = PGPExampleUtil.findSecretKey(pgpSec, pbe.getKeyID(), passwd); + } + + if (sKey == null) + { + throw new IllegalArgumentException("secret key for message not found."); + } + + InputStream clear = pbe.getDataStream(new JcePublicKeyDataDecryptorFactoryBuilder().setProvider("SC").build(sKey)); + + PGPObjectFactory plainFact = new PGPObjectFactory(clear); + + PGPCompressedData cData = (PGPCompressedData)plainFact.nextObject(); + + InputStream compressedStream = new BufferedInputStream(cData.getDataStream()); + PGPObjectFactory pgpFact = new PGPObjectFactory(compressedStream); + + Object message = pgpFact.nextObject(); + + if (message instanceof PGPLiteralData) + { + PGPLiteralData ld = (PGPLiteralData)message; + + String outFileName = ld.getFileName(); + if (outFileName.length() == 0) + { + outFileName = defaultFileName; + } + + InputStream unc = ld.getInputStream(); + OutputStream fOut = new BufferedOutputStream(new FileOutputStream(outFileName)); + + Streams.pipeAll(unc, fOut); + + fOut.close(); + } + else if (message instanceof PGPOnePassSignatureList) + { + throw new PGPException("encrypted message contains a signed message - not literal data."); + } + else + { + throw new PGPException("message is not a simple encrypted file - type unknown."); + } + + if (pbe.isIntegrityProtected()) + { + if (!pbe.verify()) + { + System.err.println("message failed integrity check"); + } + else + { + System.err.println("message integrity check passed"); + } + } + else + { + System.err.println("no message integrity check"); + } + } + catch (PGPException e) + { + System.err.println(e); + if (e.getUnderlyingException() != null) + { + e.getUnderlyingException().printStackTrace(); + } + } + } + + private static void encryptFile( + String outputFileName, + String inputFileName, + String encKeyFileName, + boolean armor, + boolean withIntegrityCheck) + throws IOException, NoSuchProviderException, PGPException + { + OutputStream out = new BufferedOutputStream(new FileOutputStream(outputFileName)); + PGPPublicKey encKey = PGPExampleUtil.readPublicKey(encKeyFileName); + encryptFile(out, inputFileName, encKey, armor, withIntegrityCheck); + out.close(); + } + + private static void encryptFile( + OutputStream out, + String fileName, + PGPPublicKey encKey, + boolean armor, + boolean withIntegrityCheck) + throws IOException, NoSuchProviderException + { + if (armor) + { + out = new ArmoredOutputStream(out); + } + + try + { + PGPEncryptedDataGenerator cPk = new PGPEncryptedDataGenerator(new JcePGPDataEncryptorBuilder(PGPEncryptedData.CAST5).setWithIntegrityPacket(withIntegrityCheck).setSecureRandom(new SecureRandom()).setProvider("SC")); + + cPk.addMethod(new JcePublicKeyKeyEncryptionMethodGenerator(encKey).setProvider("SC")); + + OutputStream cOut = cPk.open(out, new byte[1 << 16]); + + PGPCompressedDataGenerator comData = new PGPCompressedDataGenerator( + PGPCompressedData.ZIP); + + PGPUtil.writeFileToLiteralData(comData.open(cOut), PGPLiteralData.BINARY, new File(fileName), new byte[1 << 16]); + + comData.close(); + + cOut.close(); + + if (armor) + { + out.close(); + } + } + catch (PGPException e) + { + System.err.println(e); + if (e.getUnderlyingException() != null) + { + e.getUnderlyingException().printStackTrace(); + } + } + } + + public static void main( + String[] args) + throws Exception + { + Security.addProvider(new BouncyCastleProvider()); + + if (args.length == 0) + { + System.err.println("usage: KeyBasedLargeFileProcessor -e|-d [-a|ai] file [secretKeyFile passPhrase|pubKeyFile]"); + return; + } + + if (args[0].equals("-e")) + { + if (args[1].equals("-a") || args[1].equals("-ai") || args[1].equals("-ia")) + { + encryptFile(args[2] + ".asc", args[2], args[3], true, (args[1].indexOf('i') > 0)); + } + else if (args[1].equals("-i")) + { + encryptFile(args[2] + ".bpg", args[2], args[3], false, true); + } + else + { + encryptFile(args[1] + ".bpg", args[1], args[2], false, false); + } + } + else if (args[0].equals("-d")) + { + decryptFile(args[1], args[2], args[3].toCharArray(), new File(args[1]).getName() + ".out"); + } + else + { + System.err.println("usage: KeyBasedLargeFileProcessor -d|-e [-a|ai] file [secretKeyFile passPhrase|pubKeyFile]"); + } + } +} |