Skip to content

Commit f6f6a6c

Browse files
committed
Merge branch '1836-openpgp-unpacking-time' into 'main'
1836 openpgp unpacking time See merge request root/bc-java!39
2 parents b3ee77e + d38e26d commit f6f6a6c

File tree

6 files changed

+90
-9
lines changed

6 files changed

+90
-9
lines changed

pg/src/main/java/org/bouncycastle/bcpg/PublicKeyPacket.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ public byte[] getEncodedContents()
326326

327327
pOut.write(version);
328328

329-
StreamUtil.writeTime(pOut, time);
329+
StreamUtil.writeSeconds(pOut, time);
330330

331331
if (version <= VERSION_3)
332332
{

pg/src/main/java/org/bouncycastle/bcpg/SignaturePacket.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public class SignaturePacket
2626

2727
private int version;
2828
private int signatureType;
29-
private long creationTime;
29+
private long creationTime; // millis
3030
private long keyID;
3131
private int keyAlgorithm;
3232
private int hashAlgorithm;
@@ -638,10 +638,8 @@ public void encode(
638638
{
639639
pOut.write(5); // the length of the next block
640640

641-
long time = creationTime / 1000;
642-
643641
pOut.write(signatureType);
644-
StreamUtil.writeTime(pOut, time);
642+
StreamUtil.writeTime(pOut, creationTime);
645643

646644
StreamUtil.writeKeyID(pOut, keyID);
647645

pg/src/main/java/org/bouncycastle/bcpg/StreamUtil.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,13 +111,25 @@ static long readKeyID(BCPGInputStream in)
111111
static void writeTime(BCPGOutputStream pOut, long time)
112112
throws IOException
113113
{
114-
StreamUtil.write4OctetLength(pOut, (int)time);
114+
StreamUtil.writeSeconds(pOut, time / 1000);
115115
}
116116

117117
static long readTime(BCPGInputStream in)
118118
throws IOException
119119
{
120-
return ((long)read4OctetLength(in) & 0xFFFFFFFFL) * 1000L;
120+
return readSeconds(in) * 1000L;
121+
}
122+
123+
static void writeSeconds(BCPGOutputStream pOut, long time)
124+
throws IOException
125+
{
126+
StreamUtil.write4OctetLength(pOut, (int)time);
127+
}
128+
129+
static long readSeconds(BCPGInputStream in)
130+
throws IOException
131+
{
132+
return ((long)read4OctetLength(in)) & 0xFFFFFFFFL;
121133
}
122134

123135
static void write2OctetLength(OutputStream pOut, int len)

pg/src/main/java/org/bouncycastle/bcpg/sig/Utils.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ static long timeFromBytes(byte[] bytes)
5757
throw new IllegalStateException("Byte array has unexpected length. Expected length 4, got " + bytes.length);
5858
}
5959

60-
return Pack.bigEndianToInt(bytes, 0);
60+
return Pack.bigEndianToInt(bytes, 0) & 0xFFFFFFFFL; // time is unsigned
6161
}
6262

6363
static byte[] timeToBytes(long t)

pg/src/test/java/org/bouncycastle/bcpg/test/AllTests.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ public void testPacketParsing()
2424
new OnePassSignaturePacketTest(),
2525
new OpenPgpMessageTest(),
2626
new FingerprintUtilTest(),
27-
new EncryptedMessagePacketTest()
27+
new EncryptedMessagePacketTest(),
28+
new TimeEncodingTest()
2829
};
2930

3031
for (int i = 0; i != tests.length; i++)
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package org.bouncycastle.bcpg.test;
2+
3+
import org.bouncycastle.bcpg.BCPGInputStream;
4+
import org.bouncycastle.bcpg.BCPGOutputStream;
5+
import org.bouncycastle.bcpg.PacketFormat;
6+
import org.bouncycastle.bcpg.PublicKeyPacket;
7+
import org.bouncycastle.bcpg.UnknownBCPGKey;
8+
import org.bouncycastle.bcpg.sig.KeyExpirationTime;
9+
import org.bouncycastle.util.test.SimpleTest;
10+
11+
import java.io.ByteArrayInputStream;
12+
import java.io.ByteArrayOutputStream;
13+
import java.io.IOException;
14+
import java.util.Date;
15+
16+
public class TimeEncodingTest
17+
extends SimpleTest
18+
{
19+
@Override
20+
public String getName()
21+
{
22+
return "UtilsTest";
23+
}
24+
25+
@Override
26+
public void performTest()
27+
throws Exception
28+
{
29+
testRoundtrippingLargeUnsignedInt();
30+
testKeyWithLargeCreationTime();
31+
}
32+
33+
private void testRoundtrippingLargeUnsignedInt()
34+
{
35+
// Integer.MAX_VALUE < large < 0xffffffff
36+
long large = 2523592696L; // fits a 32-bit *unsigned* int, but overflows signed int
37+
// KeyExpirationTime packs the time into 4 octets
38+
KeyExpirationTime kexp = new KeyExpirationTime(false, large);
39+
// getTime() parses the time from 4 octets
40+
isEquals("Roundtripped unsigned int mismatches before packet parser pass", large, kexp.getTime());
41+
42+
// To be safe, do an additional packet encode/decode roundtrip
43+
KeyExpirationTime pKexp = new KeyExpirationTime(kexp.isCritical(), kexp.isLongLength(), kexp.getData());
44+
isEquals("Roundtripped unsigned int mismatches after packet parser pass", large, pKexp.getTime());
45+
}
46+
47+
private void testKeyWithLargeCreationTime()
48+
throws IOException
49+
{
50+
long maxSeconds = 0xFFFFFFFEL; // Fits 32 unsigned int, but not signed int
51+
Date maxPGPDate = new Date(maxSeconds * 1000);
52+
UnknownBCPGKey k = new UnknownBCPGKey(1, new byte[]{1}); // dummy
53+
PublicKeyPacket p = new PublicKeyPacket(PublicKeyPacket.VERSION_6, 99, maxPGPDate, k);
54+
isEquals("Key creation time mismatches before encoding", maxPGPDate, p.getTime());
55+
56+
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
57+
BCPGOutputStream pOut = new BCPGOutputStream(bOut, PacketFormat.CURRENT);
58+
p.encode(pOut);
59+
pOut.close();
60+
ByteArrayInputStream bIn = new ByteArrayInputStream(bOut.toByteArray());
61+
BCPGInputStream pIn = new BCPGInputStream(bIn);
62+
PublicKeyPacket parsed = (PublicKeyPacket) pIn.readPacket();
63+
isEquals("Key creation time mismatches after encoding", maxPGPDate, parsed.getTime());
64+
}
65+
66+
public static void main(String[] args)
67+
{
68+
runTest(new TimeEncodingTest());
69+
}
70+
}

0 commit comments

Comments
 (0)