@vex-chat/crypto 1.1.0-rc.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,18 +1,81 @@
1
- # @vex-chat/crypto-js
1
+ # @vex-chat/crypto
2
2
 
3
- ![typescript_ci](https://github.com/vex-chat/crypto-js/workflows/typescript_ci/badge.svg)
3
+ [![npm](https://img.shields.io/npm/v/@vex-chat/crypto?style=flat-square&color=cb3837&logo=npm)](https://www.npmjs.com/package/@vex-chat/crypto)
4
+ [![CI](https://img.shields.io/github/actions/workflow/status/vex-protocol/crypto-js/build.yml?branch=master&style=flat-square&logo=github&label=CI)](https://github.com/vex-protocol/crypto-js/actions/workflows/build.yml)
5
+ [![Released](https://img.shields.io/github/release-date/vex-protocol/crypto-js?style=flat-square&label=released)](https://github.com/vex-protocol/crypto-js/releases)
6
+ [![License](https://img.shields.io/npm/l/@vex-chat/crypto?style=flat-square&color=blue)](./LICENSE)
7
+ [![Types](https://img.shields.io/npm/types/@vex-chat/crypto?style=flat-square&logo=typescript&color=3178c6)](./dist/index.d.ts)
8
+ [![Type Coverage](https://img.shields.io/badge/dynamic/json?style=flat-square&label=type-coverage&prefix=%E2%89%A5&suffix=%25&query=$.typeCoverage.atLeast&url=https://raw.githubusercontent.com/vex-protocol/crypto-js/master/package.json&color=3178c6&logo=typescript)](https://github.com/plantain-00/type-coverage)
9
+ [![Node](https://img.shields.io/node/v/@vex-chat/crypto?style=flat-square&color=339933&logo=nodedotjs)](./package.json)
10
+ [![Bundle](https://deno.bundlejs.com/badge?q=@vex-chat/crypto&treeshake=[*])](https://bundlejs.com/?q=@vex-chat/crypto&treeshake=[*])
11
+ [![OpenSSF Scorecard](https://img.shields.io/ossf-scorecard/github.com/vex-protocol/crypto-js?style=flat-square&label=Scorecard)](https://securityscorecards.dev/viewer/?uri=github.com/vex-protocol/crypto-js)
12
+ [![Socket](https://socket.dev/api/badge/npm/package/@vex-chat/crypto)](https://socket.dev/npm/package/@vex-chat/crypto)
4
13
 
5
- All of the crypto functions for the key exchange are contained in here.
14
+ Crypto primitives for the [Vex](https://vex.wtf) encrypted chat platform. Sign, encrypt, hash, derive keys, and encode bytes — everything the client and server need to speak the protocol.
6
15
 
7
- [Documentation](https://vex-chat.github.io/crypto-js/)
16
+ ## What's in the box
8
17
 
9
- ## external crypto dependencies
18
+ - **Key generation** — `xBoxKeyPair()` / `xSignKeyPair()` / `xSignKeyPairFromSecret()` / `xBoxKeyPairFromSecret()` for X25519 (encryption) and Ed25519 (signing) keypairs.
19
+ - **Signing** — `xSign()` / `xSignVerify()` over arbitrary bytes using Ed25519.
20
+ - **Authenticated encryption** — `xSecretbox()` / `xSecretboxOpen()` (NaCl secretbox) plus `xDH()` for Diffie-Hellman shared secrets.
21
+ - **Hashing & KDF** — `xHash()` (SHA-512), `xKDF()` (HKDF-SHA256 via `@noble/hashes`), `xHMAC()`, and PBKDF2.
22
+ - **Encoding** — `xEncode()` / `xDecode()` for msgpack wire serialization; `XUtils.encodeBase64` / `encodeUTF8` for constant-time transport encoding.
23
+ - **Mnemonic keys** — `xMnemonic()` (BIP39) for deriving keys from human-readable phrases.
24
+ - **Utilities** — `xConcat()`, `xMakeNonce()`, `xRandomBytes()`, and `XKeyConvert` (Ed25519 ↔ X25519 conversion via `ed2curve`).
10
25
 
11
- This library utilizes native Node.js crypto where possible for performance and security.
26
+ All primitives use constant-time operations where relevant. Native Node crypto is used for HKDF/PBKDF2/HMAC/SHA; `tweetnacl` and `@noble/hashes` cover the rest.
12
27
 
13
- - **tweetnacl**: Primitives for signing and encryption (X25519 / Ed25519).
14
- - **ed2curve**: Ed25519 signing key to X25519 encryption key conversion.
15
- - **msgpackr**: High-performance MessagePack serialization (replacing `msgpack-lite`).
16
- - **bip39**: Mnemonic generation for keys.
17
- - **Node Crypto**: Native implementations for HKDF, PBKDF2, HMAC, and SHA hashing (replacing `futoin-hkdf`, `create-hmac`, and `sha.js`).
18
- - **@stablelib**: Constant-time encoding for Base64 and UTF8.
28
+ ## Install
29
+
30
+ ```sh
31
+ npm install @vex-chat/crypto
32
+ ```
33
+
34
+ `@vex-chat/types` is a peer dependency — install it alongside if you don't already have it:
35
+
36
+ ```sh
37
+ npm install @vex-chat/types @vex-chat/crypto
38
+ ```
39
+
40
+ ## Usage
41
+
42
+ ```ts
43
+ import {
44
+ xBoxKeyPair,
45
+ xSignKeyPair,
46
+ xSign,
47
+ xSecretbox,
48
+ xSecretboxOpen,
49
+ xDH,
50
+ xMakeNonce,
51
+ xEncode,
52
+ xDecode,
53
+ XUtils,
54
+ } from "@vex-chat/crypto";
55
+
56
+ // Generate identity keys
57
+ const signKeys = xSignKeyPair();
58
+ const boxKeys = xBoxKeyPair();
59
+
60
+ // Sign a message
61
+ const message = XUtils.encodeUTF8("hello vex");
62
+ const signature = xSign(message, signKeys.secretKey);
63
+
64
+ // Derive a shared secret and encrypt
65
+ const shared = xDH(boxKeys.secretKey, otherPartyPublicKey);
66
+ const nonce = xMakeNonce();
67
+ const ciphertext = xSecretbox(message, nonce, shared);
68
+
69
+ // Decrypt
70
+ const plaintext = xSecretboxOpen(ciphertext, nonce, shared);
71
+
72
+ // msgpack wire encoding
73
+ const frame = xEncode({ type: "success", transmissionID: "abc", data: null });
74
+ const decoded = xDecode(frame);
75
+ ```
76
+
77
+ See the generated API docs at [vex-chat.github.io/crypto-js](https://vex-chat.github.io/crypto-js/) for the full surface.
78
+
79
+ ## License
80
+
81
+ [AGPL-3.0-or-later](./LICENSE)
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
+ import type { BaseMsg } from "@vex-chat/types";
1
2
  import { decode as decodeBase64, encode as encodeBase64 } from "@stablelib/base64";
2
- import { decode as encodeUTF8, encode as decodeUTF8 } from "@stablelib/utf8";
3
- import type { IBaseMsg } from "@vex-chat/types";
3
+ import { encode as decodeUTF8, decode as encodeUTF8 } from "@stablelib/utf8";
4
4
  import ed2curve from "ed2curve";
5
5
  /**
6
6
  * Provides an interface that can map an ed25519 keypair to its equivalent
@@ -12,10 +12,10 @@ export declare const XKeyConvert: typeof ed2curve;
12
12
  * vex messages.
13
13
  */
14
14
  export declare class XUtils {
15
- static encodeUTF8: typeof encodeUTF8;
15
+ static decodeBase64: typeof decodeBase64;
16
16
  static decodeUTF8: typeof decodeUTF8;
17
17
  static encodeBase64: typeof encodeBase64;
18
- static decodeBase64: typeof decodeBase64;
18
+ static encodeUTF8: typeof encodeUTF8;
19
19
  /**
20
20
  * Checks if two buffer-like objects are equal.
21
21
  *
@@ -24,110 +24,133 @@ export declare class XUtils {
24
24
  *
25
25
  * @returns True if equal, else false.
26
26
  */
27
- static bytesEqual(buf1: Uint8Array | ArrayBuffer, buf2: Uint8Array | ArrayBuffer): boolean;
27
+ static bytesEqual(buf1: ArrayBuffer | Uint8Array, buf2: ArrayBuffer | Uint8Array): boolean;
28
28
  /**
29
- * Returns a six bit Uint8Array representation of an integer.
30
- * The integer must be positive, and it must be able to be stored
31
- * in six bytes.
29
+ * Decodes a hex string into a Uint8Array.
32
30
  *
33
- * @param n The number to convert.
34
- * @returns The Uint8Array representation of n.
31
+ * @returns The Uint8Array.
35
32
  */
36
- static numberToUint8Arr(n: number): Uint8Array;
33
+ static decodeHex(hexString: string): Uint8Array;
37
34
  /**
38
- * Converts a Uint8Array representation of an integer back into a number.
35
+ * Decrypts a secret key from the binary format produced by encryptKeyData().
36
+ * No I/O — the caller handles reading the data.
39
37
  *
40
- * @param arr The array to convert.
41
- * @returns the number representation of arr.
38
+ * @param keyData The encrypted key data as a Uint8Array.
39
+ * @param password The password used to encrypt.
40
+ * @returns The hex-encoded secret key.
42
41
  */
43
- static uint8ArrToNumber(arr: Uint8Array): number;
42
+ static decryptKeyData: (keyData: Uint8Array, password: string) => string;
44
43
  /**
45
- * Takes a vex message and unpacks it into its header and a javascript object
46
- * respresentation of its body.
44
+ * Returns the empty header (32 0's)
47
45
  *
48
- * @param arr The array to convert.
49
- * @returns [32 byte header, message body]
46
+ * @returns The empty header.
50
47
  */
51
- static unpackMessage(msg: Uint8Array | Buffer): [Uint8Array, IBaseMsg];
48
+ static emptyHeader(): Uint8Array<ArrayBuffer>;
52
49
  /**
53
- * Packs a javascript object and a 32 byte header into a vex message.
50
+ * Encodes a Uint8Array to a hex string.
54
51
  *
55
- * @param arr The array to convert.
56
- * @returns the packed message.
52
+ * @returns The hex string.
57
53
  */
58
- static packMessage(msg: any, header?: Uint8Array): Uint8Array<ArrayBufferLike>;
54
+ static encodeHex(bytes: Uint8Array): string;
59
55
  /**
60
- * Returns the empty header (32 0's)
61
- *
62
- * @returns The empty header.
63
- */
64
- static emptyHeader(): Uint8Array<ArrayBuffer>;
56
+ * Encrypts a secret key with a password and saves it as a file.
57
+ *
58
+ * @param path The path to save the keyfile.
59
+ /**
60
+ * Encrypts a secret key into a portable binary format.
61
+ * The result can be written to disk, sent over the network, etc.
62
+ * No I/O — the caller handles persistence.
63
+ *
64
+ * Format: [iterations(6)|salt(24)|nonce(24)|ciphertext(N)]
65
+ *
66
+ * @param password The password to derive the encryption key from.
67
+ * @param keyToSave The hex-encoded secret key to encrypt.
68
+ * @param iterationOverride Optional PBKDF2 iteration count (random if omitted).
69
+ * @returns The encrypted key data as a Uint8Array.
70
+ */
71
+ static encryptKeyData: (password: string, keyToSave: string, iterationOverride?: number) => Uint8Array;
65
72
  /**
66
- * Encrypts a secret key with a password and saves it as a file.
73
+ * Returns a six bit Uint8Array representation of an integer.
74
+ * The integer must be positive, and it must be able to be stored
75
+ * in six bytes.
67
76
  *
68
- * @param path The path to save the keyfile.
69
- * @param password The password to encrypt the keyfile with.
70
- * @param keyToSave The key to encrypt.
71
- * @param iterationOverride An optional override if you'd prefer to manually
72
- * select your iterations rather than having a random amount selected.
77
+ * @param n The number to convert.
78
+ * @returns The Uint8Array representation of n.
73
79
  */
74
- static saveKeyFile: (path: string, password: string, keyToSave: string, iterationOverride?: number) => void;
80
+ static numberToUint8Arr(n: number): Uint8Array;
75
81
  /**
76
- * Decrypts and returns a secret key stored in a file with saveKeyFile().
82
+ * Packs a javascript object and a 32 byte header into a vex message.
77
83
  *
78
- * @param path The path of the file.
79
- * @param password The password the file was encrypted with.
84
+ * @param arr The array to convert.
85
+ * @returns the packed message.
80
86
  */
81
- static loadKeyFile: (path: string, password: string) => string;
87
+ static packMessage(msg: unknown, header?: Uint8Array): Uint8Array<ArrayBufferLike>;
82
88
  /**
83
- * Decodes a hex string into a Uint8Array.
89
+ * Converts a Uint8Array representation of an integer back into a number.
84
90
  *
85
- * @returns The Uint8Array.
91
+ * @param arr The array to convert.
92
+ * @returns the number representation of arr.
86
93
  */
87
- static decodeHex(hexString: string): Uint8Array;
94
+ static uint8ArrToNumber(arr: Uint8Array): number;
88
95
  /**
89
- * Encodes a Uint8Array to a hex string.
96
+ * Takes a vex message and unpacks it into its header and a javascript object
97
+ * respresentation of its body.
90
98
  *
91
- * @returns The hex string.
99
+ * @param arr The array to convert.
100
+ * @returns [32 byte header, message body]
92
101
  */
93
- static encodeHex(bytes: Uint8Array): string;
102
+ static unpackMessage(msg: Buffer | Uint8Array): [Uint8Array, BaseMsg];
94
103
  }
95
- /**
96
- * Gets a word list representation of a byte sequence.
97
- *
98
- * @param entropy The bytes to derive the wordlist from.
99
- * @param wordList Optional, override the wordlist. See bip39 docs for details.
100
- */
101
- export declare function xMnemonic(entropy: Uint8Array, wordList?: string[] | undefined): string;
102
104
  /**
103
105
  * Returns a 32 byte HMAC of a javscript object.
104
106
  *
105
107
  * @param msg the message to create the HMAC of
106
108
  * @param SK the secret key to create the HMAC with
107
109
  */
108
- export declare function xHMAC(msg: any, SK: Uint8Array): Uint8Array<ArrayBuffer>;
110
+ export declare function xHMAC(msg: unknown, SK: Uint8Array): Uint8Array<ArrayBufferLike>;
109
111
  /**
110
- * Constants for vex.
112
+ * Gets a word list representation of a byte sequence.
113
+ *
114
+ * @param entropy The bytes to derive the wordlist from.
115
+ * @param wordList Optional, override the wordlist. See bip39 docs for details.
111
116
  */
112
- export declare const xConstants: XConstants;
117
+ export declare function xMnemonic(entropy: Uint8Array, wordList?: string[]): string;
113
118
  /**
114
- * Returns a 24 byte random nonce of cryptographic quality.
119
+ * Constants for vex.
115
120
  */
116
- export declare function xMakeNonce(): Uint8Array;
121
+ export declare const xConstants: XConstants;
122
+ /** Ed25519 or X25519 key pair. Structurally identical to nacl.SignKeyPair / nacl.BoxKeyPair. */
123
+ export interface KeyPair {
124
+ publicKey: Uint8Array;
125
+ secretKey: Uint8Array;
126
+ }
117
127
  /**
118
128
  * Derives a 32 byte secret key from some initial key material.
119
129
  *
120
130
  * @param IKM the initial key material.
121
131
  * @returns The generated key.
122
132
  */
123
- export declare function xKDF(IKM: Uint8Array): Uint8Array;
124
133
  /**
125
- * Hashes some data.
134
+ * @ignore
135
+ */
136
+ interface XConstants {
137
+ CURVE: "X25519";
138
+ HASH: "SHA-512";
139
+ HEADER_SIZE: 32;
140
+ INFO: string;
141
+ KEY_LENGTH: 32 | 57;
142
+ MIN_OTK_SUPPLY: number;
143
+ }
144
+ /** Generate a fresh X25519 box key pair. */
145
+ export declare function xBoxKeyPair(): KeyPair;
146
+ /** Restore an X25519 box key pair from a 32-byte secret key. */
147
+ export declare function xBoxKeyPairFromSecret(secretKey: Uint8Array): KeyPair;
148
+ /**
149
+ * Concatanates multiple Uint8Arrays.
126
150
  *
127
- * @param data the data to hash.
128
- * @returns The hash of the data.
151
+ * @param arrays As many Uint8Arrays as you would like to concatanate.
129
152
  */
130
- export declare function xHash(data: Uint8Array): string;
153
+ export declare function xConcat(...arrays: Uint8Array[]): Uint8Array;
131
154
  /**
132
155
  * Derives a shared Secret Key from a known private key and
133
156
  * a peer's known public key.
@@ -137,28 +160,38 @@ export declare function xHash(data: Uint8Array): string;
137
160
  * @returns The derived shared secret, SK.
138
161
  */
139
162
  export declare function xDH(myPrivateKey: Uint8Array, theirPublicKey: Uint8Array): Uint8Array;
140
- /**
141
- * Concatanates multiple Uint8Arrays.
142
- *
143
- * @param arrays As many Uint8Arrays as you would like to concatanate.
144
- */
145
- export declare function xConcat(...arrays: Uint8Array[]): Uint8Array;
146
163
  /**
147
164
  * Encode an X25519 or X448 public key PK into a byte sequence.
148
165
  * The encoding consists of 0 or 1 to represent the type of curve, followed by l
149
166
  * ittle-endian encoding of the u-coordinate. See [rfc 7748](https://www.ietf.org/rfc/rfc7748.txt) for more
150
167
  * details.
151
168
  */
152
- export declare function xEncode(curveType: "X25519" | "X448", publicKey: Uint8Array): Uint8Array;
169
+ export declare function xEncode(curveType: "X448" | "X25519", publicKey: Uint8Array): Uint8Array;
153
170
  /**
154
- * @ignore
171
+ * Hashes some data.
172
+ *
173
+ * @param data the data to hash.
174
+ * @returns The hash of the data.
155
175
  */
156
- interface XConstants {
157
- CURVE: "X25519";
158
- HASH: "SHA-512";
159
- INFO: string;
160
- KEY_LENGTH: 32 | 57;
161
- MIN_OTK_SUPPLY: number;
162
- HEADER_SIZE: 32;
163
- }
176
+ export declare function xHash(data: Uint8Array): string;
177
+ export declare function xKDF(IKM: Uint8Array): Uint8Array;
178
+ /**
179
+ * Returns a 24 byte random nonce of cryptographic quality.
180
+ */
181
+ export declare function xMakeNonce(): Uint8Array;
182
+ /** Cryptographically secure random bytes. */
183
+ export declare function xRandomBytes(length: number): Uint8Array;
184
+ /** Encrypt with a shared secret key. */
185
+ export declare function xSecretbox(plaintext: Uint8Array, nonce: Uint8Array, key: Uint8Array): Uint8Array;
186
+ /** Decrypt with a shared secret key. Returns null if authentication fails. */
187
+ export declare function xSecretboxOpen(ciphertext: Uint8Array, nonce: Uint8Array, key: Uint8Array): null | Uint8Array;
188
+ /** Sign a message with an Ed25519 secret key. Returns signed message (64-byte signature prefix + message). */
189
+ export declare function xSign(message: Uint8Array, secretKey: Uint8Array): Uint8Array;
190
+ /** Generate a fresh Ed25519 signing key pair. */
191
+ export declare function xSignKeyPair(): KeyPair;
192
+ /** Restore an Ed25519 signing key pair from a 64-byte secret key. */
193
+ export declare function xSignKeyPairFromSecret(secretKey: Uint8Array): KeyPair;
194
+ /** Verify and open a signed message. Returns the original message, or null if verification fails. */
195
+ export declare function xSignOpen(signedMessage: Uint8Array, publicKey: Uint8Array): null | Uint8Array;
164
196
  export {};
197
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}