@@ -188,14 +188,23 @@ public Room readRoom(final Ejson ejson, Context context) {
188188 }
189189
190190 cursor .moveToFirst ();
191- String e2eKey = cursor .getString (cursor .getColumnIndex ("e2e_key" ));
192- Boolean encrypted = cursor .getInt (cursor .getColumnIndex ("encrypted" )) > 0 ;
191+ int e2eKeyColumnIndex = cursor .getColumnIndex ("e2e_key" );
192+ int encryptedColumnIndex = cursor .getColumnIndex ("encrypted" );
193+
194+ if (e2eKeyColumnIndex == -1 ) {
195+ Log .e (TAG , "e2e_key column not found in subscriptions table" );
196+ cursor .close ();
197+ return null ;
198+ }
199+
200+ String e2eKey = cursor .getString (e2eKeyColumnIndex );
201+ Boolean encrypted = encryptedColumnIndex != -1 && cursor .getInt (encryptedColumnIndex ) > 0 ;
193202 cursor .close ();
194203
195204 return new Room (e2eKey , encrypted );
196205
197206 } catch (Exception e ) {
198- Log .e ("[ENCRYPTION]" , "Error reading room" , e );
207+ Log .e (TAG , "Error reading room" , e );
199208 return null ;
200209
201210 } finally {
@@ -236,7 +245,31 @@ public String readUserKey(final Ejson ejson) throws Exception {
236245 return null ;
237246 }
238247
239- PrivateKey privKey = gson .fromJson (privateKey , PrivateKey .class );
248+ PrivateKey privKey ;
249+ try {
250+ // First, try parsing as direct JSON object
251+ privKey = gson .fromJson (privateKey , PrivateKey .class );
252+ } catch (com .google .gson .JsonSyntaxException e ) {
253+ // If that fails, it might be a JSON-encoded string (double-encoded)
254+ // Try parsing as a string first, then parse that string as JSON
255+ try {
256+ String decoded = gson .fromJson (privateKey , String .class );
257+ privKey = gson .fromJson (decoded , PrivateKey .class );
258+ } catch (Exception e2 ) {
259+ Log .e (TAG , "Failed to parse private key" , e2 );
260+ throw new Exception ("Failed to parse private key: " + e2 .getMessage (), e2 );
261+ }
262+ }
263+
264+ if (privKey == null ) {
265+ return null ;
266+ }
267+
268+ // Validate that required fields are present
269+ if (privKey .n == null || privKey .e == null || privKey .d == null ) {
270+ Log .e (TAG , "PrivateKey missing required fields (n, e, or d)" );
271+ return null ;
272+ }
240273
241274 WritableMap jwk = Arguments .createMap ();
242275 jwk .putString ("n" , privKey .n );
@@ -252,9 +285,19 @@ public String readUserKey(final Ejson ejson) throws Exception {
252285 }
253286
254287 public RoomKeyResult decryptRoomKey (final String e2eKey , final Ejson ejson ) throws Exception {
288+ if (e2eKey == null || e2eKey .isEmpty ()) {
289+ return null ;
290+ }
291+
255292 // Parse using prefixed base64
256- PrefixedData parsed = decodePrefixedBase64 (e2eKey );
257- keyId = parsed .prefix ;
293+ PrefixedData parsed ;
294+ try {
295+ parsed = decodePrefixedBase64 (e2eKey );
296+ keyId = parsed .prefix ;
297+ } catch (Exception e ) {
298+ Log .e (TAG , "Failed to decode prefixed base64" , e );
299+ throw e ;
300+ }
258301
259302 // Decrypt the session key
260303 String userKey = readUserKey (ejson );
@@ -263,22 +306,54 @@ public RoomKeyResult decryptRoomKey(final String e2eKey, final Ejson ejson) thro
263306 }
264307
265308 String base64EncryptedData = Base64 .encodeToString (parsed .data , Base64 .NO_WRAP );
266- String decrypted = RSACrypto .INSTANCE .decrypt (base64EncryptedData , userKey );
309+ String decrypted ;
310+ try {
311+ decrypted = RSACrypto .INSTANCE .decrypt (base64EncryptedData , userKey );
312+ if (decrypted == null ) {
313+ return null ;
314+ }
315+ } catch (Exception e ) {
316+ Log .e (TAG , "RSA decryption failed" , e );
317+ throw e ;
318+ }
267319
268320 // Parse sessionKey to determine v1 vs v2 from "alg" field
269- JsonObject sessionKey = gson .fromJson (decrypted , JsonObject .class );
321+ JsonObject sessionKey ;
322+ try {
323+ sessionKey = gson .fromJson (decrypted , JsonObject .class );
324+ if (sessionKey == null ) {
325+ return null ;
326+ }
327+ } catch (com .google .gson .JsonSyntaxException e ) {
328+ Log .e (TAG , "Failed to parse decrypted session key as JSON" , e );
329+ throw new Exception ("Failed to parse decrypted session key as JSON: " + e .getMessage (), e );
330+ }
331+
332+ if (!sessionKey .has ("k" )) {
333+ return null ;
334+ }
335+
270336 String k = sessionKey .get ("k" ).getAsString ();
271- byte [] decoded = Base64 .decode (k , Base64 .NO_PADDING | Base64 .NO_WRAP | Base64 .URL_SAFE );
337+ byte [] decoded ;
338+ try {
339+ decoded = Base64 .decode (k , Base64 .NO_PADDING | Base64 .NO_WRAP | Base64 .URL_SAFE );
340+ } catch (Exception e ) {
341+ Log .e (TAG , "Failed to decode 'k' from base64" , e );
342+ throw e ;
343+ }
344+
272345 String decryptedKey = CryptoUtils .INSTANCE .bytesToHex (decoded );
273346
274347 // Determine format from "alg" field
348+ String algorithm ;
275349 if (sessionKey .has ("alg" ) && "A256GCM" .equals (sessionKey .get ("alg" ).getAsString ())) {
276350 algorithm = "rc.v2.aes-sha2" ;
277- return new RoomKeyResult (decryptedKey , "rc.v2.aes-sha2" );
278351 } else {
279352 algorithm = "rc.v1.aes-sha2" ;
280- return new RoomKeyResult (decryptedKey , "rc.v1.aes-sha2" );
281353 }
354+ this .algorithm = algorithm ;
355+
356+ return new RoomKeyResult (decryptedKey , algorithm );
282357 }
283358
284359 private String decryptContent (Ejson .Content content , String e2eKey ) throws Exception {
0 commit comments