Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support curve25519 tentatively #732

Merged
merged 1 commit into from
Sep 3, 2023
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
2 changes: 1 addition & 1 deletion .github/workflows/cd.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Publish
name: CD

on:
release:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Build
name: CI

on:
push:
Expand Down
5 changes: 3 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

## 0.4.1 ~ 0.4.5

- Support curve25519 (x25519 and ed25519) tentatively
- Revamp browser compatibility
- Export config
- Fix symmetric encryption internal types
Expand All @@ -12,8 +13,8 @@

## 0.4.0

- Change secp256k1 library to [noble-curves](https://github.com/paulmillr/noble-curves), which is [audited](https://github.com/paulmillr/noble-curves/tree/main/audit)
- Change hash library to [noble-hashes](https://github.com/paulmillr/noble-hashes)
- Change secp256k1 library to audited [noble-curves](https://github.com/paulmillr/noble-curves)
- Change hash library to audited [noble-hashes](https://github.com/paulmillr/noble-hashes)
- Change test library to [jest](https://jestjs.io/)
- Bump dependencies
- Drop Node 14 support
Expand Down
57 changes: 44 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
[![CI](https://img.shields.io/github/actions/workflow/status/ecies/js/ci.yml)](https://github.com/ecies/js/actions)
[![Codecov](https://img.shields.io/codecov/c/github/ecies/js.svg)](https://codecov.io/gh/ecies/js)

Elliptic Curve Integrated Encryption Scheme for secp256k1 in TypeScript.
Elliptic Curve Integrated Encryption Scheme for secp256k1/curve25519 in TypeScript.

This is the JavaScript/TypeScript version of [eciespy](https://github.com/ecies/py) with a built-in class-like secp256k1 [API](#privatekey), you may go there for detailed documentation and learn the mechanism under the hood.
This is the JavaScript/TypeScript version of [eciespy](https://github.com/ecies/py) with a built-in class-like secp256k1/curve25519 [API](#privatekey), you may go there for detailed documentation and learn the mechanism under the hood.

If you want a WASM version to run directly in modern browsers or on some blockchains, check [`ecies-wasm`](https://github.com/ecies/rs-wasm).

Expand All @@ -30,13 +30,15 @@ Run the code below with `npx ts-node`.
'hello world🌍'
```

See [Configuration](#configuration) to control with more granularity.

## API

### `encrypt(receiverRawPK: string | Uint8Array, msg: Uint8Array): Buffer`

Parameters:

- **receiverRawPK** - Receiver's secp256k1 public key, hex string or buffer
- **receiverRawPK** - Receiver's public key, hex string or buffer
- **msg** - Data to encrypt

Returns: **Buffer**
Expand All @@ -45,7 +47,7 @@ Returns: **Buffer**

Parameters:

- **receiverRawSK** - Receiver's secp256k1 private key, hex string or buffer
- **receiverRawSK** - Receiver's private key, hex string or buffer
- **msg** - Data to decrypt

Returns: **Buffer**
Expand All @@ -66,8 +68,9 @@ equals(other: PrivateKey): boolean;
- Properties

```typescript
readonly secret: Buffer;
get secret(): Buffer;
readonly publicKey: PublicKey;
private readonly data;
```

### `PublicKey`
Expand All @@ -76,7 +79,7 @@ readonly publicKey: PublicKey;

```typescript
static fromHex(hex: string): PublicKey;
constructor(buffer: Uint8Array);
constructor(data: Uint8Array);
toHex(compressed?: boolean): string;
decapsulate(sk: PrivateKey): Uint8Array;
equals(other: PublicKey): boolean;
Expand All @@ -85,19 +88,30 @@ equals(other: PublicKey): boolean;
- Properties

```typescript
readonly uncompressed: Buffer;
readonly compressed: Buffer;
get uncompressed(): Buffer;
get compressed(): Buffer;
private readonly data;
```

## Configuration

Ephemeral key format in the payload and shared key in the key derivation can be configured as compressed or uncompressed format.
Following configurations are available.

- Elliptic curve: secp256k1 or curve25519 (x25519/ed25519)
- Ephemeral key format in the payload: compressed or uncompressed (only for secp256k1)
- Shared elliptic curve key format in the key derivation: compressed or uncompressed (only for secp256k1)
- Symmetric cipher algorithm: AES-256-GCM or XChaCha20-Poly1305
- Symmetric nonce length: 12 or 16 bytes (only for AES-256-GCM)

For compatibility, make sure different applications share the same configuration.

```ts
export type EllipticCurve = "secp256k1" | "x25519" | "ed25519";
export type SymmetricAlgorithm = "aes-256-gcm" | "xchacha20";
export type NonceLength = 12 | 16; // bytes. Only for aes-256-gcm
export type NonceLength = 12 | 16;

class Config {
ellipticCurve: EllipticCurve = "secp256k1";
isEphemeralKeyCompressed: boolean = false;
isHkdfKeyCompressed: boolean = false;
symmetricAlgorithm: SymmetricAlgorithm = "aes-256-gcm";
Expand All @@ -107,15 +121,32 @@ class Config {
export const ECIES_CONFIG = new Config();
```

For example, if you set `isEphemeralKeyCompressed = true`, the payload would be like: `33 Bytes + AES` instead of `65 Bytes + AES`.
### Elliptic curve configuration

If you set `ellipticCurve = "x25519"` or `ellipticCurve = "ed25519"`, x25519 (key exchange function on curve25519) or ed25519 (signature algorithm on curve25519) will be used for key exchange instead of secp256k1.

In this case, the payload would always be: `32 Bytes + AES` regardless of `isEphemeralKeyCompressed`.

> If you don't know how to choose between x25519 and ed25519, just use x25519 for efficiency.

### Secp256k1-specific configuration

If you set `isEphemeralKeyCompressed = true`, the payload would be: `33 Bytes + AES` instead of `65 Bytes + AES`.

If you set `isHkdfKeyCompressed = true`, the hkdf key would be derived from `ephemeral public key (compressed) + shared public key (compressed)` instead of `ephemeral public key (uncompressed) + shared public key (uncompressed)`.

### Symmetric cipher configuration

If you set `symmetricAlgorithm = "xchacha20"`, plaintext data will encrypted with XChaCha20-Poly1305.

If you set `symmetricNonceLength = 12`, then the nonce of aes-256-gcm would be 12 bytes. XChaCha20-Poly1305's nonce is always 24 bytes.
If you set `symmetricNonceLength = 12`, the nonce of AES-256-GCM would be 12 bytes. XChaCha20-Poly1305's nonce is always 24 bytes.

For compatibility, make sure different applications share the same configuration.
## Security Audit

Following dependencies are audited:

- [noble-curves](https://github.com/paulmillr/noble-curves/tree/main/audit)
- [noble-hashes](https://github.com/paulmillr/noble-hashes#security)

## Changelog

Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@
"test": "jest"
},
"dependencies": {
"@noble/ciphers": "^0.2.0",
"@noble/ciphers": "^0.3.0",
"@noble/curves": "^1.2.0",
"@noble/hashes": "^1.3.2"
},
"devDependencies": {
"@types/jest": "^29.5.4",
"@types/node": "^20.5.6",
"@types/node": "^20.5.8",
"@types/node-fetch": "^2.6.4",
"https-proxy-agent": "^7.0.1",
"jest": "^29.6.4",
Expand Down
Loading