@@ -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
0 commit comments