Sistema seguro de criptografia de vídeo por chunks usando AES-256-GCM com validações robustas e verificação de integridade
npm install @kitsuneislife/keyring-vcm
bash
npm install @kitsuneislife/keyring-vcm
`
Requisitos:
- Node.js >= 18.0.0 (usa crypto nativo)
---
🚀 Uso Rápido
$3
`javascript
import {
generateMasterKey,
encryptFile,
decryptFile
} from '@kitsuneislife/keyring-vcm';
// 1. Gera master key (faça UMA VEZ e guarde com segurança)
const masterKey = generateMasterKey();
// 2. Encripta
await encryptFile({
inputPath: 'video.mp4',
outputPath: 'video.encrypted',
masterKey,
videoId: 'user-123-video-001'
});
// 3. Decripta
await decryptFile({
inputPath: 'video.encrypted',
outputPath: 'video-restored.mp4',
masterKey,
videoId: 'user-123-video-001'
});
`
$3
`javascript
import { encryptBuffer, decryptBuffer, generateMasterKey } from '@kitsuneislife/keyring-vcm';
const masterKey = generateMasterKey();
const videoData = Buffer.from('...');
// Encripta
const chunks = await encryptBuffer({
data: videoData,
masterKey,
videoId: 'video-001'
});
// Decripta
const restored = await decryptBuffer({
chunks,
masterKey,
videoId: 'video-001'
});
`
---
🔑 Gestão de Chaves
$3
`javascript
import { generateMasterKey, exportMasterKey, importMasterKey } from '@kitsuneislife/keyring-vcm';
// Gera (faça uma vez)
const masterKey = generateMasterKey();
// Exporta para armazenamento
const hexKey = exportMasterKey(masterKey);
// Salve em: ENV var, AWS KMS, HashiCorp Vault, etc.
// Importa quando necessário
const recovered = importMasterKey(hexKey);
`
$3
O sistema usa HKDF para derivar uma chave única por vídeo:
`
video_key = HKDF(master_key, video_id)
`
Vantagens:
- Uma master key protege infinitos vídeos
- Cada vídeo tem isolamento criptográfico
- Rotação simples (troca master key)
- Zero risco de reuso de chave
---
📚 API Completa
$3
Gera uma master key de 32 bytes (256 bits).
Retorna: Buffer
`javascript
const masterKey = generateMasterKey();
`
---
$3
Encripta um arquivo usando streaming.
Parâmetros:
`javascript
{
inputPath: string, // Caminho do arquivo original
outputPath: string, // Caminho do arquivo criptografado
masterKey: Buffer, // Master key (32 bytes)
videoId: string, // ID único do vídeo
encoding?: string, // 'binary' (padrão), 'base64', 'hex'
chunkSize?: number // Tamanho do chunk (padrão: 512KB)
}
`
Retorna: Promise<{ totalChunks, bytesProcessed }>
Exemplo:
`javascript
const stats = await encryptFile({
inputPath: 'movie.mp4',
outputPath: 'movie.enc',
masterKey,
videoId: 'movie-2024-001',
encoding: 'base64' // Texto ao invés de binário
});
console.log(Processados ${stats.totalChunks} chunks);
`
---
$3
Descriptografa um arquivo.
Parâmetros:
`javascript
{
inputPath: string, // Arquivo criptografado
outputPath: string, // Arquivo restaurado
masterKey: Buffer, // Mesma master key
videoId: string, // Mesmo videoId
encoding?: string // Mesmo encoding usado na criptografia
}
`
Retorna: Promise<{ chunksProcessed, bytesProcessed }>
---
$3
Encripta dados em memória.
Parâmetros:
`javascript
{
data: Buffer, // Dados a criptografar
masterKey: Buffer, // Master key
videoId: string, // ID do vídeo
chunkSize?: number // Tamanho do chunk
}
`
Retorna: Promise - Array de chunks criptografados
---
$3
Descriptografa dados em memória.
Parâmetros:
`javascript
{
chunks: Buffer[], // Chunks criptografados
masterKey: Buffer, // Master key
videoId: string // ID do vídeo
}
`
Retorna: Promise - Dados restaurados
---
🏗️ Arquitetura
$3
Cada chunk tem esta estrutura binária compacta:
`
┌─────────────┬─────────┬──────────┬──────────────┐
│ chunk_index │ IV │ TAG │ ciphertext │
│ 4 bytes │ 12 bytes│ 16 bytes │ N bytes │
└─────────────┴─────────┴──────────┴──────────────┘
↓ ↓ ↓ ↓
uint32BE random auth tag dados
`
Overhead: 32 bytes por chunk (~0.006% para chunks de 512KB)
$3
`
[Video File]
↓
[Chunk 512KB] → [Derive Key] → [Random IV] → [AES-256-GCM] → [Encrypted Chunk]
↓ ↓ ↓ ↓
[Chunk 512KB] [AAD] [Auth Tag] [Storage]
↓
[Last Chunk]
`
$3
Cada chunk é autenticado com:
`
AAD = SHA256(video_id || chunk_index)
`
Isso protege contra:
- ❌ Reordenação de chunks
- ❌ Substituição entre vídeos
- ❌ Ataques de replay
- ❌ Modificação silenciosa
---
🧪 Testes
Execute os testes completos:
`bash
npm test
`
Cobertura:
- ✅ Testes unitários (HKDF, AAD, Crypto)
- ✅ Testes de integração (arquivos, buffers)
- ✅ Testes de segurança (corrupção, chaves erradas)
- ✅ Testes de streaming
---
📖 Exemplos
$3
`bash
node examples/basic-usage.js
`
$3
`bash
node examples/buffer-usage.js
`
$3
`bash
node examples/streaming-usage.js
`
$3
`bash
node examples/multi-video.js
`
---
🛡️ Segurança
$3
✅ Confidencialidade: AES-256-GCM (padrão NIST)
✅ Integridade: Tag de autenticação por chunk
✅ Autenticidade: AAD vincula chunk ao contexto
✅ Unicidade: IV aleatório nunca reutilizado
✅ Isolamento: HKDF separa chaves por vídeo
$3
- Contra modificação: Tag GCM detecta qualquer alteração
- Contra reordenação: AAD inclui índice do chunk
- Contra substituição: AAD inclui videoId
- Contra replay: Combinação de IV + AAD
- Contra corrupção: Falha imediata e detectável
$3
❌ Vazamento de chave (responsabilidade do usuário)
❌ Ataques de canal lateral (timing, power)
❌ Ocultação de tamanho do arquivo
❌ DRM ou proteção contra cópia
---
⚡ Performance
$3
| Tamanho | Encriptação | Decriptação | Throughput |
|-----------|-------------|-------------|------------|
| 10 MB | ~50 ms | ~45 ms | ~200 MB/s |
| 100 MB | ~450 ms | ~420 ms | ~220 MB/s |
| 1 GB | ~4.5 s | ~4.2 s | ~230 MB/s |
Notas:
- Usa crypto nativo do Node.js (C++)
- Streaming evita uso de memória
- Gargalo é I/O, não CPU
---
🔧 Configuração Avançada
$3
`javascript
await encryptFile({
inputPath: 'video.mp4',
outputPath: 'video.enc',
masterKey,
videoId: 'video-001',
chunkSize: 1024 * 1024 // 1MB chunks
});
`
Trade-offs:
- Chunks menores: mais overhead, melhor granularidade
- Chunks maiores: menos overhead, menos granularidade
Recomendado: 512KB (padrão)
$3
`javascript
// Base64 (padrão texto)
await encryptFile({
inputPath: 'video.mp4',
outputPath: 'video.txt',
masterKey,
videoId: 'video-001',
encoding: 'base64'
});
// Hex
await encryptFile({
inputPath: 'video.mp4',
outputPath: 'video.hex',
masterKey,
videoId: 'video-001',
encoding: 'hex'
});
`
---
🔄 Casos de Uso
$3
`javascript
// Cliente
const chunks = await encryptBuffer({
data: videoBuffer,
masterKey: clientKey,
videoId: uploadId
});
// Upload chunks em paralelo
await Promise.all(chunks.map((chunk, i) =>
uploadToS3(${uploadId}/chunk-${i}, chunk)
));
`
$3
`javascript
import { EncryptionStream, ChunkSerializationStream } from '@kitsuneislife/keyring-vcm';
const encStream = new EncryptionStream(videoKey, videoId);
const serStream = new ChunkSerializationStream();
videoSource
.pipe(encStream)
.pipe(serStream)
.pipe(httpResponse);
`
$3
`javascript
// Encripta antes do backup
await encryptFile({
inputPath: 'important-video.mp4',
outputPath: 'backup/video.enc',
masterKey,
videoId: 'backup-2024-001'
});
// Restaura quando necessário
await decryptFile({
inputPath: 'backup/video.enc',
outputPath: 'restored.mp4',
masterKey,
videoId: 'backup-2024-001'
});
`
---
🤝 Contribuindo
Contribuições são bem-vindas!
Áreas de interesse:
- Otimizações de performance
- Suporte a WebCrypto (browser)
- Implementação de Base85
- Documentação adicional
---
📄 Licença
MIT License - veja LICENSE para detalhes.
---
🙏 Agradecimentos
Este projeto implementa best practices recomendadas por:
- NIST (National Institute of Standards and Technology)
- OWASP (Cryptographic Storage Cheat Sheet)
- Node.js Crypto Module Documentation
---
⚠️ Aviso de Segurança
IMPORTANTE:
1. Guarde a master key com segurança absoluta
- Use variáveis de ambiente
- KMS (AWS, GCP, Azure)
- Vaults (HashiCorp, etc.)
- NUNCA comite no código
2. Use HTTPS/TLS para transmissão
- Este módulo protege dados em repouso
- Use TLS para dados em trânsito
3. Validação de entrada
- Sempre valide videoId` antes de usar