Skip to content
Merged
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
29 changes: 29 additions & 0 deletions .cspell.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
// Version of the setting file. Always 0.2
"version": "0.2",
// language - current active spelling language
"language": "en",
// words - list of words to be always considered correct
"words": [
"chacha",
"ecies",
"eciesjs",
"FIPS",
"xchacha20"
],
// flagWords - list of words to be always considered incorrect
// This is useful for offensive words and common spelling errors.
// For example "hte" should be "the"
"flagWords": [
"hte"
],
"ignorePaths": [
".git",
".github",
".gitignore",
".cspell.jsonc",
"LICENSE",
"package.json",
"pnpm-lock.yaml"
]
}
4 changes: 4 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
* text=auto

*.ts text eol=lf
*.js text eol=lf
1 change: 1 addition & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
github: kigawas
7 changes: 7 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
version: 2
updates:
- package-ecosystem: npm
directory: "/"
schedule:
interval: monthly
open-pull-requests-limit: 3
26 changes: 26 additions & 0 deletions .github/workflows/cd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: CD

on:
release:
types: [published]

jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@v5
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v6
with:
node-version: 24
registry-url: "https://registry.npmjs.org"

- run: pnpm install && pnpm test -- --bail 1

- run: pnpm run build && npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
NPM_CONFIG_PROVENANCE: true
86 changes: 86 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
name: CI

on:
push:
branches: [main]

pull_request:
branches: [main]

jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
node: [20, 22, 24]
steps:
- uses: actions/checkout@v5
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node }}
cache: pnpm
cache-dependency-path: pnpm-lock.yaml

- run: pnpm install && pnpm test -- --bail 1
- run: pnpm check
- run: pnpm run build && npm publish --dry-run

- uses: codecov/codecov-action@v4
if: matrix.os == 'ubuntu-latest' && matrix.node == 24
with:
token: ${{ secrets.CODECOV_TOKEN }}

- name: Set .npmrc for windows
run: cp .npmrc.windows ./tests-browser/.npmrc
if: matrix.os == 'windows-latest'

- name: Set up browser tests
working-directory: tests-browser
run: pnpm install && pnpm exec playwright install chromium firefox

- name: Install webkit browser on macos
working-directory: tests-browser
run: pnpm exec playwright install
if: matrix.os == 'macos-latest'

- name: Run browser tests (chromium)
run: pnpm test:browser --browser=chromium

- name: Run browser tests (firefox)
run: pnpm test:browser --browser=firefox

- name: Run browser tests (webkit)
run: pnpm test:browser --browser=webkit
if: matrix.os == 'macos-latest'

check-runtimes:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v6
with:
node-version: 24
cache: pnpm
cache-dependency-path: pnpm-lock.yaml

- uses: oven-sh/setup-bun@v2
with:
bun-version: latest

- uses: denoland/setup-deno@v2
with:
deno-version: v2.x

- run: pnpm install && pnpm build && cd example/runtime && pnpm install

- name: check main.js
run: |
./scripts/check-runtime.sh example/runtime/main.js

