Skip to content

Commit eae449e

Browse files
committed
relates to #1228 - added parent class for PGP symmetric encrypted data. Changed add session method for PGPEncryptedDataList to a create.
1 parent 90dda3c commit eae449e

File tree

5 files changed

+180
-264
lines changed

5 files changed

+180
-264
lines changed

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

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public class PGPEncryptedDataList
3939
private static final Logger LOG = Logger.getLogger(PGPEncryptedDataList.class.getName());
4040

4141
List<PGPEncryptedData> methods = new ArrayList<PGPEncryptedData>();
42-
InputStreamPacket data;
42+
InputStreamPacket data;
4343

4444
/**
4545
* Construct an encrypted data packet holder, reading PGP encrypted method packets and an
@@ -48,6 +48,7 @@ public class PGPEncryptedDataList
4848
* The first packet in the stream should be one of {@link PacketTags#SYMMETRIC_KEY_ENC_SESSION}
4949
* or {@link PacketTags#PUBLIC_KEY_ENC_SESSION}.
5050
* </p>
51+
*
5152
* @param encData a byte array containing an encrypted stream.
5253
* @throws IOException if an error occurs reading from the PGP input.
5354
*/
@@ -65,6 +66,7 @@ public PGPEncryptedDataList(
6566
* The first packet in the stream should be one of {@link PacketTags#SYMMETRIC_KEY_ENC_SESSION}
6667
* or {@link PacketTags#PUBLIC_KEY_ENC_SESSION}.
6768
* </p>
69+
*
6870
* @param inStream the input stream being read.
6971
* @throws IOException if an error occurs reading from the PGP input.
7072
*/
@@ -82,11 +84,12 @@ public PGPEncryptedDataList(
8284
* The next packet in the stream should be one of {@link PacketTags#SYMMETRIC_KEY_ENC_SESSION}
8385
* or {@link PacketTags#PUBLIC_KEY_ENC_SESSION}.
8486
* </p>
87+
*
8588
* @param pIn the PGP object stream being read.
8689
* @throws IOException if an error occurs reading from the PGP input.
8790
*/
8891
public PGPEncryptedDataList(
89-
BCPGInputStream pIn)
92+
BCPGInputStream pIn)
9093
throws IOException
9194
{
9295
List list = new ArrayList();
@@ -130,26 +133,13 @@ public PGPEncryptedDataList(
130133
}
131134

132135
/**
133-
* Add a decryption method using a {@link PGPSessionKey}.
134-
* This method can be used to decrypt messages which do not contain a SKESK or PKESK packet using a
135-
* session key.
136-
*
137-
* @param sessionKey session key for message decryption
138-
* @return session key encrypted data
139-
*/
140-
public PGPSessionKeyEncryptedData addSessionKeyDecryptionMethod(PGPSessionKey sessionKey)
141-
{
142-
PGPSessionKeyEncryptedData sessionKeyEncryptedData = new PGPSessionKeyEncryptedData(sessionKey, data);
143-
methods.add(sessionKeyEncryptedData);
144-
return sessionKeyEncryptedData;
145-
}
146-
147-
/** Checks whether the packet is integrity protected.
136+
* Checks whether the packet is integrity protected.
148137
*
149138
* @return <code>true</code> if there is a modification detection code package associated with
150139
* this stream
151140
*/
152-
public boolean isIntegrityProtected() {
141+
public boolean isIntegrityProtected()
142+
{
153143
return data instanceof SymmetricEncIntegrityPacket;
154144
}
155145

@@ -159,7 +149,7 @@ public boolean isIntegrityProtected() {
159149
* @param index the encryption method to obtain (0 based).
160150
*/
161151
public PGPEncryptedData get(
162-
int index)
152+
int index)
163153
{
164154
return (PGPEncryptedData)methods.get(index);
165155
}
@@ -196,4 +186,16 @@ public Iterator<PGPEncryptedData> iterator()
196186
{
197187
return getEncryptedDataObjects();
198188
}
189+
190+
/**
191+
* Create a decryption method using a {@link PGPSessionKey}. This method can be used to decrypt messages which do not
192+
* contain a SKESK or PKESK packet using a session key.
193+
*
194+
* @param sessionKey session key for message decryption
195+
* @return session key encrypted data
196+
*/
197+
public PGPSessionKeyEncryptedData makeSessionKeyEncryptedData(PGPSessionKey sessionKey)
198+
{
199+
return new PGPSessionKeyEncryptedData(sessionKey, data);
200+
}
199201
}
Lines changed: 13 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,13 @@
11
package org.bouncycastle.openpgp;
22

3-
import java.io.EOFException;
43
import java.io.InputStream;
54

6-
import org.bouncycastle.bcpg.AEADEncDataPacket;
7-
import org.bouncycastle.bcpg.BCPGInputStream;
85
import org.bouncycastle.bcpg.InputStreamPacket;
9-
import org.bouncycastle.bcpg.SymmetricEncIntegrityPacket;
106
import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags;
117
import org.bouncycastle.bcpg.SymmetricKeyEncSessionPacket;
128
import org.bouncycastle.openpgp.operator.PBEDataDecryptorFactory;
13-
import org.bouncycastle.openpgp.operator.PGPDataDecryptor;
149
import org.bouncycastle.openpgp.operator.SessionKeyDataDecryptorFactory;
1510
import org.bouncycastle.util.Arrays;
16-
import org.bouncycastle.util.io.TeeInputStream;
1711

1812
/**
1913
* A password based encryption object.
@@ -23,7 +17,7 @@
2317
* </p>
2418
*/
2519
public class PGPPBEEncryptedData
26-
extends PGPEncryptedData
20+
extends PGPSymmetricEncryptedData
2721
{
2822
SymmetricKeyEncSessionPacket keyData;
2923

@@ -43,6 +37,16 @@ public class PGPPBEEncryptedData
4337
this.keyData = keyData;
4438
}
4539

40+
public int getVersion()
41+
{
42+
return keyData.getVersion();
43+
}
44+
45+
public int getAlgorithm()
46+
{
47+
return keyData.getEncAlgorithm();
48+
}
49+
4650
/**
4751
* Return the symmetric key algorithm required to decrypt the data protected by this object.
4852
*
@@ -94,28 +98,7 @@ public InputStream getDataStream(
9498
{
9599
PGPSessionKey sessionKey = getSessionKey(dataDecryptorFactory);
96100

97-
if (encData instanceof AEADEncDataPacket)
98-
{
99-
AEADEncDataPacket aeadData = (AEADEncDataPacket)encData;
100-
101-
if (aeadData.getAlgorithm() != sessionKey.getAlgorithm())
102-
{
103-
throw new PGPException("session key and AEAD algorithm mismatch");
104-
}
105-
106-
PGPDataDecryptor dataDecryptor = dataDecryptorFactory.createDataDecryptor(aeadData.getAEADAlgorithm(), aeadData.getIV(), aeadData.getChunkSize(), sessionKey.getAlgorithm(), sessionKey.getKey());
107-
108-
BCPGInputStream encIn = encData.getInputStream();
109-
110-
encStream = new BCPGInputStream(dataDecryptor.getInputStream(encIn));
111-
}
112-
else
113-
{
114-
boolean withIntegrityPacket = encData instanceof SymmetricEncIntegrityPacket;
115-
PGPDataDecryptor dataDecryptor = dataDecryptorFactory.createDataDecryptor(withIntegrityPacket, sessionKey.getAlgorithm(), sessionKey.getKey());
116-
117-
encStream = getDataStream(withIntegrityPacket, dataDecryptor);
118-
}
101+
encStream = createDecryptionStream(dataDecryptorFactory, sessionKey);
119102

120103
return encStream;
121104
}
@@ -136,79 +119,8 @@ public InputStream getDataStream(
136119
try
137120
{
138121
PGPSessionKey sessionKey = dataDecryptorFactory.getSessionKey();
139-
boolean withIntegrityPacket = encData instanceof SymmetricEncIntegrityPacket;
140-
PGPDataDecryptor dataDecryptor = dataDecryptorFactory.createDataDecryptor(withIntegrityPacket, sessionKey.getAlgorithm(), sessionKey.getKey());
141-
142-
return getDataStream(withIntegrityPacket, dataDecryptor);
143-
}
144-
catch (PGPException e)
145-
{
146-
throw e;
147-
}
148-
catch (Exception e)
149-
{
150-
throw new PGPException("Exception creating cipher", e);
151-
}
152-
}
153-
154-
private InputStream getDataStream(
155-
boolean withIntegrityPacket,
156-
PGPDataDecryptor dataDecryptor)
157-
throws PGPException
158-
{
159-
try
160-
{
161-
BCPGInputStream encIn = encData.getInputStream();
162-
encIn.mark(dataDecryptor.getBlockSize() + 2); // iv + 2 octets checksum
163-
164-
encStream = new BCPGInputStream(dataDecryptor.getInputStream(encIn));
165-
166-
if (withIntegrityPacket)
167-
{
168-
truncStream = new TruncatedStream(encStream);
169-
170-
integrityCalculator = dataDecryptor.getIntegrityCalculator();
171-
172-
encStream = new TeeInputStream(truncStream, integrityCalculator.getOutputStream());
173-
}
174-
175-
byte[] iv = new byte[dataDecryptor.getBlockSize()];
176-
for (int i = 0; i != iv.length; i++)
177-
{
178-
int ch = encStream.read();
179-
180-
if (ch < 0)
181-
{
182-
throw new EOFException("unexpected end of stream.");
183-
}
184-
185-
iv[i] = (byte)ch;
186-
}
187-
188-
int v1 = encStream.read();
189-
int v2 = encStream.read();
190-
191-
if (v1 < 0 || v2 < 0)
192-
{
193-
throw new EOFException("unexpected end of stream.");
194-
}
195-
196122

197-
// Note: the oracle attack on "quick check" bytes is not deemed
198-
// a security risk for PBE (see PGPPublicKeyEncryptedData)
199-
200-
boolean repeatCheckPassed = iv[iv.length - 2] == (byte)v1
201-
&& iv[iv.length - 1] == (byte)v2;
202-
203-
// Note: some versions of PGP appear to produce 0 for the extra
204-
// bytes rather than repeating the two previous bytes
205-
boolean zeroesCheckPassed = v1 == 0 && v2 == 0;
206-
207-
if (!repeatCheckPassed && !zeroesCheckPassed)
208-
{
209-
encIn.reset();
210-
throw new PGPDataValidationException("data check failed.");
211-
}
123+
encStream = createDecryptionStream(dataDecryptorFactory, sessionKey);
212124

213125
return encStream;
214126
}
@@ -221,14 +133,4 @@ private InputStream getDataStream(
221133
throw new PGPException("Exception creating cipher", e);
222134
}
223135
}
224-
225-
public int getVersion()
226-
{
227-
return keyData.getVersion();
228-
}
229-
230-
public int getAlgorithm()
231-
{
232-
return keyData.getEncAlgorithm();
233-
}
234136
}

0 commit comments

Comments
 (0)