Stocker les secrets des applications Windows - Éviter les configurations en clair avec DPAPI
· Mis à jour le: · Go Komura · Développement Windows, Sécurité, DPAPI, C# / .NET, Win32
Dans l’article précédent, « Liste de contrôle minimale pour la sécurité du développement d’applications Windows », nous avions posé la ligne de base : « ne pas placer de secrets dans le code source ou dans une configuration en clair » et « sous Win32 / .NET, utiliser DPAPI / ProtectedData ».
Cette fois, nous approfondissons un peu plus l’un de ces points : « utiliser DPAPI pour être, au minimum, meilleur que le texte en clair ».
Cet article s’adresse aux applications Windows du type suivant :
- Applications de bureau WPF / WinForms / WinUI
- Clients Windows en C# / .NET
- Applications tentées de stocker des identifiants de connexion ou des jetons API dans un fichier de configuration local
Ce que nous traitons ici, c’est une conception réaliste pour « ne pas laisser en clair, dans appsettings.json, un secret qu’on est de toute façon obligé de stocker localement ».
Il ne s’agit pas d’une « défense parfaite qui bat n’importe quel attaquant ». Trop en rajouter sur ce point, et un article de sécurité se transforme vite en histoire de fantômes.
1. La conclusion d’abord
En pratique, il est plus clair de raisonner dans cet ordre.
- Ne pas donner de secret de longue durée au client, pour commencer
- Privilégier l’authentification Windows, l’authentification intégrée, la connexion interactive de l’utilisateur et la gestion des secrets côté serveur
- Si un stockage local est vraiment nécessaire, ne pas le laisser en clair
- Sous Windows, faire de DPAPI /
ProtectedDatale premier choix
- Sous Windows, faire de DPAPI /
- Pour une application de bureau classique, partir sur
DataProtectionScope.CurrentUserLocalMachinen’a que des cas d’usage assez limités
- DPAPI ne protège pas jusqu’à « la machine est totalement compromise »
- Un code exécuté avec les mêmes privilèges utilisateur peut, par nature, déchiffrer tout ce que cet utilisateur peut déchiffrer
Et le point le plus important de cet article se trouve ici :
« De toute façon, la clé secrète doit être stockée quelque part, alors d’un point de vue sécurité, le texte en clair et DPAPI ne reviennent-ils pas au même ? »
C’est à moitié vrai, mais la conclusion qu’on en tire est fausse.
- Un chiffrement AES maison, avec la clé placée dans la même application ou la même configuration, reste effectivement très proche du texte en clair
- Mais DPAPI délègue la gestion des clés au système d’exploitation et lie la partie capable de déchiffrer à « cet utilisateur Windows » ou à « cet ordinateur »
- La résistance à des incidents comme une fuite isolée du fichier de configuration, son transport vers un autre PC, un envoi par erreur, une fuite de sauvegarde ou une intrusion dans un dépôt de code en est donc radicalement changée
Autrement dit : même si l’affirmation abstraite « la clé est quelque part » les fait paraître identiques, « qui peut l’utiliser, dans quel contexte, et avec quelle facilité » est totalement différent.
Dire que « poser la clé sous le paillasson » et « la remettre à l’accueil après vérification d’identité » reviennent au même, c’est un peu abusif.
2. Pourquoi une configuration en clair est dangereuse
La raison pour laquelle le stockage en clair est dangereux tient beaucoup moins à la théorie cryptographique qu’à des considérations très terre à terre. En pratique, les fuites empruntent généralement ces chemins :
- Le fichier de configuration finit tel quel dans Git
- Le fichier de configuration se retrouve intégralement dans un ZIP d’investigation d’incident
- Une demande de support est envoyée avec le fichier de configuration en pièce jointe
- Des tiers peuvent le lire via des sauvegardes ou des partages de fichiers
- Les chaînes de connexion et les jetons apparaissent tels quels dans les journaux
- Un employé parti ou un autre utilisateur peut lire le fichier sur la même machine
Le problème majeur du texte en clair, c’est que dès l’instant où il est lu, c’en est fini du secret.
- Le fichier s’ouvre : c’est terminé
- Il est copié : c’est terminé
- Il est joint à un e-mail : c’est terminé
- Il reste dans un dépôt : il faudra s’en occuper quasiment indéfiniment
L’attaquant n’a même pas besoin d’être sophistiqué. « Ça s’ouvre dans un éditeur de texte » suffit déjà à en faire une protection très faible.
3. Réponse à « la clé secrète est de toute façon stockée quelque part, alors n’est-ce pas la même chose ? »
Cette question est légitime. Et y répondre de façon approximative, c’est exactement ce qui rend un article de sécurité soudainement flou.
La réponse : oui, au sens où « une clé est nécessaire quelque part » ; non, au sens où cela rendrait les deux situations identiques.
3.1. Ce qui est identique et ce qui diffère
Il est vrai que le chiffrement a, in fine, besoin d’une racine de confiance (root of trust). Un secret ne jaillit pas gratuitement de nulle part dans l’univers. Ce monde-là ne fait pas de cadeaux.
Cependant, la différence en matière de sécurité se joue sur ces trois points :
- L’application détient-elle la clé directement ?
- À quelle partie la clé est-elle liée ?
- Si seul le fichier est volé, peut-il être déchiffré ?
Un tableau grossier de ces différences donne ceci.
| Méthode | Le fichier de configuration est lu | Seul le fichier est transporté vers un autre PC | Lu par un autre utilisateur sur le même PC | Code exécuté avec les mêmes privilèges utilisateur |
|---|---|---|---|---|
| Texte en clair | Fuite immédiate | Fuite telle quelle | Fuite telle quelle | Lisible, évidemment |
| Chiffrement maison + clé dans la même configuration / le même binaire | Fuite quasi certaine | Fuite quasi certaine | Fuite quasi certaine | Déchiffrable, évidemment |
DPAPI + CurrentUser |
Pas directement lisible depuis le fichier seul | Normalement difficile à déchiffrer | Normalement difficile à déchiffrer | Déchiffrable |
DPAPI + LocalMachine |
Pas directement lisible depuis le fichier seul | Normalement difficile à déchiffrer en dehors de ce PC | Largement déchiffrable sur ce même PC | Déchiffrable |
Le point important ici est que DPAPI sépare « pouvoir lire le fichier » de « pouvoir utiliser le secret ».
Avec le texte en clair, ces deux choses n’en font qu’une. Si le fichier peut être lu, le secret peut l’être aussi.
Mais avec DPAPI - au moins avec CurrentUser - le déchiffrement doit se faire :
- en tant que cet utilisateur Windows
- dans ce contexte Windows précis
- via le mécanisme de protection du système d’exploitation
Sur le terrain, au moment d’un incident, cette différence pèse lourd.
3.2. « Mais un même utilisateur peut quand même déchiffrer, non ? » - Exact
Ce point doit être écrit sans détour.
Un code exécuté avec les mêmes privilèges utilisateur peut, par nature, déchiffrer tout ce que cet utilisateur peut déchiffrer.
Autrement dit, DPAPI n’a pas pour objectif premier de couvrir des situations comme :
- la machine est déjà compromise par un logiciel malveillant
- l’attaquant peut exécuter du code en tant que cet utilisateur
- la machine est totalement prise de contrôle au niveau administrateur
Dans ces situations, puisque l’application elle-même peut déchiffrer, le code de l’attaquant le peut aussi. Dans ce cas, un « mais c’est chiffré » n’est pas particulièrement rassurant.
DPAPI est surtout efficace du côté « fuite de fichier / erreur de placement / exfiltration hors ligne / accès par un autre utilisateur ».
Se tromper sur ce point mène à deux écueils :
- sous-estimer ce qu’il protège et ne pas l’utiliser
- surestimer ce qu’il ne protège pas et se croire en sécurité
Les deux sont dangereux, discrètement.
3.3. Alors, quel est le bénéfice concret ?
L’intérêt de DPAPI, en une phrase :
« Découpler le secret lui-même de la lisibilité du fichier de configuration. »
Par exemple, le texte en clair et DPAPI font une vraie différence dans des incidents comme ceux-ci :
- un utilisateur a envoyé le fichier de configuration au support
- le fichier de configuration s’est retrouvé dans un ZIP d’investigation
- seul le fichier de configuration a fuité depuis une sauvegarde
- il a été copié sur un dossier partagé
- un développeur n’a vu que le texte chiffré, sans pouvoir en lire le contenu
Ce sont des bénéfices tout à fait concrets. On peut réduire le rayon des incidents du quotidien sans avoir besoin de transformer l’attaquant en surhomme de cinéma.
4. Pourquoi DPAPI tombe juste
Pour gérer des secrets stockés localement sous Windows, voici les raisons pour lesquelles DPAPI se situe exactement au bon endroit en pratique.
4.1. La gestion des clés peut être déléguée à l’OS
Générer soi-même une clé AES, la stocker, lui attribuer des permissions, la faire tourner, réfléchir à l’impact d’une fuite, et ajouter une détection de falsification. C’est plus lourd qu’il n’y paraît. Et fait à la légère, cela finit généralement par placer la clé au même endroit que le reste.
Avec DPAPI, le problème « comment créer la clé de chiffrement et où la placer » peut être retiré de l’implémentation de l’application.
En ce sens, il est plus juste de voir DPAPI comme « une API qui délègue la gestion des clés au système d’exploitation » plutôt que comme « une API permettant de choisir un algorithme de chiffrement ».
4.2. La partie qui déchiffre peut être liée à un utilisateur Windows ou à l’ordinateur
Pour une application de bureau classique, choisir CurrentUser est souvent le bon réflexe.
Le déchiffrement suppose alors :
- que cet utilisateur soit connecté
- que le traitement s’exécute dans le contexte de cet utilisateur
On obtient ainsi la propriété que copier uniquement le texte chiffré vers un autre PC ne le rend pas directement exploitable.
4.3. La détection de falsification vient facilement avec
Une erreur fréquente avec un chiffrement maison est de se dire « on a chiffré avec AES, c’est terminé » et d’oublier la détection de falsification.
DPAPI apporte aussi une protection de l’intégrité sur les données chiffrées, ce qui fait que la détection d’une réécriture du texte chiffré peut s’appuyer sur le mécanisme côté OS - un avantage bien concret en pratique.
4.4. Simple à utiliser depuis C# / .NET
En C#, on peut utiliser directement System.Security.Cryptography.ProtectedData.
Ne pas avoir à ajouter de bibliothèque supplémentaire est un vrai confort pour une application réservée à Windows.
5. Ce que DPAPI protège, et ce qu’il ne protège pas
Il est plus sûr de tracer clairement cette limite.
5.1. Ce qui devient plus facile à protéger
DPAPI est efficace, au moins, dans des situations comme celles-ci :
- fuite en clair d’un fichier de configuration
- fichier transporté vers un autre PC
- accès par un autre utilisateur sur le même PC (en supposant
CurrentUser) - fuite via une sauvegarde ou une pièce jointe
- l’état « ah, ça se lit sans faire attention » qu’on rencontre en développement ou en maintenance
5.2. Ce qu’il ne protège pas, ou protège mal
À l’inverse, il vaut mieux ne pas trop lui faire confiance dans les situations suivantes :
- du code malveillant exécuté avec les mêmes privilèges utilisateur
- une compromission complète de la machine elle-même
- une prise de contrôle au niveau administrateur
- le texte en clair en mémoire une fois que l’application a déchiffré la valeur
- un secret de longue durée distribué à l’identique sur tous les clients
Ce dernier point - « un secret de longue durée commun à tous les clients » - est particulièrement important.
Par exemple, des conceptions comme :
- intégrer la même clé API pour tous les clients
- partager le même mot de passe sur toutes les machines
- distribuer une clé de déchiffrement fixe qui vit entièrement côté client
sont des conceptions où l’extraction depuis une seule machine tend à se répercuter sur l’ensemble.
DPAPI est efficace pour « rendre cet emplacement de stockage meilleur que le texte en clair », mais il ne justifie en rien des secrets qui ne devraient tout simplement pas se trouver côté client.
6. Choisir entre CurrentUser et LocalMachine
Ce point compte énormément. Un choix fait à la légère change radicalement la portée de la protection.
6.1. CurrentUser par défaut
Pour une application de bureau Windows classique, il faut d’abord raisonner en partant de CurrentUser.
Cas bien adaptés :
- applications de bureau WPF / WinForms / WinUI destinées aux utilisateurs
- applications qui ont des paramètres et des identifiants par utilisateur
- applications qui conservent leurs paramètres sous
%LocalAppData%ou%AppData%
Dans ce cas, il devient naturel de traiter la donnée comme « le secret de cet utilisateur Windows ».
6.2. LocalMachine : des cas d’usage assez limités
LocalMachine paraît pratique, mais pour une application de bureau ordinaire, il est trop large.
Il convient plutôt à des cas comme :
- un service Windows sur une machine de confiance dédiée à un seul usage
- un secret utilisé uniquement par un processus précis sur cette machine
- des cas qui doivent réellement fonctionner à travers plusieurs utilisateurs connectés sur la même machine
Mais les précautions à prendre sont lourdes.
- Il est largement déchiffrable par les processus qui tournent sur ce PC
- Il devient facilement dangereux sur les machines partagées, les hôtes RDS, les machines rebond et les environnements multi-utilisateurs
- Le choisir « pour que tout le monde puisse s’en servir facilement » finit généralement par poser problème plus tard
6.3. En cas de doute, raisonner ainsi
- Application UI classique ->
CurrentUser - Cas particulier où l’on veut vraiment protéger au niveau de la machine ->
LocalMachine - Il faut que n’importe quel utilisateur puisse déchiffrer, mais d’autres utilisateurs sont présents sur la machine -> il vaut généralement mieux revoir la conception elle-même
6.4. Les services et l’impersonation demandent un peu plus de vigilance
Dès qu’on mêle des services Windows ou de l’impersonation, la portée de CurrentUser devient un peu plus lourde à cerner.
- Quel est le compte d’exécution ?
- Le profil de ce compte est-il chargé ?
- Dans quel contexte se produit le déchiffrement ?
Un décalage sur ces points aboutit facilement à « ça a chiffré correctement, mais ça ne déchiffre pas ».
Pour un usage de type service, se contenter de « CurrentUser par défaut » ne suffit pas toujours.
7. Consignes minimales d’implémentation
Si l’objectif se limite à « arrêter de stocker en clair dans le fichier de configuration » d’une application Windows, la conception n’a pas besoin d’être très complexe. Il y a néanmoins quelques points qu’on ne veut pas manquer.
7.1. Ne protéger que les secrets
Plutôt que de chiffrer l’ensemble de la configuration en bloc, il est plus simple de gérer les choses si l’on protège uniquement les éléments secrets.
Par exemple, on peut séparer ainsi. Ceux-ci peuvent souvent rester en clair :
- URL du serveur
- nom d’utilisateur
- nom de la base de données
- indicateurs de fonctionnalités (feature flags)
Alors que ceux-ci sont à protéger :
- mots de passe
- jetons API
- jetons de rafraîchissement (refresh tokens)
- identifiants de dossiers partagés
Avec ce découpage, on gagne :
- une édition de la configuration plus facile
- une revue de différences plus facile
- une clarté sur ce qui est secret
- une exploitation globale plus simple
7.2. Stocker par défaut dans un emplacement par utilisateur
Pour une application de bureau classique, l’emplacement de stockage par défaut doit être un emplacement par utilisateur.
%LocalAppData%\Vendor\App\settings.json%AppData%\Vendor\App\settings.json
Au minimum, il vaut mieux ne pas le placer négligemment sous le dossier d’installation ou dans un endroit facile à partager.
Même protégé par DPAPI, si les ACL de l’emplacement de stockage sont négligées, on retombe sur « le texte chiffré peut être lu », « la structure de la configuration reste visible », « des erreurs d’exploitation se produisent ». La défense fonctionne mieux en couches successives que sur un seul niveau.
7.3. optionalEntropy n’est pas une seconde clé miracle
ProtectedData permet de passer un optionalEntropy.
C’est pratique, mais ce n’est pas « une seconde clé magique qui rend tout sûr dès qu’on l’intègre dans le binaire ».
- La placer dans le même fichier n’en fait pas un secret
- L’intégrer comme valeur fixe dans le binaire n’en fait pas non plus un secret solide
- Cela reste tout de même utile pour identifier l’usage et éviter les erreurs de réutilisation
En pratique, faire passer une suite d’octets fixe construite à partir :
- du nom de l’application
- du nom de l’usage
- d’un identifiant de version
et l’utiliser « pour éviter d’accepter par erreur un texte chiffré destiné à un autre usage » est à peu près le bon niveau d’ambition.
7.4. Cela ne veut pas dire que le texte chiffré peut aller dans Git
Ce point aussi est discrètement important.
Le texte chiffré par DPAPI est bien meilleur que le texte en clair, mais cela ne veut pas dire que le fichier de configuration entier peut aller dans le dépôt.
Les raisons sont simples :
- le texte chiffré reste en place longtemps
- la même machine ou le même contexte pourrait un jour se reproduire
- le fichier contient aussi des informations autres que le secret
- une culture du « c’est protégé, donc on peut être négligent » finit par s’installer
« Meilleur que le texte en clair » et « sûr n’importe où on le place » sont deux choses complètement différentes.
7.5. Ne pas l’écrire dans les journaux
Un schéma étonnamment courant consiste à tout gâcher en écrivant la valeur dans les journaux après déchiffrement.
- afficher intégralement la chaîne de connexion en cas d’échec de connexion
- laisser l’en-tête Authorization dans les journaux lors d’une erreur API 401
- mélanger des secrets dans les messages d’exception
Faites cela, et même après avoir éliminé le texte en clair du fichier de configuration, ce sont finalement les journaux qui deviennent l’entrepôt du texte en clair. Triste, mais très réel sur le terrain.
8. Exemple d’implémentation minimale en C# / .NET
Voici un exemple minimal protégeant, avec CurrentUser, une chaîne destinée à être enregistrée dans un fichier de configuration.
Un optionalEntropy fixe y figure pour l’identification de l’usage, mais ne le considérez surtout pas comme une clé secrète.
using System;
using System.Security.Cryptography;
using System.Text;
public static class DpapiSecretProtector
{
// Pour l'identification de l'usage. Ce n'est pas une seconde clé secrète.
private static readonly byte[] Entropy =
Encoding.UTF8.GetBytes("ComComponent:DesktopApp:SettingsSecret:v1");
public static string ProtectToBase64(string plaintext)
{
ArgumentNullException.ThrowIfNull(plaintext);
byte[] plainBytes = Encoding.UTF8.GetBytes(plaintext);
byte[] protectedBytes = Array.Empty<byte>();
try
{
protectedBytes = ProtectedData.Protect(
plainBytes,
optionalEntropy: Entropy,
scope: DataProtectionScope.CurrentUser);
return Convert.ToBase64String(protectedBytes);
}
finally
{
Array.Clear(plainBytes, 0, plainBytes.Length);
if (protectedBytes.Length > 0)
{
Array.Clear(protectedBytes, 0, protectedBytes.Length);
}
}
}
public static string UnprotectFromBase64(string protectedBase64)
{
ArgumentNullException.ThrowIfNull(protectedBase64);
byte[] protectedBytes = Convert.FromBase64String(protectedBase64);
byte[] plainBytes = Array.Empty<byte>();
try
{
plainBytes = ProtectedData.Unprotect(
protectedBytes,
optionalEntropy: Entropy,
scope: DataProtectionScope.CurrentUser);
return Encoding.UTF8.GetString(plainBytes);
}
finally
{
Array.Clear(protectedBytes, 0, protectedBytes.Length);
if (plainBytes.Length > 0)
{
Array.Clear(plainBytes, 0, plainBytes.Length);
}
}
}
}
L’usage est simple.
string protectedPassword = DpapiSecretProtector.ProtectToBase64(password);
// Enregistrer dans un JSON, etc.
// settings.DbPasswordProtected = protectedPassword;
string password = DpapiSecretProtector.UnprotectFromBase64(settings.DbPasswordProtected);
Le fichier de configuration peut alors prendre une forme comme celle-ci.
{
"ApiBaseUrl": "https://api.example.com/",
"UserName": "app-user",
"PasswordProtected": "AQAAANCMnd8BFdERjHoAwE..."
}
Ce qui rend cette forme intéressante :
- l’URL et le nom d’utilisateur restent modifiables normalement
- seul le mot de passe est protégé
- la structure de la configuration reste lisible
- c’est moins propice aux incidents que de tout laisser en clair
9. Des conceptions qui restent dangereuses
Même en utilisant DPAPI, les conceptions suivantes restent dangereuses.
9.1. Conserver la valeur déchiffrée trop longtemps
Il vaut mieux éviter de prendre la valeur déchiffrée et de :
- l’écrire dans les journaux
- l’afficher à l’écran
- l’inclure dans une exception
- la laisser traîner sur un objet à durée de vie longue
« Chiffré au repos » et « sûr pendant l’utilisation » sont deux problèmes distincts.
9.2. Donner un secret commun à toutes les installations
Par exemple, une conception où tous les utilisateurs détiennent la même clé API n’est pas réellement résolue en la stockant via DPAPI.
Car si l’application peut la déchiffrer sur une seule machine, ce secret peut en être extrait à cet endroit-là.
Ce type de secret gagne à être orienté vers :
- un stockage côté serveur
- un client qui ne détient que des jetons
- des identifiants par utilisateur
- des jetons à durée limitée
9.3. Choisir LocalMachine « parce que c’est plus simple »
C’est vraiment un cas fréquent.
On est tenté de choisir LocalMachine parce que :
- ça reste lisible même après un changement d’utilisateur
- un service peut aussi le lire
- c’est pratique tant que ça fonctionne
Mais pour une application de bureau ordinaire, cela étend la possibilité de déchiffrement à d’autres processus présents sur ce PC, ce qui change considérablement la portée de la protection.
9.4. Se rassurer en ajoutant un chiffrement maison
Au lieu de DPAPI, des implémentations comme :
- intégrer une clé AES dans le code source
- placer la clé AES dans un autre champ du fichier de configuration
- traiter une « chaîne de caractères un peu obfusquée » comme une clé
sont généralement de peu d’effet.
Entre « ce n’est pas en clair » et « c’est sûr », il existe un fossé assez large.
10. Les cas où DPAPI ne suffit pas
DPAPI est pratique, mais il n’est pas la panacée. Dans les cas suivants, mieux vaut envisager une autre option.
10.1. Vous voulez fonctionner aussi hors de Windows
DPAPI / ProtectedData sont réservés à Windows.
Une application multiplateforme ne peut pas s’appuyer sur cette hypothèse.
10.2. Vous voulez partager le même secret entre plusieurs machines ou utilisateurs
Un besoin de déchiffrer le même texte chiffré sur plusieurs PC, ou de le mutualiser entre plusieurs utilisateurs, sort du domaine de prédilection de DPAPI, qui lie le secret « à cette machine, à cet utilisateur ».
Dans ce cas, il faut plutôt envisager une conception adaptée au besoin, comme :
- une gestion des secrets côté serveur
- une infrastructure d’identifiants
- l’authentification Windows / l’authentification intégrée
- un magasin d’identifiants dédié à l’application
10.3. Ce qui est stocké est directement des identifiants utilisateur
Pour une application de bureau packagée / de type WinUI, si ce qui est stocké est clairement une paire :
- nom d’utilisateur
- mot de passe
le Credential Locker devient également une option. Mais le cœur de cet article reste la ligne de base pratique de DPAPI pour « arrêter le texte en clair dans les fichiers de configuration des clients Windows ».
11. Ordre de priorité recommandé en pratique
Pour finir, en cas d’hésitation en pratique, raisonner dans cet ordre permet d’y voir clair.
Priorité 1 : ne pas le détenir du tout
- authentification Windows
- authentification intégrée
- connexion interactive
- conservation du secret côté serveur
- jetons de courte durée
Priorité 2 : privilégier des secrets par utilisateur
- privilégier le par-utilisateur plutôt qu’un secret commun
- privilégier des jetons renouvelables plutôt que des identifiants fixes de longue durée
- éviter une clé commune à tous les clients
Priorité 3 : si un stockage local est nécessaire, DPAPI
CurrentUseren règle générale- un emplacement de stockage par utilisateur
- ne protéger que les éléments secrets
- ne pas les écrire dans les journaux
Priorité 4 : traiter LocalMachine comme une exception
- est-ce vraiment nécessaire au niveau de la machine ?
- d’autres utilisateurs se connectent-ils sur cette machine ?
- est-ce cohérent en tant que conception de service ?
12. Résumé
Lorsqu’une application Windows doit stocker des informations sensibles dans un fichier de configuration, mieux vaut éviter de les laisser en clair.
Et à la question :
« De toute façon, la clé est stockée quelque part, alors n’est-ce pas la même chose ? »
la réponse pratique est la suivante :
- avec un chiffrement maison où la clé est placée au même endroit, c’est effectivement quasiment la même chose
- DPAPI, en revanche, n’est pas la même chose
- la gestion des clés peut être déléguée à l’OS
- la partie qui déchiffre peut être liée à un utilisateur Windows / un ordinateur
- une fuite isolée du fichier n’équivaut plus directement à une fuite du secret
- cela dit, cela ne résout pas :
- le cas d’un code exécuté avec les mêmes privilèges utilisateur
- le cas d’une machine totalement compromise
- le cas de secrets communs de longue durée qui ne devraient tout simplement pas se trouver côté client
En somme, DPAPI n’est pas une forteresse infranchissable. Mais il a à peu près l’effet de remplacer la vitre grande ouverte qu’est une configuration en clair par au moins une fenêtre décente.
Dans le travail quotidien sur des clients Windows, cette différence est considérable. Commencer par bien traiter ce point est l’approche la plus réaliste.
13. Références
- Article précédent : https://comcomponent.com/fr/blog/2026/03/14/001-windows-app-security-minimum-checklist/
- Microsoft Learn :
CryptProtectDatahttps://learn.microsoft.com/en-us/windows/win32/api/dpapi/nf-dpapi-cryptprotectdata - Microsoft Learn :
ProtectedDatahttps://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.protecteddata?view=windowsdesktop-10.0 - Microsoft Learn :
DataProtectionScopehttps://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.dataprotectionscope?view=windowsdesktop-10.0 - Microsoft Learn : How to: Use Data Protection https://learn.microsoft.com/en-us/dotnet/standard/security/how-to-use-data-protection
- Microsoft Learn : Credential locker for Windows apps https://learn.microsoft.com/en-us/windows/apps/develop/security/credential-locker
Articles associés
Articles récents partageant les mêmes étiquettes, pour approfondir des sujets proches.
Comment isoler concrètement, dans une application Windows, « uniquement les opérations nécessitant des privilèges administrateur »
Comment concevoir une application Windows qui garde son UI en asInvoker tout en isolant dans un helper EXE les seuls traitements nécessit...
Liste de contrôle minimale de sécurité pour le développement d'applications Windows
Pour les applications métier WPF / WinForms / WinUI / C++ / C#, cet article organise sous forme de liste de contrôle les bases concernant...
Pourquoi Windows est devenu ce qu'il est aujourd'hui : l'évolution de Windows vue par un développeur
Un panorama des évolutions de Windows 95 à Windows 11, non pas comme une simple frise visuelle, mais du point de vue d'un développeur d'a...
Quand votre application Windows maison est signalée comme un virus — gérer les faux positifs de Microsoft Defender et composer avec l'impact sur les performances
Nous détaillons la marche à suivre officielle lorsque Microsoft Defender signale à tort une application Windows développée en interne com...
MAX_PATH et les pièges des chemins et noms de fichiers Windows — la limite de 260 caractères, les noms réservés, les points de fin et la casse
Un tour d'horizon des limites de chemins et de noms de fichiers à l'origine du classique bug « fichier introuvable ». Cet article couvre ...
Sujets associés
Ces pages replacent le sujet dans un contexte plus large de services et de décisions.
Thèmes techniques Windows
Portail des sujets sur le développement Windows, l'analyse des incidents et la valorisation des actifs existants.
Services liés à ce sujet
Cet article est directement lié aux services suivants.
Développement d'applications Windows
Ce sujet touche à la conception globale d'une application Windows - la façon de stocker les identifiants, l'emplacement des paramètres par utilisateur et ce qui doit ou non apparaître dans les journaux - il s'accorde donc bien avec notre service de développement d'applications Windows.
Conseil technique et revue de conception
Si vous souhaitez commencer par revoir les configurations en clair d'une application existante ou clarifier le choix entre DPAPI et le Credential Locker, ce sujet se prête bien à un accompagnement de type conseil technique et revue de conception.
Questions fréquentes
Questions souvent posées lors d’une consultation sur le sujet de cet article.
- Qu'est-ce que DPAPI ?
- DPAPI (Data Protection API) est un mécanisme de protection des données fourni par Windows : il délègue la gestion des clés de chiffrement au système d'exploitation et lie la partie capable de déchiffrer à cet utilisateur Windows précis ou à cet ordinateur précis. Depuis C# / .NET, on l'utilise via la classe System.Security.Cryptography.ProtectedData, sans avoir à ajouter de bibliothèque supplémentaire. Il est plus juste de le voir non pas comme une API permettant de choisir un algorithme de chiffrement, mais comme une API qui délègue la gestion des clés au système d'exploitation. C'est une option réaliste pour éviter de laisser en clair, dans un fichier de configuration, les mots de passe ou les jetons API.
- La clé doit bien être stockée quelque part, alors le texte en clair et DPAPI ne reviennent-ils pas au même ?
- Non, ce n'est pas la même chose. Un chiffrement AES maison, avec la clé placée dans la même application ou le même fichier de configuration, reste effectivement très proche du texte en clair. Mais DPAPI délègue la gestion des clés au système d'exploitation et lie la partie capable de déchiffrer à un utilisateur Windows ou à un ordinateur donné. La résistance à des incidents comme une fuite isolée du fichier de configuration, son transport vers un autre PC, un envoi par erreur, une fuite de sauvegarde ou une intrusion dans un dépôt de code s'en trouve donc radicalement changée. La différence décisive avec le texte en clair, c'est que DPAPI sépare « pouvoir lire le fichier » de « pouvoir utiliser le secret ».
- Que DPAPI ne protège-t-il pas ?
- Un code exécuté avec les mêmes privilèges utilisateur peut, par nature, déchiffrer tout ce que cet utilisateur peut déchiffrer. DPAPI ne protège donc pas contre une machine déjà compromise par un logiciel malveillant, une prise de contrôle au niveau administrateur, ni contre le texte en clair présent en mémoire une fois le secret déchiffré. De même, un secret de longue durée distribué à l'identique sur tous les clients n'est pas réellement résolu par un stockage via DPAPI, car son extraction depuis une seule machine suffit à compromettre l'ensemble. DPAPI est surtout efficace du côté des fuites de fichiers, des erreurs de placement, de l'exfiltration hors ligne et de l'accès par un autre utilisateur.
- Faut-il utiliser CurrentUser ou LocalMachine pour DataProtectionScope ?
- Pour une application de bureau Windows classique, CurrentUser est le choix par défaut : le secret est alors traité comme appartenant à cet utilisateur, et copier uniquement le texte chiffré vers un autre PC ne le rend pas directement exploitable. LocalMachine, lui, peut être déchiffré largement par les processus qui tournent sur ce PC, ce qui devient risqué sur les machines partagées ou les environnements multi-utilisateurs ; ses cas d'usage restent donc assez limités, par exemple un service Windows sur une machine de confiance dédiée à un seul usage. Choisir LocalMachine parce que « tout le monde peut s'en servir, c'est plus simple » finit généralement par poser problème plus tard.
Profil de l’auteur
Page de présentation de l’auteur de l’article.
Go Komura
Représentant de KomuraSoft LLC
Spécialisé dans le développement de logiciels Windows, le conseil technique et l’analyse de pannes, notamment pour les systèmes existants et les incidents difficiles à reproduire.
Liens publics