@@ -72,13 +72,13 @@ public int getSymmetricAlgorithm(
7272 {
7373 if (keyData .getVersion () == PublicKeyEncSessionPacket .VERSION_3 )
7474 {
75- byte [] plain = dataDecryptorFactory .recoverSessionData (keyData . getAlgorithm (), keyData . getEncSessionKey () );
75+ byte [] plain = dataDecryptorFactory .recoverSessionData (keyData , encData );
7676 // symmetric cipher algorithm is stored in first octet of session data
7777 return plain [0 ];
7878 }
7979 else if (keyData .getVersion () == PublicKeyEncSessionPacket .VERSION_6 )
8080 {
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.
8282 return ((SymmetricEncIntegrityPacket )encData ).getCipherAlgorithm ();
8383 }
8484 else
@@ -98,16 +98,57 @@ public PGPSessionKey getSessionKey(
9898 PublicKeyDataDecryptorFactory dataDecryptorFactory )
9999 throws PGPException
100100 {
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 )
103118 {
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+ }
105138 }
106- if (!confirmCheckSum (sessionData ))
139+ // SED (Legacy, no integrity protection!)
140+ else
107141 {
108- throw new PGPKeyValidationException ( "key checksum failed" ) ;
142+ algorithm = sessionInfo [ 0 ] ;
109143 }
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 ;
111152 }
112153
113154 /**
@@ -169,13 +210,38 @@ private InputStream getDataStream(
169210 }
170211 else
171212 {
172- boolean withIntegrityPacket = encData instanceof SymmetricEncIntegrityPacket ;
173213
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 ());
175221
176- BCPGInputStream encIn = encData .getInputStream ();
222+ BCPGInputStream encIn = encData .getInputStream ();
177223
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+ }
179245
180246 //
181247 // some versions of PGP appear to produce 0 for the extra
0 commit comments