Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -191,5 +191,7 @@ tsconfig.tsbuildinfo
.claude/settings.local.json
.agent/

# exclude docs lib
!docs/lib
# Next.js / Docs
docs/.next/
docs/.source/
docs/next-env.d.ts
69 changes: 68 additions & 1 deletion bun.lock
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
{
"lockfileVersion": 1,
"configVersion": 0,
"workspaces": {
"": {
"dependencies": {
Expand Down Expand Up @@ -84,6 +83,14 @@
"typescript": "5.8.3",
},
},
"packages/react-native-quick-bip39": {
"name": "react-native-quick-bip39",
"version": "1.0.0",
"devDependencies": {
"@types/bun": "^1.3.4",
"esbuild": "^0.27.1",
},
},
"packages/react-native-quick-crypto": {
"name": "react-native-quick-crypto",
"version": "1.0.6",
Expand Down Expand Up @@ -397,6 +404,58 @@

"@craftzdog/react-native-buffer": ["@craftzdog/[email protected]", "", { "dependencies": { "ieee754": "^1.2.1", "react-native-quick-base64": "^2.0.5" } }, "sha512-lJXdjZ7fTllLbzDrwg/FrJLjQ5sBcAgwcqgAB6OPpXTHdCenEhHZblQpfmBLLe7/S7m0yKXL3kN3jpwOEkpjGg=="],

"@esbuild/aix-ppc64": ["@esbuild/[email protected]", "", { "os": "aix", "cpu": "ppc64" }, "sha512-HHB50pdsBX6k47S4u5g/CaLjqS3qwaOVE5ILsq64jyzgMhLuCuZ8rGzM9yhsAjfjkbgUPMzZEPa7DAp7yz6vuA=="],

"@esbuild/android-arm": ["@esbuild/[email protected]", "", { "os": "android", "cpu": "arm" }, "sha512-kFqa6/UcaTbGm/NncN9kzVOODjhZW8e+FRdSeypWe6j33gzclHtwlANs26JrupOntlcWmB0u8+8HZo8s7thHvg=="],

"@esbuild/android-arm64": ["@esbuild/[email protected]", "", { "os": "android", "cpu": "arm64" }, "sha512-45fuKmAJpxnQWixOGCrS+ro4Uvb4Re9+UTieUY2f8AEc+t7d4AaZ6eUJ3Hva7dtrxAAWHtlEFsXFMAgNnGU9uQ=="],

"@esbuild/android-x64": ["@esbuild/[email protected]", "", { "os": "android", "cpu": "x64" }, "sha512-LBEpOz0BsgMEeHgenf5aqmn/lLNTFXVfoWMUox8CtWWYK9X4jmQzWjoGoNb8lmAYml/tQ/Ysvm8q7szu7BoxRQ=="],

"@esbuild/darwin-arm64": ["@esbuild/[email protected]", "", { "os": "darwin", "cpu": "arm64" }, "sha512-veg7fL8eMSCVKL7IW4pxb54QERtedFDfY/ASrumK/SbFsXnRazxY4YykN/THYqFnFwJ0aVjiUrVG2PwcdAEqQQ=="],

"@esbuild/darwin-x64": ["@esbuild/[email protected]", "", { "os": "darwin", "cpu": "x64" }, "sha512-+3ELd+nTzhfWb07Vol7EZ+5PTbJ/u74nC6iv4/lwIU99Ip5uuY6QoIf0Hn4m2HoV0qcnRivN3KSqc+FyCHjoVQ=="],

"@esbuild/freebsd-arm64": ["@esbuild/[email protected]", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-/8Rfgns4XD9XOSXlzUDepG8PX+AVWHliYlUkFI3K3GB6tqbdjYqdhcb4BKRd7C0BhZSoaCxhv8kTcBrcZWP+xg=="],

"@esbuild/freebsd-x64": ["@esbuild/[email protected]", "", { "os": "freebsd", "cpu": "x64" }, "sha512-GITpD8dK9C+r+5yRT/UKVT36h/DQLOHdwGVwwoHidlnA168oD3uxA878XloXebK4Ul3gDBBIvEdL7go9gCUFzQ=="],

"@esbuild/linux-arm": ["@esbuild/[email protected]", "", { "os": "linux", "cpu": "arm" }, "sha512-ieMID0JRZY/ZeCrsFQ3Y3NlHNCqIhTprJfDgSB3/lv5jJZ8FX3hqPyXWhe+gvS5ARMBJ242PM+VNz/ctNj//eA=="],

"@esbuild/linux-arm64": ["@esbuild/[email protected]", "", { "os": "linux", "cpu": "arm64" }, "sha512-W9//kCrh/6in9rWIBdKaMtuTTzNj6jSeG/haWBADqLLa9P8O5YSRDzgD5y9QBok4AYlzS6ARHifAb75V6G670Q=="],

"@esbuild/linux-ia32": ["@esbuild/[email protected]", "", { "os": "linux", "cpu": "ia32" }, "sha512-VIUV4z8GD8rtSVMfAj1aXFahsi/+tcoXXNYmXgzISL+KB381vbSTNdeZHHHIYqFyXcoEhu9n5cT+05tRv13rlw=="],

"@esbuild/linux-loong64": ["@esbuild/[email protected]", "", { "os": "linux", "cpu": "none" }, "sha512-l4rfiiJRN7sTNI//ff65zJ9z8U+k6zcCg0LALU5iEWzY+a1mVZ8iWC1k5EsNKThZ7XCQ6YWtsZ8EWYm7r1UEsg=="],

"@esbuild/linux-mips64el": ["@esbuild/[email protected]", "", { "os": "linux", "cpu": "none" }, "sha512-U0bEuAOLvO/DWFdygTHWY8C067FXz+UbzKgxYhXC0fDieFa0kDIra1FAhsAARRJbvEyso8aAqvPdNxzWuStBnA=="],

"@esbuild/linux-ppc64": ["@esbuild/[email protected]", "", { "os": "linux", "cpu": "ppc64" }, "sha512-NzdQ/Xwu6vPSf/GkdmRNsOfIeSGnh7muundsWItmBsVpMoNPVpM61qNzAVY3pZ1glzzAxLR40UyYM23eaDDbYQ=="],

"@esbuild/linux-riscv64": ["@esbuild/[email protected]", "", { "os": "linux", "cpu": "none" }, "sha512-7zlw8p3IApcsN7mFw0O1Z1PyEk6PlKMu18roImfl3iQHTnr/yAfYv6s4hXPidbDoI2Q0pW+5xeoM4eTCC0UdrQ=="],

"@esbuild/linux-s390x": ["@esbuild/[email protected]", "", { "os": "linux", "cpu": "s390x" }, "sha512-cGj5wli+G+nkVQdZo3+7FDKC25Uh4ZVwOAK6A06Hsvgr8WqBBuOy/1s+PUEd/6Je+vjfm6stX0kmib5b/O2Ykw=="],

"@esbuild/linux-x64": ["@esbuild/[email protected]", "", { "os": "linux", "cpu": "x64" }, "sha512-z3H/HYI9MM0HTv3hQZ81f+AKb+yEoCRlUby1F80vbQ5XdzEMyY/9iNlAmhqiBKw4MJXwfgsh7ERGEOhrM1niMA=="],

"@esbuild/netbsd-arm64": ["@esbuild/[email protected]", "", { "os": "none", "cpu": "arm64" }, "sha512-wzC24DxAvk8Em01YmVXyjl96Mr+ecTPyOuADAvjGg+fyBpGmxmcr2E5ttf7Im8D0sXZihpxzO1isus8MdjMCXQ=="],

"@esbuild/netbsd-x64": ["@esbuild/[email protected]", "", { "os": "none", "cpu": "x64" }, "sha512-1YQ8ybGi2yIXswu6eNzJsrYIGFpnlzEWRl6iR5gMgmsrR0FcNoV1m9k9sc3PuP5rUBLshOZylc9nqSgymI+TYg=="],

"@esbuild/openbsd-arm64": ["@esbuild/[email protected]", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-5Z+DzLCrq5wmU7RDaMDe2DVXMRm2tTDvX2KU14JJVBN2CT/qov7XVix85QoJqHltpvAOZUAc3ndU56HSMWrv8g=="],

"@esbuild/openbsd-x64": ["@esbuild/[email protected]", "", { "os": "openbsd", "cpu": "x64" }, "sha512-Q73ENzIdPF5jap4wqLtsfh8YbYSZ8Q0wnxplOlZUOyZy7B4ZKW8DXGWgTCZmF8VWD7Tciwv5F4NsRf6vYlZtqg=="],

"@esbuild/openharmony-arm64": ["@esbuild/[email protected]", "", { "os": "none", "cpu": "arm64" }, "sha512-ajbHrGM/XiK+sXM0JzEbJAen+0E+JMQZ2l4RR4VFwvV9JEERx+oxtgkpoKv1SevhjavK2z2ReHk32pjzktWbGg=="],

"@esbuild/sunos-x64": ["@esbuild/[email protected]", "", { "os": "sunos", "cpu": "x64" }, "sha512-IPUW+y4VIjuDVn+OMzHc5FV4GubIwPnsz6ubkvN8cuhEqH81NovB53IUlrlBkPMEPxvNnf79MGBoz8rZ2iW8HA=="],

"@esbuild/win32-arm64": ["@esbuild/[email protected]", "", { "os": "win32", "cpu": "arm64" }, "sha512-RIVRWiljWA6CdVu8zkWcRmGP7iRRIIwvhDKem8UMBjPql2TXM5PkDVvvrzMtj1V+WFPB4K7zkIGM7VzRtFkjdg=="],

"@esbuild/win32-ia32": ["@esbuild/[email protected]", "", { "os": "win32", "cpu": "ia32" }, "sha512-2BR5M8CPbptC1AK5JbJT1fWrHLvejwZidKx3UMSF0ecHMa+smhi16drIrCEggkgviBwLYd5nwrFLSl5Kho96RQ=="],

"@esbuild/win32-x64": ["@esbuild/[email protected]", "", { "os": "win32", "cpu": "x64" }, "sha512-d5X6RMYv6taIymSk8JBP+nxv8DQAMY6A51GPgusqLdK9wBz5wWIXy1KjTck6HnjE9hqJzJRdk+1p/t5soSbCtw=="],

"@eslint-community/eslint-utils": ["@eslint-community/[email protected]", "", { "dependencies": { "eslint-visitor-keys": "^3.3.0" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, ""],

"@eslint-community/regexpp": ["@eslint-community/[email protected]", "", {}, ""],
Expand Down Expand Up @@ -715,6 +774,8 @@

"@types/babel__traverse": ["@types/[email protected]", "", { "dependencies": { "@babel/types": "^7.20.7" } }, ""],

"@types/bun": ["@types/[email protected]", "", { "dependencies": { "bun-types": "1.3.4" } }, "sha512-EEPTKXHP+zKGPkhRLv+HI0UEX8/o+65hqARxLy8Ov5rIxMBPNTjeZww00CIihrIQGEQBYg+0roO5qOnS/7boGA=="],

"@types/chai": ["@types/[email protected]", "", { "dependencies": { "@types/deep-eql": "*", "assertion-error": "^2.0.1" } }, "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA=="],

"@types/deep-eql": ["@types/[email protected]", "", {}, "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw=="],
Expand Down Expand Up @@ -945,6 +1006,8 @@

"buffer-xor": ["[email protected]", "", {}, ""],

"bun-types": ["[email protected]", "", { "dependencies": { "@types/node": "*" } }, "sha512-5ua817+BZPZOlNaRgGBpZJOSAQ9RQ17pkwPD0yR7CfJg+r8DgIILByFifDTa+IPDDxzf5VNhtNlcKqFzDgJvlQ=="],

"bundle-name": ["[email protected]", "", { "dependencies": { "run-applescript": "^7.0.0" } }, ""],

"bytes": ["[email protected]", "", {}, ""],
Expand Down Expand Up @@ -1235,6 +1298,8 @@

"es-to-primitive": ["[email protected]", "", { "dependencies": { "is-callable": "^1.2.7", "is-date-object": "^1.0.5", "is-symbol": "^1.0.4" } }, "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g=="],

"esbuild": ["[email protected]", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.1", "@esbuild/android-arm": "0.27.1", "@esbuild/android-arm64": "0.27.1", "@esbuild/android-x64": "0.27.1", "@esbuild/darwin-arm64": "0.27.1", "@esbuild/darwin-x64": "0.27.1", "@esbuild/freebsd-arm64": "0.27.1", "@esbuild/freebsd-x64": "0.27.1", "@esbuild/linux-arm": "0.27.1", "@esbuild/linux-arm64": "0.27.1", "@esbuild/linux-ia32": "0.27.1", "@esbuild/linux-loong64": "0.27.1", "@esbuild/linux-mips64el": "0.27.1", "@esbuild/linux-ppc64": "0.27.1", "@esbuild/linux-riscv64": "0.27.1", "@esbuild/linux-s390x": "0.27.1", "@esbuild/linux-x64": "0.27.1", "@esbuild/netbsd-arm64": "0.27.1", "@esbuild/netbsd-x64": "0.27.1", "@esbuild/openbsd-arm64": "0.27.1", "@esbuild/openbsd-x64": "0.27.1", "@esbuild/openharmony-arm64": "0.27.1", "@esbuild/sunos-x64": "0.27.1", "@esbuild/win32-arm64": "0.27.1", "@esbuild/win32-ia32": "0.27.1", "@esbuild/win32-x64": "0.27.1" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-yY35KZckJJuVVPXpvjgxiCuVEJT67F6zDeVTv4rizyPrfGBUpZQsvmxnN+C371c2esD/hNMjj4tpBhuueLN7aA=="],

"escalade": ["[email protected]", "", {}, ""],

"escape-html": ["[email protected]", "", {}, ""],
Expand Down Expand Up @@ -2109,6 +2174,8 @@

"react-native-quick-base64": ["[email protected]", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-WLHSifHLoamr2kF00Gov0W9ud6CfPshe1rmqWTquVIi9c62qxOaJCFVDrXFZhEBU8B8PvGLVuOlVKH78yhY0Fg=="],

"react-native-quick-bip39": ["react-native-quick-bip39@workspace:packages/react-native-quick-bip39"],

"react-native-quick-crypto": ["react-native-quick-crypto@workspace:packages/react-native-quick-crypto"],

"react-native-quick-crypto-example": ["react-native-quick-crypto-example@workspace:example"],
Expand Down
220 changes: 220 additions & 0 deletions docs/content/docs/api/bip39.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
---
title: BIP39
description: Mnemonic generation and seed derivation
---

import { Callout } from 'fumadocs-ui/components/callout';
import { TypeTable } from 'fumadocs-ui/components/type-table';
import { Tab, Tabs } from 'fumadocs-ui/components/tabs';

The `BIP39` module is a high-performance, lightweight implementation of the [Bitcoin Improvement Proposal 39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) standard. It provides functions to generate mnemonics, validate them, and derive seeds.

<Callout type="info" title="Separate Package">
This module is distributed as a separate package [`react-native-quick-bip39`](https://github.com/margelo/react-native-quick-bip39) to maintain a lightweight core for `react-native-quick-crypto`. You must install it separately.
</Callout>

## Table of Contents

- [Theory](#theory)
- [Module Methods](#module-methods)
- [Multi-Language Support](#multi-language-support)
- [Performance & Bundle Size](#performance--bundle-size)
- [Security Considerations](#security-considerations)

## Theory

**BIP39** describes the implementation of a Mnemonic Code generation scheme. It consists of two main parts: generates the mnemonic and converting it into a binary seed.

### 1. Generating the Mnemonic
Authentication tokens are generated from a source of random information, called **entropy**. The allowed size of the entropy is 128-256 bits. A checksum is appended to this initial entropy, allowing errors to be detected (e.g., typo in a word). These bits are then split into 11-bit chunks, each mapping to a word in a predefined wordlist of 2048 words.

| Entropy (bits) | Checksum (bits) | Total (bits) | Mnemonic Length (words) |
| :--- | :--- | :--- | :--- |
| 128 | 4 | 132 | **12** (Standard) |
| 160 | 5 | 165 | 15 |
| 192 | 6 | 198 | 18 |
| 224 | 7 | 231 | 21 |
| 256 | 8 | 264 | **24** (High Security) |

### 2. From Mnemonic to Seed
A user may decide to protect their mnemonic with a passphrase. A **salt** is created using the string `"mnemonic"` + the optional passphrase.
The `pbkdf2` function (using `HMAC-SHA512`) is then applied with **2048 iterations** to derive a 512-bit (64-byte) seed. This seed can be later used to generate deterministic wallets (BIP-32) or similar keys.

---

## Module Methods

### generateMnemonic(strength[, wordlist])

Generates a random mnemonic phrase.

**Parameters:**

<TypeTable
type={{
strength: {
description: 'Entropy bits. Must be a multiple of 32 (128-256).',
type: '128 | 160 | 192 | 224 | 256',
default: '128'
},
wordlist: {
description: 'Array of 2048 words.',
type: 'string[]',
default: 'english'
}
}}
/>

**Returns:** `string` (space-separated mnemonic)

**Example:**

```ts
import { generateMnemonic } from 'react-native-quick-bip39';

const mnemonic = generateMnemonic(128);
// "orphan fresh utility slice magnet believe..."
```

---

### validateMnemonic(mnemonic[, wordlist])

Validates a mnemonic phrase against a wordlist. Checks for valid word count (multiple of 3), existence in wordlist, and correct checksum.

**Parameters:**

<TypeTable
type={{
mnemonic: {
description: 'The mnemonic phrase to validate.',
type: 'string',
},
wordlist: {
description: 'Array of 2048 words.',
type: 'string[]',
default: 'english'
}
}}
/>

**Returns:** `boolean`

---

### mnemonicToSeed(mnemonic[, password])

Converts a mnemonic phrase to a binary seed asynchronously using PBKDF2 (SHA-512) with 2048 iterations. This method offloads work to the native thread pool, keeping the UI responsive.

**Parameters:**

<TypeTable
type={{
mnemonic: {
description: 'The mnemonic phrase.',
type: 'string',
},
password: {
description: 'Optional passphrase (salt extension).',
type: 'string',
default: '""'
}
}}
/>

**Returns:** `Promise<Buffer>` (64 bytes)

**Example:**

```ts
import { mnemonicToSeed } from 'react-native-quick-bip39';

const seed = await mnemonicToSeed('orphan fresh...');
```

---

### mnemonicToSeedSync(mnemonic[, password])

Synchronous version of `mnemonicToSeed`. Blocks the JS thread until completion.

**Parameters:**

<TypeTable
type={{
mnemonic: { description: 'The mnemonic phrase.', type: 'string' },
password: { description: 'Optional passphrase.', type: 'string' }
}}
/>

**Returns:** `Buffer` (64 bytes)

---

### entropyToMnemonic(entropy[, wordlist])

Converts raw entropy bytes to a mnemonic phrase.

**Parameters:**

<TypeTable
type={{
entropy: {
description: 'Buffer of entropy bytes (16-32 bytes).',
type: 'Buffer',
},
wordlist: {
description: 'Array of 2048 words.',
type: 'string[]',
default: 'english'
}
}}
/>

**Returns:** `string`

---

## Multi-Language Support

To keep bundle sizes small (~19KB), only the **English** wordlist is included by default. Additional languages must be imported explicitly.

Supported languages: `english` (default), `spanish`, `french`, `italian`, `japanese`, `korean`, `chinese_simplified`, `chinese_traditional`, `czech`, `portuguese`.

**Example:**

```ts
import { generateMnemonic } from 'react-native-quick-bip39';
import { wordlist as spanish } from 'react-native-quick-bip39/wordlists/spanish';

const mnemonic = generateMnemonic(128, spanish);
```

<Callout type="warn">
Importing all languages increases bundle size significantly (up to ~283 KB). Only import what you need.
</Callout>

### Performance & Bundle Size

- **Performance**: Up to **100x faster** than pure JS implementations for seed derivation, thanks to C++ JSI bindings for PBKDF2.
- **Bundle Size**: **~19 KB** (minified) when using default English wordlist.

---

## Real-World Examples

### Building a Crypto Wallet
For a complete guide on how to build a high-performance HD Wallet using `react-native-quick-bip39` alongside `react-native-quick-crypto`, check out the dedicated **[Crypto Wallet Guide](/docs/guides/crypto-wallet)**.

---

## Security Considerations

### 1. Passphrase Protection
BIP39 allows a user to define a password (passphrase). This serves as a "13th word" (or 25th) and significantly increases the difficulty of a brute force attack, as well as providing plausible deniability (an empty wallet can be derived from the mnemonic without password).

### 2. Randomness (Entropy)
`generateMnemonic` uses `react-native-quick-crypto`'s `randomBytes` which uses the OS's cryptographically secure pseudo-random number generator (CSPRNG). Do not attempt to generate your own entropy using `Math.random()`, as it is not secure.

### 3. Checksum Verification
Always validate user input using `validateMnemonic`. The checksum provides a basic check (1 in 256 chance of false positive for 12 words), but it ensures transcription errors are caught early.
1 change: 1 addition & 0 deletions docs/content/docs/api/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"pages": [
"index",
"install",
"bip39",
"cipher",
"hash",
"hmac",
Expand Down
Loading