PD-38 — Plan d'implémentation¶
📚 Navigation User Story
| Document | | | ---------- | -- | | 📋 [Spécification](PD-38-specification.md) | | | 🛠️ **Plan d'implémentation** | *(ce document)* | | ✅ [Critères d'acceptation](PD-38-acceptability.md) | | | 📝 [Retour d'expérience](PD-38-rex.md) | | [← Retour à crypto-proof](../PD-189-epic.md) · [↑ Index User Story](index.md)Objectif¶
Implémenter le calcul d'empreinte SHA3-256 sur les documents chiffrés pour garantir leur intégrité probatoire.
Choix techniques retenus¶
- Algorithme : SHA3-256 (NIST FIPS 202)
- Bibliothèque : js-sha3 + Node.js crypto
- Streaming : Support fichiers > 10MB
- Format : 64 caractères hexadécimaux
Architecture ciblée¶
src/modules/crypto/
└── hash.service.ts # Service de hachage
src/modules/documents/
└── services/
└── document-secure.service.ts # Intégration hash
Découpage technique¶
Phase 1 : Hash Service¶
- Créer
HashService:
@Injectable()
export class HashService {
hash(data: string | Buffer): string {
if (!data || (Buffer.isBuffer(data) && data.length === 0)) {
throw new BadRequestException('Cannot hash empty data');
}
return sha3_256(data);
}
hashDocument(file: Buffer): string {
if (!file || !Buffer.isBuffer(file) || file.length === 0) {
throw new BadRequestException('Invalid file');
}
return sha3_256(file);
}
}
Phase 2 : Streaming¶
- Implémenter
hashDocumentStream(stream): - Utiliser Node.js crypto.createHash('sha3-256')
- Traiter par chunks
- Valider stream non vide
async hashDocumentStream(stream: Readable): Promise<string> {
return new Promise((resolve, reject) => {
const hash = crypto.createHash('sha3-256');
let hasData = false;
stream
.on('data', (chunk) => {
hasData = true;
hash.update(chunk);
})
.on('end', () => {
if (!hasData) reject(new Error('Empty stream'));
else resolve(hash.digest('hex'));
})
.on('error', reject);
});
}
Phase 3 : Validation¶
- Implémenter
verify(data, expectedHash): - Calculer hash
- Comparer en constant-time
-
Retourner boolean
-
Implémenter
isValidHashFormat(hash): - Regex
/^[a-f0-9]{64}$/i - Valider longueur 64 chars
Phase 4 : Intégration documents¶
- Dans
DocumentSecureService.create(): - Recevoir fichier chiffré
- Calculer hash SHA3-256
-
Stocker dans colonne
file_hash -
Vérification doublon :
- Index unique sur (user_id, file_hash)
- Rejeter si hash déjà existant
Phase 5 : API¶
- Endpoint vérification :
GET /documents/:id/hash- Retourner hash pour vérification client
Phase 6 : Tests¶
- Tests vecteurs NIST FIPS 202
- Tests fichiers vides (rejet)
- Tests streaming grands fichiers
- Tests unicité hash par user
Points de vigilance¶
- Fichier chiffré : Hash sur ciphertext, pas plaintext
- Empty file : Toujours rejeter
- Collision : Théoriquement impossible (256 bits)
- Performance : Streaming pour fichiers > 10MB
Hors périmètre¶
- Stockage OVH (→ autre US)
- Arbre de Merkle (→ PD-60+)
- Signature HSM du hash (→ PD-37)