Skip to content

Commit

Permalink
Add xchacha20-poly1305 (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
kigawas authored Oct 19, 2024
1 parent 1dbaad6 commit 53d1362
Show file tree
Hide file tree
Showing 30 changed files with 606 additions and 305 deletions.
16 changes: 16 additions & 0 deletions .cspell.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"words": [
"chacha",
"ecies",
"hchacha",
"xchacha"
],
"ignorePaths": [
".git",
".github",
".gitignore",
".cspell.jsonc",
"LICENSE",
"package.json"
]
}
2 changes: 1 addition & 1 deletion .github/workflows/cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:

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

- run: pnpm run build && npm publish --access public
- run: pnpm build && npm publish --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
NPM_CONFIG_PROVENANCE: true
30 changes: 27 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,42 @@ jobs:
node: [18, 20, 22]
steps:
- uses: actions/checkout@v4

- uses: pnpm/action-setup@v4

- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
cache: pnpm
cache-dependency-path: pnpm-lock.yaml

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

- uses: codecov/codecov-action@v4
if: matrix.os == 'ubuntu-latest' && matrix.node == 22
with:
token: ${{ secrets.CODECOV_TOKEN }}
- run: pnpm run build && npm publish --dry-run

check-runtimes:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
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
- run: cd example && pnpm install
- run: bun run example/main.js
- run: deno run --allow-read example/main.js
- run: node example/main.js
6 changes: 4 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ node_modules/
coverage/
dist/

bun.lockb
deno.lock
# example
example/bun.lockb
example/deno.lock
example/pnpm-lock.yaml

.DS_Store
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Release Notes

## 0.2.0

- Add xchacha20-poly1305 support

## 0.1.0

- First beta version release with aes-256-gcm and aes-256-cbc support
51 changes: 47 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,52 @@
# @ecies/ciphers

