npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@karr-company/expo-crypto-extended

v1.1.1

Published

Provides a unified interface for X25519 ECDH and HKDF-SHA256

Readme

@karr-company/expo-crypto-extended

npm License

Cross-platform Expo module for modern cryptographic primitives used in end-to-end encrypted flows.

This package provides a unified API for:

  • X25519 ECDH key agreement
  • HKDF-SHA256 key derivation
  • AES-256-GCM decryption (authenticated decryption)

Why This Module Exists

expo-crypto is useful for hashing and digest operations, but many secure messaging and key-agreement workflows also need native key exchange, HKDF, and AEAD handling.

This module fills that gap with one API surface for Expo apps.

Requirements

  • Expo SDK 55+
  • React Native with Expo Modules support
  • Development builds (not Expo Go)

Important: This module depends on Expo Crypto v55 (expo-crypto@^55.x).

Installation

Install the package:

npm install @karr-company/expo-crypto-extended

or

yarn add @karr-company/expo-crypto-extended

Then rebuild your native app:

npx expo prebuild
npx expo run:ios
npx expo run:android

API

generateKeyPair()

Generates an X25519 keypair.

Returns:

Promise<{
  publicKey: string; // base64
  privateKey: string; // base64
}>

computeSharedSecret(privateKeyBase64, endPublicKeyBase64)

Computes X25519 shared secret from your private key and the other party's public key.

Returns:

Promise<string> // base64 shared secret

hkdfSha256(ikmBase64, salt, info, keyLength)

Derives keying material using HKDF-SHA256.

Parameters:

  • ikmBase64: Input key material in base64
  • salt: UTF-8 string salt
  • info: UTF-8 context info
  • keyLength: output length in bytes

Returns:

Promise<string> // base64 derived key

aesGcmDecrypt(keyBase64, nonceBase64url, ciphertextBase64url)

Performs AES-GCM authenticated decryption.

Parameters:

  • keyBase64: AES key in base64 (32 bytes for AES-256)
  • nonceBase64url: nonce/IV in base64url
  • ciphertextBase64url: ciphertext+tag in base64url

Returns:

Promise<string> // UTF-8 plaintext

Notes:

  • ciphertextBase64url must include the authentication tag.
  • Decryption fails if tag validation fails.

Usage Example

import {
  aesGcmDecrypt,
  computeSharedSecret,
  generateKeyPair,
  hkdfSha256,
} from "@karr-company/expo-crypto-extended";

async function demo() {
  const alice = await generateKeyPair();
  const bob = await generateKeyPair();

  // ECDH shared secret
  const shared = await computeSharedSecret(alice.privateKey, bob.publicKey);

  // Derive 32-byte AES key
  const aesKey = await hkdfSha256(shared, "salt-v1", "chat-message", 32);

  // Decrypt payload received from server/peer
  const plaintext = await aesGcmDecrypt(
    aesKey,
    "BASE64URL_NONCE",
    "BASE64URL_CIPHERTEXT_WITH_TAG",
  );

  return plaintext;
}

Web Compatibility

Web support relies on Web Crypto and is only available in secure contexts:

  • HTTPS origins
  • localhost

If your target environment is not a secure context, you can implement crypto operations in an Expo Router API route and execute them server-side with Node Crypto:

  • Expo Router API routes: https://docs.expo.dev/router/web/api-routes/
  • Node Crypto: https://nodejs.org/api/crypto.html

Recommended server-side primitives:

//! - X25519 ECDH for key exchange (ephemeral keys per message)
//! - HKDF-SHA256 for key derivation
//! - AES-256-GCM for authenticated encryption

Android Notes (BouncyCastle)

This module includes BouncyCastle for compatibility with older Android versions.

Dependency included by this module:

implementation("org.bouncycastle:bcprov-jdk15to18:1.81")

Warning: BouncyCastle can cause Gradle dependency conflicts in some app dependency graphs.

Recommendation: use an Expo config plugin (or your existing build plugin stack) to enforce a single BouncyCastle version and resolve conflict errors consistently.

Proguard / R8 Rules

If your app uses Proguard or R8 minification, include the following rules:

-keep class org.bouncycastle.** {*;}

# BouncyCastle LDAP/JNDI classes - not available on Android
-dontwarn javax.naming.**
-dontwarn org.bouncycastle.jce.provider.X509LDAPCertStoreSpi
-dontwarn org.bouncycastle.jce.provider.CrlCache

Security Guidance

  • Prefer ephemeral keypairs per message/session when possible.
  • Never reuse AES-GCM nonces with the same key.
  • Validate all input encoding at trust boundaries.
  • Keep private keys out of logs and analytics.
  • Consider platform secure storage for long-lived secrets.

Error Handling

Typical error categories:

  • Invalid base64/base64url input
  • Invalid key length
  • AES-GCM authentication failure
  • Unsupported platform/runtime crypto capabilities

Treat decryption failures as security-sensitive and fail closed.

Known Limitations

  • This module currently exposes AES-GCM decryption only (no encryption helper API).
  • Web behavior depends on browser Web Crypto support and secure-context restrictions.
  • Each utility expects URL-safe base64 encoding without padding.

Development

Build module:

npm run build

Lint:

npm run lint

Run tests:

npm test

Contributing

Issues and PRs are welcome: https://github.com/karr-company/expo-crypto-extended/issues

License

MIT