Weekly Update 2

Progress

  • Set up the macOS development environment successfully.
  • Checked the supported AES modes in react-native-quick-crypto on Android and iOS
  • Created a demo to produce consistent AES-GCM encryption/decryption result between javax.crypto and node:crypto
  • Created a demo to produce consistent AES-GCM encryption/decryption result between react-native-quick-crypto and node:crypto on Android and iOS
  • Checked some E2EE implementations on some mature products(Zoom, Nextcloud)

Plans

  • Evaluate the performance difference of different crypto libraries
    • sjcl/node:crypto on Windows/macOS
    • sjcl/javax.crypto/react-native-quick-crypto on Android
    • sjcl/react-native-quick-crypto on iOS
  • Evaluate the performance difference of various encryption parameters
    • Key size
    • Authentication tag size
    • Digest algorithms/iteration count/salt length in key derivation
    • With/without AAD
    • IV length
  • Confirm the encryption parameters with mentors, developers and the community.
    • Note: These parameters might change in the future.

Problems

None

2 Likes

E2EE implementations on some mature products

Nextcloud: https://www.youtube.com/watch?v=ZOoJo9BXHAI
Zoom: zoom-e2e-whitepaper/zoom_e2e.pdf at master ¡ zoom/zoom-e2e-whitepaper ¡ GitHub

Notes about react-native-quick-crypto

  1. The Android implementation is based on OpenSSL 1.1.1q. This version was released in October 2022 and is somewhat outdated. It's possible to build OpenSSL with the latest ndkports or use the binaries from KDAB, but this requires actions from upstream.
  2. The iOS implementation is based on the pod OpenSSL-Universal, which supports recent OpenSSL versions(3.1.5 and 1.1.1v).
  3. The supported ciphers for react-native-quick-crypto are the same for Android 6.0/12/13 and iOS 15.0. (2024.06.25: Well I found the supported ciphers are hard coded in the source code)
Supported ciphers
  • des-ecb
  • des
  • des-cbc
  • des3
  • des-ede3-cbc
  • des-ede3
  • des-ede-cbc
  • des-ede
  • aes-128-ecb
  • aes-192-ecb
  • aes-256-ecb
  • aes-128-cbc
  • aes-192-cbc
  • aes-256-cbc
  • aes128
  • aes192
  • aes256
  • aes-128-cfb
  • aes-192-cfb
  • aes-256-cfb
  • aes-128-cfb8
  • aes-192-cfb8
  • aes-256-cfb8
  • aes-128-cfb1
  • aes-192-cfb1
  • aes-256-cfb1
  • aes-128-ofb
  • aes-192-ofb
  • aes-256-ofb
  • aes-128-ctr
  • aes-192-ctr
  • aes-256-ctr
  • aes-128-gcm
  • aes-192-gcm
  • aes-256-gcm

I think we should use react-native-quick-crypto for its consistency and platfrom-independence across different Android SDKs and iOS versions. For example, I just found the key derivation algorithm PBKDF2withHmacSHA256, used in sjcl, is not supported in javax.crypto on Android until API 26+, whereas react-native-quick-crypto supports it. If no significant drawbacks are found in the future, I will advocate for using this library.