- name: check main.js on mininum supported node version
run: |
curl -sL https://nodejs.org/download/release/v16.0.0/node-v16.0.0-linux-x64.tar.gz | tar -xz
./node-v16.0.0-linux-x64/bin/node example/runtime/main.js && rm -rf node-v16.0.0-linux-x64
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
node_modules/
coverage/
dist/
tests-browser/*.test.ts
3 changes: 3 additions & 0 deletions .npmrc.windows
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# symlink does not work on windows for vite in browsers
# see: https://github.com/vitejs/vite/issues/10802
node-linker=hoisted
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Changelog

## 0.0.1

- First alpha release
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2025 ecies
Copyright (c) 2025 Weiliang Li

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
120 changes: 120 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# @ecies/post-quantum

[![License](https://img.shields.io/github/license/ecies/js-post-quantum.svg)](https://github.com/ecies/js-post-quantum)
[![NPM Package](https://img.shields.io/npm/v/@ecies/post-quantum.svg)](https://www.npmjs.com/package/@ecies/post-quantum)
[![NPM Downloads](https://img.shields.io/npm/dm/@ecies/post-quantum)](https://npm-stat.link/@ecies/post-quantum)
[![Bundle size](https://badgen.net/bundlephobia/minzip/@ecies/post-quantum)](https://bundlephobia.com/package/@ecies/post-quantum@latest)
[![CI](https://img.shields.io/github/actions/workflow/status/ecies/js-post-quantum/ci.yml)](https://github.com/ecies/js-post-quantum/actions)
[![Codecov](https://img.shields.io/codecov/c/github/ecies/js-post-quantum.svg)](https://codecov.io/gh/ecies/js-post-quantum)

Post-quantum Cryptography Integrated Encryption Scheme in TypeScript, replacing "ec" in [`eciesjs`](https://github.com/ecies/js) with ML-KEM (Module-Lattice Key Encapsulation Mechanism).

## Install

```bash
npm install @ecies/post-quantum
```

## Quick start

```typescript
// example/runtime/main.js
import { DEFAULT_CONFIG, decrypt, encrypt } from "@ecies/post-quantum";

const encoder = new TextEncoder();
const decoder = new TextDecoder();
const msg = encoder.encode("hello world🌍");

const { secretKey, publicKey } = DEFAULT_CONFIG.asymmetricModule.keygen();
const encrypted = encrypt(publicKey, msg);
const decrypted = decrypt(secretKey, encrypted);

console.log(decoder.decode(decrypted));
```

Or run the example code:

```bash
$ pnpm install && pnpm build && cd example/runtime && pnpm install && node main.js
hello world🌍
```

## API

### `encrypt(receiverPK: Uint8Array, data: Uint8Array, config?: Config): Uint8Array`

Parameters:

- `receiverPK` - Raw public key of the receiver
- `data` - Data to encrypt
- `config` - Configuration options, default to `DEFAULT_CONFIG`

Returns: `Uint8Array`

### `decrypt(receiverSK: Uint8Array, data: Uint8Array, config?: Config): Uint8Array`

Parameters:

- `receiverSK` - Raw private key of the receiver
- `data` - Data to decrypt
- `config` - Configuration options, default to `DEFAULT_CONFIG`

Returns: `Uint8Array`

## Configuration

Following configurations are available.

- Asymmetric key encapsulation algorithm: ML-KEM-512, ML-KEM-768 or ML-KEM-1024
- Symmetric cipher algorithm: AES-256-GCM or XChaCha20-Poly1305
- Symmetric nonce length: 12 or 16 bytes (only for AES-256-GCM)

```typescript
export type AsymmetricAlgorithm = "ml-kem-512" | "ml-kem-768" | "ml-kem-1024";
export type SymmetricAlgorithm = "aes-256-gcm" | "xchacha20";
export type NonceLength = 12 | 16; // aes-256-gcm only

export class Config {
asymmetricAlgorithm: AsymmetricAlgorithm = "ml-kem-768";
symmetricAlgorithm: SymmetricAlgorithm = "aes-256-gcm";
symmetricNonceLength: NonceLength = 16; // aes-256-gcm only
}

export const DEFAULT_CONFIG = new Config();
```

### Which configuration should I choose?

About KEM, because ML-KEM creates a bunch of extra data (respectively 768, 1088, 1568 bytes) in payload, you can just use the NIST recommended default ML-KEM-768 (see FIPS 203, p40). If you need extra security, use ML-KEM-1024.

About symmetric ciphers, if you are running on low-end devices or you are a security paranoid, XChaCha20-Poly1305 is a better choice than AES-256-GCM.

## Multi-platform Support

| | Fully Supported |
| ------------ | --------------- |
| Node | ✅ |
| Bun | ✅ |
| Deno | ✅ (see below) |
| Browser | ✅ |
| React Native | ✅ |

Via [`@ecies/ciphers`](https://github.com/ecies/js-ciphers), `node:crypto`'s native implementation of AES-256-GCM and XChaCha20-Poly1305 is chosen if available.

### Browser

This library is browser-friendly, check the [`example/browser`](./example/browser) directory for details. You can check [the online demo](https://post-quantum-demo.ecies.org/) as well.

### Bun/Deno

For bun/deno, see [`example/runtime`](./example/runtime).

For deno, you may need to run with `deno run --conditions deno` (>=2.4.0) or `deno run --unstable-node-conditions deno` (>=2.3.6,<2.4.0).

### React Native

You may need to polyfill [`crypto.getRandomValues`](https://github.com/LinusU/react-native-get-random-values) for React Native.

## Changelog

See [CHANGELOG.md](./CHANGELOG.md).
1 change: 1 addition & 0 deletions _config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
theme: jekyll-theme-minimal
62 changes: 62 additions & 0 deletions biome.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{
"$schema": "https://biomejs.dev/schemas/2.3.4/schema.json",
"vcs": {
"enabled": false,
"clientKind": "git",
"useIgnoreFile": false
},
"files": {
"includes": [
"**/src/**/*.ts",
"**/tests/**/*.ts"
],
"ignoreUnknown": false
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"lineWidth": 90
},
"assist": {
"actions": {
"source": {
"organizeImports": "on"
}
}
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"style": {
"noUselessElse": "off",
"noInferrableTypes": "off",
"useTemplate": "off",
"noParameterAssign": "error",
"useAsConstAssertion": "error",
"useDefaultParameterLast": "error",
"useEnumInitializers": "error",
"useSelfClosingElements": "error",
"useSingleVarDeclarator": "error",
"noUnusedTemplateLiteral": "error",
"useNumberNamespace": "error"
}
}
},
"javascript": {
"formatter": {
"quoteStyle": "double",
"trailingCommas": "es5"
}
},
"overrides": [
{
"includes": [
"**/biome.jsonc"
],
"formatter": {
"enabled": false
}
}
]
}
15 changes: 15 additions & 0 deletions example/browser/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!doctype html>
<html lang="en">

<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Eciesjs App</title>
</head>

<body>
<div id="app"></div>
<script type="module" src="/script.js"></script>
</body>

</html>
Loading