Skip to content

Commit 3c52f44

Browse files
committed
Merge branch '1938-extension-generator-refactor' into 'main'
PGPKeyEncryptionMethodGenerator with generate(PGPDataEncryptorBuilder dataEncryptorBuilder, byte[] sessionKey) See merge request root/bc-java!56
2 parents c609ec2 + 0b09053 commit 3c52f44

11 files changed

+711
-387
lines changed

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

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -276,9 +276,16 @@ public void encode(
276276
}
277277
else if (version == VERSION_6)
278278
{
279-
pOut.write(keyFingerprint.length + 1);
280-
pOut.write(keyVersion);
281-
pOut.write(keyFingerprint);
279+
if (keyFingerprint.length != 0)
280+
{
281+
pOut.write(keyFingerprint.length + 1);
282+
pOut.write(keyVersion);
283+
pOut.write(keyFingerprint);
284+
}
285+
else
286+
{
287+
pOut.write(0);
288+
}
282289
}
283290

284291
pOut.write(algorithm);

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

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -337,14 +337,21 @@ public void encode(
337337
pOut.write(secKeyData);
338338
}
339339
}
340-
else if (version == VERSION_5 || version == VERSION_6)
340+
else
341341
{
342-
int s2kLen = s2k.getEncoded().length;
343-
int count = 1 + 1 + 1 + s2kLen + iv.length;
344-
pOut.write(count); // len of 5 following fields
342+
int s2kLen = 0;
343+
if (version == VERSION_6)
344+
{
345+
s2kLen = s2k.getEncoded().length;
346+
int count = 1 + 1 + 1 + s2kLen + iv.length;
347+
pOut.write(count); // len of 5 following fields
348+
}
345349
pOut.write(encAlgorithm);
346350
pOut.write(aeadAlgorithm);
347-
pOut.write(s2kLen);
351+
if (version == VERSION_6)
352+
{
353+
pOut.write(s2kLen);
354+
}
348355
pOut.writeObject(s2k);
349356
pOut.write(iv);
350357

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

Lines changed: 24 additions & 162 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
import org.bouncycastle.bcpg.AEADEncDataPacket;
1010
import org.bouncycastle.bcpg.BCPGHeaderObject;
1111
import org.bouncycastle.bcpg.BCPGOutputStream;
12-
import org.bouncycastle.bcpg.ContainedPacket;
1312
import org.bouncycastle.bcpg.HashAlgorithmTags;
1413
import org.bouncycastle.bcpg.PacketTags;
1514
import org.bouncycastle.bcpg.SymmetricEncDataPacket;
@@ -141,42 +140,6 @@ public void addMethod(PGPKeyEncryptionMethodGenerator method)
141140
methods.add(method);
142141
}
143142

144-
/**
145-
* Write a checksum into the last two bytes of the array.
146-
*
147-
* @param sessionInfo byte array
148-
*/
149-
private void addCheckSum(
150-
byte[] sessionInfo)
151-
{
152-
int check = 0;
153-
154-
for (int i = 1; i != sessionInfo.length - 2; i++)
155-
{
156-
check += sessionInfo[i] & 0xff;
157-
}
158-
159-
sessionInfo[sessionInfo.length - 2] = (byte)(check >> 8);
160-
sessionInfo[sessionInfo.length - 1] = (byte)(check);
161-
}
162-
163-
/**
164-
* Create a session info array containing of the algorithm-id followed by the key and a two-byte checksum.
165-
*
166-
* @param algorithm symmetric algorithm
167-
* @param keyBytes bytes of the key
168-
* @return array of algorithm, key and checksum
169-
*/
170-
private byte[] createSessionInfo(
171-
int algorithm,
172-
byte[] keyBytes)
173-
{
174-
byte[] sessionInfo = new byte[keyBytes.length + 3];
175-
sessionInfo[0] = (byte)algorithm;
176-
System.arraycopy(keyBytes, 0, sessionInfo, 1, keyBytes.length);
177-
addCheckSum(sessionInfo);
178-
return sessionInfo;
179-
}
180143

