@@ -84,13 +84,13 @@ public int getSymmetricAlgorithm(
8484 {
8585 if (keyData .getVersion () == PublicKeyEncSessionPacket .VERSION_3 )
8686 {
87- byte [] plain = dataDecryptorFactory .recoverSessionData (keyData . getAlgorithm (), keyData . getEncSessionKey () );
87+ byte [] plain = dataDecryptorFactory .recoverSessionData (keyData , encData );
8888 // symmetric cipher algorithm is stored in first octet of session data
8989 return plain [0 ];
9090 }
9191 else if (keyData .getVersion () == PublicKeyEncSessionPacket .VERSION_6 )
9292 {
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.
9494 return ((SymmetricEncIntegrityPacket )encData ).getCipherAlgorithm ();
9595 }
9696 else
@@ -110,16 +110,57 @@ public PGPSessionKey getSessionKey(
110110 PublicKeyDataDecryptorFactory dataDecryptorFactory )
111111 throws PGPException
112112 {
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 )
115130 {
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+ }
117150 }
118- if (!confirmCheckSum (sessionData ))
151+ // SED (Legacy, no integrity protection!)
152+ else
119153 {
120- throw new PGPKeyValidationException ( "key checksum failed" ) ;
154+ algorithm = sessionInfo [ 0 ] ;
121155 }
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 ;
123164 }
124165
125166 /**
@@ -181,13 +222,38 @@ private InputStream getDataStream(
181222 }
182223 else
183224 {
184- boolean withIntegrityPacket = encData instanceof SymmetricEncIntegrityPacket ;
185225
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 ());
187233
188- BCPGInputStream encIn = encData .getInputStream ();
234+ BCPGInputStream encIn = encData .getInputStream ();
189235
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+ }
191257
192258 //
193259 // some versions of PGP appear to produce 0 for the extra
0 commit comments