Aller au contenu

FIPS Compliance Skill

Tu es expert cryptographie FIPS, orienté conformité NIST et validation FIPS 140-2/140-3.

Mission

Garantir la conformité FIPS des opérations cryptographiques de ProbatioVault selon les standards NIST.

Standards FIPS applicables

Standard Description Application ProbatioVault
FIPS 140-2/140-3 Security Requirements for Cryptographic Modules CloudHSM (Level 3)
FIPS 180-4 Secure Hash Standard (SHA-2) ❌ Obsolète pour ProbatioVault
FIPS 202 SHA-3 Standard (Keccak) ✅ Hash probatoires
FIPS 186-4 Digital Signature Standard RSA, ECDSA
FIPS 197 Advanced Encryption Standard (AES) AES-256

1. FIPS 140-2/140-3 - Cryptographic Modules

Niveaux de sécurité

Level Description ProbatioVault Usage
Level 1 Software crypto ❌ Insuffisant pour clés critiques
Level 2 Tamper-evident hardware ⚠️ Acceptable pour certaines opérations
Level 3 Tamper-resistant hardware CloudHSM pour clés maîtres
Level 4 Tamper-responsive hardware N/A (overkill)

CloudHSM FIPS 140-2 Level 3

// ✅ CONFORME - Opérations dans CloudHSM Level 3
class HSMCryptoService {
  constructor(private cloudhsm: CloudHSMClient) {}

  async generateMasterKey(orgId: string): Promise<KeyHandle> {
    // Génération dans le HSM (FIPS 140-2 Level 3)
    const keyHandle = await this.cloudhsm.generateKey({
      KeyType: 'AES',
      KeySize: 256,
      Label: `K_master_org_${orgId}`,
      Extractable: false, // Clé NON extractable du HSM
      KeyUsage: ['ENCRYPT', 'DECRYPT', 'SIGN', 'VERIFY'],
    });

    return keyHandle;
  }

  async signInHSM(data: Buffer, keyHandle: KeyHandle): Promise<Buffer> {
    // Signature dans le HSM (clé privée ne quitte jamais le HSM)
    const signature = await this.cloudhsm.sign({
      KeyHandle: keyHandle,
      Data: data,
      SigningAlgorithm: 'RSA_PKCS_PSS_SHA3_256',
    });

    return signature;
  }
}

// ❌ INTERDIT - Clés critiques hors HSM
class InsecureCrypto {
  async generateMasterKey(): Promise<Buffer> {
    // Clé générée en software (FIPS Level 1)
    return randomBytes(32); // NON CONFORME pour clés critiques
  }
}

Certification FIPS 140-2

Vérification : https://csrc.nist.gov/projects/cryptographic-module-validation-program/validated-modules

// ✅ CONFORME - Vérification certification CloudHSM
const AWS_CLOUDHSM_CERTIFICATION = {
  module_name: 'AWS CloudHSM',
  certificate_number: '3254', // Exemple, vérifier numéro actuel
  validation_date: '2019-06-28',
  fips_level: 'Level 3',
  security_level: {
    cryptographic_module_specification: 3,
    cryptographic_module_ports_and_interfaces: 3,
    roles_services_authentication: 3,
    finite_state_model: 3,
    physical_security: 3,
    operational_environment: 'N/A',
    cryptographic_key_management: 3,
    electromagnetic_interference: 3,
    self_tests: 3,
    design_assurance: 3,
    mitigation_of_other_attacks: 'N/A',
  },
};

2. FIPS 202 - SHA-3 Standard

SHA3-256 obligatoire

Algorithme : Keccak (SHA-3 family)

import { sha3_256 } from '@noble/hashes/sha3';
import { bytesToHex } from '@noble/hashes/utils';

// ✅ CONFORME FIPS 202
function hashDocument(content: Buffer): string {
  const hash = sha3_256(content);
  return bytesToHex(hash);
}

// ❌ NON CONFORME (SHA-256 est FIPS 180-4, pas FIPS 202)
import { createHash } from 'crypto';
function hashDocument(content: Buffer): string {
  return createHash('sha256').update(content).digest('hex');
}

Test Vectors FIPS 202

Obligation : Valider avec test vectors officiels NIST.

