Skip to content

Commit c005424

Browse files
committed
Merge branch '1809-pgp-librepgp-ocbencrypteddata' into 'main'
1809 pgp librepgp ocbencrypteddata See merge request root/bc-java!19
2 parents 3c9c1fa + bb58c09 commit c005424

File tree

8 files changed

+323
-40
lines changed

8 files changed

+323
-40
lines changed

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

Lines changed: 23 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package org.bouncycastle.bcpg;
22

3-
import java.io.ByteArrayInputStream;
43
import java.io.ByteArrayOutputStream;
54
import java.io.EOFException;
65
import java.io.IOException;
@@ -19,6 +18,7 @@ public class SymmetricKeyEncSessionPacket
1918

2019
/**
2120
* Version 5 SKESK packet.
21+
* LibrePGP only.
2222
* Used only with {@link AEADEncDataPacket AED} packets.
2323
*/
2424
public static final int VERSION_5 = 5;
@@ -40,11 +40,12 @@ public class SymmetricKeyEncSessionPacket
4040
private byte[] authTag; // V5, V6
4141

4242
public SymmetricKeyEncSessionPacket(
43-
BCPGInputStream in)
44-
throws IOException
43+
BCPGInputStream in)
44+
throws IOException
4545
{
4646
this(in, false);
4747
}
48+
4849
public SymmetricKeyEncSessionPacket(
4950
BCPGInputStream in,
5051
boolean newPacketFormat)
@@ -63,30 +64,28 @@ public SymmetricKeyEncSessionPacket(
6364
}
6465
else if (version == VERSION_5 || version == VERSION_6)
6566
{
66-
// https://www.rfc-editor.org/rfc/rfc9580.html#section-5.3.2-3.2.1
67-
// SymAlg + AEADAlg + S2KCount + S2K + IV
68-
int next5Fields5Count = in.read();
67+
int ivLen = 0;
68+
if (version == VERSION_6)
69+
{
70+
// https://www.rfc-editor.org/rfc/rfc9580.html#section-5.3.2-3.2.1
71+
// SymAlg + AEADAlg + S2KCount + S2K + IV
72+
ivLen = in.read(); // next5Fields5Count
73+
}
6974
encAlgorithm = in.read();
7075
aeadAlgorithm = in.read();
76+
if (version == VERSION_6)
77+
{
78+
// https://www.rfc-editor.org/rfc/rfc9580.html#section-5.3.2-3.5.1
79+
int s2kOctetCount = in.read();
80+
ivLen = ivLen - 3 - s2kOctetCount;
81+
}
82+
else
83+
{
84+
ivLen = AEADUtils.getIVLength(aeadAlgorithm);
85+
}
7186

72-
// https://www.rfc-editor.org/rfc/rfc9580.html#section-5.3.2-3.5.1
73-
int s2kOctetCount = in.read();
74-
75-
//TODO: use this line to replace the following code?
7687
s2k = new S2K(in);
77-
// s2kBytes = new byte[s2kOctetCount];
78-
// in.readFully(s2kBytes);
79-
// try
80-
// {
81-
// s2k = new S2K(new ByteArrayInputStream(s2kBytes));
82-
// }
83-
// catch (UnsupportedPacketVersionException e)
84-
// {
85-
//
86-
// // We gracefully catch the error.
87-
// }
88-
89-
int ivLen = next5Fields5Count - 3 - s2kOctetCount;
88+
9089
iv = new byte[ivLen]; // also called nonce
9190
if (in.read(iv) != iv.length)
9291
{
@@ -108,7 +107,6 @@ else if (version == VERSION_5 || version == VERSION_6)
108107
{
109108
throw new UnsupportedPacketVersionException("Unsupported PGP symmetric-key encrypted session key packet version encountered: " + version);
110109
}
111-
112110
}
113111

114112
/**
@@ -361,4 +359,4 @@ else if (version == VERSION_5 || version == VERSION_6)
361359

362360
out.writePacket(hasNewPacketFormat(), SYMMETRIC_KEY_ENC_SESSION, bOut.toByteArray());
363361
}
364-
}
362+
}

pg/src/main/java/org/bouncycastle/openpgp/PGPPublicKey.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ else if (publicPk.getVersion() == PublicKeyPacket.VERSION_4)
7070
{
7171
this.keyID = Pack.bigEndianToLong(fingerprint, fingerprint.length - 8);
7272
}
73-
else if (publicPk.getVersion() == PublicKeyPacket.VERSION_6)
73+
else if (publicPk.getVersion() == PublicKeyPacket.LIBREPGP_5 || publicPk.getVersion() == PublicKeyPacket.VERSION_6)
7474
{
7575
this.keyID = Pack.bigEndianToLong(fingerprint, 0);
7676
}

pg/src/main/java/org/bouncycastle/openpgp/operator/RFC6637Utils.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,15 @@ public static byte[] createUserKeyingMaterial(PublicKeyPacket pubKeyData, KeyFin
115115
pOut.write(ecKey.getHashAlgorithm());
116116
pOut.write(ecKey.getSymmetricKeyAlgorithm());
117117
pOut.write(ANONYMOUS_SENDER);
118-
pOut.write(fingerPrintCalculator.calculateFingerprint(pubKeyData));
119-
118+
byte[] fp = fingerPrintCalculator.calculateFingerprint(pubKeyData);
119+
if (pubKeyData.getVersion() == PublicKeyPacket.LIBREPGP_5)
120+
{
121+
pOut.write(fp, 0, 20);
122+
}
123+
else
124+
{
125+
pOut.write(fp);
126+
}
120127
return pOut.toByteArray();
121128
}
122129

pg/src/main/java/org/bouncycastle/openpgp/operator/bc/BcPBEDataDecryptorFactory.java

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags;
66
import org.bouncycastle.bcpg.SymmetricKeyEncSessionPacket;
77
import org.bouncycastle.bcpg.SymmetricKeyUtils;
8+
import org.bouncycastle.bcpg.UnsupportedPacketVersionException;
89
import org.bouncycastle.crypto.BlockCipher;
910
import org.bouncycastle.crypto.BufferedBlockCipher;
1011
import org.bouncycastle.crypto.InvalidCipherTextException;
@@ -89,12 +90,24 @@ public byte[] recoverAEADEncryptedSessionData(SymmetricKeyEncSessionPacket keyDa
8990
}
9091

9192
byte[] hkdfInfo = keyData.getAAData(); // Between v5 and v6, these bytes differ
92-
int kekLen = SymmetricKeyUtils.getKeyLengthInOctets(keyData.getEncAlgorithm());
9393

94-
// HKDF
95-
// secretKey := HKDF_sha256(ikm, hkdfInfo).generate()
96-
byte[] kek = BcAEADUtil.generateHKDFBytes(ikm, null, hkdfInfo, kekLen);
97-
final KeyParameter secretKey = new KeyParameter(kek);
94+
KeyParameter secretKey;
95+
if (keyData.getVersion() == SymmetricKeyEncSessionPacket.VERSION_5)
96+
{
97+
secretKey = new KeyParameter(ikm);
98+
}
99+
else if (keyData.getVersion() == SymmetricKeyEncSessionPacket.VERSION_6)
100+
{
101+
// HKDF
102+
// secretKey := HKDF_sha256(ikm, hkdfInfo).generate()
103+
int kekLen = SymmetricKeyUtils.getKeyLengthInOctets(keyData.getEncAlgorithm());
104+
byte[] kek = BcAEADUtil.generateHKDFBytes(ikm, null, hkdfInfo, kekLen);
105+
secretKey = new KeyParameter(kek);
106+
}
107+
else
108+
{
109+
throw new UnsupportedPacketVersionException("Unsupported SKESK packet version encountered: " + keyData.getVersion());
110+
}
98111

99112
// AEAD
100113
AEADBlockCipher aead = BcAEADUtil.createAEADCipher(keyData.getEncAlgorithm(), keyData.getAeadAlgorithm());
@@ -149,4 +162,4 @@ public PGPDataDecryptor createDataDecryptor(SymmetricEncIntegrityPacket seipd, P
149162
{
150163
return BcAEADUtil.createOpenPgpV6DataDecryptor(seipd, sessionKey);
151164
}
152-
}
165+
}

pg/src/main/java/org/bouncycastle/openpgp/operator/jcajce/JcePBEDataDecryptorFactoryBuilder.java

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import org.bouncycastle.bcpg.SymmetricEncIntegrityPacket;
1313
import org.bouncycastle.bcpg.SymmetricKeyEncSessionPacket;
1414
import org.bouncycastle.bcpg.SymmetricKeyUtils;
15+
import org.bouncycastle.bcpg.UnsupportedPacketVersionException;
1516
import org.bouncycastle.jcajce.util.DefaultJcaJceHelper;
1617
import org.bouncycastle.jcajce.util.NamedJcaJceHelper;
1718
import org.bouncycastle.jcajce.util.ProviderJcaJceHelper;
@@ -140,12 +141,24 @@ public byte[] recoverAEADEncryptedSessionData(SymmetricKeyEncSessionPacket keyDa
140141
}
141142

142143
byte[] hkdfInfo = keyData.getAAData(); // between v5 and v6, these bytes differ
143-
int kekLen = SymmetricKeyUtils.getKeyLengthInOctets(keyData.getEncAlgorithm());
144144

145-
// HKDF
146-
// secretKey := HKDF_sha256(ikm, hkdfInfo).generate()
147-
byte[] kek = JceAEADUtil.generateHKDFBytes(ikm, null, hkdfInfo, kekLen);
148-
final SecretKey secretKey = new SecretKeySpec(kek, PGPUtil.getSymmetricCipherName(keyData.getEncAlgorithm()));
145+
SecretKey secretKey;
146+
if (keyData.getVersion() == SymmetricKeyEncSessionPacket.VERSION_5)
147+
{
148+
secretKey = new SecretKeySpec(ikm, PGPUtil.getSymmetricCipherName(keyData.getEncAlgorithm()));
149+
}
150+
else if (keyData.getVersion() == SymmetricKeyEncSessionPacket.VERSION_6)
151+
{
152+
// HKDF
153+
// secretKey := HKDF_sha256(ikm, hkdfInfo).generate()
154+
int kekLen = SymmetricKeyUtils.getKeyLengthInOctets(keyData.getEncAlgorithm());
155+
byte[] kek = JceAEADUtil.generateHKDFBytes(ikm, null, hkdfInfo, kekLen);
156+
secretKey = new SecretKeySpec(kek, PGPUtil.getSymmetricCipherName(keyData.getEncAlgorithm()));
157+
}
158+
else
159+
{
160+
throw new UnsupportedPacketVersionException("Unsupported SKESK packet version encountered: " + keyData.getVersion());
161+
}
149162

150163
// AEAD
151164
Cipher aead = aeadHelper.createAEADCipher(keyData.getEncAlgorithm(), keyData.getAeadAlgorithm());
@@ -201,4 +214,4 @@ public PGPDataDecryptor createDataDecryptor(SymmetricEncIntegrityPacket seipd, P
201214
}
202215
};
203216
}
204-
}
217+
}

pg/src/test/java/org/bouncycastle/openpgp/test/PGPv5KeyTest.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ private void parseAndEncodeKey()
9090
isEncodingEqual("Fingerprint mismatch for the subkey.",
9191
Hex.decode("E4557C2B02FFBF4B04F87401EC336AF7133D0F85BE7FD09BAEFD9CAEB8C93965"), it.next().getFingerprint());
9292

93+
it = secretKeys.getPublicKeys();
94+
isEquals( "Primary key ID mismatch", 1816212655223104514L, it.next().getKeyID());
95+
isEquals("Subkey ID mismatch", -1993550735865823413L, it.next().getKeyID());
96+
9397
bOut = new ByteArrayOutputStream();
9498
BCPGOutputStream pOut = new BCPGOutputStream(bOut, PacketFormat.LEGACY);
9599
secretKeys.encode(pOut);

0 commit comments

Comments
 (0)