@purecore/one-jwt-4-all 1.2.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/CHANGELOG.md +87 -0
- package/LICENSE-COGFULNESS +117 -0
- package/examples/MTLS_AGENTS.md +288 -0
- package/examples/SELF_HEALING_AGENTS.md +269 -0
- package/examples/SIGNAL_E2EE.md +457 -0
- package/examples/mtls-agents.ts +539 -0
- package/examples/self-healing-agents.ts +355 -0
- package/examples/signal-e2ee-agents.ts +827 -0
- package/package.json +20 -0
- package/readme.md +507 -0
- package/reports/22-12-2024_01-50.md +165 -0
- package/src/examples.mcps.ts +86 -0
- package/src/examples.ts +81 -0
- package/src/index.ts +286 -0
- package/tsconfig.json +24 -0
package/package.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@purecore/one-jwt-4-all",
|
|
3
|
+
"version": "1.2.0",
|
|
4
|
+
"main": "index.js",
|
|
5
|
+
"dependencies": {
|
|
6
|
+
"@types/node": "^25.0.3",
|
|
7
|
+
"undici-types": "^7.16.0"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
11
|
+
"build": "bun build src/index.ts --outdir dist --target node"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [],
|
|
14
|
+
"author": "suissAI",
|
|
15
|
+
"license": "CEL",
|
|
16
|
+
"description": "One JWT FTW is a library for validating and verifying JSON Web Tokens (JWT) using always the newest and more secure native cryptographic algorithm.",
|
|
17
|
+
"engines": {
|
|
18
|
+
"node": ">=18.0.0"
|
|
19
|
+
}
|
|
20
|
+
}
|
package/readme.md
ADDED
|
@@ -0,0 +1,507 @@
|
|
|
1
|
+
# 🔐 @purecore/one-jwt-4-all
|
|
2
|
+
|
|
3
|
+
<img src="https://i.imgur.com/39I2vIJ.png" align="center" />
|
|
4
|
+
|
|
5
|
+
> **A Biblioteca one-jwt-4-all com Zero Dependências**
|
|
6
|
+
|
|
7
|
+
Uma biblioteca moderna e opinativa para criação e validação de JSON Web Tokens (JWT) usando exclusivamente algoritmos state-of-the-art. API compatível com `jose`, mas com uma filosofia radicalmente diferente: **Opinião Forte**.
|
|
8
|
+
|
|
9
|
+
## 🎯 Filosofia "One JWT 4 ALL"
|
|
10
|
+
|
|
11
|
+
Enquanto outras bibliotecas suportam centenas de combinações de algoritmos (muitos deles inseguros ou obsoletos), nós suportamos **apenas uma combinação para cada caso de uso**. Essa combinação é escolhida com base no que há de mais seguro e performático na versão LTS mais recente do Node.js.
|
|
12
|
+
|
|
13
|
+
### Por que EdDSA (Ed25519)?
|
|
14
|
+
|
|
15
|
+
- ⚡ **Mais rápido** que ECDSA e RSA
|
|
16
|
+
- 🔑 **Chaves menores** que RSA (256 bits vs 2048+ bits)
|
|
17
|
+
- 🛡️ **Imune a ataques** de timing e side-channels comuns
|
|
18
|
+
- 📦 **Suporte nativo** no Node.js 18+ (sem dependências externas)
|
|
19
|
+
- ✅ **Padrão moderno** recomendado por criptógrafos
|
|
20
|
+
|
|
21
|
+
> **"A complexidade é a inimiga da segurança."**
|
|
22
|
+
|
|
23
|
+
## 📊 Comparativo: jose vs Purecore JWTfy
|
|
24
|
+
|
|
25
|
+
| Funcionalidade | Biblioteca jose (Genérica) | Purecore JWTfy (Opinativa) |
|
|
26
|
+
|----------------|---------------------------|---------------------------|
|
|
27
|
+
| **Filosofia** | Suportar tudo (Legado & Novo) | Suportar apenas o Melhor (State-of-the-Art) |
|
|
28
|
+
| **JWS Signing Algs** | HS256, RS256, ES256, PS256, EdDSA... | **EdDSA (Ed25519) Apenas** |
|
|
29
|
+
| **JWE Encryption** | RSA-OAEP, A128CBC-HS256, A256GCM... | **X25519 + A256GCM** (Roadmap) |
|
|
30
|
+
| **JWS Serialization** | Compact, Flattened, General | Compact (Core) |
|
|
31
|
+
| **Key Management** | JWK, JWKS (Local/Remote), PEM, X.509 | PEM & JWK (Simples) |
|
|
32
|
+
| **Runtime** | Universal (Browser, Node, Deno, Workers) | **Node.js Nativo** (Foco em Performance) |
|
|
33
|
+
| **Dependências** | Múltiplas | **Zero (0)** |
|
|
34
|
+
|
|
35
|
+
## 🚀 Instalação
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
# Com npm
|
|
39
|
+
npm install @purecore/one-jwt-4-all
|
|
40
|
+
|
|
41
|
+
# Com bun
|
|
42
|
+
bun add @purecore/one-jwt-4-all
|
|
43
|
+
|
|
44
|
+
# Com yarn
|
|
45
|
+
yarn add @purecore/one-jwt-4-all
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## 📖 Uso Básico
|
|
49
|
+
|
|
50
|
+
### 1. Gerar Par de Chaves
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
import { generateKeyPair } from '@purecore/one-jwt-4-all';
|
|
54
|
+
|
|
55
|
+
const { publicKey, privateKey } = generateKeyPair();
|
|
56
|
+
|
|
57
|
+
// Salve as chaves de forma segura
|
|
58
|
+
console.log('Chave Privada:', privateKey);
|
|
59
|
+
console.log('Chave Pública:', publicKey);
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### 2. Criar um Token JWT
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
import { SignJWT } from '@purecore/one-jwt-4-all';
|
|
66
|
+
|
|
67
|
+
// Criar token com builder pattern (estilo jose)
|
|
68
|
+
const jwt = await new SignJWT({
|
|
69
|
+
userId: 123,
|
|
70
|
+
email: 'usuario@exemplo.com',
|
|
71
|
+
role: 'admin'
|
|
72
|
+
})
|
|
73
|
+
.setProtectedHeader({ alg: 'EdDSA', typ: 'JWT' })
|
|
74
|
+
.setIssuedAt()
|
|
75
|
+
.setIssuer('urn:meu-sistema:issuer')
|
|
76
|
+
.setAudience('urn:meu-sistema:audience')
|
|
77
|
+
.setExpirationTime('2h') // Expira em 2 horas
|
|
78
|
+
.setSubject('usuario-123')
|
|
79
|
+
.setJti('token-unique-id')
|
|
80
|
+
.sign(privateKey);
|
|
81
|
+
|
|
82
|
+
console.log('Token gerado:', jwt);
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### 3. Verificar um Token JWT
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
import { jwtVerify } from '@purecore/one-jwt-4-all';
|
|
89
|
+
|
|
90
|
+
try {
|
|
91
|
+
const { payload, protectedHeader } = await jwtVerify(jwt, publicKey, {
|
|
92
|
+
issuer: 'urn:meu-sistema:issuer',
|
|
93
|
+
audience: 'urn:meu-sistema:audience',
|
|
94
|
+
maxTokenAge: '2h' // Opcional: idade máxima do token
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
console.log('Token válido!');
|
|
98
|
+
console.log('Payload:', payload);
|
|
99
|
+
console.log('Header:', protectedHeader);
|
|
100
|
+
} catch (error) {
|
|
101
|
+
console.error('Token inválido:', error.message);
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## 🔧 API Completa
|
|
106
|
+
|
|
107
|
+
### SignJWT (Builder Pattern)
|
|
108
|
+
|
|
109
|
+
#### Métodos Disponíveis
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
new SignJWT(payload: JWTPayload)
|
|
113
|
+
.setProtectedHeader(header: JWTHeaderParameters) // Define o header protegido
|
|
114
|
+
.setIssuer(issuer: string) // Define o emissor (iss)
|
|
115
|
+
.setSubject(subject: string) // Define o assunto (sub)
|
|
116
|
+
.setAudience(audience: string | string[]) // Define a audiência (aud)
|
|
117
|
+
.setJti(jwtId: string) // Define o ID único do token (jti)
|
|
118
|
+
.setIssuedAt(timestamp?: number) // Define quando foi emitido (iat)
|
|
119
|
+
.setExpirationTime(time: number | string) // Define expiração (exp)
|
|
120
|
+
.setNotBefore(time: number | string) // Define quando fica válido (nbf)
|
|
121
|
+
.sign(privateKey: KeyObject | string) // Assina e retorna o token
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
#### Formatos de Tempo Suportados
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
// Strings de duração relativa
|
|
128
|
+
.setExpirationTime('30s') // 30 segundos
|
|
129
|
+
.setExpirationTime('5m') // 5 minutos
|
|
130
|
+
.setExpirationTime('2h') // 2 horas
|
|
131
|
+
.setExpirationTime('1d') // 1 dia
|
|
132
|
+
.setExpirationTime('1w') // 1 semana
|
|
133
|
+
.setExpirationTime('1y') // 1 ano
|
|
134
|
+
|
|
135
|
+
// Timestamp absoluto (Unix timestamp em segundos)
|
|
136
|
+
.setExpirationTime(1735689600)
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### jwtVerify (Função)
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
jwtVerify(
|
|
143
|
+
jwt: string,
|
|
144
|
+
publicKey: KeyObject | string,
|
|
145
|
+
options?: JWTVerifyOptions
|
|
146
|
+
): Promise<JWTVerifyResult>
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
#### Opções de Verificação
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
interface JWTVerifyOptions {
|
|
153
|
+
issuer?: string | string[]; // Valida o emissor (iss)
|
|
154
|
+
audience?: string | string[]; // Valida a audiência (aud)
|
|
155
|
+
algorithms?: string[]; // Lista de algoritmos permitidos (ignorado, sempre EdDSA)
|
|
156
|
+
currentDate?: Date; // Data atual para testes (mock)
|
|
157
|
+
maxTokenAge?: string | number; // Idade máxima do token ('2h' ou segundos)
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## 📝 Exemplos Práticos
|
|
162
|
+
|
|
163
|
+
### Exemplo 1: Autenticação de Usuário
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
import { SignJWT, jwtVerify, generateKeyPair } from '@purecore/one-jwt-4-all';
|
|
167
|
+
|
|
168
|
+
// Gere as chaves uma vez e guarde em variáveis de ambiente
|
|
169
|
+
const { publicKey, privateKey } = generateKeyPair();
|
|
170
|
+
|
|
171
|
+
// Login: Criar token após autenticação bem-sucedida
|
|
172
|
+
async function login(userId: string, email: string) {
|
|
173
|
+
const token = await new SignJWT({
|
|
174
|
+
userId,
|
|
175
|
+
email,
|
|
176
|
+
loginTime: Date.now()
|
|
177
|
+
})
|
|
178
|
+
.setIssuedAt()
|
|
179
|
+
.setIssuer('https://meuapp.com')
|
|
180
|
+
.setAudience('https://meuapp.com/api')
|
|
181
|
+
.setSubject(userId)
|
|
182
|
+
.setExpirationTime('24h')
|
|
183
|
+
.sign(privateKey);
|
|
184
|
+
|
|
185
|
+
return token;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Middleware: Verificar token em requisições
|
|
189
|
+
async function verifyToken(token: string) {
|
|
190
|
+
try {
|
|
191
|
+
const { payload } = await jwtVerify(token, publicKey, {
|
|
192
|
+
issuer: 'https://meuapp.com',
|
|
193
|
+
audience: 'https://meuapp.com/api',
|
|
194
|
+
maxTokenAge: '24h'
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
return payload;
|
|
198
|
+
} catch (error) {
|
|
199
|
+
throw new Error(`Token inválido: ${error.message}`);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Exemplo 2: Refresh Tokens
|
|
205
|
+
|
|
206
|
+
```typescript
|
|
207
|
+
// Access Token (curta duração)
|
|
208
|
+
const accessToken = await new SignJWT({ userId: 123 })
|
|
209
|
+
.setIssuedAt()
|
|
210
|
+
.setExpirationTime('15m') // 15 minutos
|
|
211
|
+
.setIssuer('https://meuapp.com')
|
|
212
|
+
.setAudience('https://meuapp.com/api')
|
|
213
|
+
.sign(privateKey);
|
|
214
|
+
|
|
215
|
+
// Refresh Token (longa duração)
|
|
216
|
+
const refreshToken = await new SignJWT({ userId: 123 })
|
|
217
|
+
.setIssuedAt()
|
|
218
|
+
.setExpirationTime('7d') // 7 dias
|
|
219
|
+
.setIssuer('https://meuapp.com')
|
|
220
|
+
.setAudience('https://meuapp.com/auth/refresh')
|
|
221
|
+
.sign(privateKey);
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Exemplo 3: Tokens com Not Before
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
// Token que só fica válido após 5 minutos
|
|
228
|
+
const token = await new SignJWT({ userId: 123 })
|
|
229
|
+
.setIssuedAt()
|
|
230
|
+
.setNotBefore('5m') // Válido apenas após 5 minutos
|
|
231
|
+
.setExpirationTime('1h')
|
|
232
|
+
.sign(privateKey);
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### Exemplo 4: Integração com Express.js
|
|
236
|
+
|
|
237
|
+
```typescript
|
|
238
|
+
import express from 'express';
|
|
239
|
+
import { jwtVerify } from '@purecore/one-jwt-4-all';
|
|
240
|
+
import { readFileSync } from 'fs';
|
|
241
|
+
|
|
242
|
+
const app = express();
|
|
243
|
+
const publicKey = readFileSync('./public-key.pem', 'utf-8');
|
|
244
|
+
|
|
245
|
+
// Middleware de autenticação
|
|
246
|
+
async function authenticate(req: express.Request, res: express.Response, next: express.NextFunction) {
|
|
247
|
+
const authHeader = req.headers.authorization;
|
|
248
|
+
|
|
249
|
+
if (!authHeader?.startsWith('Bearer ')) {
|
|
250
|
+
return res.status(401).json({ error: 'Token não fornecido' });
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const token = authHeader.substring(7);
|
|
254
|
+
|
|
255
|
+
try {
|
|
256
|
+
const { payload } = await jwtVerify(token, publicKey, {
|
|
257
|
+
issuer: 'https://meuapp.com',
|
|
258
|
+
audience: 'https://meuapp.com/api'
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
req.user = payload;
|
|
262
|
+
next();
|
|
263
|
+
} catch (error) {
|
|
264
|
+
return res.status(401).json({ error: `Token inválido: ${error.message}` });
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Rota protegida
|
|
269
|
+
app.get('/api/protected', authenticate, (req, res) => {
|
|
270
|
+
res.json({
|
|
271
|
+
message: 'Acesso autorizado',
|
|
272
|
+
user: req.user
|
|
273
|
+
});
|
|
274
|
+
});
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
## 🔒 Segurança
|
|
278
|
+
|
|
279
|
+
### Boas Práticas
|
|
280
|
+
|
|
281
|
+
1. **Nunca exponha a chave privada**
|
|
282
|
+
- Guarde em variáveis de ambiente
|
|
283
|
+
- Use serviços de gerenciamento de segredos em produção
|
|
284
|
+
|
|
285
|
+
2. **Use expiração curta para access tokens**
|
|
286
|
+
- Recomendado: 15 minutos a 1 hora
|
|
287
|
+
- Use refresh tokens para renovação
|
|
288
|
+
|
|
289
|
+
3. **Valide sempre issuer e audience**
|
|
290
|
+
- Previne uso de tokens em contextos errados
|
|
291
|
+
- Protege contra token reuse attacks
|
|
292
|
+
|
|
293
|
+
4. **Use HTTPS em produção**
|
|
294
|
+
- Tokens não devem trafegar em conexões não criptografadas
|
|
295
|
+
|
|
296
|
+
5. **Rotacione chaves periodicamente**
|
|
297
|
+
- Gere novos pares de chaves regularmente
|
|
298
|
+
- Mantenha versões antigas para validação durante transição
|
|
299
|
+
|
|
300
|
+
### Gerenciamento de Chaves
|
|
301
|
+
|
|
302
|
+
```typescript
|
|
303
|
+
// Gerar par de chaves
|
|
304
|
+
const { publicKey, privateKey } = generateKeyPair();
|
|
305
|
+
|
|
306
|
+
// Salvar em arquivos (nunca commite no git!)
|
|
307
|
+
import { writeFileSync } from 'fs';
|
|
308
|
+
writeFileSync('./private-key.pem', privateKey, { mode: 0o600 }); // Permissões restritas
|
|
309
|
+
writeFileSync('./public-key.pem', publicKey);
|
|
310
|
+
|
|
311
|
+
// Carregar de arquivos
|
|
312
|
+
import { readFileSync } from 'fs';
|
|
313
|
+
const privateKey = readFileSync('./private-key.pem', 'utf-8');
|
|
314
|
+
const publicKey = readFileSync('./public-key.pem', 'utf-8');
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
## 🧪 Testes
|
|
318
|
+
|
|
319
|
+
```typescript
|
|
320
|
+
import { SignJWT, jwtVerify, generateKeyPair } from '@purecore/one-jwt-4-all';
|
|
321
|
+
|
|
322
|
+
describe('JWT', () => {
|
|
323
|
+
const { publicKey, privateKey } = generateKeyPair();
|
|
324
|
+
|
|
325
|
+
it('deve criar e verificar token válido', async () => {
|
|
326
|
+
const jwt = await new SignJWT({ userId: 123 })
|
|
327
|
+
.setIssuedAt()
|
|
328
|
+
.setExpirationTime('1h')
|
|
329
|
+
.sign(privateKey);
|
|
330
|
+
|
|
331
|
+
const { payload } = await jwtVerify(jwt, publicKey);
|
|
332
|
+
|
|
333
|
+
expect(payload.userId).toBe(123);
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
it('deve rejeitar token expirado', async () => {
|
|
337
|
+
const jwt = await new SignJWT({ userId: 123 })
|
|
338
|
+
.setIssuedAt()
|
|
339
|
+
.setExpirationTime('-1h') // Expirado
|
|
340
|
+
.sign(privateKey);
|
|
341
|
+
|
|
342
|
+
await expect(jwtVerify(jwt, publicKey)).rejects.toThrow('expirado');
|
|
343
|
+
});
|
|
344
|
+
});
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
## 📚 Tipos TypeScript
|
|
348
|
+
|
|
349
|
+
A biblioteca exporta todos os tipos necessários:
|
|
350
|
+
|
|
351
|
+
```typescript
|
|
352
|
+
import type {
|
|
353
|
+
JWTPayload,
|
|
354
|
+
JWTHeaderParameters,
|
|
355
|
+
JWTVerifyResult,
|
|
356
|
+
JWTVerifyOptions
|
|
357
|
+
} from '@purecore/one-jwt-4-all';
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
## 🔄 Exemplos Avançados
|
|
361
|
+
|
|
362
|
+
### 1. Self-Healing Agentic Conversational System
|
|
363
|
+
|
|
364
|
+
Sistema onde dois agentes se identificam usando JWTs do mesmo servidor e regeneram automaticamente seus tokens quando expiram, mantendo a conversa contínua sem interrupção.
|
|
365
|
+
|
|
366
|
+
**Características:**
|
|
367
|
+
- ✅ **Auto-Renovação**: Tokens renovados automaticamente antes de expirar
|
|
368
|
+
- ✅ **Contexto Preservado**: Conversa continua mesmo após renovação
|
|
369
|
+
- ✅ **Verificação Mútua**: Agentes verificam identidade uns dos outros
|
|
370
|
+
- ✅ **Self-Healing**: Sistema se recupera automaticamente de falhas
|
|
371
|
+
|
|
372
|
+
**Exemplo Rápido:**
|
|
373
|
+
```typescript
|
|
374
|
+
import { TokenAuthority, SelfHealingAgent } from './examples/self-healing-agents';
|
|
375
|
+
|
|
376
|
+
const authority = new TokenAuthority();
|
|
377
|
+
const agentA = new SelfHealingAgent('agent-alpha', 'primary', authority);
|
|
378
|
+
const agentB = new SelfHealingAgent('agent-beta', 'secondary', authority);
|
|
379
|
+
|
|
380
|
+
await agentA.initialize();
|
|
381
|
+
await agentB.initialize();
|
|
382
|
+
agentA.startAutoRenewal(30000);
|
|
383
|
+
agentB.startAutoRenewal(30000);
|
|
384
|
+
|
|
385
|
+
await agentA.sendMessage(agentB, 'Olá! Vamos trabalhar juntos?');
|
|
386
|
+
await agentB.sendMessage(agentA, 'Perfeito! Estou pronto.');
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
📖 **Documentação**: [examples/SELF_HEALING_AGENTS.md](examples/SELF_HEALING_AGENTS.md)
|
|
390
|
+
|
|
391
|
+
### 2. Self-Healing Agents com mTLS (Mutual TLS)
|
|
392
|
+
|
|
393
|
+
Extensão do sistema anterior que adiciona **mTLS** para segurança em duas camadas: transporte (certificados) + aplicação (JWT).
|
|
394
|
+
|
|
395
|
+
**Características:**
|
|
396
|
+
- 🔒 **mTLS**: Autenticação mútua via certificados X.509
|
|
397
|
+
- 🔐 **JWT**: Autenticação de identidade e contexto
|
|
398
|
+
- 🛡️ **Prevenção MITM**: Certificados validam identidade do transporte
|
|
399
|
+
- 🔄 **Self-Healing**: Auto-renovação de tokens mantendo conexão mTLS
|
|
400
|
+
|
|
401
|
+
**Exemplo Rápido:**
|
|
402
|
+
```typescript
|
|
403
|
+
import { mTLSAgent, CertificateAuthority, TokenAuthority } from './examples/mtls-agents';
|
|
404
|
+
|
|
405
|
+
const ca = new CertificateAuthority();
|
|
406
|
+
const tokenAuthority = new TokenAuthority();
|
|
407
|
+
|
|
408
|
+
const certA = ca.generateAgentCertificate('agent-alpha');
|
|
409
|
+
const certB = ca.generateAgentCertificate('agent-beta');
|
|
410
|
+
const caCert = ca.getCACertificate();
|
|
411
|
+
|
|
412
|
+
const agentA = new mTLSAgent('agent-alpha', 'primary', tokenAuthority, certA, caCert);
|
|
413
|
+
const agentB = new mTLSAgent('agent-beta', 'secondary', tokenAuthority, certB, caCert);
|
|
414
|
+
|
|
415
|
+
await agentA.initialize();
|
|
416
|
+
await agentB.initialize();
|
|
417
|
+
|
|
418
|
+
await agentA.startTLSServer(8443);
|
|
419
|
+
await agentB.startTLSServer(8444);
|
|
420
|
+
|
|
421
|
+
await agentA.connectToPeer('localhost', 8444, 'agent-beta');
|
|
422
|
+
await agentB.connectToPeer('localhost', 8443, 'agent-alpha');
|
|
423
|
+
|
|
424
|
+
// Comunicação segura via mTLS + JWT
|
|
425
|
+
await agentA.sendMessage('agent-beta', 'Mensagem segura!');
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
📖 **Documentação**: [examples/MTLS_AGENTS.md](examples/MTLS_AGENTS.md)
|
|
429
|
+
|
|
430
|
+
### 3. Signal Protocol E2EE (End-to-End Encryption)
|
|
431
|
+
|
|
432
|
+
Implementação do **Double Ratchet Algorithm** do Signal Protocol para criptografia end-to-end entre agentes com Perfect Forward Secrecy.
|
|
433
|
+
|
|
434
|
+
**Características:**
|
|
435
|
+
- 🔐 **X3DH**: Extended Triple Diffie-Hellman para key agreement
|
|
436
|
+
- 🔄 **Double Ratchet**: Rotação contínua de chaves por mensagem
|
|
437
|
+
- 🛡️ **Perfect Forward Secrecy (PFS)**: Comprometimento não afeta passado
|
|
438
|
+
- 🔓 **Post-Compromise Security (PCS)**: Recuperação após comprometimento
|
|
439
|
+
- 🤫 **Deniability**: Negabilidade criptográfica
|
|
440
|
+
|
|
441
|
+
**Exemplo Rápido:**
|
|
442
|
+
```typescript
|
|
443
|
+
import { SignalE2EEAgent, TokenAuthority } from './examples/signal-e2ee-agents';
|
|
444
|
+
|
|
445
|
+
const tokenAuthority = new TokenAuthority();
|
|
446
|
+
|
|
447
|
+
const alice = new SignalE2EEAgent('alice', tokenAuthority);
|
|
448
|
+
const bob = new SignalE2EEAgent('bob', tokenAuthority);
|
|
449
|
+
|
|
450
|
+
await alice.initialize();
|
|
451
|
+
await bob.initialize();
|
|
452
|
+
|
|
453
|
+
// Trocar bundles públicos
|
|
454
|
+
alice.registerPeerBundle('bob', bob.getPublicKeyBundle());
|
|
455
|
+
bob.registerPeerBundle('alice', alice.getPublicKeyBundle());
|
|
456
|
+
|
|
457
|
+
// Estabelecer sessão E2EE
|
|
458
|
+
await alice.establishSession('bob');
|
|
459
|
+
await bob.acceptSession('alice', alice.getIdentityPublicKey(), alice.getPublicKeyBundle().signedPreKey);
|
|
460
|
+
|
|
461
|
+
// Enviar mensagem encriptada
|
|
462
|
+
const msg = await alice.sendMessage('bob', 'Hello, secure world!');
|
|
463
|
+
const plaintext = await bob.receiveMessage(msg);
|
|
464
|
+
// plaintext = "Hello, secure world!"
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
📖 **Documentação**: [examples/SIGNAL_E2EE.md](examples/SIGNAL_E2EE.md)
|
|
468
|
+
|
|
469
|
+
### 4. Combinando Signal E2EE + mTLS (Defesa em Profundidade)
|
|
470
|
+
|
|
471
|
+
Para máxima segurança, combine ambos os protocolos:
|
|
472
|
+
|
|
473
|
+
| Camada | Protocolo | Proteção |
|
|
474
|
+
|--------|-----------|----------|
|
|
475
|
+
| **Transporte** | mTLS | Anti-MITM, autenticação mútua |
|
|
476
|
+
| **Aplicação** | Signal E2EE | Forward secrecy, conteúdo encriptado |
|
|
477
|
+
| **Contexto** | JWT | Claims, autorização, expiração |
|
|
478
|
+
|
|
479
|
+
📖 **Documentação Completa**: [examples/SIGNAL_E2EE.md#usando-ambos-em-conjunto](examples/SIGNAL_E2EE.md#usando-ambos-em-conjunto)
|
|
480
|
+
|
|
481
|
+
## 🛠️ Requisitos
|
|
482
|
+
|
|
483
|
+
- **Node.js**: >= 18.0.0 (suporte nativo a Ed25519)
|
|
484
|
+
- **TypeScript**: >= 4.0.0 (recomendado)
|
|
485
|
+
|
|
486
|
+
## 📄 Licença
|
|
487
|
+
|
|
488
|
+
Este projeto é licenciado sob a **Cogfulness Ethical License (CEL)** - uma licença open source focada em uso ético e responsável de tecnologia cognitiva.
|
|
489
|
+
|
|
490
|
+
## 🤝 Contribuindo
|
|
491
|
+
|
|
492
|
+
Contribuições são bem-vindas! Este projeto segue uma filosofia de **zero dependencies** e simplicidade arquitetural.
|
|
493
|
+
|
|
494
|
+
## 🔗 Links Úteis
|
|
495
|
+
|
|
496
|
+
- [RFC 7519 - JSON Web Token (JWT)](https://tools.ietf.org/html/rfc7519)
|
|
497
|
+
- [RFC 8037 - Edwards-Curve Digital Signature Algorithm (EdDSA)](https://tools.ietf.org/html/rfc8037)
|
|
498
|
+
- [Node.js Crypto Documentation](https://nodejs.org/api/crypto.html)
|
|
499
|
+
- [JWT.io - Debugger de Tokens](https://jwt.io/)
|
|
500
|
+
|
|
501
|
+
## 📝 Changelog
|
|
502
|
+
|
|
503
|
+
Veja todas as mudanças em [CHANGELOG.md](CHANGELOG.md)
|
|
504
|
+
|
|
505
|
+
---
|
|
506
|
+
|
|
507
|
+
**Desenvolvido com ❤️ para promover segurança através de simplicidade e opiniões fortes.**
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# Relatório: Implementação Signal Protocol E2EE
|
|
2
|
+
|
|
3
|
+
**Data:** 22/12/2024 01:50
|
|
4
|
+
**Projeto:** @purecore/one-jwt-4-all
|
|
5
|
+
**Versão:** v1.2.0
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## O que foi feito
|
|
10
|
+
|
|
11
|
+
### 1. Implementação do Signal Protocol
|
|
12
|
+
|
|
13
|
+
Criado arquivo `examples/signal-e2ee-agents.ts` contendo:
|
|
14
|
+
|
|
15
|
+
- **X3DH Key Agreement**: Implementação do Extended Triple Diffie-Hellman para estabelecimento de sessão segura
|
|
16
|
+
- **Double Ratchet Algorithm**: Rotação contínua de chaves por mensagem
|
|
17
|
+
- **Classe `SignalE2EEAgent`**: Agente com suporte completo a E2EE
|
|
18
|
+
- **Classe `DoubleRatchet`**: State machine do algoritmo
|
|
19
|
+
- **Classe `X3DHKeyBundle`**: Gerenciamento de bundles de chaves
|
|
20
|
+
|
|
21
|
+
### 2. Documentação Completa
|
|
22
|
+
|
|
23
|
+
Criado arquivo `examples/SIGNAL_E2EE.md` contendo:
|
|
24
|
+
|
|
25
|
+
- Explicação do que é Signal Protocol
|
|
26
|
+
- Como o Double Ratchet funciona (com diagramas ASCII)
|
|
27
|
+
- Algoritmos utilizados
|
|
28
|
+
- Propriedades de segurança (PFS, PCS, Deniability)
|
|
29
|
+
- Guia de uso com exemplos de código
|
|
30
|
+
- Comparação detalhada Signal E2EE vs mTLS
|
|
31
|
+
- Guia de como usar ambos em conjunto
|
|
32
|
+
- Referências para especificações oficiais
|
|
33
|
+
|
|
34
|
+
### 3. Atualizações de Projeto
|
|
35
|
+
|
|
36
|
+
- `CHANGELOG.md`: Criado com histórico de versões
|
|
37
|
+
- `readme.md`: Atualizado com seção sobre Signal E2EE
|
|
38
|
+
- `reports/`: Pasta criada para relatórios
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Por que foi feito
|
|
43
|
+
|
|
44
|
+
### Motivação
|
|
45
|
+
|
|
46
|
+
O projeto já possuía implementação de mTLS para segurança de transporte, mas faltava uma opção para criptografia end-to-end que:
|
|
47
|
+
|
|
48
|
+
1. **Protegesse o conteúdo** mesmo de servidores intermediários
|
|
49
|
+
2. **Garantisse Perfect Forward Secrecy** por mensagem (não por sessão)
|
|
50
|
+
3. **Permitisse Post-Compromise Security** para recuperação após comprometimento
|
|
51
|
+
4. **Fosse um padrão reconhecido** na indústria
|
|
52
|
+
|
|
53
|
+
### Solução Escolhida
|
|
54
|
+
|
|
55
|
+
O Signal Protocol foi escolhido por ser:
|
|
56
|
+
|
|
57
|
+
- O padrão-ouro em mensagens seguras
|
|
58
|
+
- Usado por WhatsApp, Signal, Facebook Messenger, etc.
|
|
59
|
+
- Auditado e validado por criptógrafos renomados
|
|
60
|
+
- Documentação pública e bem especificada
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Técnicas Utilizadas
|
|
65
|
+
|
|
66
|
+
### Criptografia
|
|
67
|
+
|
|
68
|
+
| Componente | Algoritmo | Biblioteca |
|
|
69
|
+
|------------|-----------|------------|
|
|
70
|
+
| Key Exchange | X25519 (Curve25519) | Node.js crypto nativo |
|
|
71
|
+
| Key Derivation | HKDF-SHA256 | Node.js crypto nativo |
|
|
72
|
+
| Encryption | AES-256-GCM | Node.js crypto nativo |
|
|
73
|
+
| Message Auth | GCM (AEAD) | Integrado ao AES-GCM |
|
|
74
|
+
| Chain Advance | HMAC-SHA256 | Node.js crypto nativo |
|
|
75
|
+
|
|
76
|
+
### Padrões Implementados
|
|
77
|
+
|
|
78
|
+
1. **X3DH (Extended Triple Diffie-Hellman)**
|
|
79
|
+
- 4 operações DH para shared secret
|
|
80
|
+
- Identity Key, Signed Pre-Key, Ephemeral Key, One-Time Pre-Key
|
|
81
|
+
|
|
82
|
+
2. **Double Ratchet**
|
|
83
|
+
- DH Ratchet para rotação assimétrica
|
|
84
|
+
- Symmetric-key Ratchet para rotação simétrica
|
|
85
|
+
- Suporte a mensagens fora de ordem
|
|
86
|
+
|
|
87
|
+
### Arquitetura
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
91
|
+
│ SignalE2EEAgent │
|
|
92
|
+
├─────────────────────────────────────────────────────────────┤
|
|
93
|
+
│ ┌───────────────┐ ┌───────────────┐ ┌────────────────┐ │
|
|
94
|
+
│ │ X3DHKeyBundle │ │ DoubleRatchet │ │ TokenAuthority │ │
|
|
95
|
+
│ │ │ │ │ │ │ │
|
|
96
|
+
│ │ - Identity │ │ - RK │ │ - JWT signing │ │
|
|
97
|
+
│ │ - SignedPre │ │ - CKs/CKr │ │ - Verification │ │
|
|
98
|
+
│ │ - OneTimePre │ │ - DHs/DHr │ │ │ │
|
|
99
|
+
│ └───────────────┘ └───────────────┘ └────────────────┘ │
|
|
100
|
+
└─────────────────────────────────────────────────────────────┘
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Comparação com mTLS
|
|
106
|
+
|
|
107
|
+
| Aspecto | Signal E2EE | mTLS |
|
|
108
|
+
|---------|-------------|------|
|
|
109
|
+
| Camada | Aplicação | Transporte |
|
|
110
|
+
| Forward Secrecy | Por mensagem | Por sessão |
|
|
111
|
+
| Post-Compromise | ✅ Sim | ❌ Não |
|
|
112
|
+
| Visibilidade servidor | ❌ Não vê conteúdo | ⚠️ Vê conteúdo |
|
|
113
|
+
|
|
114
|
+
**Recomendação**: Usar AMBOS para defesa em profundidade.
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## Fontes de Informação
|
|
119
|
+
|
|
120
|
+
### Especificações Oficiais
|
|
121
|
+
|
|
122
|
+
1. Signal Protocol Double Ratchet (Rev. 4, 2025)
|
|
123
|
+
- https://signal.org/docs/specifications/doubleratchet/
|
|
124
|
+
|
|
125
|
+
2. Signal Protocol X3DH
|
|
126
|
+
- https://signal.org/docs/specifications/x3dh/
|
|
127
|
+
|
|
128
|
+
### Implementações de Referência
|
|
129
|
+
|
|
130
|
+
3. 2key-ratchet (TypeScript)
|
|
131
|
+
- https://github.com/PeculiarVentures/2key-ratchet
|
|
132
|
+
|
|
133
|
+
4. libsignal (Oficial)
|
|
134
|
+
- https://github.com/signalapp/libsignal
|
|
135
|
+
|
|
136
|
+
### RFCs
|
|
137
|
+
|
|
138
|
+
5. RFC 7748 - Elliptic Curves for Security (X25519)
|
|
139
|
+
6. RFC 5869 - HKDF
|
|
140
|
+
7. RFC 8446 - TLS 1.3
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## Arquivos Modificados/Criados
|
|
145
|
+
|
|
146
|
+
| Arquivo | Ação | Linhas |
|
|
147
|
+
|---------|------|--------|
|
|
148
|
+
| `examples/signal-e2ee-agents.ts` | Criado | ~550 |
|
|
149
|
+
| `examples/SIGNAL_E2EE.md` | Criado | ~400 |
|
|
150
|
+
| `CHANGELOG.md` | Criado | ~80 |
|
|
151
|
+
| `readme.md` | Atualizado | +50 |
|
|
152
|
+
| `reports/22-12-2024_01-50.md` | Criado | Este arquivo |
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## Próximos Passos Sugeridos
|
|
157
|
+
|
|
158
|
+
1. **Testes Unitários**: Criar testes para Double Ratchet
|
|
159
|
+
2. **Benchmark**: Comparar performance com outras implementações
|
|
160
|
+
3. **PQXDH**: Adicionar suporte Post-Quantum (ML-KEM)
|
|
161
|
+
4. **Header Encryption**: Implementar opção de encriptar headers
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
*Relatório gerado automaticamente para rastreabilidade do projeto.*
|