Skip to content

Commit ee613a6

Browse files
author
gefeili
committed
Refactor in PGPKeyEncryptionMethodGenerator
1 parent be646c2 commit ee613a6

File tree

5 files changed

+185
-69
lines changed

5 files changed

+185
-69
lines changed

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

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@
1212
import org.bouncycastle.bcpg.ContainedPacket;
1313
import org.bouncycastle.bcpg.HashAlgorithmTags;
1414
import org.bouncycastle.bcpg.PacketTags;
15+
import org.bouncycastle.bcpg.PublicKeyEncSessionPacket;
1516
import org.bouncycastle.bcpg.SymmetricEncDataPacket;
1617
import org.bouncycastle.bcpg.SymmetricEncIntegrityPacket;
1718
import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags;
19+
import org.bouncycastle.bcpg.SymmetricKeyEncSessionPacket;
1820
import org.bouncycastle.openpgp.operator.PBEKeyEncryptionMethodGenerator;
1921
import org.bouncycastle.openpgp.operator.PGPAEADDataEncryptor;
2022
import org.bouncycastle.openpgp.operator.PGPDataEncryptor;
@@ -284,7 +286,7 @@ else if (directS2K)
284286
for (int i = 0; i < methods.size(); i++)
285287
{
286288
PGPKeyEncryptionMethodGenerator method = methods.get(i);
287-
writeOpenPGPv6ESKPacket(method, aeadDataEncryptor.getAEADAlgorithm(), sessionInfo);
289+
writeOpenPGPv6ESKPacket(method, sessionInfo);
288290
}
289291
encOut = SymmetricEncIntegrityPacket.createVersion2Packet(
290292
dataEncryptorBuilder.getAlgorithm(),
@@ -382,13 +384,14 @@ private void writeOpenPGPv4ESKPacket(PGPKeyEncryptionMethodGenerator m, byte[] s
382384
if (m instanceof PBEKeyEncryptionMethodGenerator)
383385
{
384386
PBEKeyEncryptionMethodGenerator mGen = (PBEKeyEncryptionMethodGenerator)m;
385-
ContainedPacket esk = mGen.generateV4(mGen.getSessionKeyWrapperAlgorithm(defAlgorithm), sessionInfo);
387+
ContainedPacket esk = mGen.setKekAlgorithm(mGen.getSessionKeyWrapperAlgorithm(defAlgorithm))
388+
.generate(SymmetricKeyEncSessionPacket.VERSION_4, sessionInfo);
386389
pOut.writePacket(esk);
387390
}
388391
else if (m instanceof PublicKeyKeyEncryptionMethodGenerator)
389392
{
390393
PublicKeyKeyEncryptionMethodGenerator mGen = (PublicKeyKeyEncryptionMethodGenerator)m;
391-
pOut.writePacket(mGen.generateV3(sessionInfo));
394+
pOut.writePacket(mGen.generate(PublicKeyEncSessionPacket.VERSION_3, sessionInfo));
392395
}
393396
}
394397

@@ -408,16 +411,15 @@ private void writeOpenPGPv5ESKPacket(PGPKeyEncryptionMethodGenerator m, byte[] s
408411
if (m instanceof PBEKeyEncryptionMethodGenerator)
409412
{
410413
PBEKeyEncryptionMethodGenerator mGen = (PBEKeyEncryptionMethodGenerator)m;
411-
ContainedPacket esk = mGen.generateV5(
412-
mGen.getSessionKeyWrapperAlgorithm(defAlgorithm),
413-
dataEncryptorBuilder.getAeadAlgorithm(),
414-
sessionInfo);
414+
ContainedPacket esk = mGen.setKekAlgorithm(mGen.getSessionKeyWrapperAlgorithm(defAlgorithm))
415+
.setAEADAlgorithm(dataEncryptorBuilder.getAeadAlgorithm())
416+
.generate(SymmetricKeyEncSessionPacket.VERSION_5, sessionInfo);
415417
pOut.writePacket(esk);
416418
}
417419
else if (m instanceof PublicKeyKeyEncryptionMethodGenerator)
418420
{
419421
PublicKeyKeyEncryptionMethodGenerator mGen = (PublicKeyKeyEncryptionMethodGenerator)m;
420-
pOut.writePacket(mGen.generateV3(sessionInfo));
422+
pOut.writePacket(mGen.generate(PublicKeyEncSessionPacket.VERSION_3, sessionInfo));
421423
}
422424
}
423425

@@ -427,27 +429,25 @@ else if (m instanceof PublicKeyKeyEncryptionMethodGenerator)
427429
* depending on the method generator. This method is used by what can be referred to as OpenPGP v6.
428430
*
429431
* @param m session key encryption method generator.
430-
* @param aeadAlgorithm AEAD encryption algorithm
431432
* @param sessionInfo session info
432433
* @throws IOException
433434
* @throws PGPException
434435
*/
435-
private void writeOpenPGPv6ESKPacket(PGPKeyEncryptionMethodGenerator m, int aeadAlgorithm, byte[] sessionInfo)
436+
private void writeOpenPGPv6ESKPacket(PGPKeyEncryptionMethodGenerator m, byte[] sessionInfo)
436437
throws IOException, PGPException
437438
{
438439
if (m instanceof PBEKeyEncryptionMethodGenerator)
439440
{
440441
PBEKeyEncryptionMethodGenerator mGen = (PBEKeyEncryptionMethodGenerator)m;
441-
ContainedPacket esk = mGen.generateV6(
442-
mGen.getSessionKeyWrapperAlgorithm(defAlgorithm),
443-
aeadAlgorithm,
444-
sessionInfo);
442+
ContainedPacket esk = mGen.setKekAlgorithm(mGen.getSessionKeyWrapperAlgorithm(defAlgorithm))
443+
.setAEADAlgorithm(dataEncryptorBuilder.getAeadAlgorithm())
444+
.generate(SymmetricKeyEncSessionPacket.VERSION_6, sessionInfo);
445445
pOut.writePacket(esk);
446446
}
447447
else if (m instanceof PublicKeyKeyEncryptionMethodGenerator)
448448
{
449449
PublicKeyKeyEncryptionMethodGenerator mGen = (PublicKeyKeyEncryptionMethodGenerator)m;
450-
pOut.writePacket(mGen.generateV6(sessionInfo));
450+
pOut.writePacket(mGen.generate(PublicKeyEncSessionPacket.VERSION_6, sessionInfo));
451451
}
452452
}
453453

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

Lines changed: 91 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ public abstract class PBEKeyEncryptionMethodGenerator
3030
private SecureRandom random;
3131
private int s2kCount;
3232
private int wrapAlg = -1;
33+
private int kekAlgorithm;
34+
private int aeadAlgorithm;
3335

3436
/**
3537
* Construct a PBE key generator using the default iteration count (<code>0x60</code> == 65536
@@ -115,6 +117,18 @@ public PBEKeyEncryptionMethodGenerator setSessionKeyWrapperAlgorithm(int wrapAlg
115117
return this;
116118
}
117119

120+
public PBEKeyEncryptionMethodGenerator setKekAlgorithm(int kekAlgorithm)
121+
{
122+
this.kekAlgorithm = kekAlgorithm;
123+
return this;
124+
}
125+
126+
public PBEKeyEncryptionMethodGenerator setAEADAlgorithm(int aeadAlgorithm)
127+
{
128+
this.aeadAlgorithm = aeadAlgorithm;
129+
return this;
130+
}
131+
118132
/**
119133
* Return the key wrapping algorithm this PBE key method is associated with.
120134
*
@@ -160,6 +174,62 @@ public byte[] getKey(int encAlgorithm)
160174
return PGPUtil.makeKeyFromPassPhrase(s2kDigestCalculator, encAlgorithm, s2k, passPhrase);
161175
}
162176

177+
public ContainedPacket generate(int version, byte[] sessionInfo)
178+
throws PGPException
179+
{
180+
if (version == SymmetricKeyEncSessionPacket.VERSION_4)
181+
{
182+
if (sessionInfo == null)
183+
{
184+
return SymmetricKeyEncSessionPacket.createV4Packet(kekAlgorithm, s2k, null);
185+
}
186+
187+
byte[] key = getKey(kekAlgorithm);
188+
//
189+
// the passed in session info has the an RSA/ElGamal checksum added to it, for PBE this is not included.
190+
//
191+
byte[] nSessionInfo = new byte[sessionInfo.length - 2];
192+
193+
System.arraycopy(sessionInfo, 0, nSessionInfo, 0, nSessionInfo.length);
194+
195+
return SymmetricKeyEncSessionPacket.createV4Packet(kekAlgorithm, s2k, encryptSessionInfo(kekAlgorithm, key, nSessionInfo));
196+
}
197+
else if (version == SymmetricKeyEncSessionPacket.VERSION_5 || version == SymmetricKeyEncSessionPacket.VERSION_6)
198+
{
199+
byte[] ikm = getKey(kekAlgorithm);
200+
byte[] info = new byte[]{
201+
(byte)0xC3,
202+
(byte)version,
203+
(byte)kekAlgorithm,
204+
(byte)aeadAlgorithm
205+
};
206+
207+
if (version == 6)
208+
{
209+
ikm = generateV6KEK(kekAlgorithm, ikm, info); // ikm is kek
210+
}
211+
212+
byte[] iv = new byte[AEADUtils.getIVLength(aeadAlgorithm)];
213+
random.nextBytes(iv);
214+
215+
int tagLen = AEADUtils.getAuthTagLength(aeadAlgorithm);
216+
byte[] sessionKey = getSessionKey(sessionInfo);
217+
byte[] eskAndTag = getEskAndTag(kekAlgorithm, aeadAlgorithm, sessionKey, ikm, iv, info);
218+
byte[] esk = Arrays.copyOfRange(eskAndTag, 0, eskAndTag.length - tagLen);
219+
byte[] tag = Arrays.copyOfRange(eskAndTag, esk.length, eskAndTag.length);
220+
221+
if (version == SymmetricKeyEncSessionPacket.VERSION_5)
222+
{
223+
return SymmetricKeyEncSessionPacket.createV5Packet(kekAlgorithm, aeadAlgorithm, iv, s2k, esk, tag);
224+
}
225+
else
226+
{
227+
return SymmetricKeyEncSessionPacket.createV6Packet(kekAlgorithm, aeadAlgorithm, iv, s2k, esk, tag);
228+
}
229+
}
230+
throw new PGPException("Unexpected version number");
231+
}
232+
163233
/**
164234
* Generates a version 4 Symmetric-Key-Encrypted-Session-Key (SKESK) packet, encoding the encrypted
165235
* session-key for this method.
@@ -169,16 +239,15 @@ public byte[] getKey(int encAlgorithm)
169239
* instead in that case).
170240
*
171241
* @param kekAlgorithm the {@link SymmetricKeyAlgorithmTags encryption algorithm} being used to
172-
* wrap the session key
173-
* @param sessionInfo session data generated by the encrypted data generator.
242+
* wrap the session key
243+
* @param sessionInfo session data generated by the encrypted data generator.
174244
* @return a packet encoding the provided information and the configuration of this instance.
175-
*
176245
* @throws PGPException if an error occurs constructing the packet.
177246
* @see <a href="https://www.rfc-editor.org/rfc/rfc9580.html#name-version-4-symmetric-key-enc">
178-
* RFC9580 - Symmetric-Key Encrypted Session-Key Packet version 4</a>
247+
* RFC9580 - Symmetric-Key Encrypted Session-Key Packet version 4</a>
179248
*/
180249
public ContainedPacket generateV4(int kekAlgorithm, byte[] sessionInfo)
181-
throws PGPException
250+
throws PGPException
182251
{
183252
if (sessionInfo == null)
184253
{
@@ -202,25 +271,24 @@ public ContainedPacket generateV4(int kekAlgorithm, byte[] sessionInfo)
202271
* SKESKv5 packets are used with {@link org.bouncycastle.bcpg.AEADEncDataPacket OCB-Encrypted Data (OED) packets}
203272
* only.
204273
*
205-
* @param kekAlgorithm the {@link SymmetricKeyAlgorithmTags encryption algorithm} being used to
206-
* wrap the session key
274+
* @param kekAlgorithm the {@link SymmetricKeyAlgorithmTags encryption algorithm} being used to
275+
* wrap the session key
207276
* @param aeadAlgorithm AEAD algorithm ID (MUST be {@link org.bouncycastle.bcpg.AEADAlgorithmTags#OCB})
208-
* @param sessionInfo session data generated by the encrypted data generator.
277+
* @param sessionInfo session data generated by the encrypted data generator.
209278
* @return a packet encoding the provided information and the configuration of this instance.
210-
*
211279
* @throws PGPException if an error occurs constructing the packet.
212280
* @see <a href="https://www.ietf.org/archive/id/draft-koch-librepgp-02.html#section-5.3-8">
213-
* LibrePGP - Symmetric-Key Encrypted Session-Key Packet version 5</a>
281+
* LibrePGP - Symmetric-Key Encrypted Session-Key Packet version 5</a>
214282
*/
215283
public ContainedPacket generateV5(int kekAlgorithm, int aeadAlgorithm, byte[] sessionInfo)
216-
throws PGPException
284+
throws PGPException
217285
{
218286
byte[] ikm = getKey(kekAlgorithm);
219287
byte[] info = new byte[]{
220-
(byte)0xC3,
221-
(byte)SymmetricKeyEncSessionPacket.VERSION_5,
222-
(byte)kekAlgorithm,
223-
(byte)aeadAlgorithm
288+
(byte)0xC3,
289+
(byte)SymmetricKeyEncSessionPacket.VERSION_5,
290+
(byte)kekAlgorithm,
291+
(byte)aeadAlgorithm
224292
};
225293

226294
byte[] iv = new byte[AEADUtils.getIVLength(aeadAlgorithm)];
@@ -242,25 +310,24 @@ public ContainedPacket generateV5(int kekAlgorithm, int aeadAlgorithm, byte[] se
242310
* version 2 only.
243311
* A SKESKv6 packet MUST NOT precede a SEIPDv1, OED or SED packet.
244312
*
245-
* @param kekAlgorithm the {@link SymmetricKeyAlgorithmTags encryption algorithm} being used to
246-
* wrap the session key
313+
* @param kekAlgorithm the {@link SymmetricKeyAlgorithmTags encryption algorithm} being used to
314+
* wrap the session key
247315
* @param aeadAlgorithm AEAD algorithm ID
248-
* @param sessionInfo session data generated by the encrypted data generator.
316+
* @param sessionInfo session data generated by the encrypted data generator.
249317
* @return a packet encoding the provided information and the configuration of this instance.
250-
*
251318
* @throws PGPException if an error occurs constructing the packet.
252319
* @see <a href="https://www.rfc-editor.org/rfc/rfc9580.html#name-version-6-symmetric-key-enc">
253-
* RFC9580 - Symmetric-Key Encrypted Session-Key Packet version 6</a>
320+
* RFC9580 - Symmetric-Key Encrypted Session-Key Packet version 6</a>
254321
*/
255322
public ContainedPacket generateV6(int kekAlgorithm, int aeadAlgorithm, byte[] sessionInfo)
256323
throws PGPException
257324
{
258325
byte[] ikm = getKey(kekAlgorithm);
259326
byte[] info = new byte[]{
260-
(byte)0xC3,
261-
(byte)SymmetricKeyEncSessionPacket.VERSION_6,
262-
(byte)kekAlgorithm,
263-
(byte)aeadAlgorithm
327+
(byte)0xC3,
328+
(byte)SymmetricKeyEncSessionPacket.VERSION_6,
329+
(byte)kekAlgorithm,
330+
(byte)aeadAlgorithm
264331
};
265332
byte[] kek = generateV6KEK(kekAlgorithm, ikm, info);
266333

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
package org.bouncycastle.openpgp.operator;
22

3+
import org.bouncycastle.bcpg.ContainedPacket;
34
import org.bouncycastle.openpgp.PGPEncryptedDataGenerator;
5+
import org.bouncycastle.openpgp.PGPException;
46

57
/**
68
* An encryption method that can be applied to encrypt data in a {@link PGPEncryptedDataGenerator}.
79
*/
810
public interface PGPKeyEncryptionMethodGenerator
911
{
10-
12+
ContainedPacket generate(int version, byte[] sessionInfo)
13+
throws PGPException;
1114
}

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

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,49 @@ private byte[] convertToEncodedMPI(byte[] encryptedSessionInfo)
164164
}
165165
}
166166

167+
public ContainedPacket generate(int version, byte[] sessionInfo)
168+
throws PGPException
169+
{
170+
if (version == PublicKeyEncSessionPacket.VERSION_3)
171+
{
172+
long keyId;
173+
if (useWildcardRecipient)
174+
{
175+
keyId = WILDCARD_KEYID;
176+
}
177+
else
178+
{
179+
keyId = pubKey.getKeyID();
180+
}
181+
byte[] encryptedSessionInfo = encryptSessionInfo(pubKey, sessionInfo, sessionInfo, sessionInfo[0]);
182+
byte[][] encodedEncSessionInfo = encodeEncryptedSessionInfo(encryptedSessionInfo);
183+
return PublicKeyEncSessionPacket.createV3PKESKPacket(keyId, pubKey.getAlgorithm(), encodedEncSessionInfo);
184+
}
185+
else if (version == PublicKeyEncSessionPacket.VERSION_6)
186+
{
187+
byte[] keyFingerprint;
188+
int keyVersion;
189+
if (useWildcardRecipient)
190+
{
191+
keyFingerprint = WILDCARD_FINGERPRINT;
192+
keyVersion = 0;
193+
}
194+
else
195+
{
196+
keyFingerprint = pubKey.getFingerprint();
197+
keyVersion = pubKey.getVersion();
198+
}
199+
// In V6, do not include the symmetric-key algorithm in the session-info
200+
byte[] sessionInfoWithoutAlgId = new byte[sessionInfo.length - 1];
201+
System.arraycopy(sessionInfo, 1, sessionInfoWithoutAlgId, 0, sessionInfoWithoutAlgId.length);
202+
203+
byte[] encryptedSessionInfo = encryptSessionInfo(pubKey, sessionInfo, sessionInfoWithoutAlgId, (byte)0);
204+
byte[][] encodedEncSessionInfo = encodeEncryptedSessionInfo(encryptedSessionInfo);
205+
return PublicKeyEncSessionPacket.createV6PKESKPacket(keyVersion, keyFingerprint, pubKey.getAlgorithm(), encodedEncSessionInfo);
206+
}
207+
throw new PGPException("Unexpected version number");
208+
}
209+
167210
/**
168211
* Generate a Public-Key Encrypted Session-Key (PKESK) packet of version 3.
169212
* PKESKv3 packets are used with Symmetrically-Encrypted-Integrity-Protected Data (SEIPD) packets of

0 commit comments

Comments
 (0)