|
9 | 9 | import org.bouncycastle.bcpg.AEADEncDataPacket; |
10 | 10 | import org.bouncycastle.bcpg.BCPGHeaderObject; |
11 | 11 | import org.bouncycastle.bcpg.BCPGOutputStream; |
12 | | -import org.bouncycastle.bcpg.ContainedPacket; |
13 | 12 | import org.bouncycastle.bcpg.HashAlgorithmTags; |
14 | 13 | import org.bouncycastle.bcpg.PacketTags; |
15 | 14 | import org.bouncycastle.bcpg.SymmetricEncDataPacket; |
@@ -141,42 +140,6 @@ public void addMethod(PGPKeyEncryptionMethodGenerator method) |
141 | 140 | methods.add(method); |
142 | 141 | } |
143 | 142 |
|
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 | | - } |
180 | 143 |
|
181 | 144 | /** |
182 | 145 | * Create an OutputStream based on the configured methods. |
@@ -247,78 +210,56 @@ else if (directS2K) |
247 | 210 | else |
248 | 211 | { |
249 | 212 | sessionKey = PGPUtil.makeRandomKey(defAlgorithm, rand); |
250 | | - // prepend algorithm, append checksum |
251 | | - sessionInfo = createSessionInfo(defAlgorithm, sessionKey); |
252 | 213 | messageKey = sessionKey; |
253 | 214 | } |
254 | 215 |
|
255 | 216 | PGPDataEncryptor dataEncryptor = dataEncryptorBuilder.build(messageKey); |
256 | 217 | digestCalc = dataEncryptor.getIntegrityCalculator(); |
257 | | - |
| 218 | + BCPGHeaderObject encOut; |
258 | 219 | for (int i = 0; i < methods.size(); i++) |
259 | 220 | { |
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)); |
282 | 223 | } |
283 | | - |
284 | 224 | try |
285 | 225 | { |
286 | | - BCPGHeaderObject encOut; |
| 226 | + // OpenPGP v5 or v6 |
287 | 227 | if (dataEncryptor instanceof PGPAEADDataEncryptor) |
288 | 228 | { |
289 | | - PGPAEADDataEncryptor encryptor = (PGPAEADDataEncryptor)dataEncryptor; |
| 229 | + PGPAEADDataEncryptor aeadDataEncryptor = (PGPAEADDataEncryptor)dataEncryptor; |
290 | 230 | long ivOrSaltLen; |
291 | | - // OpenPGP V5 style AEAD |
| 231 | + // data is encrypted by AEAD Encrypted Data packet (rfc4880bis10), so write v5 SKESK packet |
292 | 232 | if (isV5StyleAEAD) |
293 | 233 | { |
294 | | - byte[] iv = encryptor.getIV(); |
| 234 | + byte[] iv = aeadDataEncryptor.getIV(); |
295 | 235 | encOut = new AEADEncDataPacket( |
296 | | - dataEncryptorBuilder.getAlgorithm(), encryptor.getAEADAlgorithm(), encryptor.getChunkSize(), iv); |
| 236 | + defAlgorithm, aeadDataEncryptor.getAEADAlgorithm(), aeadDataEncryptor.getChunkSize(), iv); |
297 | 237 | ivOrSaltLen = iv.length; |
298 | 238 | } |
299 | | - else // OpenPGP V6 style AEAD |
| 239 | + else // data is encrypted by v2 SEIPD (AEAD), so write v6 SKESK packet |
300 | 240 | { |
| 241 | + //AEAD(HKDF(S2K(passphrase), info), secrets, packetprefix) |
301 | 242 | encOut = SymmetricEncIntegrityPacket.createVersion2Packet( |
302 | | - dataEncryptorBuilder.getAlgorithm(), |
303 | | - encryptor.getAEADAlgorithm(), |
304 | | - encryptor.getChunkSize(), |
| 243 | + defAlgorithm, |
| 244 | + aeadDataEncryptor.getAEADAlgorithm(), |
| 245 | + aeadDataEncryptor.getChunkSize(), |
305 | 246 | salt); |
306 | 247 | ivOrSaltLen = salt.length; |
307 | 248 | } |
308 | | - |
309 | | - if (buffer != null) |
| 249 | + if (buffer == null) |
310 | 250 | { |
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)); |
312 | 254 | } |
313 | 255 | else |
314 | 256 | { |
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); |
318 | 258 | } |
319 | 259 | genOut = cOut = dataEncryptor.getOutputStream(pOut); |
320 | 260 | } |
321 | | - else |
| 261 | + // OpenPGP v4 |
| 262 | + else // data is encrypted by v1 SEIPD or SED packet, so write v4 SKESK packet |
322 | 263 | { |
323 | 264 | if (digestCalc != null) |
324 | 265 | { |
@@ -360,95 +301,16 @@ else if (directS2K) |
360 | 301 | inLineIv[inLineIv.length - 2] = inLineIv[inLineIv.length - 4]; |
361 | 302 |
|
362 | 303 | genOut.write(inLineIv); |
363 | | - |
364 | 304 | } |
365 | 305 | return new WrappedGeneratorStream(genOut, this); |
366 | 306 | } |
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) |
421 | 308 | { |
422 | | - pOut.writePacket(m.generate(defAlgorithm, sessionInfo)); |
| 309 | + throw e; |
423 | 310 | } |
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) |
450 | 312 | { |
451 | | - pOut.writePacket(m.generate(defAlgorithm, sessionInfo)); |
| 313 | + throw new PGPException("Exception creating cipher", e); |
452 | 314 | } |
453 | 315 | } |
454 | 316 |
|
|
0 commit comments