OpenSSL for Android
v4.0.2AndroidOpenSSL 4.0.2 for React Native apps on Android, precompiled for arm64-v8a devices and the x86_64 emulator as @crossbind/port-openssl-android.
npm install @crossbind/port-openssl-android@betaInstall
The whole flow, including Expo, is in the React Native playbook.
Usage
The examples the WebAssembly page runs, as Android compiles them: the same headers and the same calls. They are checked on the WebAssembly build.
Read a certificate like openssl x509 -text
What people open a certificate for, from C++: PEM_read_bio_X509 parses it, X509_NAME_print_ex writes the subject and issuer, ASN1_TIME_print_ex the validity, X509V3_EXT_print the alternative names, X509_check_host matches a host name the way a TLS client does and X509_digest takes the SHA-256 fingerprint. WebCrypto has no X.509 parser.
CN=shop.example.com,O=Example Shop,C=US issued by CN=Example Shop Test CA,O=Example Shop,C=US valid 2026-03-01 00:00:00Z to 2026-05-30 00:00:00Z DNS:shop.example.com, DNS:www.shop.example.com, IP Address:192.0.2.10 EC prime256v1 256 bits, self-signed false www.shop.example.com true shop.example.org false 68:2D:81:9E:75:7E:2C:15:C1:92:FB:84:3D:BE:AA:99:B4:54:58:D4:5F:A3:F3:3A:C8:13:1E:9D:03:9C:89:3C
Hash and HMAC
EVP_Q_digest hashes data already in memory with any digest by name, EVP_DigestUpdate takes it in pieces as a file or a download arrives, and EVP_Q_mac makes the HMAC that webhook and API request signatures use. WebCrypto stops at SHA-1 and SHA-2; SHA-3 and BLAKE2 come from OpenSSL here. Every line is the published test vector of its standard.
SHA256 ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad SHA3-256 3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532 BLAKE2B-512 ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d17d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923 HMAC-SHA256 5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843 streamed SHA256 cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0
Encrypt and authenticate with AES-256-GCM
EVP_CipherInit_ex2 with AES-256-GCM encrypts and authenticates in one pass; EVP_CTRL_AEAD_GET_TAG reads the 16-byte tag, and with EVP_CTRL_AEAD_SET_TAG decryption refuses anything that changed, including the associated data that travels in the clear. The output is ciphertext then tag, the layout WebCrypto reads.
ciphertext 78b3da886495443e7a46341982c948837dbf7b3510d774e5072034 tag 4f8c8f6e9e6177f201ed83f957fbe6d7 meet at the north gate at 7 refused: std::runtime_error: authentication failed: wrong key, nonce or AAD, or the data was changed
Generate a key, sign and verify
EVP_PKEY_Q_keygen makes a key pair, PEM_write_bio_PUBKEY exports its public half, EVP_DigestSign signs and EVP_DigestVerify checks with nothing but that PEM. The same calls sign with ECDSA P-256, Ed25519 and ML-DSA-65, the post-quantum signature of FIPS 204. Keys are random, so the example prints what stays the same: sizes, strength and the verdicts.
P-256: EC, 128-bit security, signatures up to 72 bytes, valid true, altered message false ED25519: ED25519, 128-bit security, signatures up to 64 bytes, valid true, altered message false ML-DSA-65: ML-DSA-65, 192-bit security, signatures up to 3309 bytes, valid true, altered message false
Make a self-signed certificate for localhost
The most asked OpenSSL question, answered in C++: X509_new, a random serial, X509V3_EXT_conf_nid for the subjectAltName browsers match, and X509_sign with the key it certifies, the fields openssl req -x509 -addext subjectAltName=... writes. The key comes from the signing example, and the certificate example reads the result back.
-----BEGIN CERTIFICATE----- CN=localhost DNS:localhost, IP Address:127.0.0.1 valid 2026-01-01 00:00:00Z to 2027-01-01 00:00:00Z EC prime256v1 256 bits, self-signed true localhost true example.com false
What is different on Android
- The React Native plugin compiles your headers with the library inside Gradle's native build, so
npm run androidbuilds everything. - Named imports from
./native/<header>.hwork as on the web:await initNative()once, then call the classes. - There is no
m.FSand no/memfs: files live in the app's own storage, and your C++ takes their paths. - No Worker and no COOP or COEP:
runtime: 'mt'uses pthreads directly.
Other platforms
- OpenSSL overview: the apps, every platform's setup and the packages.
- OpenSSL for WebAssembly: browsers, Node.js and edge runtimes.
- OpenSSL for iOS: React Native apps on iOS.
- OpenSSL for WASI: command-line programs under wasmtime.
Facts on this page come from the port manifests in the repository and from what npm served on beta when the site was built. See the Libraries guide for the full consumer flow.