Node/Pure js symmetric ciphers adapter.
[![License](https://img.shields.io/github/license/ecies/js-ciphers.svg)](https://github.com/ecies/js-ciphers)
[![Npm Package](https://img.shields.io/npm/v/@ecies/ciphers.svg)](https://www.npmjs.com/package/@ecies/ciphers)
[![CI](https://img.shields.io/github/actions/workflow/status/ecies/js-ciphers/ci.yml)](https://github.com/ecies/js-ciphers/actions)
[![Codecov](https://img.shields.io/codecov/c/github/ecies/js-ciphers.svg)](https://codecov.io/gh/ecies/js-ciphers)

On browsers (or deno), it'll use `@noble/ciphers`'s implementation.
Node/Pure JavaScript symmetric ciphers adapter.

On node (or bun), it'll use `node:crypto`'s implementation.
On browsers (or deno), it'll use [`@noble/ciphers`](https://github.com/paulmillr/noble-ciphers)'s implementation for compatibility.

Check the [example](./example/) folder for the bun/deno usage.
On node (or bun), it'll use [`node:crypto`](https://nodejs.org/api/crypto.html#cryptocreatecipherivalgorithm-key-iv-options)'s implementation for efficiency.

> [!NOTE]
> There are some limitations, see [Known limitations](#known-limitations) below.
Check the [example](./example/) folder for bun/deno usage.

## Quick start

```js
import { aes256gcm } from "@ecies/ciphers/aes";
import { randomBytes } from "@noble/ciphers/webcrypto";

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

const key = randomBytes();
const nonce = randomBytes(16);
const cipher = aes256gcm(key, nonce);
console.log("decrypted:", decoder.decode(cipher.decrypt(cipher.encrypt(msg))));
```

The API follows `@noble/ciphers`'s API for ease of use, you can check their [examples](https://github.com/paulmillr/noble-ciphers#examples) as well.

## Supported ciphers

- `aes-256-gcm`
- Both 16 bytes and 12 bytes nonce are supported.
- `aes-256-cbc`
- **Only for legacy applications**. You should use `xchacha20-poly1305` or `aes-256-gcm` as possible.
- Nonce is always 16 bytes.
- `xchacha20-poly1305`
- Nonce is always 24 bytes.

## Known limitations

- `xchacha20-poly1305` is implemented with pure JS [`hchacha`](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha#section-2.2) function and `node:crypto`'s `chacha20-poly1305`.
- Currently (Oct 2024), `node:crypto`'s `chacha20-poly1305` is not supported on deno and [bun](https://github.com/oven-sh/bun/issues/8072), `@noble/ciphers`'s implementation is used on both platforms instead.
- `deno` does not support **indirect** conditional exports. If you use this library to build another library, client code of your library probably falls back to the `node:crypto` implementation and may not work properly, specifically `aes-256-gcm` (16 bytes nonce) and `chacha20-poly1305`.
14 changes: 11 additions & 3 deletions example/README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
# example
# runtime-example

## Install

Run with `bun install` (or `pnpm install`)

## bun

Run with `bun install && bun run index.ts`
Run with `bun run main.js`

## deno

Run with `deno run main.ts`
Run with `deno run --allow-read main.js`

## node

Run with `node main.js`
12 changes: 0 additions & 12 deletions example/bun/index.ts

This file was deleted.

14 changes: 0 additions & 14 deletions example/bun/package.json

This file was deleted.

22 changes: 0 additions & 22 deletions example/bun/tsconfig.json

This file was deleted.

9 changes: 0 additions & 9 deletions example/deno/deno.json

This file was deleted.

12 changes: 0 additions & 12 deletions example/deno/main.ts

This file was deleted.

46 changes: 46 additions & 0 deletions example/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { aes256cbc, aes256gcm } from "@ecies/ciphers/aes";
import { xchacha20 } from "@ecies/ciphers/chacha";

import { randomBytes } from "@noble/ciphers/webcrypto";

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

const ciphers = [
{
keyLength: 32,
nonceLength: 16,
callback: aes256gcm,
aad: randomBytes(16),
},
{
keyLength: 32,
nonceLength: 12,
callback: aes256gcm,
aad: randomBytes(16),
},
{
keyLength: 32,
nonceLength: 16,
callback: aes256cbc,
aad: undefined,
},
{
keyLength: 32,
nonceLength: 24,
callback: xchacha20,
aad: randomBytes(16),
},
];

for (const { keyLength, nonceLength, callback, aad } of ciphers) {
const key = randomBytes(keyLength);
const nonce = randomBytes(nonceLength);
const cipher = callback(key, nonce, aad);
console.log(
`${callback.name} (nonce length ${nonce.length}) decrypted:`,
decoder.decode(cipher.decrypt(cipher.encrypt(msg)))
);
}
8 changes: 8 additions & 0 deletions example/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "runtime-example",
"main": "main.js",
"type": "module",
"dependencies": {
"@ecies/ciphers": "file:.."
}
}
46 changes: 30 additions & 16 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@ecies/ciphers",
"description": "Node/Pure js symmetric ciphers adapter",
"description": "Node/Pure JavaScript symmetric ciphers adapter",
"license": "MIT",
"author": {
"name": "Weiliang Li",
Expand All @@ -11,38 +11,52 @@
"type": "git",
"url": "git+https://github.com/ecies/js-ciphers.git"
},
"version": "0.1.0",
"version": "0.2.0",
"engines": {
"node": ">=16.0.0"
"node": ">=16",
"bun": ">=1",
"deno": ">=2"
},
"keywords": [
"cryptography",
"aes"
"cipher",
"aes",
"chacha",
"xchacha20",
"xchacha20poly1305"
],
"main": "dist/node.js",
"types": "dist/node.d.ts",
"files": [
"dist"
],
"exports": {
"types": "./dist/node.d.ts",
"browser": "./dist/noble.js",
"deno": "./dist/noble.js",
"bun": "./dist/node.js",
"default": "./dist/node.js"
".": null,
"./aes": {
"types": "./dist/aes/node.d.ts",
"browser": "./dist/aes/noble.js",
"deno": "./dist/aes/noble.js",
"bun": "./dist/aes/node.js",
"default": "./dist/aes/node.js"
},
"./chacha": {
"types": "./dist/chacha/node.d.ts",
"browser": "./dist/chacha/noble.js",
"deno": "./dist/chacha/noble.js",
"bun": "./dist/chacha/noble.js",
"default": "./dist/chacha/node.js"
}
},
"scripts": {
"build": "npx tsc",
"test": "vitest"
},
"dependencies": {
"peerDependencies": {
"@noble/ciphers": "^1.0.0"
},
"devDependencies": {
"@types/node": "^22.7.5",
"@vitest/coverage-v8": "^2.1.2",
"@types/node": "^22.7.6",
"@vitest/coverage-v8": "^2.1.3",
"typescript": "^5.6.3",
"vitest": "^2.1.2"
"vitest": "^2.1.3"
},
"packageManager": "[email protected].1+sha512.e5a7e52a4183a02d5931057f7a0dbff9d5e9ce3161e33fa68ae392125b79282a8a8a470a51dfc8a0ed86221442eb2fb57019b0990ed24fab519bf0e1bc5ccfc4"
"packageManager": "[email protected].2+sha512.22721b3a11f81661ae1ec68ce1a7b879425a1ca5b991c975b074ac220b187ce56c708fe5db69f4c962c989452eee76c82877f4ee80f474cebd61ee13461b6228"
}
Loading

0 comments on commit 53d1362

Please sign in to comment.