Supported `SecretKeyFactory` algorithms
Algorithm Supported API Levels
AES 23+
DES 1+
DESede 1+
HmacSHA1 23+
HmacSHA224 23+
HmacSHA256 23+
HmacSHA384 23+
HmacSHA512 23+
PBEwithHmacSHA1 1+
PBEwithHmacSHA1AndAES_128 26+
PBEwithHmacSHA1AndAES_256 26+
PBEwithHmacSHA224AndAES_128 26+
PBEwithHmacSHA224AndAES_256 26+
PBEwithHmacSHA256AndAES_128 26+
PBEwithHmacSHA256AndAES_256 26+
PBEwithHmacSHA384AndAES_128 26+
PBEwithHmacSHA384AndAES_256 26+
PBEwithHmacSHA512AndAES_128 26+
PBEwithHmacSHA512AndAES_256 26+
PBEwithMD5AND128BITAES-CBC-OPENSSL 1+
PBEwithMD5AND192BITAES-CBC-OPENSSL 1+
PBEwithMD5AND256BITAES-CBC-OPENSSL 1+
PBEwithMD5ANDDES 1+
PBEwithMD5ANDRC2 1+
PBEwithSHA1ANDDES 1+
PBEwithSHA1ANDRC2 1+
PBEwithSHA256AND128BITAES-CBC-BC 1+
PBEwithSHA256AND192BITAES-CBC-BC 1+
PBEwithSHA256AND256BITAES-CBC-BC 1+
PBEwithSHAAND128BITAES-CBC-BC 1+
PBEwithSHAAND128BITRC2-CBC 10+
PBEwithSHAAND128BITRC4 10+
PBEwithSHAAND192BITAES-CBC-BC 1+
PBEwithSHAAND2-KEYTRIPLEDES-CBC 1+
PBEwithSHAAND256BITAES-CBC-BC 1+
PBEwithSHAAND3-KEYTRIPLEDES-CBC 1+
PBEwithSHAAND40BITRC2-CBC 1+
PBEwithSHAAND40BITRC4 10+
PBEwithSHAANDTWOFISH-CBC 10+
PBKDF2withHmacSHA1 10+
PBKDF2withHmacSHA1And8BIT 19+
PBKDF2withHmacSHA224 26+
PBKDF2withHmacSHA256 26+
PBKDF2withHmacSHA384 26+
PBKDF2withHmacSHA512 26+

Honestly you can ignore Nextcloud E2EE as what they did it not up to standards. Maybe Signal or Proton would be worth looking at for example.

One reason things are slow in React Native is that crossing the bridge between the native and JS part is very slow, so maybe you can get better performance by avoiding the bridge. For example, by encrypting/decrypting and saving to database all on the native side. I don't know how easy it would be to do this as that might require significant changes of the app architecture

1 Like

I suspect the slowest part is dealing with attachments rather than notes and these are just files in storage and don't need the database. Maybe this could be the first step?

I will check them. Thanks for your suggestion.

It could be very easy if the New Architecture works. But it's still in beta and I don't know if it brings any regressions.

1 Like

We use several old and unmaintained libraries that might need to be updated before switching to the New Architecture (tracking spreadsheet).

2 Likes

I found some possible alternatives for the libraries you mentioned

rn-fetch-blob -> react-native-blob-util (fully compatible with rn-fetch-blob, ready for the bridgeless mode)
react-native-fs -> expo-file-system
react-native-device-info -> expo-device
react-native-sqlite-storage -> op-sqlite (ready for the bridgeless mode, fast), react-native-quick-sqlite, expo-sqlite

Hope they help.

1 Like

That's what they say but when I switched to it there was many issues with it. But yes it would be good eventually to find replacements so that we can switch to the bridgeless architecture

2 Likes

Since when are we using this? I created react-native-version-info since we needed a way to get access to the version info data on mobile. Anyway, if react-native-device-info is now used, we can get rid of react-native-version-info. I'm pretty sure that the device info module also has functions to retrieve the CFBundleShortVersionString and versionName.

The first time it was referenced in the git commit history was in e865a5d7c61d2dc9bf8f1409e3f4bbaeb140c1f8 (2020), but it's possible it has been removed and re-added since then.

Edit: I think it was since removed — it was re-added in e21a5c1b80be703ed90bfefab01af65b7415d250 (2023).

I think this is something that has to be done at one point anyway. I understand that it is annoying, but using unmaintained libs/modules seems quite dangerous to me.
Maybe one release can be dedicated to upgrading all libs.

Yes — it would be very good to migrate to maintained libraries :slight_smile: . I also think it would be a good idea to migrate to the New Architecture, particularly because the legacy API will eventually be deprecated (though this won't be in the near future).

I've looked at several other mobile app dependencies and linked the ones that will likely need to be migrated away from.

Not all of these will need to be migrated away from to support the New Architecture.

Notes:

  • For future reference, this comment above contains possible migrations for several libraries.
  • Based on this comment, an interop layer might also be available for legacy modules.
  • It might make sense to transfer this discussion to a GitHub issue.

  1. provides a component, so might work with the renderer compatibility layer. It is causing other issues, though. ↩ī¸Ž

1 Like

I just found it's still possible to do the AEC-CCM encryption/decryption in react-native-quick-crypto, based on my test. So we can still reach Goal #2 on mobile clients.

For your information, the status is now tracked on React Native Directory and the old spreadsheet seems to be obsolete (reference)

1 Like