> 🇧🇷 Tradução em Português. [English version](../../security/MANIFEST_SIGNING.md)

# Guia de Assinatura de Manifest

Este documento explica como configurar e usar o sistema de assinatura criptográfica para manifests de instalação do LMAS-Core.

## Visão Geral

O LMAS-Core usa **assinaturas digitais Ed25519** (via formato minisign) para verificar a integridade e autenticidade do arquivo `install-manifest.yaml`. Isso garante que:

1. O manifest não foi adulterado após a assinatura
2. O manifest foi assinado por uma parte que possui a chave de assinatura autorizada
3. Todos os hashes de arquivos no manifest podem ser confiáveis como originados da mesma autoridade de assinatura

**Modelo de Confiança**: A raiz de confiança é a chave pública fixada no código-fonte. Registros de pacotes (npm, etc.) servem apenas como canais de distribuição e são explicitamente excluídos do modelo de confiança. A verificação depende exclusivamente de prova criptográfica contra a chave fixada.

## Arquitetura

```
┌─────────────────────────────────────────────────────────────────┐
│                    SIGNING WORKFLOW (Offline)                    │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  Ambiente de Assinatura (Máquina Segura)                         │
│  ┌──────────────────┐    ┌───────────────────────────────────┐  │
│  │ CHAVE SECRETA    │───▶│ minisign -Sm install-manifest.yaml│  │
│  │ (lmas-core.key)  │    │         -s lmas-core.key          │  │
│  │ NUNCA COMPARTILHE│    └───────────────────────────────────┘  │
│  └──────────────────┘                    │                       │
│                                          ▼                       │
│                          ┌───────────────────────────────────┐  │
│                          │ install-manifest.yaml.minisig     │  │
│                          │ (assinatura Ed25519 de 64 bytes)  │  │
│                          └───────────────────────────────────┘  │
│                                          │                       │
└──────────────────────────────────────────│───────────────────────┘
                                           │
                                           ▼ Distribuído via npm (canal não confiável)
┌─────────────────────────────────────────────────────────────────┐
│                  VERIFICATION WORKFLOW (pós-instalação)          │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  Máquina do Usuário (pós-instalação)                             │
│  ┌──────────────────┐    ┌───────────────────────────────────┐  │
│  │ CHAVE PÚBLICA    │───▶│ post-install-validator.js         │  │
│  │ FIXADA (hardcoded│    │   1. Carregar manifest + assinatura│  │
│  │  no código-fonte)│    │   2. Verificar assinatura Ed25519  │  │
│  └──────────────────┘    │   3. Parsear manifest (se válido)  │  │
│                          │   4. Verificar hashes SHA256       │  │
│                          └───────────────────────────────────┘  │
│                                          │                       │
│                                          ▼                       │
│                          ┌───────────────────────────────────┐  │
│                          │ ✓ Instalação verificada            │  │
│                          │   ou                               │  │
│                          │ ✗ AVISO DE SEGURANÇA              │  │
│                          └───────────────────────────────────┘  │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘
```

## Configuração Inicial (Única Vez)

### 1. Instalar minisign

```bash
# macOS
brew install minisign

# Ubuntu/Debian
apt install minisign

# Windows (via scoop)
scoop install minisign

# Ou baixar de: https://jedisct1.github.io/minisign/
```

### 2. Gerar Par de Chaves

```bash
# Gerar um novo par de chaves Ed25519
minisign -G -p lmas-core.pub -s lmas-core.key

# Será solicitada uma senha para proteger a chave secreta
# ESCOLHA UMA SENHA FORTE!

# Saída:
#   lmas-core.pub  - Chave PÚBLICA (segura para compartilhar, será fixada no código)
#   lmas-core.key  - Chave SECRETA (NUNCA compartilhe, armazene com segurança)
```

### 3. Visualizar Chave Pública

