@@ -72,13 +72,13 @@ public int getSymmetricAlgorithm(
72
72
{
73
73
if (keyData .getVersion () == PublicKeyEncSessionPacket .VERSION_3 )
74
74
{
75
- byte [] plain = dataDecryptorFactory .recoverSessionData (keyData . getAlgorithm (), keyData . getEncSessionKey () );
75
+ byte [] plain = dataDecryptorFactory .recoverSessionData (keyData , encData );
76
76
// symmetric cipher algorithm is stored in first octet of session data
77
77
return plain [0 ];
78
78
}
79
79
else if (keyData .getVersion () == PublicKeyEncSessionPacket .VERSION_6 )
80
80
{
81
- // PKESK v5 stores the cipher algorithm in the SEIPD v2 packet fields.
81
+ // PKESK v6 stores the cipher algorithm in the SEIPD v2 packet fields.
82
82
return ((SymmetricEncIntegrityPacket )encData ).getCipherAlgorithm ();
83
83
}
84
84
else
@@ -98,16 +98,57 @@ public PGPSessionKey getSessionKey(
98
98
PublicKeyDataDecryptorFactory dataDecryptorFactory )
99
99
throws PGPException
100
100
{
101
- byte [] sessionData = dataDecryptorFactory .recoverSessionData (keyData .getAlgorithm (), keyData .getEncSessionKey ());
102
- if (keyData .getAlgorithm () == PublicKeyAlgorithmTags .X25519 || keyData .getAlgorithm () == PublicKeyAlgorithmTags .X448 )
101
+ byte [] sessionInfo = dataDecryptorFactory .recoverSessionData (keyData , encData );
102
+
103
+ // Confirm and discard checksum
104
+ if (containsChecksum (keyData .getAlgorithm ()))
105
+ {
106
+ if (!confirmCheckSum (sessionInfo ))
107
+ {
108
+ throw new PGPException ("Key checksum failed." );
109
+ }
110
+ sessionInfo = Arrays .copyOf (sessionInfo , sessionInfo .length - 2 );
111
+ }
112
+
113
+ byte [] sessionKey = Arrays .copyOfRange (sessionInfo , 1 , sessionInfo .length );
114
+ int algorithm ;
115
+
116
+ // OCB (LibrePGP v5 style AEAD)
117
+ if (encData instanceof AEADEncDataPacket )
103
118
{
104
- return new PGPSessionKey (sessionData [0 ] & 0xff , Arrays .copyOfRange (sessionData , 1 , sessionData .length ));
119
+ algorithm = ((AEADEncDataPacket ) encData ).getAlgorithm ();
120
+ }
121
+
122
+ // SEIPD (OpenPGP v4 / OpenPGP v6)
123
+ else if (encData instanceof SymmetricEncIntegrityPacket )
124
+ {
125
+ SymmetricEncIntegrityPacket seipd = (SymmetricEncIntegrityPacket ) encData ;
126
+ if (seipd .getVersion () == SymmetricEncIntegrityPacket .VERSION_1 )
127
+ {
128
+ algorithm = sessionInfo [0 ];
129
+ }
130
+ else if (seipd .getVersion () == SymmetricEncIntegrityPacket .VERSION_2 )
131
+ {
132
+ algorithm = seipd .getCipherAlgorithm ();
133
+ }
134
+ else
135
+ {
136
+ throw new UnsupportedPacketVersionException ("Unsupported SEIPD packet version: " + seipd .getVersion ());
137
+ }
105
138
}
106
- if (!confirmCheckSum (sessionData ))
139
+ // SED (Legacy, no integrity protection!)
140
+ else
107
141
{
108
- throw new PGPKeyValidationException ( "key checksum failed" ) ;
142
+ algorithm = sessionInfo [ 0 ] ;
109
143
}
110
- return new PGPSessionKey (sessionData [0 ] & 0xff , Arrays .copyOfRange (sessionData , 1 , sessionData .length - 2 ));
144
+
145
+ return new PGPSessionKey (algorithm & 0xff , sessionKey );
146
+ }
147
+
148
+ private boolean containsChecksum (int algorithm )
149
+ {
150
+ return algorithm != PublicKeyAlgorithmTags .X25519 &&
151
+ algorithm != PublicKeyAlgorithmTags .X448 ;
111
152
}
112
153
113
154
/**
@@ -169,13 +210,38 @@ private InputStream getDataStream(
169
210
}
170
211
else
171
212
{
172
- boolean withIntegrityPacket = encData instanceof SymmetricEncIntegrityPacket ;
173
213
174
- PGPDataDecryptor dataDecryptor = dataDecryptorFactory .createDataDecryptor (withIntegrityPacket , sessionKey .getAlgorithm (), sessionKey .getKey ());
214
+ if (encData instanceof SymmetricEncIntegrityPacket )
215
+ {
216
+ SymmetricEncIntegrityPacket seipd = (SymmetricEncIntegrityPacket ) encData ;
217
+ // SEIPD v1 (OpenPGP v4)
218
+ if (seipd .getVersion () == SymmetricEncIntegrityPacket .VERSION_1 )
219
+ {
220
+ PGPDataDecryptor dataDecryptor = dataDecryptorFactory .createDataDecryptor (true , sessionKey .getAlgorithm (), sessionKey .getKey ());
175
221
176
- BCPGInputStream encIn = encData .getInputStream ();
222
+ BCPGInputStream encIn = encData .getInputStream ();
177
223
178
- processSymmetricEncIntegrityPacketDataStream (withIntegrityPacket , dataDecryptor , encIn );
224
+ processSymmetricEncIntegrityPacketDataStream (true , dataDecryptor , encIn );
225
+ }
226
+ // SEIPD v2 (OpenPGP v6 AEAD)
227
+ else
228
+ {
229
+ PGPDataDecryptor dataDecryptor = dataDecryptorFactory .createDataDecryptor (seipd , sessionKey );
230
+
231
+ BCPGInputStream encIn = encData .getInputStream ();
232
+
233
+ encStream = new BCPGInputStream (dataDecryptor .getInputStream (encIn ));
234
+ }
235
+ }
236
+ // SED (Symmetrically Encrypted Data without Integrity Protection; Deprecated)
237
+ else
238
+ {
239
+ PGPDataDecryptor dataDecryptor = dataDecryptorFactory .createDataDecryptor (false , sessionKey .getAlgorithm (), sessionKey .getKey ());
240
+
241
+ BCPGInputStream encIn = encData .getInputStream ();
242
+
243
+ processSymmetricEncIntegrityPacketDataStream (false , dataDecryptor , encIn );
244
+ }
179
245
180
246
//
181
247
// some versions of PGP appear to produce 0 for the extra
0 commit comments