@unknownncat/curve25519-node 1.0.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,56 +1,27 @@
1
1
  # @unknownncat/curve25519-node
2
2
 
3
+ > 🇺🇸 English version: [README.en.md](./README.en.md)
4
+
5
+ Implementação sem dependências de runtime de:
6
+
7
+ - X25519 + Ed25519 (modo moderno via OpenSSL em `node:crypto`)
8
+ - axlsign legado (modo opcional via WASM, compatível com `curve25519-js`)
9
+
3
10
  [![npm](https://img.shields.io/npm/v/@unknownncat/curve25519-node)](https://www.npmjs.com/package/@unknownncat/curve25519-node)
4
- [![downloads](https://img.shields.io/badge/downloads-new%20package-lightgrey)](https://www.npmjs.com/package/@unknownncat/curve25519-node)
5
- [![types](https://img.shields.io/badge/types-included-blue)](./dist/index.d.ts)
6
- [![license](https://img.shields.io/badge/license-MIT-green)](./LICENSE)
7
11
  [![node](https://img.shields.io/badge/node-%3E%3D20-339933?logo=node.js&logoColor=white)](https://nodejs.org/)
12
+ [![types](https://img.shields.io/badge/types-included-blue)](./dist/index.d.ts)
8
13
  ![runtime deps](https://img.shields.io/badge/runtime%20deps-0-brightgreen)
9
14
  ![esm+cjs](https://img.shields.io/badge/ESM%20%2B%20CJS-compatible-blue)
15
+ [![license](https://img.shields.io/badge/license-MIT-green)](./LICENSE)
10
16
 
11
- Modern **zero-dependency** X25519 + Ed25519 for Node.js using OpenSSL via `node:crypto`.
12
-
13
- - **Node:** `>= 20`
14
- - **Runtime deps:** `0`
15
- - **TypeScript:** `strict`, **ESM-first**
16
- - **Compat:** ESM + CJS (`import` e `require`)
17
-
18
- ---
19
-
20
- ## Why
21
-
22
- O projeto original ([curve25519-js](https://github.com/harveyconnor/curve25519-js)) faz aritmética de campo manual em `Float64Array` (derivado de TweetNaCl) para Curve25519/Ed25519.
23
-
24
- Este pacote troca isso por primitivas nativas do OpenSSL (via `node:crypto`), com foco em:
25
-
26
- - **segurança** por implementação consolidada
27
- - **performance** melhor em Node moderno
28
- - **API pequena** e **bem tipada**
29
-
30
- ---
31
-
32
- ## Compatibility notes (importante)
33
-
34
- Este pacote **não replica o esquema `axlsign`** do `curve25519-js`.
35
-
36
- Aqui a API é **padrão moderna**:
37
-
38
- - acordo de chave: **X25519**
39
- - assinatura: **Ed25519**
40
-
41
- Consequências:
42
-
43
- - Chaves de X25519 e Ed25519 são **diferentes** (public keys diferentes).
44
- - `sign`/`verify` usam chaves **Ed25519**.
45
- - Conversão X25519 public key ↔ Ed25519 public key **não é exposta** por `node:crypto`.
46
- - `opt_random` (64 bytes) do legado **não é suportado** em Ed25519 com `node:crypto`.
47
- - O compat layer aceita um 3º argumento apenas por compatibilidade de chamada, mas **sempre lança erro** se ele for fornecido.
48
- - As assinaturas Ed25519 aqui são determinísticas (comportamento padrão do OpenSSL para Ed25519).
49
- - No legado, `openMessage` pode alterar o `signedMsg` recebido (bit de sinal); nesta implementação, as entradas não são modificadas.
17
+ - Node: `>= 20`
18
+ - Dependências de runtime: `0`
19
+ - TypeScript: `strict`
20
+ - Formatos de módulo: ESM + CJS
50
21
 
51
22
  ---
52
23
 
53
- ## Install
24
+ ## Instalação
54
25
 
55
26
  ```bash
56
27
  npm i @unknownncat/curve25519-node
@@ -58,152 +29,206 @@ npm i @unknownncat/curve25519-node
58
29
 
59
30
  ---
60
31
 
61
- ## Usage
62
-
63
- ### ESM (TypeScript / Node moderno)
32
+ ## Uso Rápido
64
33
 
65
34
  ```ts
66
- import {
67
- asBytes32,
68
- x25519,
69
- ed25519,
70
- sign, // compat top-level (Ed25519)
71
- verify, // compat top-level (Ed25519)
72
- } from "@unknownncat/curve25519-node";
35
+ import { randomBytes } from "node:crypto";
36
+ import { asBytes32, x25519, ed25519 } from "@unknownncat/curve25519-node";
73
37
 
74
- const aliceSeed = asBytes32(crypto.getRandomValues(new Uint8Array(32)));
75
- const bobSeed = asBytes32(crypto.getRandomValues(new Uint8Array(32)));
38
+ const aliceSeed = asBytes32(randomBytes(32));
39
+ const bobSeed = asBytes32(randomBytes(32));
76
40
 
77
41
  const aliceX = x25519.generateKeyPair(aliceSeed);
78
42
  const bobX = x25519.generateKeyPair(bobSeed);
79
43
 
80
- const s1 = x25519.sharedKey(aliceX.private, bobX.public);
81
- const s2 = x25519.sharedKey(bobX.private, aliceX.public);
82
- // s1 e s2 devem ser iguais
83
-
84
- const signerSeed = asBytes32(crypto.getRandomValues(new Uint8Array(32)));
85
- const ed = ed25519.generateKeyPair(signerSeed);
44
+ const segredo1 = x25519.sharedKey(aliceX.private, bobX.public);
45
+ const segredo2 = x25519.sharedKey(bobX.private, aliceX.public);
46
+ // segredo1 === segredo2
86
47
 
48
+ const signerSeed = asBytes32(randomBytes(32));
49
+ const signer = ed25519.generateKeyPair(signerSeed);
87
50
  const msg = new TextEncoder().encode("hello");
88
51
 
89
52
  const sig = ed25519.sign(signerSeed, msg);
90
- const ok = verify(ed.public, msg, sig);
91
-
92
- const signedMsg = ed25519.signMessage(signerSeed, msg);
93
- const opened = ed25519.openMessage(ed.public, signedMsg);
53
+ const ok = ed25519.verify(signer.public, msg, sig);
94
54
  ```
95
55
 
96
- ### CommonJS
56
+ CommonJS:
97
57
 
98
58
  ```js
99
59
  const { x25519, ed25519, asBytes32 } = require("@unknownncat/curve25519-node");
100
-
101
- const seed = asBytes32(new Uint8Array(32));
102
- const kp = x25519.generateKeyPair(seed);
103
-
104
- const sig = ed25519.sign(seed, Buffer.from("hello"));
105
60
  ```
106
61
 
107
- ### Subpath imports (opcional)
62
+ Legado axlsign via WASM:
108
63
 
109
64
  ```ts
110
- import { generateKeyPair as xGenerateKeyPair, sharedKey } from "@unknownncat/curve25519-node/x25519";
111
- import { sign, verify } from "@unknownncat/curve25519-node/ed25519";
112
- import type { Bytes32, Bytes64 } from "@unknownncat/curve25519-node/types";
65
+ import { asBytes32, axlsign } from "@unknownncat/curve25519-node";
66
+
67
+ const seed = asBytes32(new Uint8Array(32));
68
+ const kp = axlsign.generateKeyPair(seed); // X25519 keypair compatível com curve25519-js
69
+ const sig = axlsign.sign(
70
+ kp.private,
71
+ new TextEncoder().encode("hello"),
72
+ new Uint8Array(64),
73
+ );
74
+ const ok = axlsign.verify(kp.public, new TextEncoder().encode("hello"), sig);
113
75
  ```
114
76
 
115
77
  ---
116
78
 
117
79
  ## API
118
80
 
119
- ### Namespace `x25519`
81
+ ### `x25519`
120
82
 
121
83
  - `publicKey(secretKey32: Bytes32): Bytes32`
122
84
  - `sharedKey(secretKey32: Bytes32, publicKey32: Bytes32): Bytes32`
123
85
  - `generateKeyPair(seed32: Bytes32): { public: Bytes32; private: Bytes32 }`
124
86
 
125
- ### Namespace `ed25519`
87
+ ### `ed25519`
126
88
 
127
89
  - `publicKey(secretSeed32: Bytes32): Bytes32`
128
90
  - `generateKeyPair(seed32: Bytes32): { public: Bytes32; private: Bytes32 }`
129
91
  - `sign(secretSeed32: Bytes32, msg: Uint8Array): Bytes64`
130
92
  - `verify(publicKey32: Bytes32, msg: Uint8Array, signature64: Bytes64): boolean`
131
- - `signMessage(secretSeed32: Bytes32, msg: Uint8Array): Uint8Array`
93
+ - `signMessage(secretSeed32: Bytes32, msg: Uint8Array): Uint8Array` (`assinatura || mensagem`)
132
94
  - `openMessage(publicKey32: Bytes32, signedMsg: Uint8Array): Uint8Array | null`
133
95
 
134
- ### Top-level compat layer
96
+ ### `axlsign` (compatibilidade legado, via WASM)
97
+
98
+ - `publicKey(secretKey32: Bytes32): Bytes32`
99
+ - `sharedKey(secretKey32: Bytes32, publicKey32: Bytes32): Bytes32`
100
+ - `generateKeyPair(seed32: Bytes32): { public: Bytes32; private: Bytes32 }`
101
+ - `sign(secretKey32: Bytes32, msg: Uint8Array, opt_random?: Bytes64): Bytes64`
102
+ - `verify(publicKey32: Bytes32, msg: Uint8Array, signature64: Bytes64): boolean`
103
+ - `signMessage(secretKey32: Bytes32, msg: Uint8Array, opt_random?: Bytes64): Uint8Array`
104
+ - `openMessage(publicKey32: Bytes32, signedMsg: Uint8Array): Uint8Array | null`
105
+
106
+ ### Aliases de compatibilidade (top-level)
135
107
 
136
108
  - `sharedKey = x25519.sharedKey`
137
109
  - `generateKeyPair = x25519.generateKeyPair`
138
- - `sign`, `verify`, `signMessage`, `openMessage` (**Ed25519**)
110
+ - `sign`, `verify`, `signMessage`, `openMessage` (semântica Ed25519)
139
111
  - `generateKeyPairX25519`, `generateKeyPairEd25519`
140
112
 
141
- > `sign` e `signMessage` aceitam um terceiro argumento opcional **apenas para compatibilidade de chamada**, mas **sempre lançam erro** se ele for fornecido (`opt_random` legado não suportado).
113
+ ---
114
+
115
+ ## Notas de Compatibilidade
116
+
117
+ Este pacote suporta dois modos:
118
+
119
+ - **moderno (recomendado):** `x25519` + `ed25519` via `node:crypto`
120
+ - **legado:** `axlsign` via WASM para compatibilidade com `curve25519-js`
121
+
122
+ | Recurso | `curve25519-js` | `curve25519-node` |
123
+ | ----------------------------------- | --------------- | -------------------------------------------- |
124
+ | Esquema de assinatura (moderno) | axlsign | Ed25519 (padrão) |
125
+ | Esquema de assinatura (legado) | axlsign | axlsign (namespace `axlsign`) |
126
+ | Acordo de chave | X25519 | X25519 |
127
+ | Mesma chave para assinatura + ECDH | sim | apenas no namespace `axlsign` |
128
+ | `opt_random` nas APIs de assinatura | sim | sim no `axlsign`, não no top-level/`ed25519` |
129
+ | Backend OpenSSL | não | sim |
130
+
131
+ Importante:
132
+
133
+ - Chaves públicas X25519 e Ed25519 são diferentes.
134
+ - `node:crypto` não expõe API para converter public key X25519 ↔ Ed25519.
135
+ - Top-level `sign`/`signMessage` e namespace `ed25519` continuam com semântica Ed25519 e rejeitam `opt_random`.
136
+ - Para compatibilidade com `curve25519-js` (incluindo `opt_random`), use o namespace `axlsign`.
137
+ - Assinaturas Ed25519 continuam determinísticas (comportamento padrão do OpenSSL).
142
138
 
143
139
  ---
144
140
 
145
- ## Branded types
141
+ ## Motivação
142
+
143
+ O `curve25519-js` é um projeto importante, mas usa aritmética de campo manual em JS (`Float64Array`, estilo TweetNaCl).
144
+
145
+ Este pacote foca em Node moderno com primitivas do OpenSSL:
146
+
147
+ - caminho de implementação mais seguro
148
+ - melhor desempenho em Node >= 20
149
+ - API menor e explícita
150
+ - tipagem forte com zero dependências de runtime
151
+
152
+ Além disso, o namespace `axlsign` via WASM permite migração progressiva de código legado sem reintroduzir aritmética de curva em JavaScript puro.
153
+
154
+ ---
155
+
156
+ ## Tipos Branded
146
157
 
147
158
  - `Bytes32`
148
159
  - `Bytes64`
149
160
 
150
- Helpers:
161
+ Helpers (validam sem copiar):
151
162
 
152
163
  - `asBytes32(u8)`
153
164
  - `asBytes64(u8)`
154
165
 
155
- ✅ Os helpers validam tamanho e retornam o **mesmo objeto** (sem cópia).
156
-
157
166
  ---
158
167
 
159
- ## Technical details (RFC 8410 DER)
168
+ ## Mapa de RFCs (uso no projeto)
160
169
 
161
- Prefixos usados para importar/exportar RAW(32) `KeyObject` via DER prealocado:
170
+ | RFC | Seções usadas | Uso no projeto | Onde no código |
171
+ | --------------------------------- | ------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------- |
172
+ | RFC 7748 (X25519) | Seção 5 (`The X25519 and X448 Functions`) | Regras de clamping/decoding do escalar e comportamento da função X25519 (zera 3 bits baixos, zera bit mais alto, seta o segundo bit mais alto). | `src/x25519.ts` |
173
+ | RFC 7748 (X25519) | Seção 5.2 (`Test Vectors`), Seção 6.1 (`Diffie-Hellman / Curve25519`) | Vetores oficiais para validação de interoperabilidade e corretude. | `test/x25519.test.mjs` |
174
+ | RFC 8032 (Ed25519) | Seção 5.1.5 (`Key Generation`), 5.1.6 (`Sign`), 5.1.7 (`Verify`) | Semântica de keygen/sign/verify Ed25519 (executada por OpenSSL via `node:crypto`). | `src/ed25519.ts` |
175
+ | RFC 8032 (Ed25519) | Seção 7.1 (`Test Vectors for Ed25519`) | Vetores determinísticos para validação de chave pública e assinatura. | `test/ed25519.test.mjs` |
176
+ | RFC 8410 (X25519/Ed25519 em PKIX) | Seção 3 (identificadores de algoritmo), Seção 4 (`Subject Public Key Fields`), Seção 7 (`Private Key Format`) | Estrutura DER para import/export de chaves raw de 32 bytes em SPKI/PKCS#8 com OIDs de X25519 e Ed25519. | `src/internal/der.ts` |
162
177
 
163
- - X25519 PKCS#8 prefix: `302e020100300506032b656e04220420`
164
- - X25519 SPKI prefix: `302a300506032b656e032100`
165
- - Ed25519 PKCS#8 prefix: `302e020100300506032b657004220420`
166
- - Ed25519 SPKI prefix: `302a300506032b6570032100`
178
+ Referências indiretas por estrutura ASN.1/PKIX:
167
179
 
168
- As operações usam buffers DER prealocados + `.set`, sem loops byte-a-byte.
180
+ - RFC 5958 (OneAsymmetricKey / família PKCS#8)
181
+ - RFC 5280, Seção 4.1.2.7 (`Subject Public Key Info`)
169
182
 
170
- ---
183
+ Observações:
171
184
 
172
- ## Performance notes
185
+ - O projeto não reimplementa aritmética de curva em JS; as operações criptográficas usam OpenSSL via `node:crypto`.
186
+ - A suíte de testes cobre vetores oficiais do RFC 7748 e RFC 8032.
173
187
 
174
- - Sem `Buffer.concat` no hot path; buffers montados por prealloc + `.set`.
175
- - `Uint8Array` → `Buffer` usa view zero-copy:
176
- - `Buffer.from(u8.buffer, u8.byteOffset, u8.byteLength)`
188
+ Rodar testes:
177
189
 
178
- - `signMessage` monta `signature || msg` com `Uint8Array` prealocado e `.set`.
179
- - Para throughput máximo em loops longos, considere cachear `KeyObject` no nível da aplicação (evita parse ASN.1 repetido).
190
+ ```bash
191
+ npm test
192
+ ```
180
193
 
181
194
  ---
182
195
 
183
- ## Security
196
+ ## Detalhes Técnicos (DER / RFC 8410)
197
+
198
+ Chaves raw de 32 bytes são importadas/exportadas com prefixos fixos:
199
+
200
+ - X25519 PKCS#8: `302e020100300506032b656e04220420`
201
+ - X25519 SPKI: `302a300506032b656e032100`
202
+ - Ed25519 PKCS#8: `302e020100300506032b657004220420`
203
+ - Ed25519 SPKI: `302a300506032b6570032100`
184
204
 
185
- - Validação de tipo/tamanho em todas as entradas públicas.
186
- - Sem logs de segredo.
187
- - Comparações internas de DER prefix usam `timingSafeEqual`.
205
+ Notas de implementação:
206
+
207
+ - buffers prealocados + `.set`
208
+ - views zero-copy de `Uint8Array` quando seguro
209
+ - sem `Buffer.concat` em hot path
188
210
 
189
211
  ---
190
212
 
191
- ## Tests
213
+ ## Notas de Performance
192
214
 
193
- ```bash
194
- npm test
195
- ```
215
+ - Evita cópias desnecessárias de bytes nos caminhos críticos.
216
+ - `signMessage` monta `assinatura || mensagem` com um único `Uint8Array` prealocado.
217
+ - Para throughput máximo em loops longos, cache de `KeyObject` no nível da aplicação reduz overhead de parse ASN.1.
218
+
219
+ ---
196
220
 
197
- Cobertura inclui vetores RFC:
221
+ ## Notas de Segurança
198
222
 
199
- - X25519: RFC 7748
200
- - Ed25519: RFC 8032
223
+ - validação estrita de tipo/tamanho nas APIs públicas
224
+ - sem log de segredos
225
+ - `timingSafeEqual` em comparações internas de tamanho fixo quando necessário
201
226
 
202
227
  ---
203
228
 
204
229
  ## Benchmarks
205
230
 
206
- um subprojeto isolado em `bench/` para comparar este pacote com `curve25519-js` sem adicionar dependências ao pacote principal.
231
+ A suíte de benchmark fica isolada em `bench/` (subprojeto separado) e compara com `curve25519-js`.
207
232
 
208
233
  ```bash
209
234
  npm run build
@@ -212,14 +237,96 @@ npm install
212
237
  npm run bench
213
238
  ```
214
239
 
240
+ ### Snapshot real de benchmark (`npm run bench:ci`) no GitHub Codespaces
241
+
242
+ Comando:
243
+
244
+ ```bash
245
+ node --expose-gc bench.mjs --rounds=16 --roundMs=350 --warmupMs=500 --vectors=64 --variants=raw,cached --strict --verifyEvery=64 --jsonFile=results/bench-results.json
246
+ ```
247
+
248
+ Ambiente:
249
+
250
+ - Node: `v24.11.1`
251
+ - OpenSSL: `3.5.4`
252
+ - CPU: `AMD EPYC 7763 64-Core Processor`
253
+ - Cores lógicos: `4`
254
+ - Vetores: `64`
255
+
256
+ ### Tabela 1 - API moderna (`x25519` + `ed25519`)
257
+
258
+ `sign`/`verify` abaixo comparam throughput de API, não equivalência criptográfica (Ed25519 vs axlsign legado).
259
+
260
+ | Operação | Moderno raw | Legado raw (`curve25519-js`) | Speedup raw | Moderno cached | Legado cached (`curve25519-js`) | Speedup cached |
261
+ | ------------------------------ | ----------: | ---------------------------: | ----------: | -------------: | ------------------------------: | -------------: |
262
+ | `x25519.generateKeyPair` | 14,378 | 1,591 | 9.04x | 41,120 | 1,478 | 27.83x |
263
+ | `x25519.sharedKey` | 9,970 | 1,591 | 6.27x | 23,995 | 1,554 | 15.44x |
264
+ | `ed25519.sign (msg32)` | 11,273 | 143 | 78.95x | 23,696 | 133 | 178.10x |
265
+ | `ed25519.sign (msg1024)` | 10,800 | 138 | 78.07x | 22,502 | 147 | 152.92x |
266
+ | `ed25519.verify (msg32)` | 7,280 | 136 | 53.36x | 8,271 | 155 | 53.37x |
267
+ | `ed25519.verify (msg1024)` | 7,160 | 132 | 54.33x | 8,159 | 154 | 52.90x |
268
+ | `ed25519.signMessage (msg256)` | 10,624 | 131 | 81.09x | 23,304 | 148 | 156.97x |
269
+ | `ed25519.openMessage (msg256)` | 6,574 | 124 | 52.93x | 8,129 | 154 | 52.64x |
270
+
271
+ ### Tabela 2 - Compatibilidade `axlsign` (equivalente ao `curve25519-js`)
272
+
273
+ Aqui a comparação é de mesmo esquema criptográfico (equivalência + throughput).
274
+
275
+ | Operação | Moderno raw | Legado raw (`curve25519-js`) | Speedup raw | Moderno cached | Legado cached (`curve25519-js`) | Speedup cached |
276
+ | ----------------------------------------- | ----------: | ---------------------------: | ----------: | -------------: | ------------------------------: | -------------: |
277
+ | `axlsign.generateKeyPair` | 8,429 | 1,583 | 5.33x | 8,384 | 1,585 | 5.29x |
278
+ | `axlsign.sharedKey` | 8,452 | 1,583 | 5.34x | 8,396 | 1,570 | 5.35x |
279
+ | `axlsign.sign (msg32)` | 3,973 | 144 | 27.61x | 3,952 | 140 | 28.28x |
280
+ | `axlsign.sign (msg32,opt_random)` | 3,969 | 147 | 27.03x | 3,984 | 139 | 28.58x |
281
+ | `axlsign.sign (msg1024)` | 3,881 | 143 | 27.16x | 3,864 | 139 | 27.72x |
282
+ | `axlsign.verify (msg32)` | 6,527 | 146 | 44.70x | 6,534 | 143 | 45.72x |
283
+ | `axlsign.verify (msg32,opt_random)` | 6,506 | 144 | 45.07x | 6,469 | 141 | 45.80x |
284
+ | `axlsign.verify (msg1024)` | 6,361 | 141 | 45.03x | 6,337 | 135 | 46.92x |
285
+ | `axlsign.signMessage (msg256)` | 3,902 | 140 | 27.79x | 3,935 | 141 | 27.98x |
286
+ | `axlsign.signMessage (msg256,opt_random)` | 3,885 | 142 | 27.40x | 3,864 | 145 | 26.60x |
287
+ | `axlsign.openMessage (msg256)` | 6,441 | 138 | 46.57x | 6,300 | 131 | 47.93x |
288
+ | `axlsign.openMessage (msg256,opt_random)` | 6,362 | 141 | 45.24x | 6,285 | 130 | 48.22x |
289
+
290
+ Notas:
291
+
292
+ - `raw` inclui custo fim-a-fim da API.
293
+ - `cached` reduz overhead de setup para evidenciar melhor o throughput criptográfico.
294
+ - Fonte dos números: saída JSON de `bench:ci` (`results/bench-results.json`).
295
+
215
296
  ---
216
297
 
217
- ## License
298
+ ## Build do namespace `axlsign`
299
+
300
+ No pacote publicado no npm, os artefatos WASM já vêm prontos em `dist/`.
301
+
302
+ Para buildar a partir do código-fonte, você precisa:
303
+
304
+ - Rust toolchain
305
+ - `wasm-pack` instalado
218
306
 
219
- MIT © unknownncat veja [LICENSE](./LICENSE)
307
+ Com isso, `npm run build` executa:
308
+
309
+ 1. `wasm-pack build` (`wasm/axlsign`)
310
+ 2. `tsc` ESM + CJS
311
+ 3. cópia dos artefatos WASM para `dist/internal/axlsign-wasm`
220
312
 
221
313
  ---
222
314
 
223
- ## Thanks
315
+ ## Licença
316
+
317
+ MIT
318
+
319
+ ---
224
320
 
225
- ❤️ [curve25519-js](https://github.com/harveyconnor/curve25519-js)
321
+ ## Créditos
322
+
323
+ - [curve25519-js](https://github.com/harveyconnor/curve25519-js) (Harvey Connor, Dmitry Chestnykh)
324
+ - [TweetNaCl.js](https://tweetnacl.js.org/)
325
+ - Trevor Perrin, ideia de assinaturas Curve25519: <https://moderncrypto.org/mail-archive/curves/2014/000205.html>
326
+ - [Documentação Node.js `crypto`](https://nodejs.org/api/crypto.html)
327
+ - [OpenSSL](https://www.openssl.org/)
328
+ - [RFC 7748](https://www.rfc-editor.org/rfc/rfc7748)
329
+ - [RFC 8032](https://www.rfc-editor.org/rfc/rfc8032)
330
+ - [RFC 8410](https://www.rfc-editor.org/rfc/rfc8410)
331
+ - [RFC 5958](https://www.rfc-editor.org/rfc/rfc5958)
332
+ - [RFC 5280](https://www.rfc-editor.org/rfc/rfc5280)
@@ -0,0 +1,31 @@
1
+ import type { Bytes32, Bytes64, KeyPair32 } from "./types.js";
2
+ /**
3
+ * Derives an axlsign-compatible public key (Montgomery/X25519 format).
4
+ */
5
+ export declare function publicKey(secretKey32: Bytes32): Bytes32;
6
+ /**
7
+ * Computes an axlsign-compatible X25519 shared key.
8
+ */
9
+ export declare function sharedKey(secretKey32: Bytes32, publicKey32: Bytes32): Bytes32;
10
+ /**
11
+ * Generates an axlsign-compatible key pair from a 32-byte seed.
12
+ */
13
+ export declare function generateKeyPair(seed32: Bytes32): KeyPair32;
14
+ /**
15
+ * Detached axlsign signature using X25519-format secret key.
16
+ * opt_random (64 bytes) enables randomized signing as in curve25519-js.
17
+ */
18
+ export declare function sign(secretKey32: Bytes32, msg: Uint8Array, opt_random?: Uint8Array): Bytes64;
19
+ /**
20
+ * Verifies detached axlsign signature.
21
+ */
22
+ export declare function verify(publicKey32: Bytes32, msg: Uint8Array, signature64: Bytes64): boolean;
23
+ /**
24
+ * Returns signature || message (axlsign mode).
25
+ */
26
+ export declare function signMessage(secretKey32: Bytes32, msg: Uint8Array, opt_random?: Uint8Array): Uint8Array;
27
+ /**
28
+ * Verifies signature || message and returns original message on success.
29
+ */
30
+ export declare function openMessage(publicKey32: Bytes32, signedMsg: Uint8Array): Uint8Array | null;
31
+ //# sourceMappingURL=axlsign.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"axlsign.d.ts","sourceRoot":"","sources":["../src/axlsign.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAiB9D;;GAEG;AACH,wBAAgB,SAAS,CAAC,WAAW,EAAE,OAAO,GAAG,OAAO,CAIvD;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,WAAW,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,GAAG,OAAO,CAK7E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,OAAO,GAAG,SAAS,CAQ1D;AAED;;;GAGG;AACH,wBAAgB,IAAI,CAAC,WAAW,EAAE,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,UAAU,CAAC,EAAE,UAAU,GAAG,OAAO,CAU5F;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,WAAW,EAAE,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,WAAW,EAAE,OAAO,GAAG,OAAO,CAK3F;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,WAAW,EAAE,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,UAAU,CAAC,EAAE,UAAU,GAAG,UAAU,CAUtG;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,GAAG,UAAU,GAAG,IAAI,CAe1F"}
@@ -0,0 +1,96 @@
1
+ import { asBytes32, asBytes64, assertBytes32, assertBytes64, assertUint8Array } from "./internal/assert.js";
2
+ import * as wasmAxl from "./internal/axlsign-wasm/axlsign_wasm.js";
3
+ function clampScalar(seed32) {
4
+ const out = new Uint8Array(32);
5
+ out.set(seed32);
6
+ out[0] = (out[0] ?? 0) & 248;
7
+ const last = out[31] ?? 0;
8
+ out[31] = (last & 127) | 64;
9
+ return asBytes32(out, "clamped scalar");
10
+ }
11
+ function assertOptionalRandom64(value, fnName) {
12
+ if (value === undefined)
13
+ return;
14
+ assertBytes64(value, `${fnName} opt_random`);
15
+ }
16
+ /**
17
+ * Derives an axlsign-compatible public key (Montgomery/X25519 format).
18
+ */
19
+ export function publicKey(secretKey32) {
20
+ assertBytes32(secretKey32, "secretKey32");
21
+ const out = wasmAxl.axlsignPublicKey(secretKey32);
22
+ return asBytes32(out, "axlsign public key");
23
+ }
24
+ /**
25
+ * Computes an axlsign-compatible X25519 shared key.
26
+ */
27
+ export function sharedKey(secretKey32, publicKey32) {
28
+ assertBytes32(secretKey32, "secretKey32");
29
+ assertBytes32(publicKey32, "publicKey32");
30
+ const out = wasmAxl.axlsignSharedKey(secretKey32, publicKey32);
31
+ return asBytes32(out, "axlsign shared key");
32
+ }
33
+ /**
34
+ * Generates an axlsign-compatible key pair from a 32-byte seed.
35
+ */
36
+ export function generateKeyPair(seed32) {
37
+ assertBytes32(seed32, "seed32");
38
+ const privateKey = clampScalar(seed32);
39
+ const publicKey32 = publicKey(privateKey);
40
+ return {
41
+ public: publicKey32,
42
+ private: privateKey,
43
+ };
44
+ }
45
+ /**
46
+ * Detached axlsign signature using X25519-format secret key.
47
+ * opt_random (64 bytes) enables randomized signing as in curve25519-js.
48
+ */
49
+ export function sign(secretKey32, msg, opt_random) {
50
+ assertBytes32(secretKey32, "secretKey32");
51
+ assertUint8Array(msg, "msg");
52
+ assertOptionalRandom64(opt_random, "sign");
53
+ const signature = opt_random === undefined
54
+ ? wasmAxl.axlsignSign(secretKey32, msg)
55
+ : wasmAxl.axlsignSignRnd(secretKey32, msg, opt_random);
56
+ return asBytes64(signature, "axlsign signature");
57
+ }
58
+ /**
59
+ * Verifies detached axlsign signature.
60
+ */
61
+ export function verify(publicKey32, msg, signature64) {
62
+ assertBytes32(publicKey32, "publicKey32");
63
+ assertUint8Array(msg, "msg");
64
+ assertBytes64(signature64, "signature64");
65
+ return wasmAxl.axlsignVerify(publicKey32, msg, signature64);
66
+ }
67
+ /**
68
+ * Returns signature || message (axlsign mode).
69
+ */
70
+ export function signMessage(secretKey32, msg, opt_random) {
71
+ assertBytes32(secretKey32, "secretKey32");
72
+ assertUint8Array(msg, "msg");
73
+ assertOptionalRandom64(opt_random, "signMessage");
74
+ const signature = sign(secretKey32, msg, opt_random);
75
+ const out = new Uint8Array(64 + msg.byteLength);
76
+ out.set(signature, 0);
77
+ out.set(msg, 64);
78
+ return out;
79
+ }
80
+ /**
81
+ * Verifies signature || message and returns original message on success.
82
+ */
83
+ export function openMessage(publicKey32, signedMsg) {
84
+ assertBytes32(publicKey32, "publicKey32");
85
+ assertUint8Array(signedMsg, "signedMsg");
86
+ if (signedMsg.byteLength < 64) {
87
+ return null;
88
+ }
89
+ const signature64 = asBytes64(signedMsg.subarray(0, 64), "signedMsg signature");
90
+ const msg = signedMsg.subarray(64);
91
+ if (!verify(publicKey32, msg, signature64)) {
92
+ return null;
93
+ }
94
+ return new Uint8Array(msg);
95
+ }
96
+ //# sourceMappingURL=axlsign.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"axlsign.js","sourceRoot":"","sources":["../src/axlsign.ts"],"names":[],"mappings":"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"}