diff --git a/pg/src/main/java/org/bouncycastle/bcpg/ArmoredOutputStream.java b/pg/src/main/java/org/bouncycastle/bcpg/ArmoredOutputStream.java index 9e51fa1233..5233d1a2d5 100644 --- a/pg/src/main/java/org/bouncycastle/bcpg/ArmoredOutputStream.java +++ b/pg/src/main/java/org/bouncycastle/bcpg/ArmoredOutputStream.java @@ -6,7 +6,7 @@ import java.util.Hashtable; /** - * Basic output stream. + * Output stream that writes data in ASCII Armored format. */ public class ArmoredOutputStream extends OutputStream @@ -84,7 +84,7 @@ private void encode( boolean start = true; boolean clearText = false; boolean newLine = false; - + String nl = System.getProperty("line.separator"); String type; @@ -94,22 +94,34 @@ private void encode( String footerTail = "-----"; String version = "BCPG v@RELEASE_NAME@"; - + Hashtable headers = new Hashtable(); - + + /** + * Constructs an armored output stream with {@link #resetHeaders() default headers}. + * + * @param out the OutputStream to wrap. + */ public ArmoredOutputStream( OutputStream out) { this.out = out; - + if (nl == null) { nl = "\r\n"; } - + resetHeaders(); } - + + /** + * Constructs an armored output stream with default and custom headers. + * + * @param out the OutputStream to wrap. + * @param headers additional headers that add to or override the {@link #resetHeaders() default + * headers}. + */ public ArmoredOutputStream( OutputStream out, Hashtable headers) @@ -117,18 +129,18 @@ public ArmoredOutputStream( this(out); Enumeration e = headers.keys(); - + while (e.hasMoreElements()) { Object key = e.nextElement(); - + this.headers.put(key, headers.get(key)); } } - + /** * Set an additional header entry. - * + * * @param name the name of the header entry. * @param value the value of the header entry. */ @@ -138,7 +150,7 @@ public void setHeader( { this.headers.put(name, value); } - + /** * Reset the headers to only contain a Version string. */ @@ -147,17 +159,17 @@ public void resetHeaders() headers.clear(); headers.put("Version", version); } - + /** * Start a clear text signed message. * @param hashAlgorithm */ public void beginClearText( - int hashAlgorithm) + int hashAlgorithm) throws IOException { String hash; - + switch (hashAlgorithm) { case HashAlgorithmTags.SHA1: @@ -184,43 +196,43 @@ public void beginClearText( default: throw new IOException("unknown hash algorithm tag in beginClearText: " + hashAlgorithm); } - + String armorHdr = "-----BEGIN PGP SIGNED MESSAGE-----" + nl; String hdrs = "Hash: " + hash + nl + nl; - + for (int i = 0; i != armorHdr.length(); i++) { out.write(armorHdr.charAt(i)); } - + for (int i = 0; i != hdrs.length(); i++) { out.write(hdrs.charAt(i)); } - + clearText = true; newLine = true; lastb = 0; } - + public void endClearText() { clearText = false; } - + private void writeHeaderEntry( String name, - String value) + String value) throws IOException { for (int i = 0; i != name.length(); i++) { out.write(name.charAt(i)); } - + out.write(':'); out.write(' '); - + for (int i = 0; i != value.length(); i++) { out.write(value.charAt(i)); @@ -231,7 +243,7 @@ private void writeHeaderEntry( out.write(nl.charAt(i)); } } - + public void write( int b) throws IOException @@ -259,12 +271,12 @@ public void write( lastb = b; return; } - + if (start) { boolean newPacket = (b & 0x40) != 0; int tag = 0; - + if (newPacket) { tag = b & 0x3f; @@ -288,7 +300,7 @@ public void write( default: type = "MESSAGE"; } - + for (int i = 0; i != headerStart.length(); i++) { out.write(headerStart.charAt(i)); @@ -308,20 +320,20 @@ public void write( { out.write(nl.charAt(i)); } - + writeHeaderEntry("Version", (String)headers.get("Version")); Enumeration e = headers.keys(); while (e.hasMoreElements()) { String key = (String)e.nextElement(); - + if (!key.equals("Version")) { writeHeaderEntry(key, (String)headers.get(key)); } } - + for (int i = 0; i != nl.length(); i++) { out.write(nl.charAt(i)); @@ -346,12 +358,12 @@ public void write( crc.update(b); buf[bufPtr++] = b & 0xff; } - + public void flush() throws IOException { } - + /** * Note: close does nor close the underlying stream. So it is possible to write * multiple objects using armoring to a single stream. @@ -362,48 +374,48 @@ public void close() if (type != null) { encode(out, buf, bufPtr); - + for (int i = 0; i != nl.length(); i++) { out.write(nl.charAt(i)); } out.write('='); - + int crcV = crc.getValue(); - + buf[0] = ((crcV >> 16) & 0xff); buf[1] = ((crcV >> 8) & 0xff); buf[2] = (crcV & 0xff); - + encode(out, buf, 3); - + for (int i = 0; i != nl.length(); i++) { out.write(nl.charAt(i)); } - + for (int i = 0; i != footerStart.length(); i++) { out.write(footerStart.charAt(i)); } - + for (int i = 0; i != type.length(); i++) { out.write(type.charAt(i)); } - + for (int i = 0; i != footerTail.length(); i++) { out.write(footerTail.charAt(i)); } - + for (int i = 0; i != nl.length(); i++) { out.write(nl.charAt(i)); } - + out.flush(); - + type = null; start = true; } diff --git a/pg/src/main/java/org/bouncycastle/bcpg/BCPGInputStream.java b/pg/src/main/java/org/bouncycastle/bcpg/BCPGInputStream.java index 1e2e072350..bc7cb802bd 100644 --- a/pg/src/main/java/org/bouncycastle/bcpg/BCPGInputStream.java +++ b/pg/src/main/java/org/bouncycastle/bcpg/BCPGInputStream.java @@ -7,7 +7,7 @@ import org.bouncycastle.util.io.Streams; /** - * reader for PGP objects + * Stream reader for PGP objects */ public class BCPGInputStream extends InputStream implements PacketTags @@ -15,19 +15,19 @@ public class BCPGInputStream InputStream in; boolean next = false; int nextB; - + public BCPGInputStream( InputStream in) { this.in = in; } - + public int available() throws IOException { return in.available(); } - + public int read() throws IOException { @@ -98,11 +98,11 @@ public void readFully( } /** - * returns the next packet tag in the stream. - * - * @return the tag number. - * - * @throws IOException + * Obtains the tag of the next packet in the stream. + * + * @return the {@link PacketTags tag number}. + * + * @throws IOException if an error occurs reading the tag from the stream. */ public int nextPacketTag() throws IOException @@ -117,8 +117,8 @@ public int nextPacketTag() { nextB = -1; } - } - + } + next = true; if (nextB >= 0) @@ -132,20 +132,24 @@ public int nextPacketTag() return ((nextB & 0x3f) >> 2); } } - + return nextB; } + /** + * Reads the next packet from the stream. + * @throws IOException + */ public Packet readPacket() throws IOException { int hdr = this.read(); - + if (hdr < 0) { return null; } - + if ((hdr & 0x80) == 0) { throw new IOException("invalid header encountered"); @@ -155,11 +159,11 @@ public Packet readPacket() int tag = 0; int bodyLen = 0; boolean partial = false; - + if (newPacket) { tag = hdr & 0x3f; - + int l = this.read(); if (l < 192) @@ -185,7 +189,7 @@ else if (l == 255) else { int lengthType = hdr & 0x3; - + tag = (hdr & 0x3f) >> 2; switch (lengthType) @@ -208,7 +212,7 @@ else if (l == 255) } BCPGInputStream objStream; - + if (bodyLen == 0 && partial) { objStream = this; @@ -265,13 +269,13 @@ else if (l == 255) throw new IOException("unknown packet type encountered: " + tag); } } - + public void close() throws IOException { in.close(); } - + /** * a stream that overlays our input stream, allowing the user to only read a segment of it. * @@ -317,12 +321,12 @@ private int loadDataLength() throws IOException { int l = in.read(); - + if (l < 0) { return -1; } - + partial = false; if (l < 192) { @@ -341,10 +345,10 @@ else if (l == 255) partial = true; dataLength = 1 << (l & 0x1f); } - + return dataLength; } - + public int read(byte[] buf, int offset, int len) throws IOException { @@ -366,7 +370,7 @@ public int read(byte[] buf, int offset, int len) return -1; } - + public int read() throws IOException { diff --git a/pg/src/main/java/org/bouncycastle/bcpg/BCPGObject.java b/pg/src/main/java/org/bouncycastle/bcpg/BCPGObject.java index 7b05d8a87b..1018f189d1 100644 --- a/pg/src/main/java/org/bouncycastle/bcpg/BCPGObject.java +++ b/pg/src/main/java/org/bouncycastle/bcpg/BCPGObject.java @@ -4,21 +4,21 @@ import java.io.IOException; /** - * base class for a PGP object. + * Base class for a PGP object. */ -public abstract class BCPGObject +public abstract class BCPGObject { - public byte[] getEncoded() + public byte[] getEncoded() throws IOException { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); BCPGOutputStream pOut = new BCPGOutputStream(bOut); - + pOut.writeObject(this); - + return bOut.toByteArray(); } - + public abstract void encode(BCPGOutputStream out) throws IOException; } diff --git a/pg/src/main/java/org/bouncycastle/bcpg/CompressedDataPacket.java b/pg/src/main/java/org/bouncycastle/bcpg/CompressedDataPacket.java index 0b4005918c..7239d91eec 100644 --- a/pg/src/main/java/org/bouncycastle/bcpg/CompressedDataPacket.java +++ b/pg/src/main/java/org/bouncycastle/bcpg/CompressedDataPacket.java @@ -3,26 +3,26 @@ import java.io.IOException; /** - * generic compressed data object. + * A generic compressed data object. */ -public class CompressedDataPacket +public class CompressedDataPacket extends InputStreamPacket { int algorithm; - + CompressedDataPacket( BCPGInputStream in) throws IOException { super(in); - - algorithm = in.read(); + + algorithm = in.read(); } - + /** - * return the algorithm tag value. + * Gets the {@link CompressionAlgorithmTags compression algorithm} used for this packet. * - * @return algorithm tag value. + * @return the compression algorithm tag value. */ public int getAlgorithm() { diff --git a/pg/src/main/java/org/bouncycastle/bcpg/CompressionAlgorithmTags.java b/pg/src/main/java/org/bouncycastle/bcpg/CompressionAlgorithmTags.java index 5b684cf076..0e947d543f 100644 --- a/pg/src/main/java/org/bouncycastle/bcpg/CompressionAlgorithmTags.java +++ b/pg/src/main/java/org/bouncycastle/bcpg/CompressionAlgorithmTags.java @@ -3,10 +3,17 @@ /** * Basic tags for compression algorithms */ -public interface CompressionAlgorithmTags +public interface CompressionAlgorithmTags { - public static final int UNCOMPRESSED = 0; // Uncompressed - public static final int ZIP = 1; // ZIP (RFC 1951) - public static final int ZLIB = 2; // ZLIB (RFC 1950) - public static final int BZIP2 = 3; // BZ2 + /** No compression. */ + public static final int UNCOMPRESSED = 0; + + /** ZIP (RFC 1951) compression. Unwrapped DEFLATE. */ + public static final int ZIP = 1; + + /** ZLIB (RFC 1950) compression. DEFLATE with a wrapper for better error detection. */ + public static final int ZLIB = 2; + + /** BZIP2 compression. Better compression than ZIP but much slower to compress and decompress. */ + public static final int BZIP2 = 3; } diff --git a/pg/src/main/java/org/bouncycastle/bcpg/InputStreamPacket.java b/pg/src/main/java/org/bouncycastle/bcpg/InputStreamPacket.java index 411fa475d4..9073a2e8e9 100644 --- a/pg/src/main/java/org/bouncycastle/bcpg/InputStreamPacket.java +++ b/pg/src/main/java/org/bouncycastle/bcpg/InputStreamPacket.java @@ -1,23 +1,25 @@ package org.bouncycastle.bcpg; /** - * + * A block of data associated with other packets in a PGP object stream. */ public class InputStreamPacket extends Packet { private BCPGInputStream in; - + public InputStreamPacket( BCPGInputStream in) { this.in = in; } - + /** + * Obtains an input stream to read the contents of the packet. + *

* Note: you can only read from this once... * - * @return the InputStream + * @return the data in this packet. */ public BCPGInputStream getInputStream() { diff --git a/pg/src/main/java/org/bouncycastle/bcpg/LiteralDataPacket.java b/pg/src/main/java/org/bouncycastle/bcpg/LiteralDataPacket.java index b660ce798b..b57c8bdecc 100644 --- a/pg/src/main/java/org/bouncycastle/bcpg/LiteralDataPacket.java +++ b/pg/src/main/java/org/bouncycastle/bcpg/LiteralDataPacket.java @@ -2,27 +2,28 @@ import java.io.IOException; +import org.bouncycastle.util.Arrays; import org.bouncycastle.util.Strings; /** - * generic literal data packet. + * Generic literal data packet. */ -public class LiteralDataPacket +public class LiteralDataPacket extends InputStreamPacket { int format; byte[] fileName; long modDate; - + LiteralDataPacket( BCPGInputStream in) throws IOException { super(in); - - format = in.read(); + + format = in.read(); int l = in.read(); - + fileName = new byte[l]; for (int i = 0; i != fileName.length; i++) { @@ -31,11 +32,9 @@ public class LiteralDataPacket modDate = ((long)in.read() << 24) | (in.read() << 16) | (in.read() << 8) | in.read(); } - + /** - * return the format tag value. - * - * @return format tag value. + * Return the format tag of the data packet. */ public int getFormat() { @@ -43,32 +42,26 @@ public int getFormat() } /** - * Return the modification time of the file in milli-seconds. - * - * @return the modification time in millis + * Return the modification time for the file (milliseconds at second level precision). */ public long getModificationTime() { return modDate * 1000L; } - + /** - * @return filename + * Return the file name associated with the data packet. */ public String getFileName() { return Strings.fromUTF8ByteArray(fileName); } + /** + * Return the file name as an uninterpreted byte array. + */ public byte[] getRawFileName() { - byte[] tmp = new byte[fileName.length]; - - for (int i = 0; i != tmp.length; i++) - { - tmp[i] = fileName[i]; - } - - return tmp; + return Arrays.clone(fileName); } } diff --git a/pg/src/main/java/org/bouncycastle/bcpg/S2K.java b/pg/src/main/java/org/bouncycastle/bcpg/S2K.java index 167e7155a2..389814f7a5 100644 --- a/pg/src/main/java/org/bouncycastle/bcpg/S2K.java +++ b/pg/src/main/java/org/bouncycastle/bcpg/S2K.java @@ -4,34 +4,44 @@ import java.io.IOException; import java.io.InputStream; + /** - * The string to key specifier class + * Parameter specifier for the PGP string-to-key password based key derivation function. + *

+ * In iterated mode, S2K takes a single byte iteration count specifier, which is converted to an + * actual iteration count using a formula that grows the iteration count exponentially as the byte + * value increases.
+ * e.g. 0x01 == 1088 iterations, and 0xFF == 65,011,712 iterations. */ -public class S2K +public class S2K extends BCPGObject { private static final int EXPBIAS = 6; - + + /** Simple key generation. A single non-salted iteration of a hash function */ public static final int SIMPLE = 0; + /** Salted key generation. A single iteration of a hash function with a (unique) salt */ public static final int SALTED = 1; + /** Salted and iterated key generation. Multiple iterations of a hash function, with a salt */ public static final int SALTED_AND_ITERATED = 3; + public static final int GNU_DUMMY_S2K = 101; - + int type; int algorithm; byte[] iv; int itCount = -1; int protectionMode = -1; - + S2K( InputStream in) throws IOException { DataInputStream dIn = new DataInputStream(in); - + type = dIn.read(); algorithm = dIn.read(); - + // // if this happens we have a dummy-S2K packet. // @@ -56,14 +66,25 @@ public class S2K protectionMode = dIn.read(); // protection mode } } - + + /** + * Constructs a specifier for a {@link #SIMPLE simple} S2K generation. + * + * @param algorithm the {@link HashAlgorithmTags digest algorithm} to use. + */ public S2K( int algorithm) { this.type = 0; this.algorithm = algorithm; } - + + /** + * Constructs a specifier for a {@link #SALTED salted} S2K generation. + * + * @param algorithm the {@link HashAlgorithmTags digest algorithm} to use. + * @param iv the salt to apply to input to the key generation. + */ public S2K( int algorithm, byte[] iv) @@ -73,6 +94,13 @@ public S2K( this.iv = iv; } + /** + * Constructs a specifier for a {@link #SALTED_AND_ITERATED salted and iterated} S2K generation. + * + * @param algorithm the {@link HashAlgorithmTags digest algorithm} to iterate. + * @param iv the salt to apply to input to the key generation. + * @param itCount the single byte iteration count specifier. + */ public S2K( int algorithm, byte[] iv, @@ -83,58 +111,61 @@ public S2K( this.iv = iv; this.itCount = itCount; } - + + /** + * Gets the {@link HashAlgorithmTags digest algorithm} specified. + */ public int getType() { return type; } - + /** - * return the hash algorithm for this S2K + * Gets the {@link HashAlgorithmTags hash algorithm} for this S2K. */ public int getHashAlgorithm() { return algorithm; } - + /** - * return the iv for the key generation algorithm + * Gets the iv/salt to use for the key generation. */ public byte[] getIV() { return iv; } - + /** - * return the iteration count + * Gets the actual (expanded) iteration count. */ public long getIterationCount() { return (16 + (itCount & 15)) << ((itCount >> 4) + EXPBIAS); } - + /** - * the protection mode - only if GNU_DUMMY_S2K + * Gets the protection mode - only if GNU_DUMMY_S2K */ public int getProtectionMode() { return protectionMode; } - + public void encode( BCPGOutputStream out) throws IOException { out.write(type); out.write(algorithm); - + if (type != GNU_DUMMY_S2K) { if (type != 0) { out.write(iv); } - + if (type == 3) { out.write(itCount); diff --git a/pg/src/main/java/org/bouncycastle/bcpg/SymmetricEncIntegrityPacket.java b/pg/src/main/java/org/bouncycastle/bcpg/SymmetricEncIntegrityPacket.java index edf6e2adbe..8e8fac6653 100644 --- a/pg/src/main/java/org/bouncycastle/bcpg/SymmetricEncIntegrityPacket.java +++ b/pg/src/main/java/org/bouncycastle/bcpg/SymmetricEncIntegrityPacket.java @@ -3,18 +3,19 @@ import java.io.IOException; /** + * A symmetric key encrypted packet with an associated integrity check code. */ -public class SymmetricEncIntegrityPacket +public class SymmetricEncIntegrityPacket extends InputStreamPacket -{ +{ int version; - + SymmetricEncIntegrityPacket( BCPGInputStream in) throws IOException { super(in); - + version = in.read(); } } diff --git a/pg/src/main/java/org/bouncycastle/openpgp/PGPCompressedData.java b/pg/src/main/java/org/bouncycastle/openpgp/PGPCompressedData.java index 4f13a98fb6..a609b5b356 100644 --- a/pg/src/main/java/org/bouncycastle/openpgp/PGPCompressedData.java +++ b/pg/src/main/java/org/bouncycastle/openpgp/PGPCompressedData.java @@ -6,52 +6,62 @@ import java.util.zip.Inflater; import java.util.zip.InflaterInputStream; +import org.bouncycastle.apache.bzip2.CBZip2InputStream; import org.bouncycastle.bcpg.BCPGInputStream; import org.bouncycastle.bcpg.CompressedDataPacket; import org.bouncycastle.bcpg.CompressionAlgorithmTags; -import org.bouncycastle.apache.bzip2.CBZip2InputStream; +import org.bouncycastle.bcpg.PacketTags; /** - * Compressed data objects. + * A PGP compressed data object. */ -public class PGPCompressedData +public class PGPCompressedData implements CompressionAlgorithmTags { CompressedDataPacket data; - + + /** + * Construct a compressed data object, reading a single {@link PacketTags#COMPRESSED_DATA} + * packet from the stream. + * + * @param pIn a PGP input stream, with a compressed data packet as the current packet. + * @throws IOException if an error occurs reading the packet from the stream. + */ public PGPCompressedData( BCPGInputStream pIn) throws IOException { data = (CompressedDataPacket)pIn.readPacket(); } - + /** - * Return the algorithm used for compression - * - * @return algorithm code + * Return the {@link CompressionAlgorithmTags compression algorithm} used for this packet. + * + * @return the compression algorithm code */ public int getAlgorithm() { return data.getAlgorithm(); } - + /** * Return the raw input stream contained in the object. - * - * @return InputStream + *

+ * Note that this stream is shared with the decompression stream, so consuming the returned + * stream will affect decompression. + * + * @return the raw data in the compressed data packet. */ public InputStream getInputStream() { return data.getInputStream(); } - + /** - * Return an uncompressed input stream which allows reading of the - * compressed data. - * - * @return InputStream - * @throws PGPException + * Return an input stream that decompresses and returns data in the compressed packet. + * + * @return a stream over the uncompressed data. + * @throws PGPException if an error occurs constructing the decompression stream. */ public InputStream getDataStream() throws PGPException @@ -62,9 +72,9 @@ public InputStream getDataStream() } if (this.getAlgorithm() == ZIP) { - return new InflaterInputStream(this.getInputStream(), new Inflater(true)) + return new InflaterInputStream(this.getInputStream(), new Inflater(true)) { - // If the "nowrap" inflater option is used the stream can + // If the "nowrap" inflater option is used the stream can // apparently overread - we override fill() and provide // an extra byte for the end of the input stream to get // around this. @@ -77,16 +87,16 @@ protected void fill() throws IOException { throw new EOFException("Unexpected end of ZIP input stream"); } - + len = this.in.read(buf, 0, buf.length); - + if (len == -1) { buf[0] = 0; len = 1; eof = true; } - + inf.setInput(buf, 0, len); } @@ -97,7 +107,7 @@ protected void fill() throws IOException { return new InflaterInputStream(this.getInputStream()) { - // If the "nowrap" inflater option is used the stream can + // If the "nowrap" inflater option is used the stream can // apparently overread - we override fill() and provide // an extra byte for the end of the input stream to get // around this. @@ -110,9 +120,9 @@ protected void fill() throws IOException { throw new EOFException("Unexpected end of ZIP input stream"); } - + len = this.in.read(buf, 0, buf.length); - + if (len == -1) { buf[0] = 0; @@ -137,7 +147,7 @@ protected void fill() throws IOException throw new PGPException("I/O problem with stream: " + e, e); } } - + throw new PGPException("can't recognise compression algorithm: " + this.getAlgorithm()); } } diff --git a/pg/src/main/java/org/bouncycastle/openpgp/PGPCompressedDataGenerator.java b/pg/src/main/java/org/bouncycastle/openpgp/PGPCompressedDataGenerator.java index 4a3ebaf66b..e680a02ad3 100644 --- a/pg/src/main/java/org/bouncycastle/openpgp/PGPCompressedDataGenerator.java +++ b/pg/src/main/java/org/bouncycastle/openpgp/PGPCompressedDataGenerator.java @@ -1,19 +1,40 @@ package org.bouncycastle.openpgp; -import org.bouncycastle.apache.bzip2.CBZip2OutputStream; -import org.bouncycastle.bcpg.BCPGOutputStream; -import org.bouncycastle.bcpg.CompressionAlgorithmTags; -import org.bouncycastle.bcpg.PacketTags; - import java.io.IOException; import java.io.OutputStream; import java.util.zip.Deflater; import java.util.zip.DeflaterOutputStream; +import org.bouncycastle.apache.bzip2.CBZip2OutputStream; +import org.bouncycastle.bcpg.BCPGOutputStream; +import org.bouncycastle.bcpg.CompressionAlgorithmTags; +import org.bouncycastle.bcpg.PacketTags; + /** - *class for producing compressed data packets. + * Generator for producing compressed data packets. + *

+ * A PGPCompressedDataGenerator is used by invoking one of the open functions to create an + * OutputStream that raw data can be supplied to for compression: + *

+ *

+ * A PGPCompressedDataGenerator is usually used to wrap the OutputStream + * {@link PGPEncryptedDataGenerator#open(OutputStream, byte[]) obtained} from a + * {@link PGPEncryptedDataGenerator} (i.e. to compress data prior to encrypting it). + *

+ * Raw data is not typically written directly to the OutputStream obtained from a + * PGPCompressedDataGenerator. The OutputStream is usually wrapped by a + * {@link PGPLiteralDataGenerator}, which encodes the raw data prior to compression. + *

+ * Once data for compression has been written to the constructed OutputStream, writing of the object + * stream is completed by closing the OutputStream obtained from the open() method, or + * equivalently invoking {@link #close()} on this generator. */ -public class PGPCompressedDataGenerator +public class PGPCompressedDataGenerator implements CompressionAlgorithmTags, StreamGenerator { private int algorithm; @@ -21,13 +42,26 @@ public class PGPCompressedDataGenerator private OutputStream dOut; private BCPGOutputStream pkOut; - + + /** + * Construct a new compressed data generator. + * + * @param algorithm the identifier of the {@link CompressionAlgorithmTags compression algorithm} + * to use. + */ public PGPCompressedDataGenerator( int algorithm) { this(algorithm, Deflater.DEFAULT_COMPRESSION); } - + + /** + * Construct a new compressed data generator. + * + * @param algorithm the identifier of the {@link CompressionAlgorithmTags compression algorithm} + * to use. + * @param compression the {@link Deflater} compression level to use. + */ public PGPCompressedDataGenerator( int algorithm, int compression) @@ -56,17 +90,17 @@ public PGPCompressedDataGenerator( } /** - * Return an OutputStream which will save the data being written to + * Return an OutputStream which will save the data being written to * the compressed object. *

* The stream created can be closed off by either calling close() * on the stream or close() on the generator. Closing the returned * stream does not close off the OutputStream parameter out. - * + * * @param out underlying OutputStream to be used. * @return OutputStream * @throws IOException, IllegalStateException - */ + */ public OutputStream open( OutputStream out) throws IOException @@ -82,29 +116,30 @@ public OutputStream open( return new WrappedGeneratorStream(dOut, this); } - + /** - * Return an OutputStream which will compress the data as it is written - * to it. The stream will be written out in chunks according to the size of the - * passed in buffer. + * Return an OutputStream which will compress the data as it is written to it. The stream will + * be written out in chunks (partials) according to the size of the passed in buffer. *

- * The stream created can be closed off by either calling close() - * on the stream or close() on the generator. Closing the returned - * stream does not close off the OutputStream parameter out. + * The stream created can be closed off by either calling close() on the stream or close() on + * the generator. Closing the returned stream does not close off the OutputStream parameter out. *

- * Note: if the buffer is not a power of 2 in length only the largest power of 2 - * bytes worth of the buffer will be used. + * Note: if the buffer is not a power of 2 in length only the largest power of 2 bytes + * worth of the buffer will be used. *

*

- * Note: using this may break compatibility with RFC 1991 compliant tools. Only recent OpenPGP - * implementations are capable of accepting these streams. + * Note: using this may break compatibility with RFC 1991 compliant tools. Only recent + * OpenPGP implementations are capable of accepting these streams. *

- * - * @param out underlying OutputStream to be used. - * @param buffer the buffer to use. - * @return OutputStream - * @throws IOException + * + * @param out the stream to write compressed packets to. + * @param buffer a buffer to use to buffer and write partial packets. The returned stream takes + * ownership of the buffer and will use it to buffer plaintext data for compression. + * @return the output stream to write data to. + * @throws IOException if an error occurs writing stream header information to the provider + * output stream. * @throws PGPException + * @throws IllegalStateException if this generator already has an open OutputStream. */ public OutputStream open( OutputStream out, @@ -150,7 +185,7 @@ private void doOpen() throws IOException /** * Close the compressed object - this is equivalent to calling close on the stream * returned by the open() method. - * + * * @throws IOException */ public void close() diff --git a/pg/src/main/java/org/bouncycastle/openpgp/PGPEncryptedData.java b/pg/src/main/java/org/bouncycastle/openpgp/PGPEncryptedData.java index cf01ece23a..8b570bc56c 100644 --- a/pg/src/main/java/org/bouncycastle/openpgp/PGPEncryptedData.java +++ b/pg/src/main/java/org/bouncycastle/openpgp/PGPEncryptedData.java @@ -8,9 +8,17 @@ import org.bouncycastle.bcpg.InputStreamPacket; import org.bouncycastle.bcpg.SymmetricEncIntegrityPacket; import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags; +import org.bouncycastle.openpgp.operator.PGPDataDecryptor; +import org.bouncycastle.openpgp.operator.PGPDataDecryptorFactory; import org.bouncycastle.openpgp.operator.PGPDigestCalculator; import org.bouncycastle.util.Arrays; +/** + * A PGP encrypted data object. + *

+ * Encrypted data packets are decrypted using a {@link PGPDataDecryptor} obtained from a + * {@link PGPDataDecryptorFactory}. + */ public abstract class PGPEncryptedData implements SymmetricKeyAlgorithmTags { @@ -19,9 +27,9 @@ protected class TruncatedStream extends InputStream int[] lookAhead = new int[22]; int bufPtr; InputStream in; - + TruncatedStream( - InputStream in) + InputStream in) throws IOException { for (int i = 0; i != lookAhead.length; i++) @@ -31,34 +39,34 @@ protected class TruncatedStream extends InputStream throw new EOFException(); } } - + bufPtr = 0; this.in = in; } - public int read() + public int read() throws IOException { int ch = in.read(); - + if (ch >= 0) { int c = lookAhead[bufPtr]; - + lookAhead[bufPtr] = ch; bufPtr = (bufPtr + 1) % lookAhead.length; - + return c; } - + return -1; } - + int[] getLookAhead() { int[] tmp = new int[lookAhead.length]; int count = 0; - + for (int i = bufPtr; i != lookAhead.length; i++) { tmp[count++] = lookAhead[i]; @@ -67,11 +75,11 @@ int[] getLookAhead() { tmp[count++] = lookAhead[i]; } - + return tmp; } } - + InputStreamPacket encData; InputStream encStream; TruncatedStream truncStream; @@ -82,31 +90,41 @@ int[] getLookAhead() { this.encData = encData; } - + /** * Return the raw input stream for the data stream. - * - * @return InputStream + *

+ * Note this stream is shared with all other encryption methods in the same + * {@link PGPEncryptedDataList} and with any decryption methods in sub-classes, so consuming + * this stream will affect decryption. + * + * @return the encrypted data in this packet. */ public InputStream getInputStream() { return encData.getInputStream(); } - + /** - * Return true if the message is integrity protected. - * @return true if there is a modification detection code package associated with this stream + * Checks whether the packet is integrity protected. + * + * @return true if there is a modification detection code package associated with + * this stream */ public boolean isIntegrityProtected() { return (encData instanceof SymmetricEncIntegrityPacket); } - + /** + * Verifies the integrity of the packet against the modification detection code associated with + * it in the stream. + *

* Note: This can only be called after the message has been read. - * - * @return true if the message verifies, false otherwise. - * @throws PGPException if the message is not integrity protected. + * + * @return true if the message verifies, false otherwise. + * @throws PGPException if the message is not {@link #isIntegrityProtected() integrity + * protected}. */ public boolean verify() throws PGPException, IOException diff --git a/pg/src/main/java/org/bouncycastle/openpgp/PGPEncryptedDataGenerator.java b/pg/src/main/java/org/bouncycastle/openpgp/PGPEncryptedDataGenerator.java index 6ae92d13a1..855e9842bf 100644 --- a/pg/src/main/java/org/bouncycastle/openpgp/PGPEncryptedDataGenerator.java +++ b/pg/src/main/java/org/bouncycastle/openpgp/PGPEncryptedDataGenerator.java @@ -18,11 +18,30 @@ import org.bouncycastle.util.io.TeeOutputStream; /** - * Generator for encrypted objects. + * Generator for encrypted objects. + *

+ * A PGPEncryptedDataGenerator is used by configuring one or more {@link #methods encryption + * methods}, and then invoking one of the open functions to create an OutputStream that raw data can + * be supplied to for encryption: + *

+ *

+ * Raw data is not typically written directly to the OutputStream obtained from a + * PGPEncryptedDataGenerator. The OutputStream is usually wrapped by a + * {@link PGPLiteralDataGenerator}, and often with a {@link PGPCompressedDataGenerator} between. + *

+ * Once plaintext data for encryption has been written to the constructed OutputStream, writing of + * the encrypted object stream is completed by closing the OutputStream obtained from the + * open() method, or equivalently invoking {@link #close()} on this generator. */ public class PGPEncryptedDataGenerator implements SymmetricKeyAlgorithmTags, StreamGenerator { + // TODO: These seem to belong on the PBE classes. Are they even used now? /** * Specifier for SHA-1 S2K PBE generator. */ @@ -85,11 +104,11 @@ public PGPEncryptedDataGenerator(PGPDataEncryptorBuilder encryptorBuilder, boole } /** - * Added a key encryption method to be used to encrypt the session data associated - * with this encrypted data. - * - * @param method key encryption method to use. - */ + * Add a key encryption method to be used to encrypt the session data associated with this + * encrypted data. + * + * @param method key encryption method to use. + */ public void addMethod(PGPKeyEncryptionMethodGenerator method) { methods.add(method); @@ -99,12 +118,12 @@ private void addCheckSum( byte[] sessionInfo) { int check = 0; - + for (int i = 1; i != sessionInfo.length - 2; i++) { check += sessionInfo[i] & 0xff; } - + sessionInfo[sessionInfo.length - 2] = (byte)(check >> 8); sessionInfo[sessionInfo.length - 1] = (byte)(check); } @@ -121,20 +140,26 @@ private byte[] createSessionInfo( } /** - * If buffer is non null stream assumed to be partial, otherwise the - * length will be used to output a fixed length packet. + * Create an OutputStream based on the configured methods. + * + * If the supplied buffer is non null the stream returned will write a sequence of + * partial packets, otherwise the length will be used to output a fixed length packet. *

- * The stream created can be closed off by either calling close() - * on the stream or close() on the generator. Closing the returned - * stream does not close off the OutputStream parameter out. - * - * @param out - * @param length - * @param buffer + * The stream created can be closed off by either calling close() on the stream or close() on + * the generator. Closing the returned stream does not close off the OutputStream parameter out. + * + * @param out the stream to write encrypted packets to. + * @param length the length of the data to be encrypted. Ignored if buffer is non + * null. + * @param buffer a buffer to use to buffer and write partial packets. * @return the generator's output stream. - * @throws java.io.IOException - * @throws PGPException - * @throws IllegalStateException + * @throws IOException if an error occurs writing stream header information to the provider + * output stream. + * @throws PGPException if an error occurs initialising PGP encryption for the configured + * encryption methods. + * @throws IllegalStateException if this generator already has an open OutputStream, or no + * {@link #addMethod(PGPKeyEncryptionMethodGenerator) encryption methods} are + * configured. */ private OutputStream open( OutputStream out, @@ -160,7 +185,7 @@ private OutputStream open( rand = dataEncryptorBuilder.getSecureRandom(); if (methods.size() == 1) - { + { if (methods.get(0) instanceof PBEKeyEncryptionMethodGenerator) { @@ -197,7 +222,7 @@ private OutputStream open( PGPDataEncryptor dataEncryptor = dataEncryptorBuilder.build(key); digestCalc = dataEncryptor.getIntegrityCalculator(); - + if (buffer == null) { // @@ -250,18 +275,23 @@ private OutputStream open( } /** - * Return an outputstream which will encrypt the data as it is written - * to it. + * Create an OutputStream based on the configured methods to write a single encrypted object of + * known length. + * *

- * The stream created can be closed off by either calling close() - * on the stream or close() on the generator. Closing the returned - * stream does not close off the OutputStream parameter out. - * - * @param out - * @param length - * @return OutputStream - * @throws IOException - * @throws PGPException + * The stream created can be closed off by either calling close() on the stream or close() on + * the generator. Closing the returned stream does not close off the OutputStream parameter out. + * + * @param out the stream to write encrypted packets to. + * @param length the length of the data to be encrypted. + * @return the output stream to write data to for encryption. + * @throws IOException if an error occurs writing stream header information to the provider + * output stream. + * @throws PGPException if an error occurs initialising PGP encryption for the configured + * encryption methods. + * @throws IllegalStateException if this generator already has an open OutputStream, or no + * {@link #addMethod(PGPKeyEncryptionMethodGenerator) encryption methods} are + * configured. */ public OutputStream open( OutputStream out, @@ -270,24 +300,29 @@ public OutputStream open( { return this.open(out, length, null); } - + /** - * Return an outputstream which will encrypt the data as it is written - * to it. The stream will be written out in chunks according to the size of the + * Create an OutputStream which will encrypt the data as it is written to it. The stream of + * encrypted data will be written out in chunks (partial packets) according to the size of the * passed in buffer. *

- * The stream created can be closed off by either calling close() - * on the stream or close() on the generator. Closing the returned - * stream does not close off the OutputStream parameter out. + * The stream created can be closed off by either calling close() on the stream or close() on + * the generator. Closing the returned stream does not close off the OutputStream parameter out. *

- * Note: if the buffer is not a power of 2 in length only the largest power of 2 - * bytes worth of the buffer will be used. + * Note: if the buffer is not a power of 2 in length only the largest power of 2 bytes + * worth of the buffer will be used. * - * @param out - * @param buffer the buffer to use. - * @return OutputStream - * @throws IOException - * @throws PGPException + * @param out the stream to write encrypted packets to. + * @param buffer a buffer to use to buffer and write partial packets. The returned stream takes + * ownership of the buffer and will use it to buffer plaintext data for encryption. + * @return the output stream to write data to for encryption. + * @throws IOException if an error occurs writing stream header information to the provider + * output stream. + * @throws PGPException if an error occurs initialising PGP encryption for the configured + * encryption methods. + * @throws IllegalStateException if this generator already has an open OutputStream, or no + * {@link #addMethod(PGPKeyEncryptionMethodGenerator) encryption methods} are + * configured. */ public OutputStream open( OutputStream out, @@ -296,19 +331,22 @@ public OutputStream open( { return this.open(out, 0, buffer); } - + /** - * Close off the encrypted object - this is equivalent to calling close on the stream - * returned by the open() method. + * Close off the encrypted object - this is equivalent to calling close on the stream returned + * by the open() methods. *

- * Note: This does not close the underlying output stream, only the stream on top of it created by the open() method. - * @throws java.io.IOException + * Note: This does not close the underlying output stream, only the stream on top of it + * created by the open() method. + * + * @throws IOException if an error occurs writing trailing information (such as integrity check + * information) to the underlying stream. */ public void close() throws IOException { if (cOut != null) - { + { if (digestCalc != null) { // diff --git a/pg/src/main/java/org/bouncycastle/openpgp/PGPEncryptedDataList.java b/pg/src/main/java/org/bouncycastle/openpgp/PGPEncryptedDataList.java index 7fd9c2549a..65c58a67e8 100644 --- a/pg/src/main/java/org/bouncycastle/openpgp/PGPEncryptedDataList.java +++ b/pg/src/main/java/org/bouncycastle/openpgp/PGPEncryptedDataList.java @@ -12,13 +12,33 @@ import org.bouncycastle.bcpg.SymmetricKeyEncSessionPacket; /** - * A holder for a list of PGP encryption method packets. + * A holder for a list of PGP encryption method packets and the encrypted data associated with them. + *

+ * This holder supports reading a sequence of the following encryption methods, followed by an + * encrypted data packet: + *

+ *

+ * All of the objects returned from this holder share a reference to the same encrypted data input + * stream, which can only be consumed once. */ public class PGPEncryptedDataList { List list = new ArrayList(); InputStreamPacket data; - + + /** + * Construct an encrypted data packet holder, reading PGP encrypted method packets and an + * encrytped data packet from the stream. + *

+ * The next packet in the stream should be one of {@link PacketTags#SYMMETRIC_KEY_ENC_SESSION} + * or {@link PacketTags#PUBLIC_KEY_ENC_SESSION}. + * + * @param pIn the PGP object stream being read. + * @throws IOException if an error occurs reading from the PGP input. + */ public PGPEncryptedDataList( BCPGInputStream pIn) throws IOException @@ -30,36 +50,47 @@ public PGPEncryptedDataList( } data = (InputStreamPacket)pIn.readPacket(); - + for (int i = 0; i != list.size(); i++) { if (list.get(i) instanceof SymmetricKeyEncSessionPacket) { list.set(i, new PGPPBEEncryptedData((SymmetricKeyEncSessionPacket)list.get(i), data)); } - else + else { list.set(i, new PGPPublicKeyEncryptedData((PublicKeyEncSessionPacket)list.get(i), data)); } } } - + + /** + * Gets the encryption method object at the specified index. + * + * @param index the encryption method to obtain (0 based). + */ public Object get( int index) { return list.get(index); } - + + /** + * Gets the number of encryption methods in this list. + */ public int size() { return list.size(); } - + + /** + * Returns true iff there are 0 encryption methods in this list. + */ public boolean isEmpty() { return list.isEmpty(); } - + /** * @deprecated misspelt - use getEncryptedDataObjects() */ @@ -67,7 +98,11 @@ public Iterator getEncyptedDataObjects() { return list.iterator(); } - + + /** + * Returns an iterator over the encryption method objects held in this list, in the order they + * appeared in the stream they are read from. + */ public Iterator getEncryptedDataObjects() { return list.iterator(); diff --git a/pg/src/main/java/org/bouncycastle/openpgp/PGPLiteralData.java b/pg/src/main/java/org/bouncycastle/openpgp/PGPLiteralData.java index b163b86a64..c90fb1f1b2 100644 --- a/pg/src/main/java/org/bouncycastle/openpgp/PGPLiteralData.java +++ b/pg/src/main/java/org/bouncycastle/openpgp/PGPLiteralData.java @@ -8,48 +8,47 @@ import org.bouncycastle.bcpg.LiteralDataPacket; /** - * class for processing literal data objects. + * A single literal data packet in a PGP object stream. */ -public class PGPLiteralData +public class PGPLiteralData { + /** Format tag for binary literal data */ public static final char BINARY = 'b'; + /** Format tag for textual literal data */ public static final char TEXT = 't'; + /** Format tag for UTF-8 encoded textual literal data */ public static final char UTF8 = 'u'; /** * The special name indicating a "for your eyes only" packet. */ public static final String CONSOLE = "_CONSOLE"; - + /** * The special time for a modification time of "now" or * the present time. */ public static final Date NOW = new Date(0L); - + LiteralDataPacket data; - + public PGPLiteralData( BCPGInputStream pIn) throws IOException { data = (LiteralDataPacket)pIn.readPacket(); } - + /** - * Return the format of the data stream - BINARY or TEXT. - * - * @return int + * Return the format of the data packet. One of {@link #BINARY}, {@link #TEXT} or {@link #UTF8} */ public int getFormat() { return data.getFormat(); } - + /** - * Return the file name that's associated with the data stream. - * - * @return String + * Return the file name associated with the data packet. */ public String getFileName() { @@ -57,7 +56,7 @@ public String getFileName() } /** - * Return the file name as an unintrepreted byte array. + * Return the file name as an uninterpreted (UTF-8 encoded) byte array. */ public byte[] getRawFileName() { @@ -65,29 +64,24 @@ public byte[] getRawFileName() } /** - * Return the modification time for the file. - * - * @return the modification time. + * Return the modification time for the file (at second level precision). */ public Date getModificationTime() { return new Date(data.getModificationTime()); } - + /** - * Return the raw input stream for the data stream. - * - * @return InputStream + * Return the raw input stream for the data packet. */ public InputStream getInputStream() { return data.getInputStream(); } - + /** - * Return the input stream representing the data stream - * - * @return InputStream + * Return the input stream representing the data stream.
+ * Equivalent to {@link #getInputStream()}. */ public InputStream getDataStream() { diff --git a/pg/src/main/java/org/bouncycastle/openpgp/PGPLiteralDataGenerator.java b/pg/src/main/java/org/bouncycastle/openpgp/PGPLiteralDataGenerator.java index d60b535520..1b8da659d1 100644 --- a/pg/src/main/java/org/bouncycastle/openpgp/PGPLiteralDataGenerator.java +++ b/pg/src/main/java/org/bouncycastle/openpgp/PGPLiteralDataGenerator.java @@ -10,49 +10,77 @@ import org.bouncycastle.util.Strings; /** - * Class for producing literal data packets. + * Generator for producing literal data packets. + *

+ * A PGPLiteralData is used by invoking one of the open functions to create an OutputStream that raw + * data can be supplied to for encoding: + *

+ *

+ * A PGPLiteralDataGenerator is usually used to wrap the OutputStream + * {@link PGPEncryptedDataGenerator#open(OutputStream, byte[]) obtained} from a + * {@link PGPEncryptedDataGenerator} or a {@link PGPCompressedDataGenerator}. + *

+ * Once literal data has been written to the constructed OutputStream, writing of the object stream + * is completed by closing the OutputStream obtained from the open() method, or + * equivalently invoking {@link #close()} on this generator. */ public class PGPLiteralDataGenerator implements StreamGenerator -{ - public static final char BINARY = PGPLiteralData.BINARY; +{ + /** Format tag for binary literal data */ + public static final char BINARY = PGPLiteralData.BINARY; + /** Format tag for textual literal data */ public static final char TEXT = PGPLiteralData.TEXT; + /** Format tag for UTF-8 encoded textual literal data */ public static final char UTF8 = PGPLiteralData.UTF8; - + /** * The special name indicating a "for your eyes only" packet. */ + // TODO: Not used? public static final String CONSOLE = PGPLiteralData.CONSOLE; - + /** * The special time for a modification time of "now" or * the present time. */ public static final Date NOW = PGPLiteralData.NOW; - + private BCPGOutputStream pkOut; private boolean oldFormat = false; - + + /** + * Constructs a generator for literal data objects. + */ public PGPLiteralDataGenerator() - { + { } - + /** - * Generates literal data objects in the old format, this is - * important if you need compatability with PGP 2.6.x. - * - * @param oldFormat + * Constructs a generator for literal data objects, specifying to use new or old (PGP 2.6.x + * compatible) format. + *

+ * This can be used for compatibility with PGP 2.6.x. + * + * @param oldFormat true to use PGP 2.6.x compatible format. */ public PGPLiteralDataGenerator( boolean oldFormat) { this.oldFormat = oldFormat; } - + private void writeHeader( OutputStream out, char format, byte[] encName, - long modificationTime) + long modificationTime) throws IOException { out.write(format); @@ -71,19 +99,18 @@ private void writeHeader( out.write((byte)(modDate >> 8)); out.write((byte)(modDate)); } - + /** - * Open a literal data packet, returning a stream to store the data inside - * the packet. + * Open a literal data packet, returning a stream to store the data inside the packet. *

- * The stream created can be closed off by either calling close() - * on the stream or close() on the generator. Closing the returned - * stream does not close off the OutputStream parameter out. - * - * @param out the stream we want the packet in - * @param format the format we are using - * @param name the name of the "file" - * @param length the length of the data we will write + * The stream created can be closed off by either calling close() on the stream or close() on + * the generator. Closing the returned stream does not close off the OutputStream parameter out. + * + * @param out the underlying output stream to write the literal data packet to. + * @param format the format of the literal data that will be written to the output stream (one + * of {@link #BINARY}, {@link #TEXT} or {@link #UTF8}). + * @param name the name of the "file" to encode in the literal data object. + * @param length the length of the data that will be written. * @param modificationTime the time of last modification we want stored. */ public OutputStream open( @@ -102,30 +129,37 @@ public OutputStream open( byte[] encName = Strings.toUTF8ByteArray(name); pkOut = new BCPGOutputStream(out, PacketTags.LITERAL_DATA, length + 2 + encName.length + 4, oldFormat); - + writeHeader(pkOut, format, encName, modificationTime.getTime()); return new WrappedGeneratorStream(pkOut, this); } - + /** - * Open a literal data packet, returning a stream to store the data inside - * the packet as an indefinite length stream. The stream is written out as a - * series of partial packets with a chunk size determined by the size of the - * passed in buffer. + * Open a literal data packet, returning a stream to store the data inside the packet as an + * indefinite length stream. The stream is written out as a series of partial packets with a + * chunk size determined by the size of the passed in buffer. *

- * The stream created can be closed off by either calling close() - * on the stream or close() on the generator. Closing the returned - * stream does not close off the OutputStream parameter out. + * The stream created can be closed off by either calling close() on the stream or close() on + * the generator. Closing the returned stream does not close off the OutputStream parameter out. + * *

- * Note: if the buffer is not a power of 2 in length only the largest power of 2 - * bytes worth of the buffer will be used. - * - * @param out the stream we want the packet in - * @param format the format we are using - * @param name the name of the "file" - * @param modificationTime the time of last modification we want stored. - * @param buffer the buffer to use for collecting data to put into chunks. + * Note: if the buffer is not a power of 2 in length only the largest power of 2 bytes + * worth of the buffer will be used. + * + * @param out the underlying output stream to write the literal data packet to. + * @param format the format of the literal data that will be written to the output stream (one + * of {@link #BINARY}, {@link #TEXT} or {@link #UTF8}). + * @param name the name of the "file" to encode in the literal data object. + * @param modificationTime the time of last modification we want stored (will be stored to + * second level precision). + * @param buffer a buffer to use to buffer and write partial packets. The returned stream takes + * ownership of the buffer. + * + * @return the output stream to write data to. + * @throws IOException if an error occurs writing stream header information to the provider + * output stream. + * @throws IllegalStateException if this generator already has an open OutputStream. */ public OutputStream open( OutputStream out, @@ -148,20 +182,26 @@ public OutputStream open( return new WrappedGeneratorStream(pkOut, this); } - + /** - * Open a literal data packet for the passed in File object, returning - * an output stream for saving the file contents. - *

- * The stream created can be closed off by either calling close() - * on the stream or close() on the generator. Closing the returned - * stream does not close off the OutputStream parameter out. - * - * @param out - * @param format - * @param file - * @return OutputStream - * @throws IOException + * Open a literal data packet for the passed in File object, returning an output stream for + * saving the file contents. + *

+ * This method configures the generator to store the file contents in a single literal data + * packet, taking the filename and modification time from the file, but does not store the + * actual file data. + *

+ * The stream created can be closed off by either calling close() on the stream or close() on + * the generator. Closing the returned stream does not close off the OutputStream parameter out. + * + * @param out the underlying output stream to write the literal data packet to. + * @param format the format of the literal data that will be written to the output stream (one + * of {@link #BINARY}, {@link #TEXT} or {@link #UTF8}). + * @param file the file to determine the length and filename from. + * @return the output stream to write data to. + * @throws IOException if an error occurs writing stream header information to the provider + * output stream. + * @throws IllegalStateException if this generator already has an open OutputStream. */ public OutputStream open( OutputStream out, @@ -169,24 +209,13 @@ public OutputStream open( File file) throws IOException { - if (pkOut != null) - { - throw new IllegalStateException("generator already in open state"); - } - - byte[] encName = Strings.toUTF8ByteArray(file.getName()); - - pkOut = new BCPGOutputStream(out, PacketTags.LITERAL_DATA, file.length() + 2 + encName.length + 4, oldFormat); - - writeHeader(pkOut, format, encName, file.lastModified()); - - return new WrappedGeneratorStream(pkOut, this); + return open(out, format, file.getName(), file.length(), new Date(file.lastModified())); } - + /** * Close the literal data packet - this is equivalent to calling close on the stream * returned by the open() method. - * + * * @throws IOException */ public void close() diff --git a/pg/src/main/java/org/bouncycastle/openpgp/PGPObjectFactory.java b/pg/src/main/java/org/bouncycastle/openpgp/PGPObjectFactory.java index bc06d92df9..5d2b90df48 100644 --- a/pg/src/main/java/org/bouncycastle/openpgp/PGPObjectFactory.java +++ b/pg/src/main/java/org/bouncycastle/openpgp/PGPObjectFactory.java @@ -8,16 +8,32 @@ import org.bouncycastle.bcpg.BCPGInputStream; import org.bouncycastle.bcpg.PacketTags; +import org.bouncycastle.openpgp.bc.BcPGPObjectFactory; +import org.bouncycastle.openpgp.jcajce.JcaPGPObjectFactory; import org.bouncycastle.openpgp.operator.KeyFingerPrintCalculator; import org.bouncycastle.openpgp.operator.bc.BcKeyFingerprintCalculator; /** * General class for reading a PGP object stream. - *

- * Note: if this class finds a PGPPublicKey or a PGPSecretKey it - * will create a PGPPublicKeyRing, or a PGPSecretKeyRing for each - * key found. If all you are trying to do is read a key ring file use - * either PGPPublicKeyRingCollection or PGPSecretKeyRingCollection. + *

+ * Note: if this class finds a {@link PGPPublicKey} or a {@link PGPSecretKey} it will create a + * {@link PGPPublicKeyRing}, or a {@link PGPSecretKeyRing} for each key found. If all you are trying + * to do is read a key ring file use either {@link PGPPublicKeyRingCollection} or + * {@link PGPSecretKeyRingCollection}. + *

+ * This factory supports reading the following types of objects: + *

*/ public class PGPObjectFactory { @@ -25,7 +41,7 @@ public class PGPObjectFactory private KeyFingerPrintCalculator fingerPrintCalculator; /** - * @deprecated use JcaPGPObjectFactory or BcPGPObjectFactory + * @deprecated use {@link JcaPGPObjectFactory} or {@link BcPGPObjectFactory} */ public PGPObjectFactory( InputStream in) @@ -34,10 +50,11 @@ public PGPObjectFactory( } /** - * Create an object factor suitable for reading keys, key rings and key ring collections. + * Create an object factory suitable for reading PGP objects such as keys, key rings and key + * ring collections, or PGP encrypted data. * - * @param in stream to read from - * @param fingerPrintCalculator calculator to use in key finger print calculations. + * @param in stream to read PGP data from. + * @param fingerPrintCalculator calculator to use in key finger print calculations. */ public PGPObjectFactory( InputStream in, @@ -57,10 +74,11 @@ public PGPObjectFactory( } /** - * Create an object factor suitable for reading keys, key rings and key ring collections. + * Create an object factory suitable for reading PGP objects such as keys, key rings and key + * ring collections, or PGP encrypted data. * - * @param bytes stream to read from - * @param fingerPrintCalculator calculator to use in key finger print calculations. + * @param bytes PGP encoded data. + * @param fingerPrintCalculator calculator to use in key finger print calculations. */ public PGPObjectFactory( byte[] bytes, @@ -70,10 +88,10 @@ public PGPObjectFactory( } /** - * Return the next object in the stream, or null if the end is reached. - * - * @return Object - * @throws IOException on a parse error + * Return the next object in the stream, or null if the end of stream is reached. + * + * @return one of the supported objects - see class docs for details. + * @throws IOException if an error occurs reading from the wrapped stream or parsing data. */ public Object nextObject() throws IOException @@ -86,7 +104,7 @@ public Object nextObject() return null; case PacketTags.SIGNATURE: l = new ArrayList(); - + while (in.nextPacketTag() == PacketTags.SIGNATURE) { try @@ -98,7 +116,7 @@ public Object nextObject() throw new IOException("can't create signature object: " + e); } } - + return new PGPSignatureList((PGPSignature[])l.toArray(new PGPSignature[l.size()])); case PacketTags.SECRET_KEY: try @@ -129,7 +147,7 @@ public Object nextObject() return new PGPEncryptedDataList(in); case PacketTags.ONE_PASS_SIGNATURE: l = new ArrayList(); - + while (in.nextPacketTag() == PacketTags.ONE_PASS_SIGNATURE) { try @@ -141,7 +159,7 @@ public Object nextObject() throw new IOException("can't create one pass signature object: " + e); } } - + return new PGPOnePassSignatureList((PGPOnePassSignature[])l.toArray(new PGPOnePassSignature[l.size()])); case PacketTags.MARKER: return new PGPMarker(in); @@ -151,7 +169,7 @@ public Object nextObject() case PacketTags.EXPERIMENTAL_4: return in.readPacket(); } - + throw new IOException("unknown object in stream: " + in.nextPacketTag()); } } diff --git a/pg/src/main/java/org/bouncycastle/openpgp/PGPPBEEncryptedData.java b/pg/src/main/java/org/bouncycastle/openpgp/PGPPBEEncryptedData.java index a24cdc470b..c14ad5487f 100644 --- a/pg/src/main/java/org/bouncycastle/openpgp/PGPPBEEncryptedData.java +++ b/pg/src/main/java/org/bouncycastle/openpgp/PGPPBEEncryptedData.java @@ -6,6 +6,7 @@ import org.bouncycastle.bcpg.BCPGInputStream; import org.bouncycastle.bcpg.InputStreamPacket; import org.bouncycastle.bcpg.SymmetricEncIntegrityPacket; +import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags; import org.bouncycastle.bcpg.SymmetricKeyEncSessionPacket; import org.bouncycastle.openpgp.operator.PBEDataDecryptorFactory; import org.bouncycastle.openpgp.operator.PGPDataDecryptor; @@ -13,36 +14,37 @@ /** * A password based encryption object. + *

+ * PBE encrypted data objects can be {@link #getDataStream(PBEDataDecryptorFactory) decrypted } + * using a {@link PBEDataDecryptorFactory}. */ public class PGPPBEEncryptedData extends PGPEncryptedData { SymmetricKeyEncSessionPacket keyData; - + + /** + * Construct a PBE encryped data object. + * + * @param keyData the PBE key data packet associated with the encrypted data in the PGP object + * stream. + * @param encData the encrypted data. + */ PGPPBEEncryptedData( SymmetricKeyEncSessionPacket keyData, InputStreamPacket encData) { super(encData); - + this.keyData = keyData; } - - /** - * Return the raw input stream for the data stream. - * - * @return InputStream - */ - public InputStream getInputStream() - { - return encData.getInputStream(); - } - /** + /** * Return the symmetric key algorithm required to decrypt the data protected by this object. * - * @param dataDecryptorFactory decryptor factory to use to recover the session data. - * @return the integer encryption algorithm code. + * @param dataDecryptorFactory decryptor factory to use to recover the session data. + * @return the identifier of the {@link SymmetricKeyAlgorithmTags encryption algorithm} used to + * encrypt this object. * @throws PGPException if the session data cannot be recovered. */ public int getSymmetricAlgorithm( @@ -55,12 +57,14 @@ public int getSymmetricAlgorithm( return sessionData[0]; } - /** + /** * Open an input stream which will provide the decrypted data protected by this object. - * - * @param dataDecryptorFactory decryptor factory to use to recover the session data and provide the stream. - * @return the resulting input stream - * @throws PGPException if the session data cannot be recovered or the stream cannot be created. + * + * @param dataDecryptorFactory decryptor factory to use to recover the session data and provide + * the stream. + * @return the resulting decrypted input stream, probably containing a sequence of PGP data + * objects. + * @throws PGPException if the session data cannot be recovered or the stream cannot be created. */ public InputStream getDataStream( PBEDataDecryptorFactory dataDecryptorFactory) diff --git a/pg/src/main/java/org/bouncycastle/openpgp/PGPPublicKeyEncryptedData.java b/pg/src/main/java/org/bouncycastle/openpgp/PGPPublicKeyEncryptedData.java index 1dde086b44..18e5f6448a 100644 --- a/pg/src/main/java/org/bouncycastle/openpgp/PGPPublicKeyEncryptedData.java +++ b/pg/src/main/java/org/bouncycastle/openpgp/PGPPublicKeyEncryptedData.java @@ -17,15 +17,15 @@ */ public class PGPPublicKeyEncryptedData extends PGPEncryptedData -{ +{ PublicKeyEncSessionPacket keyData; - + PGPPublicKeyEncryptedData( PublicKeyEncSessionPacket keyData, InputStreamPacket encData) { super(encData); - + this.keyData = keyData; } @@ -33,19 +33,19 @@ private boolean confirmCheckSum( byte[] sessionInfo) { int check = 0; - + for (int i = 1; i != sessionInfo.length - 2; i++) { check += sessionInfo[i] & 0xff; } - + return (sessionInfo[sessionInfo.length - 2] == (byte)(check >> 8)) && (sessionInfo[sessionInfo.length - 1] == (byte)(check)); } - + /** * Return the keyID for the key used to encrypt the data. - * + * * @return long */ public long getKeyID() @@ -55,9 +55,10 @@ public long getKeyID() /** * Return the symmetric key algorithm required to decrypt the data protected by this object. - * - * @param dataDecryptorFactory decryptor factory to use to recover the session data. - * @return the integer encryption algorithm code. + * + * @param dataDecryptorFactory decryptor factory to use to recover the session data. + * @return the identifier of the {@link SymmetricKeyAlgorithmTags encryption algorithm} used to + * encrypt this object. * @throws PGPException if the session data cannot be recovered. */ public int getSymmetricAlgorithm( diff --git a/pg/src/main/java/org/bouncycastle/openpgp/PGPSecretKeyRing.java b/pg/src/main/java/org/bouncycastle/openpgp/PGPSecretKeyRing.java index 538c47191a..ce356cebe1 100644 --- a/pg/src/main/java/org/bouncycastle/openpgp/PGPSecretKeyRing.java +++ b/pg/src/main/java/org/bouncycastle/openpgp/PGPSecretKeyRing.java @@ -24,7 +24,7 @@ * Class to hold a single master secret key and its subkeys. *

* Often PGP keyring files consist of multiple master keys, if you are trying to process - * or construct one of these you should use the PGPSecretKeyRingCollection class. + * or construct one of these you should use the {@link PGPSecretKeyRingCollection} class. */ public class PGPSecretKeyRing extends PGPKeyRing diff --git a/pg/src/main/java/org/bouncycastle/openpgp/PGPUtil.java b/pg/src/main/java/org/bouncycastle/openpgp/PGPUtil.java index 4ea779d755..42e922bfaf 100644 --- a/pg/src/main/java/org/bouncycastle/openpgp/PGPUtil.java +++ b/pg/src/main/java/org/bouncycastle/openpgp/PGPUtil.java @@ -6,7 +6,9 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.security.MessageDigest; import java.security.SecureRandom; +import java.security.Signature; import java.util.Date; import org.bouncycastle.asn1.ASN1InputStream; @@ -20,7 +22,7 @@ import org.bouncycastle.util.encoders.Base64; /** - * Basic utility class + * PGP utilities. */ public class PGPUtil implements HashAlgorithmTags @@ -28,30 +30,30 @@ public class PGPUtil private static String defProvider = "BC"; /** - * Return the provider that will be used by factory classes in situations - * where a provider must be determined on the fly. - * - * @return String + * Return the JCA/JCE provider that will be used by factory classes in situations where a + * provider must be determined on the fly. + * + * @return the name of the default provider. */ public static String getDefaultProvider() { + // TODO: This is unused? return defProvider; } - + /** - * Set the provider to be used by the package when it is necessary to - * find one on the fly. - * - * @param provider + * Set the provider to be used by the package when it is necessary to find one on the fly. + * + * @param provider the name of the JCA/JCE provider to use by default. */ public static void setDefaultProvider( String provider) { defProvider = provider; } - + static MPInteger[] dsaSigToMpi( - byte[] encoding) + byte[] encoding) throws PGPException { ASN1InputStream aIn = new ASN1InputStream(encoding); @@ -72,13 +74,21 @@ static MPInteger[] dsaSigToMpi( } MPInteger[] values = new MPInteger[2]; - + values[0] = new MPInteger(i1.getValue()); values[1] = new MPInteger(i2.getValue()); - + return values; } - + + /** + * Translates a PGP {@link HashAlgorithmTags hash algorithm tag} to a JCA {@link MessageDigest} + * algorithm name + * + * @param hashAlgorithm the hash algorithm identifier. + * @return the corresponding JCA algorithm name. + * @throws PGPException if the hash algorithm is unknown. + */ static String getDigestName( int hashAlgorithm) throws PGPException @@ -105,14 +115,23 @@ static String getDigestName( throw new PGPException("unknown hash algorithm tag in getDigestName: " + hashAlgorithm); } } - + + /** + * Translates a PGP {@link PublicKeyAlgorithmTags public key algorithm tag} and a + * {@link HashAlgorithmTags hash algorithm tag} to a JCA {@link Signature} algorithm name. + * + * @param keyAlgorithm they public key algorithm identifier. + * @param hashAlgorithm the hash algorithm identifier. + * @return the corresponding JCA algorithm name. + * @throws PGPException if the public key or hash algorithm is unknown. + */ static String getSignatureName( int keyAlgorithm, int hashAlgorithm) throws PGPException { String encAlg; - + switch (keyAlgorithm) { case PublicKeyAlgorithmTags.RSA_GENERAL: @@ -133,13 +152,22 @@ static String getSignatureName( return getDigestName(hashAlgorithm) + "with" + encAlg; } + /** + * Generates a random key for a {@link SymmetricKeyAlgorithmTags symmetric encryption algorithm} + * . + * + * @param algorithm the symmetric key algorithm identifier. + * @param random a source of random data. + * @return a key of the length required by the specified encryption algorithm. + * @throws PGPException if the encryption algorithm is unknown. + */ public static byte[] makeRandomKey( int algorithm, - SecureRandom random) + SecureRandom random) throws PGPException { int keySize = 0; - + switch (algorithm) { case SymmetricKeyAlgorithmTags.TRIPLE_DES: @@ -184,22 +212,22 @@ public static byte[] makeRandomKey( default: throw new PGPException("unknown symmetric algorithm: " + algorithm); } - + byte[] keyBytes = new byte[(keySize + 7) / 8]; - + random.nextBytes(keyBytes); - + return keyBytes; } /** - * write out the passed in file as a literal data packet. - * - * @param out - * @param fileType the LiteralData type for the file. - * @param file - * - * @throws IOException + * Write out the contents of the provided file as a literal data packet. + * + * @param out the stream to write the literal data to. + * @param fileType the {@link PGPLiteralData} type to use for the file data. + * @param file the file to write the contents of. + * + * @throws IOException if an error occurs reading the file or writing to the output stream. */ public static void writeFileToLiteralData( OutputStream out, @@ -208,19 +236,21 @@ public static void writeFileToLiteralData( throws IOException { PGPLiteralDataGenerator lData = new PGPLiteralDataGenerator(); - OutputStream pOut = lData.open(out, fileType, file.getName(), file.length(), new Date(file.lastModified())); + OutputStream pOut = lData.open(out, fileType, file); pipeFileContents(file, pOut, 4096); } - + /** - * write out the passed in file as a literal data packet in partial packet format. - * - * @param out - * @param fileType the LiteralData type for the file. - * @param file + * Write out the contents of the provided file as a literal data packet in partial packet + * format. + * + * @param out the stream to write the literal data to. + * @param fileType the {@link PGPLiteralData} type to use for the file data. + * @param file the file to write the contents of. * @param buffer buffer to be used to chunk the file into partial packets. - * - * @throws IOException + * @see {@link PGPLiteralDataGenerator#open(OutputStream, char, String, Date, byte[])}. + * + * @throws IOException if an error occurs reading the file or writing to the output stream. */ public static void writeFileToLiteralData( OutputStream out, @@ -250,41 +280,45 @@ private static void pipeFileContents(File file, OutputStream pOut, int bufSize) } private static final int READ_AHEAD = 60; - + private static boolean isPossiblyBase64( int ch) { - return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') + return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || (ch == '+') || (ch == '/') || (ch == '\r') || (ch == '\n'); } - + /** - * Return either an ArmoredInputStream or a BCPGInputStream based on - * whether the initial characters of the stream are binary PGP encodings or not. - * - * @param in the stream to be wrapped - * @return a BCPGInputStream - * @throws IOException + * Obtains a stream that can be used to read PGP data from the provided stream. + *

+ * If the initial bytes of the underlying stream are binary PGP encodings, then the stream will + * be returned directly, otherwise an {@link ArmoredInputStream} is used to wrap the provided + * stream and remove ASCII-Armored encoding. + * + * @param in the stream to be checked and possibly wrapped. + * @return a stream that will return PGP binary encoded data. + * @throws IOException if an error occurs reading the stream, or initalising the + * {@link ArmoredInputStream}. */ public static InputStream getDecoderStream( - InputStream in) + InputStream in) throws IOException { if (!in.markSupported()) { in = new BufferedInputStreamExt(in); } - + in.mark(READ_AHEAD); - + int ch = in.read(); - + if ((ch & 0x80) != 0) { in.reset(); - + return in; } else @@ -292,34 +326,34 @@ public static InputStream getDecoderStream( if (!isPossiblyBase64(ch)) { in.reset(); - + return new ArmoredInputStream(in); } - + byte[] buf = new byte[READ_AHEAD]; int count = 1; int index = 1; - + buf[0] = (byte)ch; while (count != READ_AHEAD && (ch = in.read()) >= 0) { if (!isPossiblyBase64(ch)) { in.reset(); - + return new ArmoredInputStream(in); } - + if (ch != '\n' && ch != '\r') { buf[index++] = (byte)ch; } - + count++; } - + in.reset(); - + // // nothing but new lines, little else, assume regular armoring // @@ -327,16 +361,16 @@ public static InputStream getDecoderStream( { return new ArmoredInputStream(in); } - + // // test our non-blank data // byte[] firstBlock = new byte[8]; - + System.arraycopy(buf, 0, firstBlock, 0, firstBlock.length); byte[] decoded = Base64.decode(firstBlock); - + // // it's a base64 PGP block. // @@ -344,11 +378,11 @@ public static InputStream getDecoderStream( { return new ArmoredInputStream(in, false); } - + return new ArmoredInputStream(in); } } - + static class BufferedInputStreamExt extends BufferedInputStream { BufferedInputStreamExt(InputStream input) diff --git a/pg/src/main/java/org/bouncycastle/openpgp/StreamGenerator.java b/pg/src/main/java/org/bouncycastle/openpgp/StreamGenerator.java index 58628d13a8..75e927678e 100644 --- a/pg/src/main/java/org/bouncycastle/openpgp/StreamGenerator.java +++ b/pg/src/main/java/org/bouncycastle/openpgp/StreamGenerator.java @@ -2,8 +2,15 @@ import java.io.IOException; +/** + * Callback interface for generators that produce a stream to be informed when the stream has been + * closed by the client. + */ interface StreamGenerator { + /** + * Signal that the stream has been closed. + */ void close() throws IOException; } diff --git a/pg/src/main/java/org/bouncycastle/openpgp/bc/BcPGPObjectFactory.java b/pg/src/main/java/org/bouncycastle/openpgp/bc/BcPGPObjectFactory.java index 2fcde0fa38..7ee93c7309 100644 --- a/pg/src/main/java/org/bouncycastle/openpgp/bc/BcPGPObjectFactory.java +++ b/pg/src/main/java/org/bouncycastle/openpgp/bc/BcPGPObjectFactory.java @@ -6,14 +6,28 @@ import org.bouncycastle.openpgp.PGPObjectFactory; import org.bouncycastle.openpgp.operator.bc.BcKeyFingerprintCalculator; +/** + * {@link PGPObjectFactory} that uses the Bouncy Castle lightweight API to implement cryptographic + * primitives. + */ public class BcPGPObjectFactory extends PGPObjectFactory { - public BcPGPObjectFactory(byte[] encoding) + /** + * Construct an object factory to read PGP objects from encoded data. + * + * @param encoded the PGP encoded data. + */ + public BcPGPObjectFactory(byte[] encoded) { - this(new ByteArrayInputStream(encoding)); + this(new ByteArrayInputStream(encoded)); } + /** + * Construct an object factory to read PGP objects from a stream. + * + * @param in the stream containing PGP encoded objects. + */ public BcPGPObjectFactory(InputStream in) { super(in, new BcKeyFingerprintCalculator()); diff --git a/pg/src/main/java/org/bouncycastle/openpgp/jcajce/JcaPGPObjectFactory.java b/pg/src/main/java/org/bouncycastle/openpgp/jcajce/JcaPGPObjectFactory.java index e645973d8e..bff681ab13 100644 --- a/pg/src/main/java/org/bouncycastle/openpgp/jcajce/JcaPGPObjectFactory.java +++ b/pg/src/main/java/org/bouncycastle/openpgp/jcajce/JcaPGPObjectFactory.java @@ -6,16 +6,30 @@ import org.bouncycastle.openpgp.PGPObjectFactory; import org.bouncycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator; +/** + * {@link PGPObjectFactory} that uses the sources cryptographic primitives from the JCA API. + */ public class JcaPGPObjectFactory extends PGPObjectFactory { - public JcaPGPObjectFactory(byte[] encoding) + /** + * Construct an object factory to read PGP objects from encoded data. + * + * @param encoded the PGP encoded data. + */ + public JcaPGPObjectFactory(byte[] encoded) { - this(new ByteArrayInputStream(encoding)); + this(new ByteArrayInputStream(encoded)); } + /** + * Construct an object factory to read PGP objects from a stream. + * + * @param in the stream containing PGP encoded objects. + */ public JcaPGPObjectFactory(InputStream in) { + // FIXME: Convert this to builder style so we can set provider? super(in, new JcaKeyFingerprintCalculator()); } } diff --git a/pg/src/main/java/org/bouncycastle/openpgp/operator/PBEDataDecryptorFactory.java b/pg/src/main/java/org/bouncycastle/openpgp/operator/PBEDataDecryptorFactory.java index 05c93e16c9..8538e4f67d 100644 --- a/pg/src/main/java/org/bouncycastle/openpgp/operator/PBEDataDecryptorFactory.java +++ b/pg/src/main/java/org/bouncycastle/openpgp/operator/PBEDataDecryptorFactory.java @@ -1,26 +1,57 @@ package org.bouncycastle.openpgp.operator; import org.bouncycastle.bcpg.S2K; +import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags; import org.bouncycastle.openpgp.PGPException; +/** + * A factory for performing PBE decryption operations. + */ public abstract class PBEDataDecryptorFactory implements PGPDataDecryptorFactory { private char[] passPhrase; private PGPDigestCalculatorProvider calculatorProvider; + /** + * Construct a PBE data decryptor factory. + * + * @param passPhrase the pass phrase to generate decryption keys with. + * @param calculatorProvider the digest to use in key generation. + */ protected PBEDataDecryptorFactory(char[] passPhrase, PGPDigestCalculatorProvider calculatorProvider) { this.passPhrase = passPhrase; this.calculatorProvider = calculatorProvider; } + /** + * Generates an encryption key using the pass phrase and digest calculator configured for this + * factory. + * + * @param keyAlgorithm the {@link SymmetricKeyAlgorithmTags encryption algorithm} to generate a + * key for. + * @param s2k the string-to-key specification to use to generate the key. + * @return the key bytes for the encryption algorithm, generated using the pass phrase of this + * factory. + * @throws PGPException if an error occurs generating the key. + */ public byte[] makeKeyFromPassPhrase(int keyAlgorithm, S2K s2k) throws PGPException { return PGPUtil.makeKeyFromPassPhrase(calculatorProvider, keyAlgorithm, s2k, passPhrase); } + /** + * Decrypts session data from an encrypted data packet. + * + * @param keyAlgorithm the {@link SymmetricKeyAlgorithmTags encryption algorithm} used to + * encrypt the session data. + * @param key the key bytes for the encryption algorithm. + * @param seckKeyData the encrypted session data to decrypt. + * @return the decrypted session data. + * @throws PGPException if an error occurs decrypting the session data. + */ public abstract byte[] recoverSessionData(int keyAlgorithm, byte[] key, byte[] seckKeyData) throws PGPException; } diff --git a/pg/src/main/java/org/bouncycastle/openpgp/operator/PBEKeyEncryptionMethodGenerator.java b/pg/src/main/java/org/bouncycastle/openpgp/operator/PBEKeyEncryptionMethodGenerator.java index 189467dfea..2907439b3a 100644 --- a/pg/src/main/java/org/bouncycastle/openpgp/operator/PBEKeyEncryptionMethodGenerator.java +++ b/pg/src/main/java/org/bouncycastle/openpgp/operator/PBEKeyEncryptionMethodGenerator.java @@ -4,9 +4,21 @@ import org.bouncycastle.bcpg.ContainedPacket; import org.bouncycastle.bcpg.S2K; +import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags; import org.bouncycastle.bcpg.SymmetricKeyEncSessionPacket; import org.bouncycastle.openpgp.PGPException; +/** + * PGP style PBE encryption method. + *

+ * A pass phrase is used to generate an encryption key using the PGP {@link S2K string-to-key} + * method. This class always uses the {@link S2K#SALTED_AND_ITERATED salted and iterated form of the + * S2K algorithm}. + *

+ * Note that the iteration count provided to this method is a single byte as described by the + * {@link S2K} algorithm, and the actual iteration count ranges exponentially from + * 0x01 == 1088 to 0xFF == 65,011,712. + */ public abstract class PBEKeyEncryptionMethodGenerator extends PGPKeyEncryptionMethodGenerator { @@ -16,6 +28,13 @@ public abstract class PBEKeyEncryptionMethodGenerator private SecureRandom random; private int s2kCount; + /** + * Construct a PBE key generator using the default iteration count (0x60 == 65536 + * iterations). + * + * @param passPhrase the pass phrase to encrypt with. + * @param s2kDigestCalculator a digest calculator to use in the string-to-key function. + */ protected PBEKeyEncryptionMethodGenerator( char[] passPhrase, PGPDigestCalculator s2kDigestCalculator) @@ -23,6 +42,14 @@ protected PBEKeyEncryptionMethodGenerator( this(passPhrase, s2kDigestCalculator, 0x60); } + /** + * Construct a PBE key generator using a specific iteration level. + * + * @param passPhrase the pass phrase to encrypt with. + * @param s2kDigestCalculator a digest calculator to use in the string-to-key function. + * @param s2kCount a single byte {@link S2K} iteration count specifier, which is translated to + * an actual iteration count by the S2K class. + */ protected PBEKeyEncryptionMethodGenerator( char[] passPhrase, PGPDigestCalculator s2kDigestCalculator, @@ -39,6 +66,13 @@ protected PBEKeyEncryptionMethodGenerator( this.s2kCount = s2kCount; } + /** + * Sets a user defined source of randomness. + *

+ * If no SecureRandom is configured, a default SecureRandom will be used. + * + * @return the current generator. + */ public PBEKeyEncryptionMethodGenerator setSecureRandom(SecureRandom random) { this.random = random; @@ -46,6 +80,15 @@ public PBEKeyEncryptionMethodGenerator setSecureRandom(SecureRandom random) return this; } + /** + * Generate a key for a symmetric encryption algorithm using the PBE configuration in this + * method. + * + * @param encAlgorithm the {@link SymmetricKeyAlgorithmTags encryption algorithm} to generate + * the key for. + * @return the bytes of the generated key. + * @throws PGPException if an error occurs performing the string-to-key generation. + */ public byte[] getKey(int encAlgorithm) throws PGPException { diff --git a/pg/src/main/java/org/bouncycastle/openpgp/operator/PGPDataDecryptor.java b/pg/src/main/java/org/bouncycastle/openpgp/operator/PGPDataDecryptor.java index 7f79640af3..862b342e9a 100644 --- a/pg/src/main/java/org/bouncycastle/openpgp/operator/PGPDataDecryptor.java +++ b/pg/src/main/java/org/bouncycastle/openpgp/operator/PGPDataDecryptor.java @@ -2,11 +2,29 @@ import java.io.InputStream; +/** + * A decryptor that wraps a stream of PGP encrypted data to decrypt, and optionally integrity check, + * the data. + */ public interface PGPDataDecryptor { + /** + * Wraps an encrypted data stream with a stream that will return the decrypted data. + * + * @param in the encrypted data. + * @return a decrypting stream. + */ InputStream getInputStream(InputStream in); + /** + * Obtains the block size of the encryption algorithm used in this decryptor. + * + * @return the block size of the cipher in bytes. + */ int getBlockSize(); + /** + * Obtains the digest calculator used to verify the integrity check. + */ PGPDigestCalculator getIntegrityCalculator(); } diff --git a/pg/src/main/java/org/bouncycastle/openpgp/operator/PGPDataDecryptorFactory.java b/pg/src/main/java/org/bouncycastle/openpgp/operator/PGPDataDecryptorFactory.java index 87d7891da1..39ac30fd93 100644 --- a/pg/src/main/java/org/bouncycastle/openpgp/operator/PGPDataDecryptorFactory.java +++ b/pg/src/main/java/org/bouncycastle/openpgp/operator/PGPDataDecryptorFactory.java @@ -1,9 +1,25 @@ package org.bouncycastle.openpgp.operator; +import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags; import org.bouncycastle.openpgp.PGPException; +/** + * Base interface of factories for {@link PGPDataDecryptor}. + */ public interface PGPDataDecryptorFactory { + /** + * Constructs a data decryptor. + * + * @param withIntegrityPacket true if the packet to be decrypted has integrity + * checking enabled. + * @param encAlgorithm the identifier of the {@link SymmetricKeyAlgorithmTags encryption + * algorithm} to decrypt with. + * @param key the bytes of the key for the cipher. + * @return a data decryptor that can decrypt (and verify) streams of encrypted data. + * @throws PGPException if an error occurs initialising the decryption and integrity checking + * functions. + */ public PGPDataDecryptor createDataDecryptor(boolean withIntegrityPacket, int encAlgorithm, byte[] key) throws PGPException; } diff --git a/pg/src/main/java/org/bouncycastle/openpgp/operator/PGPDataEncryptor.java b/pg/src/main/java/org/bouncycastle/openpgp/operator/PGPDataEncryptor.java index 20d40a3958..fbd994a002 100644 --- a/pg/src/main/java/org/bouncycastle/openpgp/operator/PGPDataEncryptor.java +++ b/pg/src/main/java/org/bouncycastle/openpgp/operator/PGPDataEncryptor.java @@ -2,11 +2,38 @@ import java.io.OutputStream; +/** + * A data encryptor, combining a cipher instance and an optional integrity check calculator. + *

+ * {@link PGPDataEncryptor} instances are generally not constructed directly, but obtained from a + * {@link PGPDataEncryptorBuilder}. + */ public interface PGPDataEncryptor { + /** + * Constructs an encrypting output stream that encrypts data using the underlying cipher of this + * encryptor. + *

+ * The cipher instance in this encryptor is used for all output streams obtained from this + * method, so it should only be invoked once. + * + * @param out the stream to wrap and write encrypted data to. + * @return a cipher output stream appropriate to the type of this data encryptor. + */ OutputStream getOutputStream(OutputStream out); + /** + * Obtains the integrity check calculator configured for this encryptor instance. + * + * @return the integrity check calculator, or null if no integrity checking was + * configured. + */ PGPDigestCalculator getIntegrityCalculator(); + /** + * Gets the block size of the underlying cipher used by this encryptor. + * + * @return the block size in bytes. + */ int getBlockSize(); } diff --git a/pg/src/main/java/org/bouncycastle/openpgp/operator/PGPDataEncryptorBuilder.java b/pg/src/main/java/org/bouncycastle/openpgp/operator/PGPDataEncryptorBuilder.java index 13f94775fb..91660b01d6 100644 --- a/pg/src/main/java/org/bouncycastle/openpgp/operator/PGPDataEncryptorBuilder.java +++ b/pg/src/main/java/org/bouncycastle/openpgp/operator/PGPDataEncryptorBuilder.java @@ -2,14 +2,35 @@ import java.security.SecureRandom; +import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags; import org.bouncycastle.openpgp.PGPException; +/** + * A builder for {@link PGPDataEncryptor} instances, which can be used to encrypt data objects. + */ public interface PGPDataEncryptorBuilder { + /** + * The encryption algorithm used by data encryptors created by this builder. + * + * @return one of the {@link SymmetricKeyAlgorithmTags symmetric encryption algorithms}. + */ int getAlgorithm(); + /** + * Builds a data encryptor using the algorithm configured for this builder. + * + * @param keyBytes the bytes of the key to use for the cipher. + * @return a data encryptor with an initialised cipher. + * @throws PGPException if an error occurs initialising the configured encryption. + */ PGPDataEncryptor build(byte[] keyBytes) throws PGPException; + /** + * Gets the SecureRandom instance used by this builder.
+ * If a SecureRandom has not been explicitly configured, a default {@link SecureRandom} is + * constructed and retained by the this builder. + */ SecureRandom getSecureRandom(); } diff --git a/pg/src/main/java/org/bouncycastle/openpgp/operator/PGPDigestCalculator.java b/pg/src/main/java/org/bouncycastle/openpgp/operator/PGPDigestCalculator.java index a917a55b60..70efe8a6f1 100644 --- a/pg/src/main/java/org/bouncycastle/openpgp/operator/PGPDigestCalculator.java +++ b/pg/src/main/java/org/bouncycastle/openpgp/operator/PGPDigestCalculator.java @@ -2,30 +2,35 @@ import java.io.OutputStream; +import org.bouncycastle.bcpg.HashAlgorithmTags; + +/** + * A digest calculator, which consumes a stream of data and computes a digest value over it. + */ public interface PGPDigestCalculator { /** - * Return the algorithm number representing the digest implemented by - * this calculator. - * - * @return algorithm number - */ + * Return the {@link HashAlgorithmTags algorithm number} representing the digest implemented by + * this calculator. + * + * @return the hash algorithm number + */ int getAlgorithm(); /** - * Returns a stream that will accept data for the purpose of calculating - * a digest. Use org.bouncycastle.util.io.TeeOutputStream if you want to accumulate - * the data on the fly as well. - * - * @return an OutputStream - */ + * Returns a stream that will accept data for the purpose of calculating a digest. Use + * org.bouncycastle.util.io.TeeOutputStream if you want to accumulate the data on the fly as + * well. + * + * @return an OutputStream that data to be digested can be written to. + */ OutputStream getOutputStream(); /** - * Return the digest calculated on what has been written to the calculator's output stream. - * - * @return a digest. - */ + * Return the digest calculated on what has been written to the calculator's output stream. + * + * @return a digest. + */ byte[] getDigest(); /** diff --git a/pg/src/main/java/org/bouncycastle/openpgp/operator/PGPDigestCalculatorProvider.java b/pg/src/main/java/org/bouncycastle/openpgp/operator/PGPDigestCalculatorProvider.java index bbde1ab52f..dcfce65c5b 100644 --- a/pg/src/main/java/org/bouncycastle/openpgp/operator/PGPDigestCalculatorProvider.java +++ b/pg/src/main/java/org/bouncycastle/openpgp/operator/PGPDigestCalculatorProvider.java @@ -1,9 +1,21 @@ package org.bouncycastle.openpgp.operator; +import org.bouncycastle.bcpg.HashAlgorithmTags; import org.bouncycastle.openpgp.PGPException; +/** + * A factory for digest algorithms. + */ public interface PGPDigestCalculatorProvider { + /** + * Construct a new instance of a cryptographic digest. + * + * @param algorithm the identifier of the {@link HashAlgorithmTags digest algorithm} to + * instantiate. + * @return a digest calculator for the specified algorithm. + * @throws PGPException if an error occurs constructing the specified digest. + */ PGPDigestCalculator get(int algorithm) throws PGPException; } diff --git a/pg/src/main/java/org/bouncycastle/openpgp/operator/PGPKeyEncryptionMethodGenerator.java b/pg/src/main/java/org/bouncycastle/openpgp/operator/PGPKeyEncryptionMethodGenerator.java index 0cffaa53b2..97e703d6db 100644 --- a/pg/src/main/java/org/bouncycastle/openpgp/operator/PGPKeyEncryptionMethodGenerator.java +++ b/pg/src/main/java/org/bouncycastle/openpgp/operator/PGPKeyEncryptionMethodGenerator.java @@ -1,10 +1,23 @@ package org.bouncycastle.openpgp.operator; import org.bouncycastle.bcpg.ContainedPacket; +import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags; +import org.bouncycastle.openpgp.PGPEncryptedDataGenerator; import org.bouncycastle.openpgp.PGPException; +/** + * An encryption method that can be applied to encrypt data in a {@link PGPEncryptedDataGenerator}. + */ public abstract class PGPKeyEncryptionMethodGenerator { + /** + * Generates a packet encoding the details of this encryption method. + * + * @param encAlgorithm the {@link SymmetricKeyAlgorithmTags encryption algorithm} being used + * @param sessionInfo session data generated by the encrypted data generator. + * @return a packet encoding the provided information and the configuration of this instance. + * @throws PGPException if an error occurs constructing the packet. + */ public abstract ContainedPacket generate(int encAlgorithm, byte[] sessionInfo) throws PGPException; } diff --git a/pg/src/main/java/org/bouncycastle/openpgp/operator/PGPUtil.java b/pg/src/main/java/org/bouncycastle/openpgp/operator/PGPUtil.java index 0cbe5d8741..fc9d4c10bb 100644 --- a/pg/src/main/java/org/bouncycastle/openpgp/operator/PGPUtil.java +++ b/pg/src/main/java/org/bouncycastle/openpgp/operator/PGPUtil.java @@ -22,6 +22,7 @@ static byte[] makeKeyFromPassPhrase( char[] passPhrase) throws PGPException { + // TODO: Never used String algName = null; int keySize = 0; diff --git a/pg/src/main/java/org/bouncycastle/openpgp/operator/bc/BcPBEDataDecryptorFactory.java b/pg/src/main/java/org/bouncycastle/openpgp/operator/bc/BcPBEDataDecryptorFactory.java index 81449ebcc0..fdc143b716 100644 --- a/pg/src/main/java/org/bouncycastle/openpgp/operator/bc/BcPBEDataDecryptorFactory.java +++ b/pg/src/main/java/org/bouncycastle/openpgp/operator/bc/BcPBEDataDecryptorFactory.java @@ -7,7 +7,8 @@ import org.bouncycastle.openpgp.operator.PGPDataDecryptor; /** - * A decryptor factory for handling PBE decryption operations. + * A {@link PBEDataDecryptorFactory} for handling PBE decryption operations using the Bouncy Castle + * lightweight API to implement cryptographic primitives. */ public class BcPBEDataDecryptorFactory extends PBEDataDecryptorFactory diff --git a/pg/src/main/java/org/bouncycastle/openpgp/operator/bc/BcPBEKeyEncryptionMethodGenerator.java b/pg/src/main/java/org/bouncycastle/openpgp/operator/bc/BcPBEKeyEncryptionMethodGenerator.java index 0a965fe6d6..17aa28cc24 100644 --- a/pg/src/main/java/org/bouncycastle/openpgp/operator/bc/BcPBEKeyEncryptionMethodGenerator.java +++ b/pg/src/main/java/org/bouncycastle/openpgp/operator/bc/BcPBEKeyEncryptionMethodGenerator.java @@ -2,6 +2,7 @@ import java.security.SecureRandom; +import org.bouncycastle.bcpg.S2K; import org.bouncycastle.crypto.BlockCipher; import org.bouncycastle.crypto.BufferedBlockCipher; import org.bouncycastle.crypto.InvalidCipherTextException; @@ -16,10 +17,11 @@ public class BcPBEKeyEncryptionMethodGenerator extends PBEKeyEncryptionMethodGenerator { /** - * Create a PBE encryption method generator using the provided calculator for key calculation. + * Create a PBE encryption method generator using the provided digest and the default S2K count + * for key generation. * - * @param passPhrase the passphrase to use as the primary source of key material. - * @param s2kDigestCalculator the digest calculator to use for key calculation. + * @param passPhrase the passphrase to use as the primary source of key material. + * @param s2kDigestCalculator the digest calculator to use for key calculation. */ public BcPBEKeyEncryptionMethodGenerator(char[] passPhrase, PGPDigestCalculator s2kDigestCalculator) { @@ -27,9 +29,10 @@ public BcPBEKeyEncryptionMethodGenerator(char[] passPhrase, PGPDigestCalculator } /** - * Create a PBE encryption method generator using the default SHA-1 digest calculator for key calculation. + * Create a PBE encryption method generator using the default SHA-1 digest and the default S2K + * count for key generation. * - * @param passPhrase the passphrase to use as the primary source of key material. + * @param passPhrase the passphrase to use as the primary source of key material. */ public BcPBEKeyEncryptionMethodGenerator(char[] passPhrase) { @@ -37,11 +40,12 @@ public BcPBEKeyEncryptionMethodGenerator(char[] passPhrase) } /** - * Create a PBE encryption method generator using the provided calculator and S2K count for key calculation. - * - * @param passPhrase the passphrase to use as the primary source of key material. - * @param s2kDigestCalculator the digest calculator to use for key calculation. - * @param s2kCount the S2K count to use. + * Create a PBE encryption method generator using the provided calculator and S2K count for key + * generation. + * + * @param passPhrase the passphrase to use as the primary source of key material. + * @param s2kDigestCalculator the digest calculator to use for key calculation. + * @param s2kCount the single byte {@link S2K} count to use. */ public BcPBEKeyEncryptionMethodGenerator(char[] passPhrase, PGPDigestCalculator s2kDigestCalculator, int s2kCount) { @@ -49,23 +53,17 @@ public BcPBEKeyEncryptionMethodGenerator(char[] passPhrase, PGPDigestCalculator } /** - * Create a PBE encryption method generator using the default SHA-1 digest calculator and - * a S2K count other than the default of 0x60 for key calculation. + * Create a PBE encryption method generator using the default SHA-1 digest calculator and a S2K + * count other than the default for key generation. * * @param passPhrase the passphrase to use as the primary source of key material. - * @param s2kCount the S2K count to use. + * @param s2kCount the single byte {@link S2K} count to use. */ public BcPBEKeyEncryptionMethodGenerator(char[] passPhrase, int s2kCount) { super(passPhrase, new SHA1PGPDigestCalculator(), s2kCount); } - /** - * Provide a user defined source of randomness. - * - * @param random the secure random to be used. - * @return the current generator. - */ public PBEKeyEncryptionMethodGenerator setSecureRandom(SecureRandom random) { super.setSecureRandom(random); diff --git a/pg/src/main/java/org/bouncycastle/openpgp/operator/bc/BcPGPDataEncryptorBuilder.java b/pg/src/main/java/org/bouncycastle/openpgp/operator/bc/BcPGPDataEncryptorBuilder.java index 51fd69d0b8..a47b311121 100644 --- a/pg/src/main/java/org/bouncycastle/openpgp/operator/bc/BcPGPDataEncryptorBuilder.java +++ b/pg/src/main/java/org/bouncycastle/openpgp/operator/bc/BcPGPDataEncryptorBuilder.java @@ -3,6 +3,7 @@ import java.io.OutputStream; import java.security.SecureRandom; +import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags; import org.bouncycastle.crypto.BlockCipher; import org.bouncycastle.crypto.BufferedBlockCipher; import org.bouncycastle.crypto.io.CipherOutputStream; @@ -11,6 +12,10 @@ import org.bouncycastle.openpgp.operator.PGPDataEncryptorBuilder; import org.bouncycastle.openpgp.operator.PGPDigestCalculator; +/** + * {@link PGPDataEncryptorBuilder} implementation that uses the Bouncy Castle lightweight API to + * implement cryptographic primitives. + */ public class BcPGPDataEncryptorBuilder implements PGPDataEncryptorBuilder { @@ -18,6 +23,12 @@ public class BcPGPDataEncryptorBuilder private boolean withIntegrityPacket; private int encAlgorithm; + /** + * Constructs a new data encryptor builder for a specified cipher type. + * + * @param encAlgorithm one of the {@link SymmetricKeyAlgorithmTags supported symmetric cipher + * algorithms}. May not be {@link SymmetricKeyAlgorithmTags#NULL}. + */ public BcPGPDataEncryptorBuilder(int encAlgorithm) { this.encAlgorithm = encAlgorithm; @@ -28,11 +39,11 @@ public BcPGPDataEncryptorBuilder(int encAlgorithm) } } - /** - * Determine whether or not the resulting encrypted data will be protected using an integrity packet. + /** + * Sets whether or not the resulting encrypted data will be protected using an integrity packet. * * @param withIntegrityPacket true if an integrity packet is to be included, false otherwise. - * @return the current builder. + * @return the current builder. */ public BcPGPDataEncryptorBuilder setWithIntegrityPacket(boolean withIntegrityPacket) { @@ -43,9 +54,11 @@ public BcPGPDataEncryptorBuilder setWithIntegrityPacket(boolean withIntegrityPac /** * Provide a user defined source of randomness. + *

+ * If no SecureRandom is configured, a default SecureRandom will be used. * - * @param random the secure random to be used. - * @return the current builder. + * @param random the secure random to be used. + * @return the current builder. */ public BcPGPDataEncryptorBuilder setSecureRandom(SecureRandom random) { diff --git a/pg/src/main/java/org/bouncycastle/openpgp/operator/jcajce/JcaKeyFingerprintCalculator.java b/pg/src/main/java/org/bouncycastle/openpgp/operator/jcajce/JcaKeyFingerprintCalculator.java index 1bcb92c483..e4fa495ea7 100644 --- a/pg/src/main/java/org/bouncycastle/openpgp/operator/jcajce/JcaKeyFingerprintCalculator.java +++ b/pg/src/main/java/org/bouncycastle/openpgp/operator/jcajce/JcaKeyFingerprintCalculator.java @@ -14,6 +14,8 @@ public class JcaKeyFingerprintCalculator implements KeyFingerPrintCalculator { + + // FIXME: Convert this to builder style so we can set provider? public byte[] calculateFingerprint(PublicKeyPacket publicPk) throws PGPException { diff --git a/pg/src/main/java/org/bouncycastle/openpgp/operator/jcajce/JcaPGPDigestCalculatorProviderBuilder.java b/pg/src/main/java/org/bouncycastle/openpgp/operator/jcajce/JcaPGPDigestCalculatorProviderBuilder.java index f743544210..1a8ccef54a 100644 --- a/pg/src/main/java/org/bouncycastle/openpgp/operator/jcajce/JcaPGPDigestCalculatorProviderBuilder.java +++ b/pg/src/main/java/org/bouncycastle/openpgp/operator/jcajce/JcaPGPDigestCalculatorProviderBuilder.java @@ -13,14 +13,31 @@ import org.bouncycastle.openpgp.operator.PGPDigestCalculator; import org.bouncycastle.openpgp.operator.PGPDigestCalculatorProvider; +/** + * A builder for {@link PGPDigestCalculatorProvider} instances that obtain cryptographic primitives + * using the JCA API. + *

+ * By default digest calculator providers obtained from this builder will use the default JCA + * algorithm lookup mechanisms (i.e. specifying no provider), but a specific provider can be + * specified prior to building. + */ public class JcaPGPDigestCalculatorProviderBuilder { private OperatorHelper helper = new OperatorHelper(new DefaultJcaJceHelper()); + /** + * Default constructor. + */ public JcaPGPDigestCalculatorProviderBuilder() { } + /** + * Sets the provider to use to obtain cryptographic primitives. + * + * @param provider the JCA provider to use. + * @return the current builder. + */ public JcaPGPDigestCalculatorProviderBuilder setProvider(Provider provider) { this.helper = new OperatorHelper(new ProviderJcaJceHelper(provider)); @@ -28,6 +45,12 @@ public JcaPGPDigestCalculatorProviderBuilder setProvider(Provider provider) return this; } + /** + * Sets the provider to use to obtain cryptographic primitives. + * + * @param providerName the name of the JCA provider to use. + * @return the current builder. + */ public JcaPGPDigestCalculatorProviderBuilder setProvider(String providerName) { this.helper = new OperatorHelper(new NamedJcaJceHelper(providerName)); @@ -35,6 +58,13 @@ public JcaPGPDigestCalculatorProviderBuilder setProvider(String providerName) return this; } + /** + * Constructs a new PGPDigestCalculatorProvider + * + * @return a PGPDigestCalculatorProvider that will use the JCA algorithm lookup strategy + * configured on this builder. + * @throws PGPException if an error occurs constructing the digest calculator provider. + */ public PGPDigestCalculatorProvider build() throws PGPException { diff --git a/pg/src/main/java/org/bouncycastle/openpgp/operator/jcajce/JcePBEDataDecryptorFactoryBuilder.java b/pg/src/main/java/org/bouncycastle/openpgp/operator/jcajce/JcePBEDataDecryptorFactoryBuilder.java index cd7118fe3c..d1ef90015b 100644 --- a/pg/src/main/java/org/bouncycastle/openpgp/operator/jcajce/JcePBEDataDecryptorFactoryBuilder.java +++ b/pg/src/main/java/org/bouncycastle/openpgp/operator/jcajce/JcePBEDataDecryptorFactoryBuilder.java @@ -14,6 +14,10 @@ import org.bouncycastle.openpgp.operator.PGPDataDecryptor; import org.bouncycastle.openpgp.operator.PGPDigestCalculatorProvider; +/** + * Builder for {@link PBEDataDecryptorFactory} instances that obtain cryptographic primitives using + * the JCE API. + */ public class JcePBEDataDecryptorFactoryBuilder { private OperatorHelper helper = new OperatorHelper(new DefaultJcaJceHelper()); @@ -55,6 +59,12 @@ public JcePBEDataDecryptorFactoryBuilder setProvider(String providerName) return this; } + /** + * Construct a {@link PBEDataDecryptorFactory} to use to decrypt PBE encrypted data. + * + * @param passPhrase the pass phrase to use to generate keys in the resulting factory. + * @return a decryptor factory that can be used to generate PBE keys. + */ public PBEDataDecryptorFactory build(char[] passPhrase) { return new PBEDataDecryptorFactory(passPhrase, calculatorProvider) diff --git a/pg/src/main/java/org/bouncycastle/openpgp/operator/jcajce/JcePBEKeyEncryptionMethodGenerator.java b/pg/src/main/java/org/bouncycastle/openpgp/operator/jcajce/JcePBEKeyEncryptionMethodGenerator.java index 851c0a7965..71429f9643 100644 --- a/pg/src/main/java/org/bouncycastle/openpgp/operator/jcajce/JcePBEKeyEncryptionMethodGenerator.java +++ b/pg/src/main/java/org/bouncycastle/openpgp/operator/jcajce/JcePBEKeyEncryptionMethodGenerator.java @@ -12,6 +12,7 @@ import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; +import org.bouncycastle.bcpg.S2K; import org.bouncycastle.jcajce.util.DefaultJcaJceHelper; import org.bouncycastle.jcajce.util.NamedJcaJceHelper; import org.bouncycastle.jcajce.util.ProviderJcaJceHelper; @@ -28,10 +29,11 @@ public class JcePBEKeyEncryptionMethodGenerator private OperatorHelper helper = new OperatorHelper(new DefaultJcaJceHelper()); /** - * Create a PBE encryption method generator using the provided calculator for key calculation. + * Create a PBE encryption method generator using the provided digest and the default S2K count + * for key generation. * - * @param passPhrase the passphrase to use as the primary source of key material. - * @param s2kDigestCalculator the digest calculator to use for key calculation. + * @param passPhrase the passphrase to use as the primary source of key material. + * @param s2kDigestCalculator the digest calculator to use for key calculation. */ public JcePBEKeyEncryptionMethodGenerator(char[] passPhrase, PGPDigestCalculator s2kDigestCalculator) { @@ -39,9 +41,10 @@ public JcePBEKeyEncryptionMethodGenerator(char[] passPhrase, PGPDigestCalculator } /** - * Create a PBE encryption method generator using the default SHA-1 digest calculator for key calculation. + * Create a PBE encryption method generator using the default SHA-1 digest and the default S2K + * count for key generation. * - * @param passPhrase the passphrase to use as the primary source of key material. + * @param passPhrase the passphrase to use as the primary source of key material. */ public JcePBEKeyEncryptionMethodGenerator(char[] passPhrase) { @@ -49,11 +52,12 @@ public JcePBEKeyEncryptionMethodGenerator(char[] passPhrase) } /** - * Create a PBE encryption method generator using the provided calculator and S2K count for key calculation. + * Create a PBE encryption method generator using the provided calculator and S2K count for key + * generation. * - * @param passPhrase the passphrase to use as the primary source of key material. - * @param s2kDigestCalculator the digest calculator to use for key calculation. - * @param s2kCount the S2K count to use. + * @param passPhrase the passphrase to use as the primary source of key material. + * @param s2kDigestCalculator the digest calculator to use for key calculation. + * @param s2kCount the single byte {@link S2K} count to use. */ public JcePBEKeyEncryptionMethodGenerator(char[] passPhrase, PGPDigestCalculator s2kDigestCalculator, int s2kCount) { @@ -61,17 +65,23 @@ public JcePBEKeyEncryptionMethodGenerator(char[] passPhrase, PGPDigestCalculator } /** - * Create a PBE encryption method generator using the default SHA-1 digest calculator and - * a S2K count other than the default of 0x60 for key calculation + * Create a PBE encryption method generator using the default SHA-1 digest calculator and a S2K + * count other than the default for key generation. * * @param passPhrase the passphrase to use as the primary source of key material. - * @param s2kCount the S2K count to use. + * @param s2kCount the single byte {@link S2K} count to use. */ public JcePBEKeyEncryptionMethodGenerator(char[] passPhrase, int s2kCount) { super(passPhrase, new SHA1PGPDigestCalculator(), s2kCount); } + /** + * Sets the JCE provider to source cryptographic primitives from. + * + * @param provider the JCE provider to use. + * @return the current generator. + */ public JcePBEKeyEncryptionMethodGenerator setProvider(Provider provider) { this.helper = new OperatorHelper(new ProviderJcaJceHelper(provider)); @@ -79,6 +89,12 @@ public JcePBEKeyEncryptionMethodGenerator setProvider(Provider provider) return this; } + /** + * Sets the JCE provider to source cryptographic primitives from. + * + * @param providerName the name of the JCE provider to use. + * @return the current generator. + */ public JcePBEKeyEncryptionMethodGenerator setProvider(String providerName) { this.helper = new OperatorHelper(new NamedJcaJceHelper(providerName)); @@ -86,12 +102,6 @@ public JcePBEKeyEncryptionMethodGenerator setProvider(String providerName) return this; } - /** - * Provide a user defined source of randomness. - * - * @param random the secure random to be used. - * @return the current generator. - */ public PBEKeyEncryptionMethodGenerator setSecureRandom(SecureRandom random) { super.setSecureRandom(random); diff --git a/pg/src/main/java/org/bouncycastle/openpgp/operator/jcajce/JcePGPDataEncryptorBuilder.java b/pg/src/main/java/org/bouncycastle/openpgp/operator/jcajce/JcePGPDataEncryptorBuilder.java index ff0380786a..f0c075cef7 100644 --- a/pg/src/main/java/org/bouncycastle/openpgp/operator/jcajce/JcePGPDataEncryptorBuilder.java +++ b/pg/src/main/java/org/bouncycastle/openpgp/operator/jcajce/JcePGPDataEncryptorBuilder.java @@ -10,6 +10,7 @@ import javax.crypto.CipherOutputStream; import javax.crypto.spec.IvParameterSpec; +import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags; import org.bouncycastle.jcajce.util.DefaultJcaJceHelper; import org.bouncycastle.jcajce.util.NamedJcaJceHelper; import org.bouncycastle.jcajce.util.ProviderJcaJceHelper; @@ -18,6 +19,14 @@ import org.bouncycastle.openpgp.operator.PGPDataEncryptorBuilder; import org.bouncycastle.openpgp.operator.PGPDigestCalculator; +/** + * {@link PGPDataEncryptorBuilder} implementation that sources cryptographic primitives using the + * JCE APIs. + *

+ * By default, cryptographic primitives will be loaded using the default JCE load order (i.e. + * without specifying a provider).
+ * A specific provider can be specified using one of the {@link #setProvider(String)} methods. + */ public class JcePGPDataEncryptorBuilder implements PGPDataEncryptorBuilder { @@ -26,6 +35,12 @@ public class JcePGPDataEncryptorBuilder private boolean withIntegrityPacket; private int encAlgorithm; + /** + * Constructs a new data encryptor builder for a specified cipher type. + * + * @param encAlgorithm one of the {@link SymmetricKeyAlgorithmTags supported symmetric cipher + * algorithms}. May not be {@link SymmetricKeyAlgorithmTags#NULL}. + */ public JcePGPDataEncryptorBuilder(int encAlgorithm) { this.encAlgorithm = encAlgorithm; @@ -37,10 +52,10 @@ public JcePGPDataEncryptorBuilder(int encAlgorithm) } /** - * Determine whether or not the resulting encrypted data will be protected using an integrity packet. + * Sets whether or not the resulting encrypted data will be protected using an integrity packet. * * @param withIntegrityPacket true if an integrity packet is to be included, false otherwise. - * @return the current builder. + * @return the current builder. */ public JcePGPDataEncryptorBuilder setWithIntegrityPacket(boolean withIntegrityPacket) { @@ -49,6 +64,12 @@ public JcePGPDataEncryptorBuilder setWithIntegrityPacket(boolean withIntegrityPa return this; } + /** + * Sets the JCE provider to source cryptographic primitives from. + * + * @param provider the JCE provider to use. + * @return the current builder. + */ public JcePGPDataEncryptorBuilder setProvider(Provider provider) { this.helper = new OperatorHelper(new ProviderJcaJceHelper(provider)); @@ -56,6 +77,12 @@ public JcePGPDataEncryptorBuilder setProvider(Provider provider) return this; } + /** + * Sets the JCE provider to source cryptographic primitives from. + * + * @param providerName the name of the JCE provider to use. + * @return the current builder. + */ public JcePGPDataEncryptorBuilder setProvider(String providerName) { this.helper = new OperatorHelper(new NamedJcaJceHelper(providerName)); @@ -65,9 +92,11 @@ public JcePGPDataEncryptorBuilder setProvider(String providerName) /** * Provide a user defined source of randomness. - * - * @param random the secure random to be used. - * @return the current builder. + *

+ * If no SecureRandom is configured, a default SecureRandom will be used. + * + * @param random the secure random to be used. + * @return the current builder. */ public JcePGPDataEncryptorBuilder setSecureRandom(SecureRandom random) { diff --git a/prov/src/main/java/org/bouncycastle/jcajce/util/DefaultJcaJceHelper.java b/prov/src/main/java/org/bouncycastle/jcajce/util/DefaultJcaJceHelper.java index 4094ba6749..43a97f3084 100644 --- a/prov/src/main/java/org/bouncycastle/jcajce/util/DefaultJcaJceHelper.java +++ b/prov/src/main/java/org/bouncycastle/jcajce/util/DefaultJcaJceHelper.java @@ -17,6 +17,10 @@ import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKeyFactory; +/** + * {@link JcaJceHelper} that obtains all algorithms using the default JCA/JCE mechanism (i.e. + * without specifying a provider). + */ public class DefaultJcaJceHelper implements JcaJceHelper { diff --git a/prov/src/main/java/org/bouncycastle/jcajce/util/JcaJceHelper.java b/prov/src/main/java/org/bouncycastle/jcajce/util/JcaJceHelper.java index 9e8125a2d2..f5da3354a6 100644 --- a/prov/src/main/java/org/bouncycastle/jcajce/util/JcaJceHelper.java +++ b/prov/src/main/java/org/bouncycastle/jcajce/util/JcaJceHelper.java @@ -18,6 +18,9 @@ import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKeyFactory; +/** + * Factory interface for instantiating JCA/JCE primitives. + */ public interface JcaJceHelper { Cipher createCipher( diff --git a/prov/src/main/java/org/bouncycastle/jcajce/util/NamedJcaJceHelper.java b/prov/src/main/java/org/bouncycastle/jcajce/util/NamedJcaJceHelper.java index 139c8bfde6..ebbfacc1ac 100644 --- a/prov/src/main/java/org/bouncycastle/jcajce/util/NamedJcaJceHelper.java +++ b/prov/src/main/java/org/bouncycastle/jcajce/util/NamedJcaJceHelper.java @@ -18,6 +18,9 @@ import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKeyFactory; +/** + * {@link JcaJceHelper} that obtains all algorithms using a specific named provider. + */ public class NamedJcaJceHelper implements JcaJceHelper { diff --git a/prov/src/main/java/org/bouncycastle/jcajce/util/ProviderJcaJceHelper.java b/prov/src/main/java/org/bouncycastle/jcajce/util/ProviderJcaJceHelper.java index d10a893411..fad10481eb 100644 --- a/prov/src/main/java/org/bouncycastle/jcajce/util/ProviderJcaJceHelper.java +++ b/prov/src/main/java/org/bouncycastle/jcajce/util/ProviderJcaJceHelper.java @@ -18,6 +18,9 @@ import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKeyFactory; +/** + * {@link JcaJceHelper} that obtains all algorithms from a specific {@link Provider} instance. + */ public class ProviderJcaJceHelper implements JcaJceHelper {