```bash
cat lmas-core.pub
# Exemplo de saída:
# untrusted comment: minisign public key LMAS0001
# RWQf6LRCGA9i8VYn7sGv...base64...
```

### 4. Incorporar Chave Pública no Código-Fonte

Editar `src/installer/manifest-signature.js`:

```javascript
const PINNED_PUBLIC_KEY = {
  // Key ID do arquivo de chave pública
  keyId: 'LMAS0001',
  // Chave pública em Base64 (a segunda linha de lmas-core.pub)
  publicKey: 'RWQf6LRCGA9i8VYn7sGv...sua-chave-real...',
  algorithm: 'Ed25519',
};
```

**IMPORTANTE**: A chave pública DEVE ser fixada diretamente no código-fonte. Nunca carregue-a de arquivos externos ou variáveis de ambiente — ela é a raiz de confiança.

### 5. Proteger a Chave Secreta

- Armazene `lmas-core.key` em local seguro (gerenciador de senhas, HSM, etc.)
- NUNCA faça commit no git
- Adicione ao `.gitignore`:
  ```gitignore
  *.key
  lmas-core.key
  ```
- Considere usar uma chave de segurança de hardware para proteção adicional

## Fluxo de Release

### Antes de Cada Release

1. **Gerar/Atualizar Manifest**

   ```bash
   node bin/lmas.js manifest:generate
   # Cria .lmas-core/install-manifest.yaml com todos os hashes de arquivos
   ```

2. **Assinar o Manifest**

   ```bash
   cd .lmas-core
   minisign -Sm install-manifest.yaml -s /path/to/lmas-core.key

   # Digite sua senha quando solicitado
   # Cria: install-manifest.yaml.minisig
   ```

3. **Verificar Assinatura (Opcional mas Recomendado)**

   ```bash
   minisign -Vm install-manifest.yaml -p /path/to/lmas-core.pub
   # Deve exibir: Signature and comment signature verified
   ```

4. **Commitar Ambos os Arquivos**

   ```bash
   git add .lmas-core/install-manifest.yaml
   git add .lmas-core/install-manifest.yaml.minisig
   git commit -m "chore: update manifest and signature for vX.Y.Z"
   ```

5. **Publicar**
   ```bash
   npm publish
   ```

## Formato do Arquivo de Assinatura

O arquivo `.minisig` segue o formato minisign conforme especificado em https://jedisct1.github.io/minisign/.

```text
untrusted comment: signature from minisign secret key
RUQf6LRCGA9i8...base64-encoded-signature-blob...
trusted comment: timestamp:1234567890 file:install-manifest.yaml
...base64-encoded-global-signature...
```

### Estrutura do Blob de Assinatura

A codificação do blob de assinatura segue a especificação do minisign. Para referência, a estrutura contém:

- Identificador de algoritmo (2 bytes)
- Key ID (8 bytes)
- Assinatura Ed25519 (64 bytes)

**Nota**: Aplicações devem usar o módulo de verificação (`manifest-signature.js`) em vez de parsear o formato de assinatura diretamente. O formato exato é definido pela especificação do minisign e pode variar em campos opcionais.

## Modo de Desenvolvimento

Durante desenvolvimento e testes, a verificação de assinatura pode ser ignorada:

```javascript
const validator = new PostInstallValidator(projectRoot, frameworkRoot, {
  requireSignature: false, // Pular verificação de assinatura
  verifyHashes: true, // Ainda verificar hashes de arquivos
});
```

**AVISO CRÍTICO DE SEGURANÇA**: Definir `requireSignature: false` desabilita completamente a verificação de assinatura e invalida todas as garantias de segurança criptográfica fornecidas por este sistema. Com a verificação de assinatura desabilitada:

- A autenticidade do manifest não pode ser verificada
- Manifests adulterados serão aceitos
- A cadeia de confiança é quebrada

