💻 Développement

dev-face-matching-kyc

Vérification biométrique d'identité : face matching selfie vs document, liveness detection, deepfake detection, pipeline KYC complet avec seuils décision, conformité RGPD/loi 09-08.

⚡ Installation & lancement en 1 commande

Copiez-collez dans votre terminal : le skill s'installe dans ~/.claude/skills et Claude Code se lance directement dessus.

macOS / Linux
curl -fsSL https://raw.githubusercontent.com/khalilbenaz/claude-skills-collection/main/install.sh | sh -s -- dev-face-matching-kyc --launch
Windows (PowerShell)
iex "& { $(iwr -useb https://raw.githubusercontent.com/khalilbenaz/claude-skills-collection/main/install.ps1) } dev-face-matching-kyc -Launch"

🚀 Déjà installé ?

claude "/dev-face-matching-kyc"

Ou tapez /dev-face-matching-kyc dans une session Claude Code, ou décrivez simplement votre besoin — le skill se déclenche automatiquement via le skill-router.

🔑 Déclencheurs automatiques

Le skill s'active automatiquement quand votre demande contient :

face matchingvérification identitéKYC biométriqueselfie vs documentlivenessdeepfakebiometrieone-to-one matching

📦 Installation manuelle

git clone https://github.com/khalilbenaz/claude-skills-collection.git cp -r claude-skills-collection/skills/dev-face-matching-kyc ~/.claude/skills/

Payload du plugin : skills/dev-face-matching-kyc · source éditable : dev-skills/face-matching-kyc

📖 Manuel

Face Matching KYC

Workflow KYC — étapes numérotées

1. Détection et alignement de visage

Librairies recommandées (par priorité) :

ContexteLibrairiePoints repères
Mobile Android/iOS (offline)MediaPipe FaceMesh468 points
Qualité maximale (backend)RetinaFace5 points
Équilibre vitesse/qualitéMTCNN5 points

Transform affine sur 5 points (yeux G/D, nez, coins bouche) → normalisation 112×112 px.

# Python – alignement avec insightface
from insightface.app import FaceAnalysis
app = FaceAnalysis(allowed_modules=["detection", "recognition"])
app.prepare(ctx_id=0, det_size=(640, 640))

def align_and_embed(img_bgr):
    faces = app.get(img_bgr)
    if not faces:
        raise ValueError("Aucun visage détecté")
    return faces[0].normed_embedding  # float32 array 512-D, L2-normalisé

Critères de rejet image avant traitement :

2. Extraction d'embedding facial

Modèle par contexte :

ModèleEmbeddingFAR @ threshold 0.75Cas d'usage
ArcFace R100512-D~0.05%KYC bancaire, onboarding critique
MobileFaceNet128-D~0.3%Mobile, contrainte latence
FaceNet InceptionResNetV1128-D~0.1%Backend général

Règle : toujours L2-normaliser l'embedding avant le calcul de similarité.

import numpy as np

def cosine_similarity(emb1: np.ndarray, emb2: np.ndarray) -> float:
    # Les embeddings insightface/ArcFace sont déjà L2-normalisés
    return float(np.dot(emb1, emb2))  # dot product = cosine similarity si normalisés

3. Seuil de décision — similarity score

Score cosinus   Décision             Cas d'usage
─────────────   ──────────────────   ─────────────────────────────────
< 0.65          REJECT               Blocage systématique
0.65 – 0.75     REVIEW               File de revue manuelle obligatoire
0.75 – 0.85     PASS (medium)        Login biométrique, flux secondaires
≥ 0.85          PASS (high)          Ouverture compte, transaction critique

Score final pondéré (à adapter selon contexte réglementaire) :

def compute_final_score(face_score: float, liveness_score: float) -> dict:
    final = 0.6 * face_score + 0.4 * liveness_score
    if final >= 0.85:
        decision = "PASS_HIGH"
    elif final >= 0.75:
        decision = "PASS_MEDIUM"
    elif final >= 0.65:
        decision = "REVIEW"
    else:
        decision = "REJECT"
    return {"final_score": round(final, 4), "decision": decision}

4. Liveness Detection (anti-spoofing)

Passive (premier frame, zéro friction utilisateur)

Active (si passive score < 0.7 — défi challenge)

# Passive liveness avec Silent Face Anti-Spoofing (miniFASNet)
# pip install silent-face-anti-spoofing
from silent_face import SilentFaceAntiSpoofing
model = SilentFaceAntiSpoofing()

def check_liveness(img_bgr) -> dict:
    score = model.predict(img_bgr)  # 0=spoof, 1=real
    return {
        "liveness_score": round(float(score), 4),
        "liveness_result": "PASS" if score >= 0.7 else "FAIL"
    }

