Le problème, que vous décrivez, me semble très intéressant, mais sans que des informations supplémentaires et certaines expériences, il est difficile définitivement à dire ce qu'est la raison. J'ai donc essayer de décrire comment je comprends le problème.
Tout d'abord .NET classes de chiffrement utilisent en interne non managé CryptoAPI. Donc, la méthode de _OpenCSP
d'appels en interne CryptAcquireContext fonction. Dans sa les documents, nous pouvons lire ce qui suit à propos de l'erreur NTE_BAD_KEY_STATE
(0x8009000BL):
Le mot de passe utilisateur a changé depuis
les clés privées ont été chiffrés.
Les utilisateurs privés, les clés utilisées par la DSA, fournisseur sont enregistrés en tant que fichiers dans le répertoire %APPDATA%\Microsoft\Crypto\DSS\[SID]
, et seront chiffrées avec relativement algorithme sophistiqué sur lequel vous pouvez lire ici. Important de comprendre que les fichiers à partir du répertoire correspond à l'conteneurs de clés de l'utilisateur touches. Généralement, l'utilisateur a accès à tous les fichiers dans le système de fichiers. Les fichiers seront cryptés avec la clé qui dépendent de l'utilisateur mot de passe. Dans de nombreux cas standard, les fichiers seront chiffrés à nouveau après le changement de mot de passe, mais l'algorithme de récupération, qui dépendent de beaucoup de choses. Si le mot de passe a été réinitialisé au lieu de la 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]
n'a pas pu être plus utile. Par exemple, si l'utilisateur n'est pas un annuaire Active Directory de l'utilisateur (un utilisateur local) et le local de l'administrateur de réinitialiser son mot de passe, puis le problème avec les crypto-conteneurs auront lieu.
Donc, la première suggestion serait de demander à l'utilisateur son mot de passe Active Directory a été réinitialisé. Ensuite, vous devez vérifier que le répertoire %APPDATA%\Microsoft\Crypto\DSS\[SID]
existent dans le profil de l'utilisateur et que l'utilisateur a un accès complet au répertoire du système de fichiers. Vous devez supprimer tous les fichiers du répertoire (la création d'précédemment la copie de sauvegarde des fichiers). Au passage, il est intéressant de savoir si l'utilisateur au centre du profil enregistré (enregistré sur le serveur). Si il a du profil central on peut vérifier que le même problème que vous décrivez, il existe sur l'autre ordinateur de l'utilisateur et d'autres utilisateur n'a pas de problèmes sur son ordinateur d'origine.
Encore une question, qui n'est pas très clair pour moi, c'est pourquoi le conteneur de clé de la le répertoire %APPDATA%\Microsoft\Crypto\DSS\[SID]
sont utilisés à tous parce que vous utilisez seulement les clés publiques. Dans CryptoAPI il faut utiliser CryptAcquireContext
avec NULL
comme pszContainer
paramètre et CRYPT_VERIFYCONTEXT
en dwFlags
. Je ne suis pas sûr que .NET, utilisez l' CRYPT_VERIFYCONTEXT
drapeau et il pourrait être indirect votre problème.
Vous pouvez créer DSACryptoServiceProvider
avec le constructeur ayant CspParameters paramètre. CspParameters de l'autre côté a des Drapeaux de la propriété qui se prolonge dans le .NET 4.0 avec la valeur CreateEphemeralKey. La description de l' CspProviderFlags.CreateEphemeralKey
est très proche de la description de l' CRYPT_VERIFYCONTEXT
drapeau de l' CryptAcquireContext
fonction. Donc, utiliser pouvez essayer d'utiliser CspProviderFlags.CreateEphemeralKey ou CspProviderFlags.CreateEphemeralKey
avec CspProviderFlags.UseDefaultKeyContainer
(NULL
comme pszContainer
paramètre de CryptAcquireContext
signifie aussi, le conteneur de clé par défaut).
De plus, si c'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 .NET sources, qui peut être activé (voir ici et ici) ou téléchargé à partir d' ici. Vous pouvez ensuite répondre à quelques questions sur les valeurs de CspParameters
qui est actuellement utilisé dans votre programme et de comparer les valeurs .NET 3.5 et .NET 4.0.
Si ce que j'ai écrit ne va pas aider à résoudre le problème, s'il vous plaît pourriez-vous ajouter à votre question avec plus d'informations:
- Dont le système d'exploitation et le service pack a l'ordinateur où le problème peut être reproduit?
- Est le problème dépendantes de l'utilisateur? Je veux dire: a d'autres utilisateurs sur le même ordinateur et le même problème?
- Est la le problème existe avec le contrôleur de domaine (active directory) de l'utilisateur ou avec le compte d'utilisateur local? A l'utilisateur qui a le problème central de profil de l'utilisateur qui sont enregistrés sur le serveur? Si il a, que ne peut 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 la situation, vous utilisez la clé publique de vérification? Est en particulier le programme s'exécute dans le contexte de sécurité utilisateur ou de vous faire quelques usurpation d'identité?
Mise à JOUR: Après la lecture de la tribune où le problème de l'origine a été posté, je deviens pessimiste à propos de la résolution du problème. Si vous n'avez pas de contact direct à l'ordinateur où le problème peut être reproduit et la communication avec le seul utilisateur qui a le problème ne sont effectués que par poster dans le forum... Néanmoins, j'ai été la réflexion sur le problème et j'ai donc décidé d'essayer de reproduire le problème moi-même. Et j'ai eu du succès dans ce. Je vais donc décrire ici mes résultats avec précaution. Je vais décrire comment le pouvez reproduire le problème afin qu'il ressemble exactement comme il est décrit dans le fil de discussion du forum.
Vous devez faire les étapes suivantes:
1) Vous créez un test local sur votre ordinateur.
2) vous Vous connectez avec le compte de test et de générer de la valeur par défaut du conteneur de clé pour le DSA fournisseur. Vous pouvez le faire par exemple dans le domaine de la petite .NET programme appel de fonction suivante:
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 par paire.
3) vous Vous déconnectez le test de compte et de se connecter avec un autre compte qui a les droits d'administrateur local. Vous réinitialiser le mot de passe du compte de test.
4) vous Vous connectez une fois de plus avec le compte de test et vérifier que le programme de test, qui vous avez posté, compilé dans Visual Studio 2010 .NET 4.0 produit l'erreur NTE_BAD_KEY_STATE
(0x8009000b) et le correspondant de l'exception sera levée.
5) Si vous recompilez le programme pour .NET 3.5 au lieu de .NET 4.0 (vous pouvez 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 le fil de discussion du forum.
Si vous supprimez ou renommez le fichier avec le conteneur de clé par défaut pour le DSA fournisseur le problème sera résolu. Comme je l'ai décrit avant, après la réinitialisation du mot de passe des utilisateurs le contenu du conteneur de clé par défaut sera pas en mesure d'ê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 des traces de l' analyse de Processus) il vous suffit de copier n'importe quelle touche du fichier conteneur de tout autre utilisateur et de toute autre ordinateur dans le répertoire %APPDATA%\Microsoft\Crypto\DSS\[SID]
, renommez le fichier, de sorte que le nom sera la valeur par défaut nom de conteneur 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 de l' CspParameters
comme le paramètre d' DSACryptoServiceProvider
(voir mon premier suggestions à propos de l'utilisation de CspProviderFlags.CreateEphemeralKey), mais sans succès. Après cela, j'ai débogué le code source de .NET 4.0 et peut définitivement dire que l'appel d' _OpenCSP
de la fonction, le code n'est pas ouvert, sera appelé avec les paramètres qui sont indépendants à partir des paramètres de l' DSACryptoServiceProvider
constructeur. Donc vous ne pouvez pas trouver une solution de contournement du problème .NET 4.0 dans la manière dont les différents paramètres de l' CspParameters
comme le paramètre d' DSACryptoServiceProvider
.
Donc, si vous voulez modifier votre code, de sorte qu'il devrait fonctionner également dans la situation avec le corrompu par défaut fournisseur clé je vois pour le moment que 2 façons de résoudre le problème:
- Mettre en œuvre la totalité ou la partie de code à l'aide de non géré
CryptAcquireContext
fonction avec l' CRYPT_VERIFYCONTEXT
drapeau.
- Détecter le problème avec l'erreur
NTE_BAD_KEY_STATE
(0x8009000b) et inclure la partie de code qui supprime ou temporaire renommé le fichier à partir d' %APPDATA%\Microsoft\Crypto\DSS\[SID]
qui contient le corrompu conteneur de clé par défaut. Pour détecter le nom du fichier, je pense que vous pouvez essayer d'utiliser l' CryptGetProvParam
fonction avec l' PP_UNIQUE_CONTAINER
ou/et PP_ENUMCONTAINERS
paramètres.
Je suis désolé pour le long texte de ma réponse et merci à tous ceux qui sont en mesure de le lire jusqu'à cet endroit. :-)
J'espère que ma réponse ne vous aider à KristoferA pour résoudre le problème et d'améliorer un logiciel qui vous développer.