Skip to content

💭 🔧 Android: libcrypto.so collision when using SQLCipher-based libraries alongside react-native-quick-crypto #1059

@timmy3000

Description

@timmy3000

Question

Hi everyone 👋

First, thank you for building and maintaining react-native-quick-crypto. The performance and native JSI approach have been extremely valuable, especially for applications that need real cryptographic operations on React Native.

I am opening this issue because I encountered an Android native library conflict when using react-native-quick-crypto together with another native dependency that enables SQLCipher (@op-engineering/op-sqlite).

I may be misunderstanding the intended native dependency model here, so I would appreciate guidance from the maintainers/community.

Thank you again to everyone contributing to this project.


Environment

  • React Native: 0.86.0
  • react-native-quick-crypto: 1.1.5

Other native dependency:

  • @op-engineering/op-sqlite
  • SQLCipher enabled:
{
  "op-sqlite": {
    "sqlcipher": true
  }
}

Problem

When building Android, Gradle fails because both libraries include the same native OpenSSL libraries:

libcrypto.so
libssl.so

Build error:

Execution failed for task ':app:mergeDebugNativeLibs'.

2 files found with path:
'lib/arm64-v8a/libcrypto.so'

From:

@op-engineering/op-sqlite/.../libcrypto.so

and:

react-native-quick-crypto/.../libcrypto.so

What I tried

1. Gradle pickFirst

Example:

android {
    packagingOptions {
        pickFirst "lib/**/libcrypto.so"
        pickFirst "lib/**/libssl.so"
    }
}

This allows the APK to build.

However, the application crashes at runtime because only one OpenSSL library remains packaged, while both native modules expect their own OpenSSL symbols.


2. Excluding one library

I tried excluding the duplicated .so files, but this breaks the native dependency that requires them.


My understanding

I believe the root issue is that both dependencies ship OpenSSL symbols into the same Android process.

The current situation looks like:

Application

 |
 +-- react-native-quick-crypto
 |       |
 |       +-- OpenSSL
 |       |      |
 |       |      +-- libcrypto.so
 |       |      +-- libssl.so
 |
 |
 +-- SQLCipher
         |
         +-- OpenSSL
                |
                +-- libcrypto.so
                +-- libssl.so

Because Android loads shared libraries globally, having two independent OpenSSL builds with identical library names can cause conflicts.


Possible solutions I was considering

I am not sure which approach is best and would appreciate maintainer feedback.

Option A: Rename quick-crypto bundled OpenSSL libraries

Example:

libcrypto.so
libssl.so

becoming:

libquickcrypto.so
libquickssl.so

Then update:

  • CMake linking
  • JNI loading
  • Gradle packaging

This would allow:

libcrypto.so
libssl.so

libquickcrypto.so
libquickssl.so

to coexist.


Option B: Static-link OpenSSL into quick-crypto

Instead of shipping:

libcrypto.so
libssl.so

bundle OpenSSL privately inside the quick-crypto native library.

Potentially:

libreactnativequickcrypto.so
        |
        +-- private OpenSSL symbols

with hidden symbols.


Option C: Provide a build option

Something like:

quickCrypto {
    bundledOpenSSL = false
}

or:

quickCrypto {
    useSystemOpenSSL = true
}

so applications with another OpenSSL consumer can avoid duplicate native libraries.


Questions

  1. Is supporting coexistence with other OpenSSL-based native libraries a goal for react-native-quick-crypto?

  2. Would renaming the bundled OpenSSL libraries be considered a valid approach?

  3. Would the maintainers prefer applications to only have one OpenSSL provider in the process?

  4. Is there currently a recommended way to integrate react-native-quick-crypto with SQLCipher-based libraries?

Thank you again for all the work on this library. I appreciate the time and effort that goes into maintaining native cryptography tooling for React Native.

What I tried

QuickCrypto Version

1.1.5

Additional information

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions