Naar hoofdinhoud gaan

Chiffrement GPS

Le module GPS chiffre protege les coordonnees de localisation des ruchers lors des evaluations. Les coordonnees sont chiffrees cote client avec OpenPGP.js --- le serveur ne voit jamais les positions en clair. Seul l'eleveur (via son code PIN) et le moteur de calcul genetique BLUP (via sa cle privee) peuvent lire les coordonnees.

Page eleveur : Parametres > Securite > Protection GPS | Formulaire evaluation : capture automatique


Architecture

ELEVEUR                           SERVEUR (Supabase)
| |
|== CONSENTEMENT GDPR == |
|-- Bandeau opt-in (1ere fois) ---> profiles.gps_consent = true/false
|-- Detection mobile/desktop |
| |
|== SETUP PIN == |
|-- PIN 6+ chiffres |
|-- PBKDF2 + AES-256-GCM |
|-- Genere paire OpenPGP |
|-- Chiffre cle privee ---------> pgp_encrypted_private_key (blob)
|-- Cle publique ----------------> pgp_public_key
|-- 8 recovery codes ------------> gps_recovery_codes (hash + blob)
| |
|== EVALUATION (terrain) == |
|-- Consent check (gps_consent) |
|-- Mobile: GPS natif auto |
|-- Desktop: saisie manuelle |
| lat/lng + validation bornes |
|-- Chiffre avec cle publique ----> gps_encrypted (PGP armored)
|-- SHA-256 commitment -----------> gps_commitment
|-- Trigger verrouille -----------> gps_locked_at (immutable)
| |
|== CONSULTATION (carte) == |
|-- PIN --> AES --> cle privee |
|-- Dechiffre coords localement |

Composants techniques

Services cryptographiques

ServiceFichierRole
PIN Servicesrc/lib/gps/gps-pin-service.tsPBKDF2 derivation, AES-256-GCM encrypt/decrypt, session 15min
PGP Servicesrc/lib/gps/gps-pgp-service.tsOpenPGP encrypt multi-destinataires, signature EdDSA, dechiffrement

Les deux services sont lazy-loaded (await import()) --- ils ne sont charges que dans le formulaire d'evaluation et la page parametres (~200KB openpgp.js).

Base de donnees

Table/ColonneUsage
profiles.pgp_public_keyCle publique OpenPGP (armored)
profiles.pgp_encrypted_private_keyCle privee chiffree AES (blob illisible sans PIN)
profiles.pgp_key_fingerprint16 chars hex pour verification PIN
profiles.pgp_pin_setBoolean --- PIN configure ou non
profiles.gps_consentBoolean --- Consentement GDPR geolocalisation (opt-in explicite, default false)
gps_recovery_codes8 codes de secours (hash SHA-256 + salt + blob AES)
queen_evaluations.gps_encryptedBloc PGP armored (coords chiffrees)
queen_evaluations.gps_signatureSignature EdDSA detachee
queen_evaluations.gps_commitmentSHA-256 du plaintext (audit)
queen_evaluations.gps_locked_atTimestamp verrouillage (immutable)

Triggers d'immutabilite

TriggerComportement
trg_lock_gps_updateBloque toute modification de gps_encrypted, gps_commitment et gps_signature une fois gps_locked_at renseigne
trg_lock_gps_deleteBloque la suppression d'une evaluation dont le GPS est verrouille

RPC Supabase

FonctionUsage
setup_gps_pin()Transaction atomique : met a jour le profil + insere 8 recovery codes. Valide le format PGP et fingerprint
create_annual_evaluations()Rotation annuelle : clone evaluations N-1 vers N avec GPS vierge. Idempotent (ON CONFLICT DO NOTHING)

Consentement GDPR et detection device

Le module GPS inclut un bandeau de consentement GDPR (opt-in explicite) affiche lors du premier acces au formulaire d'evaluation. Le consentement reste local uniquement (state React) jusqu'a la sauvegarde reussie de l'evaluation --- profiles.gps_consent n'est persiste en DB qu'au moment du save. L'eleveur peut revoquer son consentement a tout moment via le bouton Desactiver la geolocalisation dans Parametres > Securite > Protection GPS.

Detection mobile/desktop : le hook useGpsCapture detecte le type d'appareil via navigator.userAgent et navigator.maxTouchPoints :

DeviceComportement GPSSource
Mobile (smartphone/tablette)Capture automatique via navigator.geolocationGPS natif
Desktop (ordinateur)Saisie manuelle latitude/longitudeChamps input avec validation bornes (lat -90/+90, lng -180/+180)

L'indicateur GPS sur le formulaire d'evaluation affiche le mode actif (automatique, manuel, ou desactive si consentement refuse). Les coordonnees manuelles sont soumises a la meme chaine de chiffrement OpenPGP que les coordonnees automatiques.


Cle BLUP

La paire de cles du moteur BLUP est generee une seule fois :

  • Cle publique : stockee dans NEXT_PUBLIC_BLUP_PGP_PUBLIC_KEY (.env.local + .env serveur). Exposee dans le bundle JS --- acceptable pour une cle publique
  • Cle privee : stockee dans blup_engine/blup_private_key.asc (jamais commitee, .gitignore). Utilisee uniquement par le moteur Python pour dechiffrer les coords avant calcul de correction environnementale
Rotation de cle

Si la cle privee BLUP est compromise, toutes les coordonnees GPS chiffrees pour BLUP sont lisibles. Generer une nouvelle paire immediatement et re-chiffrer les evaluations concernees.


Cron rotation annuelle

Route : POST /api/cron/annual-evaluation-rotation Auth : Bearer CRON_SECRET (timingSafeEqual) Schedule : 1er janvier 00:00 UTC

Clone les evaluations de l'annee precedente vers la nouvelle annee avec GPS vierge. Idempotent grace a la contrainte UNIQUE(queen_id, eval_year).

# Test manuel
curl -sf -X POST -H "Authorization: Bearer $CRON_SECRET" \
https://beepass.io/api/cron/annual-evaluation-rotation

Securite

AspectImplementation
ChiffrementOpenPGP ECDH curve25519 (multi-destinataires : owner + BLUP)
SignatureOpenPGP EdDSA curve25519 detachee
Derivation PINPBKDF2-SHA256, 600 000 iterations (OWASP 2024)
Chiffrement cle priveeAES-256-GCM (Web Crypto API)
Recovery codesFormat XXXX-XXXX (4 bytes random), SHA-256 + salt 16 bytes
SessionCle privee en memoire, expire apres 15 minutes
ImmutabiliteTriggers Postgres BEFORE UPDATE/DELETE
Zero-knowledgeSupabase ne voit que des blobs AES et PGP illisibles

Voir aussi