Skip to content

Commit 3317546

Browse files
committed
Merge branch 'main' of gitlab.cryptoworkshop.com:root/bc-java
2 parents 667251e + e404cef commit 3317546

5 files changed

Lines changed: 157 additions & 168 deletions

File tree

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
import org.bouncycastle.bcpg.AEADAlgorithmTags;
99
import org.bouncycastle.bcpg.AEADEncDataPacket;
10-
import org.bouncycastle.bcpg.BCPGInputStream;
1110
import org.bouncycastle.bcpg.InputStreamPacket;
1211
import org.bouncycastle.bcpg.SymmetricEncIntegrityPacket;
1312
import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags;
@@ -276,10 +275,11 @@ public int getAlgorithm()
276275
throw new UnsupportedOperationException("not supported - override required");
277276
}
278277

279-
boolean processSymmetricEncIntegrityPacketDataStream(boolean withIntegrityPacket, PGPDataDecryptor dataDecryptor, BCPGInputStream encIn)
278+
boolean processSymmetricEncIntegrityPacketDataStream(boolean withIntegrityPacket, PGPDataDecryptor dataDecryptor,
279+
InputStream encIn)
280280
throws IOException
281281
{
282-
encStream = new BCPGInputStream(dataDecryptor.getInputStream(encIn));
282+
encStream = dataDecryptor.getInputStream(encIn);
283283

284284
if (withIntegrityPacket)
285285
{

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

Lines changed: 58 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import java.io.InputStream;
44

55
import org.bouncycastle.bcpg.AEADEncDataPacket;
6-
import org.bouncycastle.bcpg.BCPGInputStream;
76
import org.bouncycastle.bcpg.InputStreamPacket;
87
import org.bouncycastle.bcpg.KeyIdentifier;
98
import org.bouncycastle.bcpg.PublicKeyAlgorithmTags;
@@ -201,93 +200,85 @@ private InputStream getDataStream(
201200
PGPSessionKey sessionKey)
202201
throws PGPException
203202
{
204-
if (sessionKey.getAlgorithm() != SymmetricKeyAlgorithmTags.NULL)
203+
if (sessionKey.getAlgorithm() == SymmetricKeyAlgorithmTags.NULL)
205204
{
206-
try
207-
{
208-
// OpenPGP V5 style AEAD
209-
if (encData instanceof AEADEncDataPacket)
210-
{
211-
AEADEncDataPacket aeadData = (AEADEncDataPacket)encData;
212-
213-
if (aeadData.getAlgorithm() != sessionKey.getAlgorithm())
214-
{
215-
throw new PGPException("session key and AEAD algorithm mismatch");
216-
}
205+
return getInputStream();
206+
}
217207

218-
PGPDataDecryptor dataDecryptor = dataDecryptorFactory.createDataDecryptor(aeadData, sessionKey);
208+
try
209+
{
210+
InputStream encIn = getInputStream();
219211

220-
BCPGInputStream encIn = encData.getInputStream();
212+
// OpenPGP V5 style AEAD
213+
if (encData instanceof AEADEncDataPacket)
214+
{
215+
AEADEncDataPacket aeadData = (AEADEncDataPacket)encData;
221216

222-
encStream = new BCPGInputStream(dataDecryptor.getInputStream(encIn));
223-
}
224-
else
217+
if (aeadData.getAlgorithm() != sessionKey.getAlgorithm())
225218
{
219+
throw new PGPException("session key and AEAD algorithm mismatch");
220+
}
226221

227-
if (encData instanceof SymmetricEncIntegrityPacket)
228-
{
229-
SymmetricEncIntegrityPacket seipd = (SymmetricEncIntegrityPacket) encData;
230-
// SEIPD v1 (OpenPGP v4)
231-
if (seipd.getVersion() == SymmetricEncIntegrityPacket.VERSION_1)
232-
{
233-
PGPDataDecryptor dataDecryptor = dataDecryptorFactory.createDataDecryptor(true, sessionKey.getAlgorithm(), sessionKey.getKey());
234-
235-
BCPGInputStream encIn = encData.getInputStream();
222+
PGPDataDecryptor dataDecryptor = dataDecryptorFactory.createDataDecryptor(aeadData, sessionKey);
236223

237-
processSymmetricEncIntegrityPacketDataStream(true, dataDecryptor, encIn);
238-
}
239-
// SEIPD v2 (OpenPGP v6 AEAD)
240-
else
241-
{
242-
PGPDataDecryptor dataDecryptor = dataDecryptorFactory.createDataDecryptor(seipd, sessionKey);
224+
encStream = dataDecryptor.getInputStream(encIn);
225+
}
226+
else
227+
{
243228

244-
BCPGInputStream encIn = encData.getInputStream();
229+
if (encData instanceof SymmetricEncIntegrityPacket)
230+
{
231+
SymmetricEncIntegrityPacket seipd = (SymmetricEncIntegrityPacket) encData;
232+
// SEIPD v1 (OpenPGP v4)
233+
if (seipd.getVersion() == SymmetricEncIntegrityPacket.VERSION_1)
234+
{
235+
PGPDataDecryptor dataDecryptor = dataDecryptorFactory.createDataDecryptor(true, sessionKey.getAlgorithm(), sessionKey.getKey());
245236

246-
encStream = new BCPGInputStream(dataDecryptor.getInputStream(encIn));
247-
}
237+
processSymmetricEncIntegrityPacketDataStream(true, dataDecryptor, encIn);
248238
}
249-
// SED (Symmetrically Encrypted Data without Integrity Protection; Deprecated)
239+
// SEIPD v2 (OpenPGP v6 AEAD)
250240
else
251241
{
252-
PGPDataDecryptor dataDecryptor = dataDecryptorFactory.createDataDecryptor(false, sessionKey.getAlgorithm(), sessionKey.getKey());
253-
254-
BCPGInputStream encIn = encData.getInputStream();
242+
PGPDataDecryptor dataDecryptor = dataDecryptorFactory.createDataDecryptor(seipd, sessionKey);
255243

256-
processSymmetricEncIntegrityPacketDataStream(false, dataDecryptor, encIn);
244+
encStream = dataDecryptor.getInputStream(encIn);
257245
}
246+
}
247+
// SED (Symmetrically Encrypted Data without Integrity Protection; Deprecated)
248+
else
249+
{
250+
PGPDataDecryptor dataDecryptor = dataDecryptorFactory.createDataDecryptor(false, sessionKey.getAlgorithm(), sessionKey.getKey());
258251

259-
//
260-
// some versions of PGP appear to produce 0 for the extra
261-
// bytes rather than repeating the two previous bytes
262-
//
263-
/*
264-
* Commented out in the light of the oracle attack.
265-
if (iv[iv.length - 2] != (byte)v1 && v1 != 0)
266-
{
267-
throw new PGPDataValidationException("data check failed.");
268-
}
252+
processSymmetricEncIntegrityPacketDataStream(false, dataDecryptor, encIn);
253+
}
269254

270-
if (iv[iv.length - 1] != (byte)v2 && v2 != 0)
271-
{
272-
throw new PGPDataValidationException("data check failed.");
273-
}
274-
*/
255+
//
256+
// some versions of PGP appear to produce 0 for the extra
257+
// bytes rather than repeating the two previous bytes
258+
//
259+
/*
260+
* Commented out in the light of the oracle attack.
261+
if (iv[iv.length - 2] != (byte)v1 && v1 != 0)
262+
{
263+
throw new PGPDataValidationException("data check failed.");
275264
}
276265
277-
return encStream;
278-
}
279-
catch (PGPException e)
280-
{
281-
throw e;
282-
}
283-
catch (Exception e)
284-
{
285-
throw new PGPException("Exception starting decryption", e);
266+
if (iv[iv.length - 1] != (byte)v2 && v2 != 0)
267+
{
268+
throw new PGPDataValidationException("data check failed.");
269+
}
270+
*/
286271
}
272+
273+
return encStream;
287274
}
288-
else
275+
catch (PGPException e)
276+
{
277+
throw e;
278+
}
279+
catch (Exception e)
289280
{
290-
return encData.getInputStream();
281+
throw new PGPException("Exception starting decryption", e);
291282
}
292283
}
293284

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

Lines changed: 81 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -552,119 +552,116 @@ public Iterator<PGPUserAttributeSubpacketVector> getUserAttributes()
552552
return pub.getUserAttributes();
553553
}
554554

555-
private byte[] extractKeyData(
556-
PBESecretKeyDecryptor decryptorFactory)
557-
throws PGPException
555+
private byte[] extractKeyData(PBESecretKeyDecryptor decryptorFactory) throws PGPException
558556
{
559557
byte[] encData = secret.getSecretKeyData();
560-
byte[] data = null;
561558

562-
if (secret.getEncAlgorithm() != SymmetricKeyAlgorithmTags.NULL)
559+
if (secret.getEncAlgorithm() == SymmetricKeyAlgorithmTags.NULL)
563560
{
564-
try
565-
{
566-
byte[] key = decryptorFactory.makeKeyFromPassPhrase(secret.getEncAlgorithm(), secret.getS2K());
567-
if (secret.getPublicKeyPacket().getVersion() >= PublicKeyPacket.VERSION_4)
568-
{
569-
if (secret.getS2KUsage() == SecretKeyPacket.USAGE_AEAD)
570-
{
571-
// privKey := AEAD(HKDF(S2K(passphrase), info), secrets, packetprefix)
572-
return decryptorFactory.recoverKeyData(
573-
secret.getEncAlgorithm(),
574-
secret.getAeadAlgorithm(),
575-
key, // s2k output = ikm for hkdf
576-
secret.getIV(), // iv = aead nonce
577-
secret.getPacketTag(),
578-
secret.getPublicKeyPacket().getVersion(),
579-
secret.getSecretKeyData(),
580-
secret.getPublicKeyPacket().getEncodedContents());
581-
}
582-
else
583-
{
584-
data = decryptorFactory.recoverKeyData(secret.getEncAlgorithm(), key, secret.getIV(), encData, 0, encData.length);
561+
return encData;
562+
}
585563

586-
boolean useSHA1 = secret.getS2KUsage() == SecretKeyPacket.USAGE_SHA1;
587-
byte[] check = checksum(useSHA1 ? decryptorFactory.getChecksumCalculator(HashAlgorithmTags.SHA1) : null, data, (useSHA1) ? data.length - 20 : data.length - 2);
564+
try
565+
{
566+
byte[] key = decryptorFactory.makeKeyFromPassPhrase(secret.getEncAlgorithm(), secret.getS2K());
567+
byte[] data;
588568

589-
if (!Arrays.constantTimeAreEqual(check.length, check, 0, data, data.length - check.length))
590-
{
591-
throw new PGPException("checksum mismatch at in checksum of " + check.length + " bytes");
592-
}
593-
}
569+
if (secret.getPublicKeyPacket().getVersion() >= PublicKeyPacket.VERSION_4)
570+
{
571+
if (secret.getS2KUsage() == SecretKeyPacket.USAGE_AEAD)
572+
{
573+
// privKey := AEAD(HKDF(S2K(passphrase), info), secrets, packetprefix)
574+
return decryptorFactory.recoverKeyData(
575+
secret.getEncAlgorithm(),
576+
secret.getAeadAlgorithm(),
577+
key, // s2k output = ikm for hkdf
578+
secret.getIV(), // iv = aead nonce
579+
secret.getPacketTag(),
580+
secret.getPublicKeyPacket().getVersion(),
581+
secret.getSecretKeyData(),
582+
secret.getPublicKeyPacket().getEncodedContents());
594583
}
595-
else // version 2 or 3, RSA only.
584+
else
596585
{
586+
data = decryptorFactory.recoverKeyData(secret.getEncAlgorithm(), key, secret.getIV(), encData, 0, encData.length);
597587

598-
data = new byte[encData.length];
599-
600-
byte[] iv = new byte[secret.getIV().length];
588+
boolean useSHA1 = secret.getS2KUsage() == SecretKeyPacket.USAGE_SHA1;
589+
byte[] check = checksum(useSHA1 ? decryptorFactory.getChecksumCalculator(HashAlgorithmTags.SHA1) : null, data, (useSHA1) ? data.length - 20 : data.length - 2);
601590

602-
System.arraycopy(secret.getIV(), 0, iv, 0, iv.length);
603-
604-
//
605-
// read in the four numbers
606-
//
607-
int pos = 0;
608-
609-
for (int i = 0; i != 4; i++)
591+
if (!Arrays.constantTimeAreEqual(check.length, check, 0, data, data.length - check.length))
610592
{
611-
int encLen = ((((encData[pos] & 0xff) << 8) | (encData[pos + 1] & 0xff)) + 7) / 8;
593+
throw new PGPException("checksum mismatch in checksum of " + check.length + " bytes");
594+
}
595+
}
596+
}
597+
else // version 2 or 3, RSA only.
598+
{
612599

613-
data[pos] = encData[pos];
614-
data[pos + 1] = encData[pos + 1];
600+
data = new byte[encData.length];
615601

616-
if (encLen > (encData.length - (pos + 2)))
617-
{
618-
throw new PGPException("out of range encLen found in encData");
619-
}
620-
byte[] tmp = decryptorFactory.recoverKeyData(secret.getEncAlgorithm(), key, iv, encData, pos + 2, encLen);
621-
System.arraycopy(tmp, 0, data, pos + 2, tmp.length);
622-
pos += 2 + encLen;
602+
byte[] iv = new byte[secret.getIV().length];
623603

624-
if (i != 3)
625-
{
626-
System.arraycopy(encData, pos - iv.length, iv, 0, iv.length);
627-
}
628-
}
604+
System.arraycopy(secret.getIV(), 0, iv, 0, iv.length);
629605

630-
//
631-
// verify and copy checksum
632-
//
606+
//
607+
// read in the four numbers
608+
//
609+
int pos = 0;
610+
611+
for (int i = 0; i != 4; i++)
612+
{
613+
int encLen = ((((encData[pos] & 0xff) << 8) | (encData[pos + 1] & 0xff)) + 7) / 8;
633614

634615
data[pos] = encData[pos];
635616
data[pos + 1] = encData[pos + 1];
636617

637-
int cs = ((encData[pos] << 8) & 0xff00) | (encData[pos + 1] & 0xff);
638-
int calcCs = 0;
639-
for (int j = 0; j < data.length - 2; j++)
618+
if (encLen > (encData.length - (pos + 2)))
640619
{
641-
calcCs += data[j] & 0xff;
620+
throw new PGPException("out of range encLen found in encData");
642621
}
622+
byte[] tmp = decryptorFactory.recoverKeyData(secret.getEncAlgorithm(), key, iv, encData, pos + 2, encLen);
623+
System.arraycopy(tmp, 0, data, pos + 2, tmp.length);
624+
pos += 2 + encLen;
643625

644-
calcCs &= 0xffff;
645-
if (calcCs != cs)
626+
if (i != 3)
646627
{
647-
throw new PGPException("checksum mismatch: passphrase wrong, expected "
648-
+ Integer.toHexString(cs)
649-
+ " found " + Integer.toHexString(calcCs));
628+
System.arraycopy(encData, pos - iv.length, iv, 0, iv.length);
650629
}
651630
}
631+
632+
//
633+
// verify and copy checksum
634+
//
635+
636+
data[pos] = encData[pos];
637+
data[pos + 1] = encData[pos + 1];
638+
639+
int cs = ((encData[pos] << 8) & 0xff00) | (encData[pos + 1] & 0xff);
640+
int calcCs = 0;
641+
for (int j = 0; j < data.length - 2; j++)
642+
{
643+
calcCs += data[j] & 0xff;
644+
}
645+
646+
calcCs &= 0xffff;
647+
if (calcCs != cs)
648+
{
649+
throw new PGPException("checksum mismatch: passphrase wrong, expected "
650+
+ Integer.toHexString(cs)
651+
+ " found " + Integer.toHexString(calcCs));
652+
}
652653
}
653-
catch (PGPException e)
654-
{
655-
throw e;
656-
}
657-
catch (Exception e)
658-
{
659-
throw new PGPException("Exception decrypting key", e);
660-
}
654+
655+
return data;
661656
}
662-
else
657+
catch (PGPException e)
663658
{
664-
data = encData;
659+
throw e;
660+
}
661+
catch (Exception e)
662+
{
663+
throw new PGPException("Exception decrypting key", e);
665664
}
666-
667-
return data;
668665
}
669666

670667
/**

0 commit comments

Comments
 (0)