diff --git a/pg/src/main/java/org/bouncycastle/bcpg/AEADEncDataPacket.java b/pg/src/main/java/org/bouncycastle/bcpg/AEADEncDataPacket.java
index 72ee63af87..57cbf24293 100644
--- a/pg/src/main/java/org/bouncycastle/bcpg/AEADEncDataPacket.java
+++ b/pg/src/main/java/org/bouncycastle/bcpg/AEADEncDataPacket.java
@@ -23,9 +23,16 @@ public class AEADEncDataPacket
private final byte[] iv;
public AEADEncDataPacket(BCPGInputStream in)
+ throws IOException
+ {
+ this(in, false);
+ }
+
+ public AEADEncDataPacket(BCPGInputStream in,
+ boolean newPacketFormat)
throws IOException
{
- super(in, AEAD_ENC_DATA);
+ super(in, AEAD_ENC_DATA, newPacketFormat);
version = (byte)in.read();
if (version != VERSION_1)
diff --git a/pg/src/main/java/org/bouncycastle/bcpg/BCPGInputStream.java b/pg/src/main/java/org/bouncycastle/bcpg/BCPGInputStream.java
index f965ec3503..7c22b8bbfd 100644
--- a/pg/src/main/java/org/bouncycastle/bcpg/BCPGInputStream.java
+++ b/pg/src/main/java/org/bouncycastle/bcpg/BCPGInputStream.java
@@ -264,52 +264,52 @@ else if (l == 255)
switch (tag)
{
case RESERVED:
- return new ReservedPacket(objStream);
+ return new ReservedPacket(objStream, newPacket);
case PUBLIC_KEY_ENC_SESSION:
- return new PublicKeyEncSessionPacket(objStream);
+ return new PublicKeyEncSessionPacket(objStream, newPacket);
case SIGNATURE:
- return new SignaturePacket(objStream);
+ return new SignaturePacket(objStream, newPacket);
case SYMMETRIC_KEY_ENC_SESSION:
- return new SymmetricKeyEncSessionPacket(objStream);
+ return new SymmetricKeyEncSessionPacket(objStream, newPacket);
case ONE_PASS_SIGNATURE:
- return new OnePassSignaturePacket(objStream);
+ return new OnePassSignaturePacket(objStream, newPacket);
case SECRET_KEY:
- return new SecretKeyPacket(objStream);
+ return new SecretKeyPacket(objStream, newPacket);
case PUBLIC_KEY:
- return new PublicKeyPacket(objStream);
+ return new PublicKeyPacket(objStream, newPacket);
case SECRET_SUBKEY:
- return new SecretSubkeyPacket(objStream);
+ return new SecretSubkeyPacket(objStream, newPacket);
case COMPRESSED_DATA:
- return new CompressedDataPacket(objStream);
+ return new CompressedDataPacket(objStream, newPacket);
case SYMMETRIC_KEY_ENC:
- return new SymmetricEncDataPacket(objStream);
+ return new SymmetricEncDataPacket(objStream, newPacket);
case MARKER:
- return new MarkerPacket(objStream);
+ return new MarkerPacket(objStream, newPacket);
case LITERAL_DATA:
- return new LiteralDataPacket(objStream);
+ return new LiteralDataPacket(objStream, newPacket);
case TRUST:
- return new TrustPacket(objStream);
+ return new TrustPacket(objStream, newPacket);
case USER_ID:
- return new UserIDPacket(objStream);
+ return new UserIDPacket(objStream, newPacket);
case USER_ATTRIBUTE:
- return new UserAttributePacket(objStream);
+ return new UserAttributePacket(objStream, newPacket);
case PUBLIC_SUBKEY:
- return new PublicSubkeyPacket(objStream);
+ return new PublicSubkeyPacket(objStream, newPacket);
case SYM_ENC_INTEGRITY_PRO:
- return new SymmetricEncIntegrityPacket(objStream);
+ return new SymmetricEncIntegrityPacket(objStream, newPacket);
case MOD_DETECTION_CODE:
- return new ModDetectionCodePacket(objStream);
+ return new ModDetectionCodePacket(objStream, newPacket);
case AEAD_ENC_DATA:
- return new AEADEncDataPacket(objStream);
+ return new AEADEncDataPacket(objStream, newPacket);
case PADDING:
- return new PaddingPacket(objStream);
+ return new PaddingPacket(objStream, newPacket);
case EXPERIMENTAL_1:
case EXPERIMENTAL_2:
case EXPERIMENTAL_3:
case EXPERIMENTAL_4:
- return new ExperimentalPacket(tag, objStream);
+ return new ExperimentalPacket(tag, objStream, newPacket);
default:
- return new UnknownPacket(tag, objStream);
+ return new UnknownPacket(tag, objStream, newPacket);
}
}
diff --git a/pg/src/main/java/org/bouncycastle/bcpg/BCPGOutputStream.java b/pg/src/main/java/org/bouncycastle/bcpg/BCPGOutputStream.java
index 6ce35b7454..63996321a8 100644
--- a/pg/src/main/java/org/bouncycastle/bcpg/BCPGOutputStream.java
+++ b/pg/src/main/java/org/bouncycastle/bcpg/BCPGOutputStream.java
@@ -29,7 +29,7 @@ public static BCPGOutputStream wrap(OutputStream out)
}
OutputStream out;
- private boolean useOldFormat;
+ private PacketFormat packetFormat;
private byte[] partialBuffer;
private int partialBufferLength;
private int partialPower;
@@ -46,11 +46,11 @@ public static BCPGOutputStream wrap(OutputStream out)
public BCPGOutputStream(
OutputStream out)
{
- this(out, false);
+ this(out, PacketFormat.ROUNDTRIP);
}
/**
- * Base constructor specifying whether or not to use packets in the new format
+ * Base constructor specifying whether to use packets in the new format
* wherever possible.
*
* @param out output stream to write encoded data to.
@@ -59,9 +59,16 @@ public BCPGOutputStream(
public BCPGOutputStream(
OutputStream out,
boolean newFormatOnly)
+ {
+ this(out, newFormatOnly ? PacketFormat.CURRENT : PacketFormat.ROUNDTRIP);
+ }
+
+ public BCPGOutputStream(
+ OutputStream out,
+ PacketFormat packetFormat)
{
this.out = out;
- this.useOldFormat = !newFormatOnly;
+ this.packetFormat = packetFormat;
}
/**
@@ -75,6 +82,7 @@ public BCPGOutputStream(
throws IOException
{
this.out = out;
+ this.packetFormat = PacketFormat.LEGACY;
this.writeHeader(tag, true, true, 0);
}
@@ -95,6 +103,7 @@ public BCPGOutputStream(
throws IOException
{
this.out = out;
+ this.packetFormat = oldFormat ? PacketFormat.LEGACY : PacketFormat.CURRENT;
if (length > 0xFFFFFFFFL)
{
@@ -122,6 +131,7 @@ public BCPGOutputStream(
throws IOException
{
this.out = out;
+ this.packetFormat = PacketFormat.CURRENT;
this.writeHeader(tag, false, false, length);
}
@@ -141,6 +151,7 @@ public BCPGOutputStream(
throws IOException
{
this.out = out;
+ this.packetFormat = PacketFormat.CURRENT;
this.writeHeader(tag, false, true, 0);
this.partialBuffer = buffer;
@@ -316,6 +327,11 @@ public void write(
}
}
+ /**
+ * Write a packet to the stream.
+ * @param p packet
+ * @throws IOException
+ */
public void writePacket(
ContainedPacket p)
throws IOException
@@ -323,15 +339,54 @@ public void writePacket(
p.encode(this);
}
+ /**
+ * Write a packet to the stream.
+ * The packet will use the old encoding format if {@link #packetFormat} is {@link PacketFormat#LEGACY}, otherwise
+ * it will be encoded using the new packet format.
+ * @param tag packet tag
+ * @param body packet body
+ * @throws IOException
+ */
void writePacket(
int tag,
byte[] body)
throws IOException
{
- this.writeHeader(tag, useOldFormat, false, body.length);
+ this.writeHeader(tag, packetFormat == PacketFormat.LEGACY, false, body.length);
this.write(body);
}
+ /**
+ * Write a packet.
+ * The packet format will be chosen primarily based on {@link #packetFormat}.
+ * If {@link #packetFormat} is {@link PacketFormat#CURRENT}, the packet will be encoded using the new format.
+ * If it is {@link PacketFormat#LEGACY}, the packet will use old encoding format.
+ * If it is {@link PacketFormat#ROUNDTRIP}, then the format will be determined by objectPrefersNewPacketFormat.
+ *
+ * @param objectPrefersNewPacketFormat whether the packet prefers to be encoded using the new packet format
+ * @param tag packet tag
+ * @param body packet body
+ * @throws IOException
+ */
+ void writePacket(
+ boolean objectPrefersNewPacketFormat,
+ int tag,
+ byte[] body)
+ throws IOException
+ {
+ boolean oldPacketFormat = packetFormat == PacketFormat.LEGACY ||
+ (packetFormat == PacketFormat.ROUNDTRIP && !objectPrefersNewPacketFormat);
+ this.writeHeader(tag, oldPacketFormat, false, body.length);
+ this.write(body);
+ }
+
+ /**
+ * Write a packet, forcing the packet format to be either old or new.
+ * @param tag packet tag
+ * @param body packet body
+ * @param oldFormat if true, old format is forced, else force new format
+ * @throws IOException
+ */
void writePacket(
int tag,
byte[] body,
@@ -379,4 +434,5 @@ public void close()
out.flush();
out.close();
}
+
}
diff --git a/pg/src/main/java/org/bouncycastle/bcpg/CompressedDataPacket.java b/pg/src/main/java/org/bouncycastle/bcpg/CompressedDataPacket.java
index 9dcafaa61c..accd96445c 100644
--- a/pg/src/main/java/org/bouncycastle/bcpg/CompressedDataPacket.java
+++ b/pg/src/main/java/org/bouncycastle/bcpg/CompressedDataPacket.java
@@ -11,10 +11,18 @@ public class CompressedDataPacket
int algorithm;
CompressedDataPacket(
- BCPGInputStream in)
+ BCPGInputStream in)
+ throws IOException
+ {
+ this(in, false);
+ }
+
+ CompressedDataPacket(
+ BCPGInputStream in,
+ boolean newPacketFormat)
throws IOException
{
- super(in, COMPRESSED_DATA);
+ super(in, COMPRESSED_DATA, newPacketFormat);
algorithm = in.read();
}
diff --git a/pg/src/main/java/org/bouncycastle/bcpg/ContainedPacket.java b/pg/src/main/java/org/bouncycastle/bcpg/ContainedPacket.java
index 27c82a5e4d..8f87a96af7 100644
--- a/pg/src/main/java/org/bouncycastle/bcpg/ContainedPacket.java
+++ b/pg/src/main/java/org/bouncycastle/bcpg/ContainedPacket.java
@@ -12,21 +12,30 @@ public abstract class ContainedPacket
extends Packet
implements Encodable
{
+
ContainedPacket(int packetTag)
{
- super(packetTag);
+ this(packetTag, false);
+ }
+
+ ContainedPacket(int packetTag, boolean newPacketFormat)
+ {
+ super(packetTag, newPacketFormat);
}
public byte[] getEncoded()
throws IOException
{
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- BCPGOutputStream pOut = new BCPGOutputStream(bOut);
-
- pOut.writePacket(this);
+ return getEncoded(PacketFormat.ROUNDTRIP);
+ }
+ public byte[] getEncoded(PacketFormat format)
+ throws IOException
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ BCPGOutputStream pOut = new BCPGOutputStream(bOut, format);
+ pOut.writePacket(this);
pOut.close();
-
return bOut.toByteArray();
}
diff --git a/pg/src/main/java/org/bouncycastle/bcpg/ExperimentalPacket.java b/pg/src/main/java/org/bouncycastle/bcpg/ExperimentalPacket.java
index 927b1bade9..b787b02ba9 100644
--- a/pg/src/main/java/org/bouncycastle/bcpg/ExperimentalPacket.java
+++ b/pg/src/main/java/org/bouncycastle/bcpg/ExperimentalPacket.java
@@ -11,7 +11,20 @@ public class ExperimentalPacket
extends ContainedPacket implements PublicKeyAlgorithmTags
{
private byte[] contents;
-
+
+ /**
+ *
+ * @param in
+ * @throws IOException
+ */
+ ExperimentalPacket(
+ int tag,
+ BCPGInputStream in)
+ throws IOException
+ {
+ this(tag, in, false);
+ }
+
/**
*
* @param in
@@ -19,10 +32,11 @@ public class ExperimentalPacket
*/
ExperimentalPacket(
int tag,
- BCPGInputStream in)
+ BCPGInputStream in,
+ boolean newPacketFormat)
throws IOException
{
- super(tag);
+ super(tag, newPacketFormat);
this.contents = in.readAll();
}
@@ -44,6 +58,6 @@ public void encode(
BCPGOutputStream out)
throws IOException
{
- out.writePacket(getPacketTag(), contents);
+ out.writePacket(hasNewPacketFormat(), getPacketTag(), contents);
}
}
diff --git a/pg/src/main/java/org/bouncycastle/bcpg/InputStreamPacket.java b/pg/src/main/java/org/bouncycastle/bcpg/InputStreamPacket.java
index f042703be2..2dfb9b87af 100644
--- a/pg/src/main/java/org/bouncycastle/bcpg/InputStreamPacket.java
+++ b/pg/src/main/java/org/bouncycastle/bcpg/InputStreamPacket.java
@@ -22,8 +22,15 @@ public InputStreamPacket(
BCPGInputStream in,
int packetTag)
{
- super(packetTag);
-
+ this(in, packetTag, false);
+ }
+
+ InputStreamPacket(
+ BCPGInputStream in,
+ int packetTag,
+ boolean newPacketFormat)
+ {
+ super(packetTag, newPacketFormat);
this.in = in;
}
diff --git a/pg/src/main/java/org/bouncycastle/bcpg/LiteralDataPacket.java b/pg/src/main/java/org/bouncycastle/bcpg/LiteralDataPacket.java
index 16e64c377b..3446c27f60 100644
--- a/pg/src/main/java/org/bouncycastle/bcpg/LiteralDataPacket.java
+++ b/pg/src/main/java/org/bouncycastle/bcpg/LiteralDataPacket.java
@@ -16,10 +16,18 @@ public class LiteralDataPacket
long modDate;
LiteralDataPacket(
- BCPGInputStream in)
+ BCPGInputStream in)
+ throws IOException
+ {
+ this(in, false);
+ }
+
+ LiteralDataPacket(
+ BCPGInputStream in,
+ boolean newPacketFormat)
throws IOException
{
- super(in, LITERAL_DATA);
+ super(in, LITERAL_DATA, newPacketFormat);
format = in.read();
int l = in.read();
diff --git a/pg/src/main/java/org/bouncycastle/bcpg/MarkerPacket.java b/pg/src/main/java/org/bouncycastle/bcpg/MarkerPacket.java
index 2f4a8da428..dad7658e3f 100644
--- a/pg/src/main/java/org/bouncycastle/bcpg/MarkerPacket.java
+++ b/pg/src/main/java/org/bouncycastle/bcpg/MarkerPacket.java
@@ -13,10 +13,18 @@ public class MarkerPacket
byte[] marker = {(byte)0x50, (byte)0x47, (byte)0x50};
public MarkerPacket(
- BCPGInputStream in)
+ BCPGInputStream in)
+ throws IOException
+ {
+ this(in, false);
+ }
+
+ public MarkerPacket(
+ BCPGInputStream in,
+ boolean newPacketFormat)
throws IOException
{
- super(MARKER);
+ super(MARKER, newPacketFormat);
in.readFully(marker);
}
@@ -25,6 +33,6 @@ public void encode(
BCPGOutputStream out)
throws IOException
{
- out.writePacket(MARKER, marker);
+ out.writePacket(hasNewPacketFormat(), MARKER, marker);
}
}
diff --git a/pg/src/main/java/org/bouncycastle/bcpg/ModDetectionCodePacket.java b/pg/src/main/java/org/bouncycastle/bcpg/ModDetectionCodePacket.java
index 7e837b510f..2fcef653da 100644
--- a/pg/src/main/java/org/bouncycastle/bcpg/ModDetectionCodePacket.java
+++ b/pg/src/main/java/org/bouncycastle/bcpg/ModDetectionCodePacket.java
@@ -9,12 +9,20 @@ public class ModDetectionCodePacket
extends ContainedPacket
{
private byte[] digest;
-
+
ModDetectionCodePacket(
- BCPGInputStream in)
+ BCPGInputStream in)
+ throws IOException
+ {
+ this(in, false);
+ }
+
+ ModDetectionCodePacket(
+ BCPGInputStream in,
+ boolean newPacketFormat)
throws IOException
{
- super(MOD_DETECTION_CODE);
+ super(MOD_DETECTION_CODE, newPacketFormat);
this.digest = new byte[20];
in.readFully(this.digest);
@@ -44,6 +52,6 @@ public void encode(
BCPGOutputStream out)
throws IOException
{
- out.writePacket(MOD_DETECTION_CODE, digest, false);
+ out.writePacket(hasNewPacketFormat(), MOD_DETECTION_CODE, digest);
}
}
diff --git a/pg/src/main/java/org/bouncycastle/bcpg/OnePassSignaturePacket.java b/pg/src/main/java/org/bouncycastle/bcpg/OnePassSignaturePacket.java
index cf6189fdd4..218ffa788b 100644
--- a/pg/src/main/java/org/bouncycastle/bcpg/OnePassSignaturePacket.java
+++ b/pg/src/main/java/org/bouncycastle/bcpg/OnePassSignaturePacket.java
@@ -45,10 +45,18 @@ public class OnePassSignaturePacket
* @throws IOException when the end of stream is prematurely reached, or when the packet is malformed
*/
OnePassSignaturePacket(
- BCPGInputStream in)
+ BCPGInputStream in)
+ throws IOException
+ {
+ this(in, false);
+ }
+
+ OnePassSignaturePacket(
+ BCPGInputStream in,
+ boolean newPacketFormat)
throws IOException
{
- super(ONE_PASS_SIGNATURE);
+ super(ONE_PASS_SIGNATURE, newPacketFormat);
version = in.read();
sigType = in.read();
@@ -274,7 +282,7 @@ else if (version == VERSION_6)
pOut.close();
- out.writePacket(ONE_PASS_SIGNATURE, bOut.toByteArray());
+ out.writePacket(hasNewPacketFormat(), ONE_PASS_SIGNATURE, bOut.toByteArray());
}
}
diff --git a/pg/src/main/java/org/bouncycastle/bcpg/Packet.java b/pg/src/main/java/org/bouncycastle/bcpg/Packet.java
index 3356c04650..697683c14c 100644
--- a/pg/src/main/java/org/bouncycastle/bcpg/Packet.java
+++ b/pg/src/main/java/org/bouncycastle/bcpg/Packet.java
@@ -6,6 +6,7 @@ public class Packet
implements PacketTags
{
private final int packetTag;
+ private final boolean newPacketFormat;
// for API compatibility
public Packet()
@@ -14,8 +15,14 @@ public Packet()
}
Packet(int packetTag)
+ {
+ this(packetTag, false);
+ }
+
+ Packet(int packetTag, boolean newPacketFormat)
{
this.packetTag = packetTag;
+ this.newPacketFormat = newPacketFormat;
}
/**
@@ -28,6 +35,17 @@ public final int getPacketTag()
return packetTag;
}
+ /**
+ * Return true, if this instance of a packet was encoded using the new packet format.
+ * If the packet was encoded using the old legacy format, return false instead.
+ *
+ * @return true if new packet format encoding is used
+ */
+ public boolean hasNewPacketFormat()
+ {
+ return newPacketFormat;
+ }
+
/**
* Returns whether the packet is to be considered critical for v6 implementations.
* Packets with tags less or equal to 39 are critical.
diff --git a/pg/src/main/java/org/bouncycastle/bcpg/PacketFormat.java b/pg/src/main/java/org/bouncycastle/bcpg/PacketFormat.java
new file mode 100644
index 0000000000..61f62d0340
--- /dev/null
+++ b/pg/src/main/java/org/bouncycastle/bcpg/PacketFormat.java
@@ -0,0 +1,26 @@
+package org.bouncycastle.bcpg;
+
+/**
+ * OpenPGP Packet Header Length Format.
+ *
+ * @see
+ * OpenPGP Packet Headers
+ */
+public enum PacketFormat
+{
+ /**
+ * Always use the old (legacy) packet format.
+ */
+ LEGACY,
+
+ /**
+ * Always use the current (new) packet format.
+ */
+ CURRENT,
+
+ /**
+ * Let the individual packet decide the format (see {@link Packet#hasNewPacketFormat()}).
+ * This allows to round-trip packets without changing the packet format.
+ */
+ ROUNDTRIP
+}
diff --git a/pg/src/main/java/org/bouncycastle/bcpg/PaddingPacket.java b/pg/src/main/java/org/bouncycastle/bcpg/PaddingPacket.java
index e50b863eaf..bd45514606 100644
--- a/pg/src/main/java/org/bouncycastle/bcpg/PaddingPacket.java
+++ b/pg/src/main/java/org/bouncycastle/bcpg/PaddingPacket.java
@@ -12,16 +12,22 @@ public class PaddingPacket
private final byte[] padding;
public PaddingPacket(BCPGInputStream in)
+ throws IOException
+ {
+ this(in, true);
+ }
+
+ public PaddingPacket(BCPGInputStream in, boolean newPacketFormat)
throws IOException
{
- super(PADDING);
+ super(PADDING, newPacketFormat);
padding = Streams.readAll(in);
}
public PaddingPacket(byte[] padding)
{
- super(PADDING);
+ super(PADDING, true);
this.padding = padding;
}
@@ -47,6 +53,6 @@ public byte[] getPadding()
public void encode(BCPGOutputStream pOut)
throws IOException
{
- pOut.writePacket(PacketTags.PADDING, padding);
+ pOut.writePacket(hasNewPacketFormat(), PacketTags.PADDING, padding);
}
}
diff --git a/pg/src/main/java/org/bouncycastle/bcpg/PublicKeyEncSessionPacket.java b/pg/src/main/java/org/bouncycastle/bcpg/PublicKeyEncSessionPacket.java
index 072bcdfdeb..b75dc5e4c3 100644
--- a/pg/src/main/java/org/bouncycastle/bcpg/PublicKeyEncSessionPacket.java
+++ b/pg/src/main/java/org/bouncycastle/bcpg/PublicKeyEncSessionPacket.java
@@ -33,10 +33,18 @@ public class PublicKeyEncSessionPacket
private byte[] keyFingerprint; // v6
PublicKeyEncSessionPacket(
- BCPGInputStream in)
+ BCPGInputStream in)
+ throws IOException
+ {
+ this(in, false);
+ }
+
+ PublicKeyEncSessionPacket(
+ BCPGInputStream in,
+ boolean newPacketFormat)
throws IOException
{
- super(PUBLIC_KEY_ENC_SESSION);
+ super(PUBLIC_KEY_ENC_SESSION, newPacketFormat);
version = in.read();
@@ -271,6 +279,6 @@ else if (version == VERSION_6)
pOut.close();
- out.writePacket(PUBLIC_KEY_ENC_SESSION, bOut.toByteArray());
+ out.writePacket(hasNewPacketFormat(), PUBLIC_KEY_ENC_SESSION, bOut.toByteArray());
}
}
diff --git a/pg/src/main/java/org/bouncycastle/bcpg/PublicKeyPacket.java b/pg/src/main/java/org/bouncycastle/bcpg/PublicKeyPacket.java
index 0026365b9a..f67e546836 100644
--- a/pg/src/main/java/org/bouncycastle/bcpg/PublicKeyPacket.java
+++ b/pg/src/main/java/org/bouncycastle/bcpg/PublicKeyPacket.java
@@ -1,5 +1,7 @@
package org.bouncycastle.bcpg;
+import sun.jvm.hotspot.types.JBooleanField;
+
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Date;
@@ -22,18 +24,34 @@ public class PublicKeyPacket
private BCPGKey key;
PublicKeyPacket(
- BCPGInputStream in)
+ BCPGInputStream in)
+ throws IOException
+ {
+ this(in, false);
+ }
+ PublicKeyPacket(
+ BCPGInputStream in,
+ boolean newPacketFormat)
throws IOException
{
- this(PUBLIC_KEY, in);
+ this(PUBLIC_KEY, in, newPacketFormat);
+ }
+
+ PublicKeyPacket(
+ int keyTag,
+ BCPGInputStream in)
+ throws IOException
+ {
+ this(keyTag, in, false);
}
PublicKeyPacket(
int keyTag,
- BCPGInputStream in)
+ BCPGInputStream in,
+ boolean newPacketFormat)
throws IOException
{
- super(keyTag);
+ super(keyTag, newPacketFormat);
version = in.read();
time = ((long)in.read() << 24) | (in.read() << 16) | (in.read() << 8) | in.read();
@@ -188,6 +206,6 @@ public void encode(
BCPGOutputStream out)
throws IOException
{
- out.writePacket(getPacketTag(), getEncodedContents());
+ out.writePacket(hasNewPacketFormat(), getPacketTag(), getEncodedContents());
}
}
diff --git a/pg/src/main/java/org/bouncycastle/bcpg/PublicSubkeyPacket.java b/pg/src/main/java/org/bouncycastle/bcpg/PublicSubkeyPacket.java
index ea02f07f59..bcf62bc0a5 100644
--- a/pg/src/main/java/org/bouncycastle/bcpg/PublicSubkeyPacket.java
+++ b/pg/src/main/java/org/bouncycastle/bcpg/PublicSubkeyPacket.java
@@ -9,11 +9,20 @@
public class PublicSubkeyPacket
extends PublicKeyPacket
{
+
+ PublicSubkeyPacket(
+ BCPGInputStream in)
+ throws IOException
+ {
+ this(in, false);
+ }
+
PublicSubkeyPacket(
- BCPGInputStream in)
+ BCPGInputStream in,
+ boolean newPacketFormat)
throws IOException
{
- super(PUBLIC_SUBKEY, in);
+ super(PUBLIC_SUBKEY, in, newPacketFormat);
}
/**
diff --git a/pg/src/main/java/org/bouncycastle/bcpg/ReservedPacket.java b/pg/src/main/java/org/bouncycastle/bcpg/ReservedPacket.java
index cf2f597c2f..bc766b6864 100644
--- a/pg/src/main/java/org/bouncycastle/bcpg/ReservedPacket.java
+++ b/pg/src/main/java/org/bouncycastle/bcpg/ReservedPacket.java
@@ -5,6 +5,11 @@ public class ReservedPacket
{
public ReservedPacket(BCPGInputStream in)
{
- super(in, RESERVED);
+ this(in, false);
+ }
+
+ public ReservedPacket(BCPGInputStream in, boolean newPacketFormat)
+ {
+ super(in, RESERVED, newPacketFormat);
}
}
diff --git a/pg/src/main/java/org/bouncycastle/bcpg/SecretKeyPacket.java b/pg/src/main/java/org/bouncycastle/bcpg/SecretKeyPacket.java
index decb8a1214..198d3333b0 100644
--- a/pg/src/main/java/org/bouncycastle/bcpg/SecretKeyPacket.java
+++ b/pg/src/main/java/org/bouncycastle/bcpg/SecretKeyPacket.java
@@ -69,22 +69,43 @@ public class SecretKeyPacket
private byte[] iv;
SecretKeyPacket(
- BCPGInputStream in)
- throws IOException
+ BCPGInputStream in)
+ throws IOException
{
this(SECRET_KEY, in);
}
+ SecretKeyPacket(
+ BCPGInputStream in,
+ boolean newPacketFormat)
+ throws IOException
+ {
+ this(SECRET_KEY, in, newPacketFormat);
+ }
+
+ /**
+ * @param in
+ * @throws IOException
+ */
+ SecretKeyPacket(
+ int keyTag,
+ BCPGInputStream in)
+ throws IOException
+ {
+ this(keyTag, in, false);
+ }
+
/**
* @param in
* @throws IOException
*/
SecretKeyPacket(
int keyTag,
- BCPGInputStream in)
+ BCPGInputStream in,
+ boolean newPacketFormat)
throws IOException
{
- super(keyTag);
+ super(keyTag, newPacketFormat);
if (this instanceof SecretSubkeyPacket)
{
@@ -323,6 +344,6 @@ public void encode(
BCPGOutputStream out)
throws IOException
{
- out.writePacket(getPacketTag(), getEncodedContents());
+ out.writePacket(hasNewPacketFormat(), getPacketTag(), getEncodedContents());
}
}
diff --git a/pg/src/main/java/org/bouncycastle/bcpg/SecretSubkeyPacket.java b/pg/src/main/java/org/bouncycastle/bcpg/SecretSubkeyPacket.java
index b7610747d9..e048aa4d16 100644
--- a/pg/src/main/java/org/bouncycastle/bcpg/SecretSubkeyPacket.java
+++ b/pg/src/main/java/org/bouncycastle/bcpg/SecretSubkeyPacket.java
@@ -18,9 +18,16 @@ public class SecretSubkeyPacket
BCPGInputStream in)
throws IOException
{
- super(SECRET_SUBKEY, in);
+ this(in, false);
}
+ SecretSubkeyPacket(
+ BCPGInputStream in,
+ boolean newPacketFormat)
+ throws IOException
+ {
+ super(SECRET_SUBKEY, in, newPacketFormat);
+ }
/**
* Create a secret subkey packet.
* If the encryption algorithm is NOT {@link SymmetricKeyAlgorithmTags#NULL},
diff --git a/pg/src/main/java/org/bouncycastle/bcpg/SignaturePacket.java b/pg/src/main/java/org/bouncycastle/bcpg/SignaturePacket.java
index 52bb39e959..d716dcdae7 100644
--- a/pg/src/main/java/org/bouncycastle/bcpg/SignaturePacket.java
+++ b/pg/src/main/java/org/bouncycastle/bcpg/SignaturePacket.java
@@ -36,10 +36,18 @@ public class SignaturePacket
private byte[] salt; // v6 only
SignaturePacket(
- BCPGInputStream in)
+ BCPGInputStream in)
+ throws IOException
+ {
+ this(in, false);
+ }
+
+ SignaturePacket(
+ BCPGInputStream in,
+ boolean newPacketFormat)
throws IOException
{
- super(SIGNATURE);
+ super(SIGNATURE, newPacketFormat);
version = in.read();
switch (version)
@@ -686,7 +694,7 @@ else if (version == VERSION_4 || version == VERSION_5 || version == VERSION_6)
pOut.close();
- out.writePacket(SIGNATURE, bOut.toByteArray());
+ out.writePacket(hasNewPacketFormat(), SIGNATURE, bOut.toByteArray());
}
private void setCreationTime()
diff --git a/pg/src/main/java/org/bouncycastle/bcpg/SymmetricEncDataPacket.java b/pg/src/main/java/org/bouncycastle/bcpg/SymmetricEncDataPacket.java
index eeca55b97c..90cf34ece3 100644
--- a/pg/src/main/java/org/bouncycastle/bcpg/SymmetricEncDataPacket.java
+++ b/pg/src/main/java/org/bouncycastle/bcpg/SymmetricEncDataPacket.java
@@ -10,9 +10,16 @@ public class SymmetricEncDataPacket
implements BCPGHeaderObject
{
public SymmetricEncDataPacket(
- BCPGInputStream in)
+ BCPGInputStream in)
{
- super(in, SYMMETRIC_KEY_ENC);
+ this(in, false);
+ }
+
+ public SymmetricEncDataPacket(
+ BCPGInputStream in,
+ boolean newPacketFormat)
+ {
+ super(in, SYMMETRIC_KEY_ENC, newPacketFormat);
}
public SymmetricEncDataPacket()
diff --git a/pg/src/main/java/org/bouncycastle/bcpg/SymmetricEncIntegrityPacket.java b/pg/src/main/java/org/bouncycastle/bcpg/SymmetricEncIntegrityPacket.java
index d2f81746c1..79bc42357c 100644
--- a/pg/src/main/java/org/bouncycastle/bcpg/SymmetricEncIntegrityPacket.java
+++ b/pg/src/main/java/org/bouncycastle/bcpg/SymmetricEncIntegrityPacket.java
@@ -31,10 +31,18 @@ public class SymmetricEncIntegrityPacket
byte[] salt; // V2
SymmetricEncIntegrityPacket(
- BCPGInputStream in)
+ BCPGInputStream in)
+ throws IOException
+ {
+ this(in, false);
+ }
+
+ SymmetricEncIntegrityPacket(
+ BCPGInputStream in,
+ boolean newPacketFormat)
throws IOException
{
- super(in, SYM_ENC_INTEGRITY_PRO);
+ super(in, SYM_ENC_INTEGRITY_PRO, newPacketFormat);
version = in.read();
diff --git a/pg/src/main/java/org/bouncycastle/bcpg/SymmetricKeyEncSessionPacket.java b/pg/src/main/java/org/bouncycastle/bcpg/SymmetricKeyEncSessionPacket.java
index 25220f10b5..c8574ca5ca 100644
--- a/pg/src/main/java/org/bouncycastle/bcpg/SymmetricKeyEncSessionPacket.java
+++ b/pg/src/main/java/org/bouncycastle/bcpg/SymmetricKeyEncSessionPacket.java
@@ -40,10 +40,17 @@ public class SymmetricKeyEncSessionPacket
private byte[] authTag; // V5, V6
public SymmetricKeyEncSessionPacket(
- BCPGInputStream in)
+ BCPGInputStream in)
+ throws IOException
+ {
+ this(in, false);
+ }
+ public SymmetricKeyEncSessionPacket(
+ BCPGInputStream in,
+ boolean newPacketFormat)
throws IOException
{
- super(SYMMETRIC_KEY_ENC_SESSION);
+ super(SYMMETRIC_KEY_ENC_SESSION, newPacketFormat);
version = in.read();
if (version == VERSION_4)
@@ -349,6 +356,6 @@ else if (version == VERSION_5 || version == VERSION_6)
pOut.close();
- out.writePacket(SYMMETRIC_KEY_ENC_SESSION, bOut.toByteArray());
+ out.writePacket(hasNewPacketFormat(), SYMMETRIC_KEY_ENC_SESSION, bOut.toByteArray());
}
}
diff --git a/pg/src/main/java/org/bouncycastle/bcpg/TrustPacket.java b/pg/src/main/java/org/bouncycastle/bcpg/TrustPacket.java
index a009240504..db920ec297 100644
--- a/pg/src/main/java/org/bouncycastle/bcpg/TrustPacket.java
+++ b/pg/src/main/java/org/bouncycastle/bcpg/TrustPacket.java
@@ -10,12 +10,20 @@ public class TrustPacket
extends ContainedPacket
{
byte[] levelAndTrustAmount;
-
+
public TrustPacket(
- BCPGInputStream in)
+ BCPGInputStream in)
+ throws IOException
+ {
+ this(in, false);
+ }
+
+ public TrustPacket(
+ BCPGInputStream in,
+ boolean newPacketFormat)
throws IOException
{
- super(TRUST);
+ super(TRUST, newPacketFormat);
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
int ch;
@@ -47,6 +55,6 @@ public void encode(
BCPGOutputStream out)
throws IOException
{
- out.writePacket(TRUST, levelAndTrustAmount);
+ out.writePacket(hasNewPacketFormat(), TRUST, levelAndTrustAmount);
}
}
diff --git a/pg/src/main/java/org/bouncycastle/bcpg/UnknownPacket.java b/pg/src/main/java/org/bouncycastle/bcpg/UnknownPacket.java
index 80fbfb4dff..5f11541625 100644
--- a/pg/src/main/java/org/bouncycastle/bcpg/UnknownPacket.java
+++ b/pg/src/main/java/org/bouncycastle/bcpg/UnknownPacket.java
@@ -12,7 +12,13 @@ public class UnknownPacket
public UnknownPacket(int tag, BCPGInputStream in)
throws IOException
{
- super(tag);
+ this(tag, in, false);
+ }
+
+ public UnknownPacket(int tag, BCPGInputStream in, boolean newPacketFormat)
+ throws IOException
+ {
+ super(tag, newPacketFormat);
this.contents = in.readAll();
}
@@ -26,6 +32,6 @@ public void encode(
BCPGOutputStream out)
throws IOException
{
- out.writePacket(getPacketTag(), contents);
+ out.writePacket(hasNewPacketFormat(), getPacketTag(), contents);
}
}
diff --git a/pg/src/main/java/org/bouncycastle/bcpg/UserAttributePacket.java b/pg/src/main/java/org/bouncycastle/bcpg/UserAttributePacket.java
index e87a36a7fe..d0b099cfb7 100644
--- a/pg/src/main/java/org/bouncycastle/bcpg/UserAttributePacket.java
+++ b/pg/src/main/java/org/bouncycastle/bcpg/UserAttributePacket.java
@@ -11,12 +11,20 @@ public class UserAttributePacket
extends ContainedPacket
{
private UserAttributeSubpacket[] subpackets;
-
+
public UserAttributePacket(
- BCPGInputStream in)
+ BCPGInputStream in)
+ throws IOException
+ {
+ this(in, false);
+ }
+
+ public UserAttributePacket(
+ BCPGInputStream in,
+ boolean newPacketFormat)
throws IOException
{
- super(USER_ATTRIBUTE);
+ super(USER_ATTRIBUTE, newPacketFormat);
UserAttributeSubpacketInputStream sIn = new UserAttributeSubpacketInputStream(in);
UserAttributeSubpacket sub;
@@ -59,6 +67,6 @@ public void encode(
subpackets[i].encode(bOut);
}
- out.writePacket(USER_ATTRIBUTE, bOut.toByteArray());
+ out.writePacket(hasNewPacketFormat(), USER_ATTRIBUTE, bOut.toByteArray());
}
}
diff --git a/pg/src/main/java/org/bouncycastle/bcpg/UserIDPacket.java b/pg/src/main/java/org/bouncycastle/bcpg/UserIDPacket.java
index 0cd550352d..7256e1466b 100644
--- a/pg/src/main/java/org/bouncycastle/bcpg/UserIDPacket.java
+++ b/pg/src/main/java/org/bouncycastle/bcpg/UserIDPacket.java
@@ -13,12 +13,20 @@ public class UserIDPacket
implements UserDataPacket
{
private byte[] idData;
-
+
+ public UserIDPacket(
+ BCPGInputStream in)
+ throws IOException
+ {
+ this(in, false);
+ }
+
public UserIDPacket(
- BCPGInputStream in)
+ BCPGInputStream in,
+ boolean newPacketFormat)
throws IOException
{
- super(USER_ID);
+ super(USER_ID, newPacketFormat);
this.idData = in.readAll();
}
@@ -67,6 +75,6 @@ public void encode(
BCPGOutputStream out)
throws IOException
{
- out.writePacket(USER_ID, idData);
+ out.writePacket(hasNewPacketFormat(), USER_ID, idData);
}
}
diff --git a/pg/src/test/java/org/bouncycastle/bcpg/test/BCPGOutputStreamTest.java b/pg/src/test/java/org/bouncycastle/bcpg/test/BCPGOutputStreamTest.java
new file mode 100644
index 0000000000..4e02f9378f
--- /dev/null
+++ b/pg/src/test/java/org/bouncycastle/bcpg/test/BCPGOutputStreamTest.java
@@ -0,0 +1,283 @@
+package org.bouncycastle.bcpg.test;
+
+import org.bouncycastle.bcpg.*;
+import org.bouncycastle.openpgp.*;
+import org.bouncycastle.openpgp.bc.BcPGPObjectFactory;
+import org.bouncycastle.util.encoders.Hex;
+import org.bouncycastle.util.test.SimpleTest;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+public class BCPGOutputStreamTest extends SimpleTest {
+
+ private void testForceNewPacketFormat() throws IOException {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ BCPGOutputStream pOut = new BCPGOutputStream(bOut, PacketFormat.CURRENT);
+
+ new UserIDPacket("Alice").encode(pOut);
+ new UserIDPacket("Bob").encode(pOut);
+
+ pOut.close();
+
+ ByteArrayInputStream bIn = new ByteArrayInputStream(bOut.toByteArray());
+ BCPGInputStream pIn = new BCPGInputStream(bIn);
+
+ isTrue(pIn.readPacket().hasNewPacketFormat());
+ isTrue(pIn.readPacket().hasNewPacketFormat());
+ }
+
+ private void testForceOldPacketFormat() throws IOException {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ BCPGOutputStream pOut = new BCPGOutputStream(bOut, PacketFormat.LEGACY);
+
+ new UserIDPacket("Alice").encode(pOut);
+ new UserIDPacket("Bob").encode(pOut);
+
+ pOut.close();
+
+ ByteArrayInputStream bIn = new ByteArrayInputStream(bOut.toByteArray());
+ BCPGInputStream pIn = new BCPGInputStream(bIn);
+
+ isTrue(!pIn.readPacket().hasNewPacketFormat());
+ isTrue(!pIn.readPacket().hasNewPacketFormat());
+ }
+
+ private void testRoundTripPacketFormat() throws IOException {
+ List oldPackets = new ArrayList<>();
+ ByteArrayInputStream obIn = new ByteArrayInputStream(Hex.decode("b405416c696365b403426f62"));
+ BCPGInputStream opIn = new BCPGInputStream(obIn);
+ oldPackets.add((UserIDPacket) opIn.readPacket());
+ oldPackets.add((UserIDPacket) opIn.readPacket());
+
+ List newPackets = new ArrayList<>();
+ ByteArrayInputStream nbIn = new ByteArrayInputStream(Hex.decode("cd05416c696365cd03426f62"));
+ BCPGInputStream npIn = new BCPGInputStream(nbIn);
+ newPackets.add((UserIDPacket) npIn.readPacket());
+ newPackets.add((UserIDPacket) npIn.readPacket());
+
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ BCPGOutputStream pOut = new BCPGOutputStream(bOut, PacketFormat.ROUNDTRIP);
+
+ // Write New, Old, Old, New
+ pOut.writePacket(newPackets.get(0));
+ pOut.writePacket(oldPackets.get(0));
+ pOut.writePacket(oldPackets.get(1));
+ pOut.writePacket(newPackets.get(1));
+ pOut.close();
+
+ ByteArrayInputStream bIn = new ByteArrayInputStream(bOut.toByteArray());
+ BCPGInputStream pIn = new BCPGInputStream(bIn);
+
+ // Test New, Old, Old, New
+ isTrue(pIn.readPacket().hasNewPacketFormat());
+ isTrue(!pIn.readPacket().hasNewPacketFormat());
+ isTrue(!pIn.readPacket().hasNewPacketFormat());
+ isTrue(pIn.readPacket().hasNewPacketFormat());
+ }
+
+ private void testRoundtripMixedPacketFormats() throws IOException {
+ // Certificate with mixed new and old packet formats
+ // The primary key + sigs use new format
+ // The signing subkey + sigs use old format
+ // The encryption subkey + sigs use new format again
+ String encodedCert = "-----BEGIN PGP PRIVATE KEY BLOCK-----\n" +
+ "Version: BCPG v@RELEASE_NAME@\n" +
+ "\n" +
+ "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\n" +
+ "3hRZb5W+1RCWcuPc/oWxMuwiBw==\n" +
+ "=7IAh\n" +
+ "-----END PGP PRIVATE KEY BLOCK-----\n";
+
+ ByteArrayInputStream bIn = new ByteArrayInputStream(encodedCert.getBytes());
+ ArmoredInputStream aIn = new ArmoredInputStream(bIn);
+ BCPGInputStream pIn = new BCPGInputStream(aIn);
+ PGPObjectFactory objectFactory = new BcPGPObjectFactory(pIn);
+ PGPSecretKeyRing secretKeys = (PGPSecretKeyRing) objectFactory.nextObject();
+
+ // ROUNDTRIP
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ ArmoredOutputStream aOut = new ArmoredOutputStream(bOut);
+ BCPGOutputStream pOut = new BCPGOutputStream(aOut, PacketFormat.ROUNDTRIP);
+ secretKeys.encode(pOut);
+ pOut.close();
+ aOut.close();
+
+ isEquals(encodedCert, bOut.toString());
+
+ // NEW PACKET FORMAT
+ bOut = new ByteArrayOutputStream();
+ aOut = new ArmoredOutputStream(bOut);
+ pOut = new BCPGOutputStream(aOut, PacketFormat.CURRENT);
+ secretKeys.encode(pOut);
+ pOut.close();
+ aOut.close();
+
+ bIn = new ByteArrayInputStream(bOut.toByteArray());
+ aIn = new ArmoredInputStream(bIn);
+ pIn = new BCPGInputStream(aIn);
+ Packet packet;
+ while ((packet = pIn.readPacket()) != null) {
+ isTrue(packet.hasNewPacketFormat());
+ }
+
+ // OLD PACKET FORMAT
+ bOut = new ByteArrayOutputStream();
+ aOut = new ArmoredOutputStream(bOut);
+ pOut = new BCPGOutputStream(aOut, PacketFormat.LEGACY);
+ secretKeys.encode(pOut);
+ pOut.close();
+ aOut.close();
+
+ bIn = new ByteArrayInputStream(bOut.toByteArray());
+ aIn = new ArmoredInputStream(bIn);
+ pIn = new BCPGInputStream(aIn);
+ while ((packet = pIn.readPacket()) != null) {
+ isTrue(!packet.hasNewPacketFormat());
+ }
+ }
+
+ @Override
+ public String getName() {
+ return "BCPGOutputStreamTest";
+ }
+
+ @Override
+ public void performTest() throws Exception {
+ testForceOldPacketFormat();
+ testForceNewPacketFormat();
+ testRoundTripPacketFormat();
+ testRoundtripMixedPacketFormats();
+ }
+
+ public static void main(String[] args) {
+ runTest(new BCPGOutputStreamTest());
+ }
+}
diff --git a/pg/src/test/java/org/bouncycastle/bcpg/test/OnePassSignaturePacketTest.java b/pg/src/test/java/org/bouncycastle/bcpg/test/OnePassSignaturePacketTest.java
index 9f26357554..69703195ae 100644
--- a/pg/src/test/java/org/bouncycastle/bcpg/test/OnePassSignaturePacketTest.java
+++ b/pg/src/test/java/org/bouncycastle/bcpg/test/OnePassSignaturePacketTest.java
@@ -105,8 +105,10 @@ private void roundtripV3Packet()
isNull("round-tripped OPS v3 MUST NOT have salt",
after.getSalt());
- isEncodingEqual("Packet encoding mismatch",
- before, after);
+ if (before.hasNewPacketFormat() && newTypeIdFormat)
+ {
+ isEncodingEqual(before, after);
+ }
}
}
@@ -178,7 +180,10 @@ private void roundtripV6Packet()
isEncodingEqual("round-tripped OPS salt mismatch",
before.getSalt(), after.getSalt());
- isEncodingEqual(before, after);
+ if (before.hasNewPacketFormat() && newTypeIdFormat)
+ {
+ isEncodingEqual(before, after);
+ }
}
}