181144
/**
182145
* Create an OutputStream based on the configured methods.
@@ -247,78 +210,56 @@ else if (directS2K)
247210
else
248211
{
249212
sessionKey = PGPUtil.makeRandomKey(defAlgorithm, rand);
250-
// prepend algorithm, append checksum
251-
sessionInfo = createSessionInfo(defAlgorithm, sessionKey);
252213
messageKey = sessionKey;
253214
}
254215

255216
PGPDataEncryptor dataEncryptor = dataEncryptorBuilder.build(messageKey);
256217
digestCalc = dataEncryptor.getIntegrityCalculator();
257-
218+
BCPGHeaderObject encOut;
258219
for (int i = 0; i < methods.size(); i++)
259220
{
260-
PGPKeyEncryptionMethodGenerator method = (PGPKeyEncryptionMethodGenerator)methods.get(i);
261-
// OpenPGP v5 or v6
262-
if (dataEncryptor instanceof PGPAEADDataEncryptor)
263-
{
264-
PGPAEADDataEncryptor aeadDataEncryptor = (PGPAEADDataEncryptor)dataEncryptor;
265-
// data is encrypted by AEAD Encrypted Data packet (rfc4880bis10), so write v5 SKESK packet
266-
if (isV5StyleAEAD)
267-
{
268-
writeOpenPGPv5ESKPacket(method, sessionInfo);
269-
}
270-
else // data is encrypted by v2 SEIPD (AEAD), so write v6 SKESK packet
271-
{
272-
//https://www.rfc-editor.org/rfc/rfc9580.html#section-3.7.2.1 Table 2
273-
//AEAD(HKDF(S2K(passphrase), info), secrets, packetprefix)
274-
writeOpenPGPv6ESKPacket(method, aeadDataEncryptor.getAEADAlgorithm(), sessionKey);
275-
}
276-
}
277-
// OpenPGP v4
278-
else // data is encrypted by v1 SEIPD or SED packet, so write v4 SKESK packet
279-
{
280-
writeOpenPGPv4ESKPacket(method, sessionInfo);
281-
}
221+
PGPKeyEncryptionMethodGenerator method = methods.get(i);
222+
pOut.writePacket(method.generate(dataEncryptorBuilder, sessionKey));
282223
}
283-
284224
try
285225
{
286-
BCPGHeaderObject encOut;
226+
// OpenPGP v5 or v6
287227
if (dataEncryptor instanceof PGPAEADDataEncryptor)
288228
{
289-
PGPAEADDataEncryptor encryptor = (PGPAEADDataEncryptor)dataEncryptor;
229+
PGPAEADDataEncryptor aeadDataEncryptor = (PGPAEADDataEncryptor)dataEncryptor;
290230
long ivOrSaltLen;
291-
// OpenPGP V5 style AEAD
231+
// data is encrypted by AEAD Encrypted Data packet (rfc4880bis10), so write v5 SKESK packet
292232
if (isV5StyleAEAD)
293233
{
294-
byte[] iv = encryptor.getIV();
234+
byte[] iv = aeadDataEncryptor.getIV();
295235
encOut = new AEADEncDataPacket(
296-
dataEncryptorBuilder.getAlgorithm(), encryptor.getAEADAlgorithm(), encryptor.getChunkSize(), iv);
236+
defAlgorithm, aeadDataEncryptor.getAEADAlgorithm(), aeadDataEncryptor.getChunkSize(), iv);
297237
ivOrSaltLen = iv.length;
298238
}
299-
else // OpenPGP V6 style AEAD
239+
else // data is encrypted by v2 SEIPD (AEAD), so write v6 SKESK packet
300240
{
241+
//AEAD(HKDF(S2K(passphrase), info), secrets, packetprefix)
301242
encOut = SymmetricEncIntegrityPacket.createVersion2Packet(
302-
dataEncryptorBuilder.getAlgorithm(),
303-
encryptor.getAEADAlgorithm(),
304-
encryptor.getChunkSize(),
243+
defAlgorithm,
244+
aeadDataEncryptor.getAEADAlgorithm(),
245+
aeadDataEncryptor.getChunkSize(),
305246
salt);
306247
ivOrSaltLen = salt.length;
307248
}
308-
309-
if (buffer != null)
249+
if (buffer == null)
310250
{
311-
pOut = new ClosableBCPGOutputStream(out, encOut, buffer);
251+
long chunkLength = 1L << (aeadDataEncryptor.getChunkSize() + 6);
252+
long tagLengths = ((length + chunkLength - 1) / chunkLength) * 16L + 16L; // data blocks + final tag
253+
pOut = new ClosableBCPGOutputStream(out, encOut, (length + tagLengths + 4L + ivOrSaltLen));
312254
}
313255
else
314256
{
315-
long chunkLength = 1L << (encryptor.getChunkSize() + 6);
316-
long tagLengths = ((length + chunkLength - 1) / chunkLength) * 16 + 16; // data blocks + final tag
317-
pOut = new ClosableBCPGOutputStream(out, encOut, (length + tagLengths + 4 + ivOrSaltLen));
257+
pOut = new ClosableBCPGOutputStream(out, encOut, buffer);
318258
}
319259
genOut = cOut = dataEncryptor.getOutputStream(pOut);
320260
}
321-
else
261+
// OpenPGP v4
262+
else // data is encrypted by v1 SEIPD or SED packet, so write v4 SKESK packet
322263
{
323264
if (digestCalc != null)
324265
{
@@ -360,95 +301,16 @@ else if (directS2K)
360301
inLineIv[inLineIv.length - 2] = inLineIv[inLineIv.length - 4];
361302

362303
genOut.write(inLineIv);
363-
364304
}
365305
return new WrappedGeneratorStream(genOut, this);
366306
}
367-
catch (Exception e)
368-
{
369-
throw new PGPException("Exception creating cipher", e);
370-
}
371-
}
372-
373-
/**
374-
* Write out a {@link org.bouncycastle.bcpg.SymmetricKeyEncSessionPacket#VERSION_4 v4 SKESK} or
375-
* {@link org.bouncycastle.bcpg.PublicKeyEncSessionPacket#VERSION_3 v3 PKESK} packet,
376-
* depending on the method generator. This method is used by what can be referred to as OpenPGP v4.
377-
*
378-
* @param m session key encryption method generator
379-
* @param sessionInfo session info
380-
* @throws IOException
381-
* @throws PGPException
382-
*/
383-
private void writeOpenPGPv4ESKPacket(PGPKeyEncryptionMethodGenerator m, byte[] sessionInfo)
384-
throws IOException, PGPException
385-
{
386-
if (m instanceof PBEKeyEncryptionMethodGenerator)
387-
{
388-
PBEKeyEncryptionMethodGenerator mGen = (PBEKeyEncryptionMethodGenerator)m;
389-
ContainedPacket esk = m.generate(mGen.getSessionKeyWrapperAlgorithm(defAlgorithm), sessionInfo);
390-
pOut.writePacket(esk);
391-
}
392-
else
393-
{
394-
pOut.writePacket(m.generate(defAlgorithm, sessionInfo));
395-
}
396-
}
397-
398-
/**
399-
* Write out a {@link org.bouncycastle.bcpg.SymmetricKeyEncSessionPacket#VERSION_5 v5 SKESK} or
400-
* {@link org.bouncycastle.bcpg.PublicKeyEncSessionPacket#VERSION_3 v3 PKESK} packet,
401-
* depending on the method generator. This method is used by what can be referred to as OpenPGP v5.
402-
*
403-
* @param m session key encryption method generator.
404-
* @param sessionInfo session info
405-
* @throws IOException
406-
* @throws PGPException
407-
*/
408-
private void writeOpenPGPv5ESKPacket(PGPKeyEncryptionMethodGenerator m, byte[] sessionInfo)
409-
throws IOException, PGPException
410-
{
411-
if (m instanceof PBEKeyEncryptionMethodGenerator)
412-
{
413-
PBEKeyEncryptionMethodGenerator mGen = (PBEKeyEncryptionMethodGenerator)m;
414-
ContainedPacket esk = m.generateV5(
415-
mGen.getSessionKeyWrapperAlgorithm(defAlgorithm),
416-
dataEncryptorBuilder.getAeadAlgorithm(),
417-
sessionInfo);
418-
pOut.writePacket(esk);
419-
}
420-
else
307+
catch (IOException e)
421308
{
422-
pOut.writePacket(m.generate(defAlgorithm, sessionInfo));
309+
throw e;
423310
}
424-
}
425-
426-
/**
427-
* Write out a {@link org.bouncycastle.bcpg.SymmetricKeyEncSessionPacket#VERSION_6 v6 SKESK} or
428-
* {@link org.bouncycastle.bcpg.PublicKeyEncSessionPacket#VERSION_6 v6 PKESK} packet,
429-
* depending on the method generator. This method is used by what can be referred to as OpenPGP v6.
430-
*
431-
* @param m session key encryption method generator.
432-
* @param aeadAlgorithm AEAD encryption algorithm
433-
* @param sessionInfo session info
434-
* @throws IOException
435-
* @throws PGPException
436-
*/
437-
private void writeOpenPGPv6ESKPacket(PGPKeyEncryptionMethodGenerator m, int aeadAlgorithm, byte[] sessionInfo)
438-
throws IOException, PGPException
439-
{
440-
if (m instanceof PBEKeyEncryptionMethodGenerator)
441-
{
442-
PBEKeyEncryptionMethodGenerator mGen = (PBEKeyEncryptionMethodGenerator)m;
443-
ContainedPacket esk = m.generateV6(
444-
mGen.getSessionKeyWrapperAlgorithm(defAlgorithm),
445-
aeadAlgorithm,
446-
sessionInfo);
447-
pOut.writePacket(esk);
448-
}
449-
else
311+
catch (Exception e)
450312
{
451-
pOut.writePacket(m.generate(defAlgorithm, sessionInfo));
313+
throw new PGPException("Exception creating cipher", e);
452314
}
453315
}
454316

0 commit comments

Comments
 (0)