Le problème, que vous décrivez, me semble très intéressant, mais sans quelques informations supplémentaires et quelques expériences il est difficile de dire définitivement quelle est la raison. Alors j'essaie de décrire comment je comprends le problème. En premier lieu, les classes de cryptographie .NET utilisent en interne le CryptoAPI non géré. Donc, la méthode _OpenCSP
appel interne CryptAcquireContext fonction. Dans sa la documentation, nous pouvons lire la suite de l'erreur NTE_BAD_KEY_STATE
(0x8009000BL):
Le mot de passe de l'utilisateur a changé depuis les clés privées ont été chiffrés.
utilisateurs privés clés utilisées par le fournisseur DSA sont enregistrées sous forme de fichiers dans le répertoire %APPDATA%\Microsoft\Crypto\DSS\[SID]
et seront cryptés avec un algorithme relativement sophistiqué sur lequel vous pouvez lire here. Important de comprendre que les fichiers du répertoire correspondent aux conteneurs clés des clés de l'utilisateur. Généralement, l'utilisateur a un accès complet aux fichiers du système de fichiers. Les fichiers seront cryptés avec la clé qui dépend du mot de passe de l'utilisateur. Dans de nombreux cas standard, les fichiers seront rechiffrés après le changement de mot de passe, mais l'algorithme de récupération, qui dépend de beaucoup de choses.Si le mot de passe a été réinitialisé au lieu de changer par l'utilisateur lui-même (par un administrateur de domaine/opérateur de compte et ainsi de suite), l'ancien contenu du répertoire %APPDATA%\Microsoft\Crypto\DSS\[SID]
pourrait ne pas être plus utile. Par exemple, si l'utilisateur n'est pas un utilisateur Active Directory (un utilisateur local) et que l'administrateur local a réinitialisé son mot de passe, alors le problème avec les conteneurs cryptographiques aura lieu.
Donc la première suggestion serait de demander à l'utilisateur si son mot de passe Active Directory a été réinitialisé. Ensuite, vous devez vérifier que le répertoire %APPDATA%\Microsoft\Crypto\DSS\[SID]
existe dans le profil de l'utilisateur et que l'utilisateur a un accès complet au répertoire dans le système de fichiers. Le vous devez supprimer tous les fichiers du répertoire (en créant précédemment la copie de sauvegarde des fichiers). Par ailleurs, il est intéressant de savoir si l'utilisateur a un profil enregistré central (enregistré sur le serveur). S'il a un profil central, on peut vérifier que le même problème, que vous décrivez, existe sur l'autre ordinateur pour l'utilisateur et que l'autre utilisateur n'aura aucun problème sur son ordinateur d'origine.
Une question qui n'est pas tout à fait clair pour moi est pourquoi le conteneur clé du répertoire %APPDATA%\Microsoft\Crypto\DSS\[SID]
sont utilisés du tout parce que vous utilisez uniquement clés publiques. Dans CryptoAPI, il faut utiliser CryptAcquireContext
avec NULL
comme paramètre pszContainer
et CRYPT_VERIFYCONTEXT
dans dwFlags
. Je ne suis pas sûr que .NET utilise le drapeau CRYPT_VERIFYCONTEXT
et il pourrait être indirect votre problème. Vous pouvez créer DSACryptoServiceProvider
avec the constructor ayant le paramètre CspParameters. de l'autre côté a la propriété Flags qui est étendue dans .NET 4.0 avec la valeur CreateEphemeralKey. La description de CspProviderFlags.CreateEphemeralKey
est très proche de la description du drapeau CRYPT_VERIFYCONTEXT
de la fonction CryptAcquireContext
. Donc, l'utilisation peut essayer d'utiliser CspProviderFlags.CreateEphemeralKey ou CspProviderFlags.CreateEphemeralKey
avec CspProviderFlags.UseDefaultKeyContainer
(NULL
comme pszContainer
paramètre de CryptAcquireContext
signifie également le conteneur de clé par défaut). En outre, si cela est possible, vous pouvez essayer de déboguer le problème sur l'ordinateur où le problème peut être reproduit. Pour le débogage, vous pouvez utiliser les sources .NET qui peuvent être activées (voir here et here) ou téléchargé depuis here. Vous pouvez ensuite répondre à certaines questions sur les valeurs de CspParameters
actuellement utilisées dans votre programme et comparer les valeurs de .NET 3.5 et .NET 4.0.
Si ce que j'ai écrit ne contribuera pas à résoudre le problème, s'il vous plaît pourriez-vous ajouter à votre question avec des informations supplémentaires:
- Quel système d'exploitation et quel service pack a l'ordinateur où le problème peut être reproduit?
- Le problème est-il lié à l'utilisateur? Je veux dire: a d'autres utilisateurs sur le même ordinateur le même problème?
- Le problème existe-t-il avec l'utilisateur de domaine (répertoire actif) ou avec le compte d'utilisateur local? A l'utilisateur qui a le profil d'utilisateur central de problème qui sont sauvés sur le serveur? S'il a, que le problème peut être reproduit également sur les autres ordinateurs par l'utilisateur?
- Pourriez-vous décrire un peu plus l'environnement dans lequel vous utilisez la vérification de clé publique? Surtout que le programme s'exécute dans le contexte de sécurité de l'utilisateur ou que vous faites une certaine usurpation d'identité?
MISE À JOUR: Après avoir lu du forum où le problème a été affiché, je deviens pessimiste sur la résolution du problème. Si vous n'avez aucun contact direct avec l'ordinateur où le problème pourrait être reproduit et la communication avec le seul utilisateur qui a le problème est faite seulement par affichage dans le forum ... Néanmoins, j'ai réfléchi au problème et j'ai donc décidé de essayez de reproduire le problème moi-même. Et j'ai eu du succès dans ça. Donc, je vais décrire ici mes résultats avec soin. Je vais décrire comment le peut reproduire le problème de sorte qu'il ressemble exactement à ce qui est décrit dans the forum thread.
Vous devez effectuer les étapes suivantes: Vous créez un compte de test local sur votre ordinateur
1). 2) Vous vous connectez avec le compte de test et générez le conteneur de clé par défaut pour le fournisseur DSA. Vous pouvez le faire par exemple en ce qui concerne le petit programme .NET qui appelle la fonction suivante simple:
static string GenerateDsaKeyInDefaultContainer()
{
const int PROV_DSS_DH = 13;
CspParameters cspParam = new CspParameters(PROV_DSS_DH);
cspParam.KeyContainerName = null;
cspParam.KeyNumber = (int)KeyNumber.Signature;
cspParam.Flags = CspProviderFlags.UseDefaultKeyContainer;
DSACryptoServiceProvider csp = new DSACryptoServiceProvider(cspParam);
return csp.CspKeyContainerInfo.UniqueKeyContainerName;
}
la fonction retourne le nom du fichier qui sera créé dans le répertoire %APPDATA%\Microsoft\Crypto\DSS\[SID]
et qui contiendra la clé générée paire. 3) Vous vous déconnectez du compte de test et vous vous connectez avec un autre compte disposant de droits d'administration locaux. Vous réinitialisez le mot de passe du compte de test. 4) Vous vous connectez une fois de plus avec le compte de test et vérifiez que le programme de test que vous avez compilé dans Visual Studio 2010 pour .NET 4.0 génère l'erreur NTE_BAD_KEY_STATE
(0x8009000b) et l'exception correspondante sera levée. 5) Si vous recompilez le programme pour .NET 3.5 au lieu de .NET 4.0 (vous pouvez également utiliser Visual Studio 2010), le programme de test sera exécuté sans erreur.
Donc, tous les résultats seront exactement comme il est décrit dans the forum thread.
Si vous supprimez ou renommer le fichier avec le conteneur de clé par défaut pour le fournisseur DSA, le problème sera résolu. Comme je l'ai décrit précédemment après la réinitialisation du mot de passe des utilisateurs, le contenu du conteneur de clé par défaut ne pourra pas être déchiffré. Donc, si vous connaissez le nom du conteneur par défaut qui est unique pour l'utilisateur (vous pouvez voir le nom par exemple à partir des traces du Process Monitor) vous pouvez simplement copier n'importe quel fichier conteneur de clé d'un autre utilisateur et n'importe quel autre ordinateur dans le répertoire %APPDATA%\Microsoft\Crypto\DSS\[SID]
, renommer le fichier de sorte que le nom sera le nom du conteneur par défaut et ... vous aurez absolument les mêmes résultats comme avec la réinitialisation du mot de passe des utilisateurs.
j'ai fait quelques expériences avec différents paramètres du CspParameters
comme paramètre de DSACryptoServiceProvider
(voir mes premières suggestions au sujet de l'utilisation de CspProviderFlags.CreateEphemeralKey), mais sans aucun succès. Après que j'ai débogué le code source de .NET 4.0 et peut définitivement dire que l'appel de _OpenCSP
fonction, ce code n'est pas ouvert, sera appelé avec les paramètres qui sont indépendant à partir des paramètres du constructeur DSACryptoServiceProvider
. Donc, on ne peut pas trouver une solution de contournement du problème pour .NET 4.0 de la manière avec les différents paramètres du CspParameters
comme paramètre de DSACryptoServiceProvider
.
Donc, si vous voulez modifier votre code afin qu'il devrait fonctionner également dans la situation avec le fournisseur de clé par défaut corrompu que je vois actuellement que deux façons de résoudre le problème:
- Mettre en oeuvre tout ou partie de code utilisant la fonction
CryptAcquireContext
non gérée avec le drapeau CRYPT_VERIFYCONTEXT
.
- Détectez le problème avec l'erreur
NTE_BAD_KEY_STATE
(0x8009000b) et incluez la partie de code supprimant ou renommant temporairement le fichier de %APPDATA%\Microsoft\Crypto\DSS\[SID]
qui contient le conteneur de clé par défaut endommagé. Pour détecter le nom du fichier, je pense que vous pouvez essayer d'utiliser la fonction CryptGetProvParam
avec les paramètres PP_UNIQUE_CONTAINER
ou/et PP_ENUMCONTAINERS
.
Je suis désolé pour le long texte de ma réponse et merci à tous ceux qui sont capables de le lire jusqu'à cet endroit. :-)
J'espère que ma réponse vous aidera KristoferA pour résoudre le problème et améliorer le logiciel que vous développez.
Ajouté une prime ... – KristoferA