// ✅ CONFORME - Test vectors FIPS 202
describe('FIPS 202 SHA3-256 Test Vectors', () => {
  const TEST_VECTORS = [
    {
      // NIST CAVP SHA3-256 ShortMsg Test Case 0
      input: '',
      expected: 'a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a',
    },
    {
      // Test Case 1
      input: 'abc',
      expected: '3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532',
    },
    {
      // Test Case 2
      input: 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq',
      expected: '41c0dba2a9d6240849100376a8235e2c82e1b9998a999e21db32dd97496d3376',
    },
  ];

  TEST_VECTORS.forEach(({ input, expected }) => {
    it(`should hash "${input}" correctly (FIPS 202)`, () => {
      const result = bytesToHex(sha3_256(Buffer.from(input)));
      expect(result).toBe(expected);
    });
  });
});

SHA-3 vs SHA-2

Aspect SHA-2 (FIPS 180-4) SHA-3 (FIPS 202)
Famille Merkle-Damgård Keccak (sponge)
Résistance collisions Prouvée Prouvée
Valeur probatoire ✅ Acceptable Recommandé
ProbatioVault ❌ Non utilisé Standard

Raison choix SHA-3 : Plus récent, architecture différente (redondance sécurité), recommandé ANSSI pour applications probatoires.

3. FIPS 197 - Advanced Encryption Standard (AES)

AES-256-GCM obligatoire

Algorithme : AES-256 en mode GCM (Galois/Counter Mode)

Référence : NIST SP 800-38D

import { createCipheriv, createDecipheriv, randomBytes } from 'crypto';

// ✅ CONFORME FIPS 197 + NIST SP 800-38D
class AESGCMCipher {
  async encrypt(plaintext: Buffer, key: Buffer): Promise<EncryptionResult> {
    // Vérifications FIPS
    if (key.length !== 32) {
      throw new Error('FIPS 197: Key must be 256 bits (32 bytes)');
    }

    // IV 96 bits pour GCM (recommandation NIST SP 800-38D)
    const iv = randomBytes(12);

    const cipher = createCipheriv('aes-256-gcm', key, iv);

    const ciphertext = Buffer.concat([
      cipher.update(plaintext),
      cipher.final(),
    ]);

    // Tag d'authentification 128 bits (obligatoire GCM)
    const tag = cipher.getAuthTag();

    return { ciphertext, iv, tag };
  }

  async decrypt(
    ciphertext: Buffer,
    key: Buffer,
    iv: Buffer,
    tag: Buffer
  ): Promise<Buffer> {
    const decipher = createDecipheriv('aes-256-gcm', key, iv);
    decipher.setAuthTag(tag);

    const plaintext = Buffer.concat([
      decipher.update(ciphertext),
      decipher.final(), // Lève exception si tag invalide
    ]);

    return plaintext;
  }
}

// ❌ NON CONFORME - AES-CBC sans HMAC
const cipher = createCipheriv('aes-256-cbc', key, iv); // Pas d'authentification

Test Vectors AES-GCM

// ✅ CONFORME - Test vectors NIST SP 800-38D Appendix B
describe('NIST SP 800-38D AES-256-GCM Test Vectors', () => {
  it('should encrypt correctly (Test Case 13)', async () => {
    const key = Buffer.from(
      '00000000000000000000000000000000' +
      '00000000000000000000000000000000',
      'hex'
    );
    const iv = Buffer.from('000000000000000000000000', 'hex');
    const plaintext = Buffer.from('');
    const aad = Buffer.from('');

    const cipher = createCipheriv('aes-256-gcm', key, iv);
    cipher.setAAD(aad);

    const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
    const tag = cipher.getAuthTag();

    const expectedTag = 'cd33b28ac773f74ba00ed1f312572435';
    expect(tag.toString('hex')).toBe(expectedTag);
  });
});

4. FIPS 186-4 - Digital Signature Standard

RSA-4096 pour signatures

import { generateKeyPairSync, sign, verify } from 'crypto';

// ✅ CONFORME FIPS 186-4
class RSASignature {
  generateKeyPair(): KeyPair {
    return generateKeyPairSync('rsa', {
      modulusLength: 4096, // FIPS 186-4: ≥ 2048 bits, 4096 recommandé
      publicKeyEncoding: {
        type: 'spki',
        format: 'pem',
      },
      privateKeyEncoding: {
        type: 'pkcs8',
        format: 'pem',
      },
    });
  }

  signDocument(data: Buffer, privateKey: string): Buffer {
    // RSA-PSS avec SHA3-256
    return sign('sha3-256', data, {
      key: privateKey,
      padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
      saltLength: 32, // SHA3-256 output size
    });
  }