5. Deepfake et attaques avancées

Modèles de détection (par ordre de précision décroissante) :

ModèleDataset entraîn.VitesseNotes
EfficientNet-B4DFDC~150ms GPUSOTA, recommandé backend
XceptionNetFaceForensics++~80ms GPUBonne généralisation
MesoNetCustom~10ms CPULéger, embarqué possible

Types d'attaques à couvrir :

Contre-mesures injection attack (mobile) :

# Seuil deepfake — bloquer sans review si probabilité haute
def evaluate_deepfake(deepfake_prob: float) -> str:
    if deepfake_prob > 0.5:
        return "BLOCK"       # Blocage immédiat, alerter équipe fraude
    elif deepfake_prob > 0.3:
        return "REVIEW"      # Revue humaine obligatoire
    return "PASS"

6. Pipeline KYC complet — orchestration

from dataclasses import dataclass, asdict
import hmac, hashlib, json, time

@dataclass
class KYCReport:
    timestamp: str
    face_match_score: float
    liveness_score: float
    deepfake_probability: float
    document_photo_quality: str   # OK | LOW
    overall_result: str           # PASS | REVIEW | REJECT
    signature: str = ""

def run_kyc(selfie_bgr, document_bgr) -> dict:
    emb_selfie   = align_and_embed(selfie_bgr)
    emb_document = align_and_embed(document_bgr)

    face_score   = cosine_similarity(emb_selfie, emb_document)
    liveness     = check_liveness(selfie_bgr)
    deepfake     = evaluate_deepfake(get_deepfake_prob(selfie_bgr))

    decision = compute_final_score(face_score, liveness["liveness_score"])

    if deepfake == "BLOCK":
        overall = "REJECT"
    elif deepfake == "REVIEW" or decision["decision"] == "REVIEW":
        overall = "REVIEW"
    elif decision["decision"].startswith("PASS"):
        overall = "PASS"
    else:
        overall = "REJECT"

    report = KYCReport(
        timestamp=str(int(time.time())),
        face_match_score=face_score,
        liveness_score=liveness["liveness_score"],
        deepfake_probability=0.0,  # à remplir
        document_photo_quality="OK",
        overall_result=overall,
    )
    payload = json.dumps(asdict(report), separators=(",", ":")).encode()
    report.signature = hmac.new(SECRET_KEY, payload, hashlib.sha256).hexdigest()
    return asdict(report)

7. Intégration mobile

Android (Kotlin)

// build.gradle.kts
implementation("com.google.mlkit:face-detection:16.1.5")
implementation("org.tensorflow:tensorflow-lite:2.14.0")
implementation("org.tensorflow:tensorflow-lite-gpu:2.14.0")
implementation("androidx.camera:camera-camera2:1.3.2")
val options = FaceDetectorOptions.Builder()
    .setPerformanceMode(FaceDetectorOptions.PERFORMANCE_MODE_ACCURATE)
    .setLandmarkMode(FaceDetectorOptions.LANDMARK_MODE_ALL)
    .setClassificationMode(FaceDetectorOptions.CLASSIFICATION_MODE_ALL)
    .build()
val detector = FaceDetection.getClient(options)

React Native

yarn add react-native-vision-camera react-native-fast-tflite

API REST — endpoints backend

POST /face/verify
  Body : { selfie: base64, document_photo: base64 }
  Return: { face_match_score, liveness_score, deepfake_probability, overall_result }

POST /face/liveness
  Body : { frames: [base64, ...] }   # 5-10 frames pour active liveness
  Return: { liveness_score, liveness_result }

8. Conformité et vie privée


Garde-fous / Anti-patterns / Pièges

PiègeConséquenceContre-mesure
Seuil unique pour tous les fluxFAR trop élevé sur les cas critiquesSeuils différenciés par flux (0.75 login, 0.85 onboarding)
Face matching sans livenessAttaque photo-sur-photo trivialeToujours combiner matching + liveness
Stocker embeddings brutsDonnées biométriques persistées = RGPD violationPrivacy by design : effacer post-session
Photo document trop petiteEmbedding de mauvaise qualité → faux rejetsVérifier résolution ≥ 200×250 px avant embedding
Ignorer les injections digitalesContournement via caméra virtuellePlay Integrity API (Android) + App Attest (iOS)
Score deepfake sans seuil de blocageDeepfake validé automatiquementBloquer strictement si deepfake_prob > 0.5
Modèle non fine-tuné sur CIN marocaineDégradation qualité sur hologramme/filigraneFine-tuner ou tester sur dataset CIN biométrique marocaine
Un seul modèle pour détection + embeddingPoint de défaillance uniquePipeline modulaire : détection / embedding / liveness séparés

Bonnes pratiques 2026