1919import org .bouncycastle .crypto .BlockCipher ;
2020import org .bouncycastle .crypto .BufferedAsymmetricBlockCipher ;
2121import org .bouncycastle .crypto .InvalidCipherTextException ;
22+ import org .bouncycastle .crypto .RawAgreement ;
2223import org .bouncycastle .crypto .Wrapper ;
2324import org .bouncycastle .crypto .agreement .ECDHBasicAgreement ;
2425import org .bouncycastle .crypto .agreement .X25519Agreement ;
@@ -67,11 +68,27 @@ public byte[] recoverSessionData(int keyAlgorithm, byte[][] secKeyData, int pkes
6768
6869 if (keyAlgorithm == PublicKeyAlgorithmTags .X25519 )
6970 {
70- return recoverX25519SessionData (secKeyData , privKey , containsSKAlg );
71+ return getSessionData (secKeyData [0 ], privKey , X25519PublicBCPGKey .LENGTH , HashAlgorithmTags .SHA256 ,
72+ SymmetricKeyAlgorithmTags .AES_128 , new X25519Agreement (), "X25519" , new PublicKeyParametersOperation ()
73+ {
74+ @ Override
75+ public AsymmetricKeyParameter getPublicKeyParameters (byte [] pEnc , int pEncOff )
76+ {
77+ return new X25519PublicKeyParameters (pEnc , 0 );
78+ }
79+ });
7180 }
7281 else if (keyAlgorithm == PublicKeyAlgorithmTags .X448 )
7382 {
74- return recoverX448SessionData (secKeyData , privKey , containsSKAlg );
83+ return getSessionData (secKeyData [0 ], privKey , X448PublicBCPGKey .LENGTH , HashAlgorithmTags .SHA512 ,
84+ SymmetricKeyAlgorithmTags .AES_256 , new X448Agreement (), "X448" , new PublicKeyParametersOperation ()
85+ {
86+ @ Override
87+ public AsymmetricKeyParameter getPublicKeyParameters (byte [] pEnc , int pEncOff )
88+ {
89+ return new X448PublicKeyParameters (pEnc , 0 );
90+ }
91+ });
7592 }
7693 else if (keyAlgorithm == PublicKeyAlgorithmTags .ECDH )
7794 {
@@ -113,20 +130,19 @@ private byte[] recoverElgamalSessionData(int keyAlgorithm,
113130 byte [] tmp = new byte [size ];
114131
115132 byte [] bi = secKeyData [0 ]; // encoded MPI
116- if (bi .length - 2 > size ) // leading Zero? Shouldn't happen but...
117- {
118- c1 .processBytes (bi , 3 , bi .length - 3 );
119- }
120- else
121- {
122- System .arraycopy (bi , 2 , tmp , tmp .length - (bi .length - 2 ), bi .length - 2 );
123- c1 .processBytes (tmp , 0 , tmp .length );
124- }
133+ procoessBytesFromElgamalSessionData (c1 , size , tmp , bi );
125134
126135 bi = secKeyData [1 ]; // encoded MPI
127136 Arrays .fill (tmp , (byte )0 );
128137
129- if (bi .length - 2 > size ) // leading Zero? Shouldn't happen but...
138+ procoessBytesFromElgamalSessionData (c1 , size , tmp , bi );
139+
140+ return c1 .doFinal ();
141+ }
142+
143+ private void procoessBytesFromElgamalSessionData (BufferedAsymmetricBlockCipher c1 , int size , byte [] tmp , byte [] bi )
144+ {
145+ if (bi .length - 2 > size ) // leading Zero? Shouldn't happen but...
130146 {
131147 c1 .processBytes (bi , 3 , bi .length - 3 );
132148 }
@@ -135,8 +151,6 @@ private byte[] recoverElgamalSessionData(int keyAlgorithm,
135151 System .arraycopy (bi , 2 , tmp , tmp .length - (bi .length - 2 ), bi .length - 2 );
136152 c1 .processBytes (tmp , 0 , tmp .length );
137153 }
138-
139- return c1 .doFinal ();
140154 }
141155
142156 private byte [] recoverRSASessionData (int keyAlgorithm ,
@@ -217,56 +231,6 @@ else if (ecPubKey.getCurveOID().equals(EdECObjectIdentifiers.id_X448))
217231 return PGPPad .unpadSessionData (unwrapSessionData (keyEnc , symmetricKeyAlgorithm , key ));
218232 }
219233
220- private byte [] recoverX25519SessionData (byte [][] secKeyData , AsymmetricKeyParameter privKey , boolean includesSesKeyAlg )
221- throws PGPException , InvalidCipherTextException
222- {
223- byte [] enc = secKeyData [0 ];
224- // 32 octets ephemeral key
225- int pLen = X25519PublicBCPGKey .LENGTH ;
226- byte [] ephemeralKey = Arrays .copyOf (enc , pLen );
227-
228- // size of following fields
229- int size = enc [pLen ] & 0xff ;
230- checkRange (pLen + 1 + size , enc );
231-
232- // encrypted session key
233- int sesKeyLen = size - (includesSesKeyAlg ? 1 : 0 );
234- int sesKeyOff = pLen + 1 + (includesSesKeyAlg ? 1 : 0 );
235- byte [] keyEnc = Arrays .copyOfRange (enc , sesKeyOff , sesKeyOff + sesKeyLen );
236-
237- byte [] secret = BcUtil .getSecret (new X25519Agreement (), privKey , new X25519PublicKeyParameters (ephemeralKey , 0 ));
238-
239- byte [] hkdfOut = RFC6637KDFCalculator .createKey (HashAlgorithmTags .SHA256 , SymmetricKeyAlgorithmTags .AES_128 ,
240- Arrays .concatenate (ephemeralKey , pgpPrivKey .getPublicKeyPacket ().getKey ().getEncoded (), secret ),
241- "OpenPGP X25519" );
242-
243- return unwrapSessionData (keyEnc , SymmetricKeyAlgorithmTags .AES_128 , new KeyParameter (hkdfOut ));
244- }
245-
246- private byte [] recoverX448SessionData (byte [][] secKeyData , AsymmetricKeyParameter privKey , boolean includesSesKeyAlg )
247- throws PGPException , InvalidCipherTextException
248- {
249- byte [] enc = secKeyData [0 ];
250- // 56 octets ephemeral key
251- int pLen = X448PublicBCPGKey .LENGTH ;
252- byte [] ephemeralKey = Arrays .copyOf (enc , pLen );
253-
254- // size of the following fields
255- int size = enc [pLen ] & 0xff ;
256- checkRange (pLen + 1 + size , enc );
257-
258- // encrypted session key
259- int sesKeyLen = size - (includesSesKeyAlg ? 1 : 0 );
260- int sesKeyOff = pLen + 1 + (includesSesKeyAlg ? 1 : 0 );
261- byte [] encSesKey = Arrays .copyOfRange (enc , sesKeyOff , sesKeyOff + sesKeyLen );
262-
263- byte [] secret = BcUtil .getSecret (new X448Agreement (), privKey , new X448PublicKeyParameters (ephemeralKey , 0 ));
264- KeyParameter key = new KeyParameter (RFC6637KDFCalculator .createKey (HashAlgorithmTags .SHA512 , SymmetricKeyAlgorithmTags .AES_256 ,
265- Arrays .concatenate (ephemeralKey , pgpPrivKey .getPublicKeyPacket ().getKey ().getEncoded (), secret ), "OpenPGP X448" ));
266-
267- return unwrapSessionData (encSesKey , SymmetricKeyAlgorithmTags .AES_256 , key );
268- }
269-
270234 // OpenPGP v4
271235 @ Override
272236 public PGPDataDecryptor createDataDecryptor (boolean withIntegrityPacket , int encAlgorithm , byte [] key )
@@ -293,6 +257,30 @@ public PGPDataDecryptor createDataDecryptor(SymmetricEncIntegrityPacket seipd, P
293257 return BcAEADUtil .createOpenPgpV6DataDecryptor (seipd , sessionKey );
294258 }
295259
260+ @ FunctionalInterface
261+ private interface PublicKeyParametersOperation
262+ {
263+ AsymmetricKeyParameter getPublicKeyParameters (byte [] pEnc , int pEncOff );
264+ }
265+
266+ private byte [] getSessionData (byte [] enc , AsymmetricKeyParameter privKey , int pLen , int hashAlgorithm , int symmetricKeyAlgorithm ,
267+ RawAgreement agreement , String algorithmName , PublicKeyParametersOperation pkp )
268+ throws PGPException , InvalidCipherTextException
269+ {
270+ byte [] pEnc = new byte [pLen ];
271+ byte [] keyEnc ;
272+ System .arraycopy (enc , 0 , pEnc , 0 , pLen );
273+ int keyLen = enc [pLen ] & 0xff ;
274+ checkRange (pLen + 1 + keyLen , enc );
275+ keyEnc = new byte [keyLen - 1 ];
276+ System .arraycopy (enc , pLen + 2 , keyEnc , 0 , keyEnc .length );
277+ byte [] secret = BcUtil .getSecret (agreement , privKey , pkp .getPublicKeyParameters (pEnc , 0 ));
278+ KeyParameter key = new KeyParameter (RFC6637KDFCalculator .createKey (hashAlgorithm , symmetricKeyAlgorithm ,
279+ Arrays .concatenate (pEnc , pgpPrivKey .getPublicKeyPacket ().getKey ().getEncoded (), secret ), "OpenPGP " + algorithmName ));
280+
281+ return Arrays .prepend (unwrapSessionData (keyEnc , symmetricKeyAlgorithm , key ), enc [pLen + 1 ]);
282+ }
283+
296284 private static byte [] unwrapSessionData (byte [] keyEnc , int symmetricKeyAlgorithm , KeyParameter key )
297285 throws PGPException , InvalidCipherTextException
298286 {
0 commit comments