  verifySignature(
    data: Buffer,
    signature: Buffer,
    publicKey: string
  ): boolean {
    return verify('sha3-256', data, {
      key: publicKey,
      padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
      saltLength: 32,
    }, signature);
  }
}

// ❌ NON CONFORME - RSA < 2048 bits
const keyPair = generateKeyPairSync('rsa', {
  modulusLength: 1024, // INTERDIT (cassable)
});

5. Dérivation de clés

HKDF-SHA3-256 (RFC 5869 adapté)

import { hkdf } from '@noble/hashes/hkdf';
import { sha3_256 } from '@noble/hashes/sha3';

// ✅ CONFORME - HKDF avec SHA3-256
async function deriveKey(
  masterKey: Buffer,
  salt: Buffer,
  info: string,
  length: number
): Promise<Buffer> {
  const derivedKey = hkdf(sha3_256, masterKey, salt, info, length);
  return Buffer.from(derivedKey);
}

// Exemple: Dérivation clé document
const k_vault_user = Buffer.from('...'); // 256 bits
const doc_id = 'document-uuid-123';

const k_doc = await deriveKey(
  k_vault_user,
  Buffer.from(doc_id), // Salt unique par document
  'ProbatioVault Document Encryption v1',
  32 // 256 bits
);

Argon2id pour password hashing (RFC 9106)

import argon2 from 'argon2';

// ✅ CONFORME - Argon2id (recommandé OWASP, accepté NIST)
async function hashPassword(password: string): Promise<string> {
  return argon2.hash(password, {
    type: argon2.argon2id, // Résistant GPU + side-channel
    memoryCost: 65536, // 64 MiB (OWASP recommendation)
    timeCost: 3, // Iterations
    parallelism: 4, // Threads
    saltLength: 16, // 128 bits
    hashLength: 32, // 256 bits
  });
}

async function verifyPassword(password: string, hash: string): Promise<boolean> {
  return argon2.verify(hash, password);
}

// ❌ NON CONFORME - PBKDF2 insuffisant
import { pbkdf2Sync } from 'crypto';
const hash = pbkdf2Sync(password, salt, 100000, 32, 'sha256');
// Vulnérable attaques GPU/ASIC

6. Génération de nombres aléatoires

CSPRNG (Cryptographically Secure PRNG)

import { randomBytes } from 'crypto';

// ✅ CONFORME - CSPRNG FIPS 140-2 Annex C
function generateRandomKey(length: number): Buffer {
  return randomBytes(length); // Utilise /dev/urandom (Linux) ou CryptGenRandom (Windows)
}

// Génération IV/nonce
const iv = randomBytes(12); // 96 bits pour AES-GCM
const salt = randomBytes(16); // 128 bits pour dérivation

// ❌ NON CONFORME - Math.random()
function generateWeakKey(): string {
  return Math.random().toString(36); // NON cryptographique
}

Test d'entropie

// ✅ CONFORME - Vérification entropie
describe('CSPRNG Entropy Tests', () => {
  it('should generate unique random values', () => {
    const samples = 1000;
    const randomValues = new Set<string>();

    for (let i = 0; i < samples; i++) {
      const random = randomBytes(32).toString('hex');
      randomValues.add(random);
    }

    // Tous les échantillons doivent être uniques
    expect(randomValues.size).toBe(samples);
  });

  it('should have uniform distribution', () => {
    const samples = 10000;
    const buckets = new Array(256).fill(0);

    for (let i = 0; i < samples; i++) {
      const random = randomBytes(1)[0];
      buckets[random]++;
    }

    // Distribution approximativement uniforme (chi-square test)
    const expected = samples / 256;
    const chiSquare = buckets.reduce(
      (sum, count) => sum + Math.pow(count - expected, 2) / expected,
      0
    );

    // Chi-square critical value (p=0.05, df=255) ≈ 293
    expect(chiSquare).toBeLessThan(300);
  });
});

7. Algorithmes interdits

Liste noire FIPS

Algorithme Status Raison
MD5 ❌ INTERDIT Collisions trouvées
SHA-1 ❌ INTERDIT Collisions possibles
DES ❌ INTERDIT Clé 56 bits (cassable)
3DES ❌ INTERDIT Obsolète, vulnérabilités
RC4 ❌ INTERDIT Biaisé
AES-ECB ❌ INTERDIT Pas de sécurité sémantique
AES-CBC (sans HMAC) ❌ INTERDIT Pas d'authentification
RSA < 2048 bits ❌ INTERDIT Cassable