Esta opção existe **exclusivamente** para ambientes de desenvolvimento local. Builds de produção **DEVEM** impor verificação de assinatura (`requireSignature: true`). Qualquer deploy com verificação de assinatura desabilitada deve ser considerado inseguro.

## Comportamento de Verificação

| Modo                                    | Assinatura Ausente | Assinatura Inválida | Assinatura Válida |
| --------------------------------------- | ------------------ | ------------------- | ----------------- |
| Produção (`requireSignature: true`)     | ERRO               | ERRO                | OK                |
| Desenvolvimento (`requireSignature: false`) | AVISO          | ERRO                | OK                |

## Solução de Problemas

### "Manifest signature file not found (.minisig)"

O arquivo de assinatura está ausente. A parte que possui a chave de assinatura deve assinar o manifest:

```bash
minisign -Sm .lmas-core/install-manifest.yaml -s /path/to/lmas-core.key
```

### "Key ID mismatch"

O manifest foi assinado com uma chave diferente da fixada no código. Certifique-se de que a parte responsável pela assinatura está usando o par de chaves correto que corresponde à chave pública fixada.

### "Signature verification failed"

O conteúdo do manifest foi modificado após a assinatura. Regenere e reassine:

```bash
node bin/lmas.js manifest:generate
minisign -Sm .lmas-core/install-manifest.yaml -s /path/to/lmas-core.key
```

### "Unsupported signature algorithm"

O arquivo de assinatura não está usando Ed25519. Certifique-se de que está usando o minisign padrão (não um fork com algoritmos diferentes).

## Considerações de Segurança

1. **Comprometimento de Chave**: Se a chave secreta for comprometida, gere um novo par de chaves e lance uma nova versão com a chave pública fixada atualizada. Os usuários devem atualizar para uma release contendo a nova chave pública fixada para restaurar as garantias de segurança. Releases assinadas com a chave comprometida devem ser consideradas não confiáveis.

2. **Rotação de Chaves**: Planeje rotação periódica de chaves. Após a rotação, os usuários devem atualizar para uma release contendo a nova chave pública fixada. Anuncie a depreciação de chaves antigas com antecedência para permitir janelas de atualização.

3. **Assinatura em CI/CD**: Para releases automatizadas, considere:
   - Usar um serviço de assinatura
   - Armazenar a chave secreta em um gerenciador de secrets (ex.: AWS Secrets Manager, HashiCorp Vault)
   - Usar GitHub Actions encrypted secrets (com cautela)

4. **Bypass de Verificação**: A opção `requireSignature: false` invalida todas as garantias de segurança e nunca deve ser usada em produção. Qualquer build distribuído com verificação de assinatura desabilitada deve ser tratado como inseguro.

## Referência da API

### `verifyManifestSignature(manifestContent, signatureContent, options)`

Verifica a assinatura de um manifest.

**Parâmetros:**

- `manifestContent` (Buffer): Conteúdo bruto do arquivo manifest
- `signatureContent` (string): Conteúdo do arquivo .minisig
- `options.publicKey` (Object): Sobrescrever chave pública (apenas para testes)

**Retorno:**

```javascript
{
  valid: boolean,      // true se a assinatura é válida
  error: string|null,  // mensagem de erro se inválida
  keyId: string|null   // key ID usada na assinatura
}
```

### `loadAndVerifyManifest(manifestPath, options)`

Carrega e verifica um arquivo manifest.

**Parâmetros:**

- `manifestPath` (string): Caminho para o arquivo manifest
- `options.requireSignature` (boolean): Falhar se assinatura ausente (padrão: true)

**Retorno:**

```javascript
{
  content: Buffer|null,  // conteúdo do manifest se válido
  verified: boolean,     // true se assinatura verificada
  error: string|null     // mensagem de erro se falhou
}
```

## Changelog

- **v3.10.0**: Implementação inicial da assinatura de manifest
  - Assinaturas Ed25519 via formato minisign
  - Chave pública fixada no código-fonte
  - Integração com o validador pós-instalação
