@@ -84,13 +84,13 @@ public int getSymmetricAlgorithm(
84
84
{
85
85
if (keyData .getVersion () == PublicKeyEncSessionPacket .VERSION_3 )
86
86
{
87
- byte [] plain = dataDecryptorFactory .recoverSessionData (keyData . getAlgorithm (), keyData . getEncSessionKey () );
87
+ byte [] plain = dataDecryptorFactory .recoverSessionData (keyData , encData );
88
88
// symmetric cipher algorithm is stored in first octet of session data
89
89
return plain [0 ];
90
90
}
91
91
else if (keyData .getVersion () == PublicKeyEncSessionPacket .VERSION_6 )
92
92
{
93
- // PKESK v5 stores the cipher algorithm in the SEIPD v2 packet fields.
93
+ // PKESK v6 stores the cipher algorithm in the SEIPD v2 packet fields.
94
94
return ((SymmetricEncIntegrityPacket )encData ).getCipherAlgorithm ();
95
95
}
96
96
else
@@ -110,16 +110,57 @@ public PGPSessionKey getSessionKey(
110
110
PublicKeyDataDecryptorFactory dataDecryptorFactory )
111
111
throws PGPException
112
112
{
113
- byte [] sessionData = dataDecryptorFactory .recoverSessionData (keyData .getAlgorithm (), keyData .getEncSessionKey ());
114
- if (keyData .getAlgorithm () == PublicKeyAlgorithmTags .X25519 || keyData .getAlgorithm () == PublicKeyAlgorithmTags .X448 )
113
+ byte [] sessionInfo = dataDecryptorFactory .recoverSessionData (keyData , encData );
114
+
115
+ // Confirm and discard checksum
116
+ if (containsChecksum (keyData .getAlgorithm ()))
117
+ {
118
+ if (!confirmCheckSum (sessionInfo ))
119
+ {
120
+ throw new PGPException ("Key checksum failed." );
121
+ }
122
+ sessionInfo = Arrays .copyOf (sessionInfo , sessionInfo .length - 2 );
123
+ }
124
+
125
+ byte [] sessionKey = Arrays .copyOfRange (sessionInfo , 1 , sessionInfo .length );
126
+ int algorithm ;
127
+
128
+ // OCB (LibrePGP v5 style AEAD)
129
+ if (encData instanceof AEADEncDataPacket )
115
130
{
116
- return new PGPSessionKey (sessionData [0 ] & 0xff , Arrays .copyOfRange (sessionData , 1 , sessionData .length ));
131
+ algorithm = ((AEADEncDataPacket ) encData ).getAlgorithm ();
132
+ }
133
+
134
+ // SEIPD (OpenPGP v4 / OpenPGP v6)
135
+ else if (encData instanceof SymmetricEncIntegrityPacket )
136
+ {
137
+ SymmetricEncIntegrityPacket seipd = (SymmetricEncIntegrityPacket ) encData ;
138
+ if (seipd .getVersion () == SymmetricEncIntegrityPacket .VERSION_1 )
139
+ {
140
+ algorithm = sessionInfo [0 ];
141
+ }
142
+ else if (seipd .getVersion () == SymmetricEncIntegrityPacket .VERSION_2 )
143
+ {
144
+ algorithm = seipd .getCipherAlgorithm ();
145
+ }
146
+ else
147
+ {
148
+ throw new UnsupportedPacketVersionException ("Unsupported SEIPD packet version: " + seipd .getVersion ());
149
+ }
117
150
}
118
- if (!confirmCheckSum (sessionData ))
151
+ // SED (Legacy, no integrity protection!)
152
+ else
119
153
{
120
- throw new PGPKeyValidationException ( "key checksum failed" ) ;
154
+ algorithm = sessionInfo [ 0 ] ;
121
155
}
122
- return new PGPSessionKey (sessionData [0 ] & 0xff , Arrays .copyOfRange (sessionData , 1 , sessionData .length - 2 ));
156
+
157
+ return new PGPSessionKey (algorithm & 0xff , sessionKey );
158
+ }
159
+
160
+ private boolean containsChecksum (int algorithm )
161
+ {
162
+ return algorithm != PublicKeyAlgorithmTags .X25519 &&
163
+ algorithm != PublicKeyAlgorithmTags .X448 ;
123
164
}
124
165
125
166
/**
@@ -181,13 +222,38 @@ private InputStream getDataStream(
181
222
}
182
223
else
183
224
{
184
- boolean withIntegrityPacket = encData instanceof SymmetricEncIntegrityPacket ;
185
225
186
- PGPDataDecryptor dataDecryptor = dataDecryptorFactory .createDataDecryptor (withIntegrityPacket , sessionKey .getAlgorithm (), sessionKey .getKey ());
226
+ if (encData instanceof SymmetricEncIntegrityPacket )
227
+ {
228
+ SymmetricEncIntegrityPacket seipd = (SymmetricEncIntegrityPacket ) encData ;
229
+ // SEIPD v1 (OpenPGP v4)
230
+ if (seipd .getVersion () == SymmetricEncIntegrityPacket .VERSION_1 )
231
+ {
232
+ PGPDataDecryptor dataDecryptor = dataDecryptorFactory .createDataDecryptor (true , sessionKey .getAlgorithm (), sessionKey .getKey ());
187
233
188
- BCPGInputStream encIn = encData .getInputStream ();
234
+ BCPGInputStream encIn = encData .getInputStream ();
189
235
190
- processSymmetricEncIntegrityPacketDataStream (withIntegrityPacket , dataDecryptor , encIn );
236
+ processSymmetricEncIntegrityPacketDataStream (true , dataDecryptor , encIn );
237
+ }
238
+ // SEIPD v2 (OpenPGP v6 AEAD)
239
+ else
240
+ {
241
+ PGPDataDecryptor dataDecryptor = dataDecryptorFactory .createDataDecryptor (seipd , sessionKey );
242
+
243
+ BCPGInputStream encIn = encData .getInputStream ();
244
+
245
+ encStream = new BCPGInputStream (dataDecryptor .getInputStream (encIn ));
246
+ }
247
+ }
248
+ // SED (Symmetrically Encrypted Data without Integrity Protection; Deprecated)
249
+ else
250
+ {
251
+ PGPDataDecryptor dataDecryptor = dataDecryptorFactory .createDataDecryptor (false , sessionKey .getAlgorithm (), sessionKey .getKey ());
252
+
253
+ BCPGInputStream encIn = encData .getInputStream ();
254
+
255
+ processSymmetricEncIntegrityPacketDataStream (false , dataDecryptor , encIn );
256
+ }
191
257
192
258
//
193
259
// some versions of PGP appear to produce 0 for the extra
0 commit comments