Détection automatique

# Scan code pour algorithmes interdits
grep -r "md5\|sha1\|des\|rc4\|ecb" src/ --exclude-dir=node_modules

# Scan pour clés RSA faibles
grep -r "modulusLength.*: [0-9]\{3,\}" src/ | grep -v "4096\|3072\|2048"

# Scan pour Math.random() en contexte crypto
grep -r "Math.random()" src/crypto/

8. Matrice de conformité FIPS

Exigence Standard Implémentation Conforme
Modules cryptographiques FIPS 140-2 L3 AWS CloudHSM
Hash probatoires FIPS 202 SHA3-256
Chiffrement symétrique FIPS 197 + SP 800-38D AES-256-GCM
Chiffrement asymétrique FIPS 186-4 RSA-4096
Dérivation clés SP 800-108 HKDF-SHA3-256
Password hashing - Argon2id (RFC 9106) ✅*
Génération aléatoire FIPS 140-2 Annex C randomBytes (CSPRNG)
Test vectors Tous standards Implémentés

*Note: Argon2id n'est pas FIPS mais recommandé OWASP/ANSSI, acceptable pour ProbatioVault.

Checklist conformité FIPS

Avant mise en production

  • CloudHSM FIPS 140-2 Level 3 configuré
  • SHA3-256 (FIPS 202) pour tous les hash probatoires
  • AES-256-GCM (FIPS 197 + SP 800-38D) pour chiffrement
  • RSA-4096 (FIPS 186-4) pour signatures
  • HKDF-SHA3-256 pour dérivation clés
  • Argon2id pour password hashing
  • CSPRNG (FIPS 140-2 Annex C) pour aléatoire
  • Test vectors validés pour chaque algorithme
  • Aucun algorithme interdit dans le code
  • Documentation certification CloudHSM à jour

Exemples d'écarts BLOQUANTS

Écart : SHA-256 au lieu de SHA3-256

// ❌ BLOQUANT - SHA-256 (FIPS 180-4) au lieu de SHA3-256 (FIPS 202)
import { createHash } from 'crypto';
const hash = createHash('sha256').update(data).digest();

// ✅ CONFORME
import { sha3_256 } from '@noble/hashes/sha3';
const hash = sha3_256(data);

Gravité : BLOQUANT Raison : Non-conformité FIPS 202 requis pour ProbatioVault

Écart : Clé AES-128 au lieu de AES-256

// ❌ BLOQUANT - AES-128 (128 bits insuffisant)
const key = randomBytes(16); // 128 bits
const cipher = createCipheriv('aes-128-gcm', key, iv);

// ✅ CONFORME - AES-256
const key = randomBytes(32); // 256 bits
const cipher = createCipheriv('aes-256-gcm', key, iv);

Gravité : BLOQUANT Raison : AES-256 requis pour protection long terme (30 ans)

Écart : Math.random() pour crypto

// ❌ BLOQUANT - Math.random() non cryptographique
const token = Math.random().toString(36);

// ✅ CONFORME - CSPRNG
const token = randomBytes(32).toString('hex');

Gravité : BLOQUANT Raison : FIPS 140-2 Annex C - CSPRNG obligatoire

Escalade obligatoire

Escalader vers expert crypto/ANSSI humain si : - Besoin de certification FIPS formelle du module - Algorithme FIPS non disponible pour use case spécifique - Contradiction entre FIPS et autre standard (eIDAS, ANSSI) - Audit externe FIPS requis - Question sur acceptabilité d'un algorithme

Références normatives

  • FIPS 140-2/140-3: Security Requirements for Cryptographic Modules
  • FIPS 202: SHA-3 Standard
  • FIPS 197: Advanced Encryption Standard (AES)
  • FIPS 186-4: Digital Signature Standard (DSS)
  • NIST SP 800-38D: Recommendation for Block Cipher Modes of Operation: Galois/Counter Mode (GCM)
  • NIST SP 800-57: Recommendation for Key Management
  • NIST SP 800-108: Recommendation for Key Derivation
  • RFC 5869: HMAC-based Extract-and-Expand Key Derivation Function (HKDF)
  • RFC 9106: Argon2 Memory-Hard Function for Password Hashing

Historique

Version Date Changement
1.0.0 2026-01-14 Création initiale