web-dev-qa-db-fra.com

Erreur "Les informations d'identification fournies au package n'ont pas été reconnues" lors de l'authentification en tant que serveur avec un certificat généré à l'aide de BouncyCastle

J'essaie de créer un certificat à l'aide de la DLL BouncyCastle.Crypto, qui est ensuite utilisée pour authentifier un SslStream en tant que serveur dans un processus de service Windows, qui s'exécute sous le compte système local.

Cependant, lorsque j'arrive à l'appel SslStream.AuthenticateAsServer (certificat), il lève une exception Win32 avec le message d'erreur "Les informations d'identification fournies au package n'ont pas été reconnues".

Il y a plusieurs questions ici à propos de ce message d'erreur, mais aucune ne semble décrire ou résoudre mon problème particulier.

Dans l'espoir que quelqu'un puisse offrir de l'aide, j'inclus le code que j'utilise pour créer et installer le certificat:

// First create a certificate using the BouncyCastle classes
BigInteger serialNumber = BigInteger.ProbablePrime(120, new Random());
AsymmetricCipherKeyPair keyPair = GenerateKeyPair();

X509V1CertificateGenerator generator = new X509V1CertificateGenerator();
generator.SetSerialNumber(serialNumber);
generator.SetIssuerDN(new X509Name("CN=My Issuer"));
generator.SetNotBefore(DateTime.Today);
generator.SetNotAfter(DateTime.Today.AddYears(100));
generator.SetSubjectDN(new X509Name("CN=My Issuer"));
generator.SetPublicKey(keyPair.Public);
generator.SetSignatureAlgorithm("SHA1WITHRSA");

Org.BouncyCastle.X509.X509Certificate cert = generator.Generate(
    keyPair.Private, SecureRandom.GetInstance("SHA1PRNG"));

// Ok, now we have a BouncyCastle certificate, we need to convert it to the 
// System.Security.Cryptography class, by writing it out to disk and reloading
X509Certificate2 dotNetCert;

string tempStorePassword = "Password01"; // In real life I'd use a random password
FileInfo tempStoreFile = new FileInfo(Path.GetTempFileName());

try
{
    Pkcs12Store newStore = new Pkcs12Store();

    X509CertificateEntry entry = new X509CertificateEntry(cert);

    newStore.SetCertificateEntry(Environment.MachineName, entry);

    newStore.SetKeyEntry(
        Environment.MachineName,
        new AsymmetricKeyEntry(keyPair.Private),
        new [] { entry });

    using (FileStream s = tempStoreFile.Create())
    {
        newStore.Save(s, 
            tempStorePassword.ToCharArray(), 
            new SecureRandom(new CryptoApiRandomGenerator()));
    }

    // Reload the certificate from disk
    dotNetCert = new X509Certificate2(tempStoreFile.FullName, tempStorePassword);
}
finally
{
    tempStoreFile.Delete();
}

// Now install it into the required certificate stores
X509Store targetStore = new X509Store(StoreName.My, StoreLocation.LocalMachine);
targetStore.Open(OpenFlags.ReadWrite);
targetStore.Add(dotNetCert);
targetStore.Close();

Ok, maintenant j'ai créé et installé le certificat. Je configure ensuite mon service Windows pour utiliser ce certificat en lui fournissant l'empreinte numérique du certificat généré. J'utilise ensuite le certificat comme ceci:

// First load the certificate
X509Certificate2 certificate = null;

X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);

foreach (X509Certificate2 certInStore in store.Certificates)
{
    if (certInStore.Thumbprint == "...value not shown...")
    {
        certificate = certInStore;
        break;
    }
}

SslStream sslStream = new SslStream(new NetworkStream(socket, false), false);

// Now this line throws a Win32Exception 
// "The credentials supplied to the package were not recognized"
sslStream.AuthenticateAsServer(certificate);

Quelqu'un a-t-il une idée du problème qui pourrait se poser ici?

Je ne reçois pas le problème si j'installe un certificat créé avec 'makecert', mais cela ne convient pas aux certificats de production.

J'ai également essayé de créer un certificat CA x509v1 distinct puis un certificat x509v3 pour l'authentification du serveur, mais j'obtiens la même erreur, j'ai donc supprimé cela dans l'exemple de code pour plus de simplicité.

30
peter reay

Ce message d'erreur particulier sonne une cloche. Je suppose que soit vous n'avez pas stocké la clé privée avec le certificat, soit le service Windows n'a pas accès à la clé privée. Pour vérifier cela, ouvrez le composant logiciel enfichable Certificats MMC:

  1. Exécutez mmc (par exemple à partir du menu Démarrer)
  2. Menu Fichier> Ajouter/Supprimer un composant logiciel enfichable
  3. Sélectionnez "Certificats" dans le volet gauche, puis cliquez sur Ajouter
  4. Sélectionnez "Compte d'ordinateur" (pour LocalMachine) puis cliquez sur Suivant, puis sur Terminer

Accédez au certificat et double-cliquez dans le volet droit. Sur l'onglet Général qui apparaît, vous devriez voir une petite icône de clé en bas, avec le texte, "Vous avez une clé privée qui correspond à ce certificat." Sinon, c'est le problème. La clé privée n'a pas été enregistrée.

Si la clé privée est présente, cliquez sur Ok pour fermer cette boîte de dialogue, puis cliquez avec le bouton droit sur le certificat dans le volet droit et sélectionnez-le dans le menu contextuel : Toutes les tâches> Gérer les clés privées. Dans cette boîte de dialogue, assurez-vous que le compte Windows sous lequel le service s'exécute dispose d'un accès en lecture à la clé privée. Si ce n'est pas le cas, c'est bien le problème.

Edit: Oups, vous avez écrit que le service s'exécute en tant que système local, il doit donc y avoir une clé privée manquante, s'il s'agit de l'un de ces deux problèmes. Je laisserai quand même la vérification de l'accès aux clés dans ma réponse, pour toute autre personne qui frappe cela et ne s'exécute pas en tant que système local.

41
Jim Flood

Parfois, le problème se produit lorsque l'application tente d'accéder au certificat ne dispose pas de privilèges suffisants pour accéder au certificat, le problème peut être résolu en exécutant l'application en tant qu'administrateur.

11
Bruce

J'ai trouvé cette solution en ligne mais je ne trouve pas la source pour donner le crédit.

Depuis que je suis tombé sur le problème "Les informations d'identification fournies au package n'ont pas été reconnues" avec AuthenticateAsClient () (pour la vérification du client), je voudrais documenter comment je l'ai résolu. C'est une méthode différente avec le même objectif final. Puisqu'il pourrait être utile pour AuthenticateAsServer (), compris pourquoi.

Ici, je convertis un certificat BC en un certificat .NET. Ajoutez une étape supplémentaire dans sa conversion en .NET X509Certificate2 pour stocker sa propriété PrivateKey.

Org.BouncyCastle.X509.X509Certificate bcCert;

X509Certificate dotNetCert = DotNetUtilities.ToX509Certificate(bcCert);
X509Certificate2 dotNetCert2 = new X509Certificate2(dotNetCert);

Le problème est apparu lors de l'ajout d'une clé privée BouncyCastle à une clé privée .NET. Les certificats X509 ont bien converti mais pas les clés privées. J'ai converti la clé privée BC en RSACryptoServiceProvider en utilisant les DotNetUtilities fournis. Malheureusement, il semble que la conversion ne soit pas terminée. J'ai donc créé un autre RSACryptoServiceProvider que j'ai ensuite initialisé. J'ai ensuite importé la clé privée dans celle que j'ai créée.

// Apparently, using DotNetUtilities to convert the private key is a little iffy. Have to do some init up front.
RSACryptoServiceProvider tempRcsp = (RSACryptoServiceProvider)DotNetUtilities.ToRSA((RsaPrivateCrtKeyParameters)ackp.Private);
RSACryptoServiceProvider rcsp = new RSACryptoServiceProvider(new CspParameters(1, "Microsoft Strong Cryptographic Provider", 
            new Guid().ToString(), 
            new CryptoKeySecurity(), null));

rcsp.ImportCspBlob(tempRcsp.ExportCspBlob(true));
dotNetCert2.PrivateKey = rcsp;

Après cela, j'ai pu enregistrer l'objet X509Certificate2 directement dans le magasin de clés. Je n'avais pas besoin du fichier réel, j'ai donc sauté cette étape.

6
Miguel Moll

J'ai le même problème, j'ai tout essayé à partir de nombreux messages et fait des recherches sur Google. Mais on dirait que j'ai trouvé un correctif. Quand j'ai changé Identify de ApplicationPoolIdentity à LocalSystem tout commence à fonctionner parfaitement.

Peut être utile à quelqu'un.

3
rootnix911

Pour moi, fonctionne sur Windows Server 2012 R2 (.net 4.6.1) - "Toutes les tâches> Gérer les clés privées" et définissez l'accès à Tout le monde (le paramètre IS_IUSRS n'était pas suffisant)

2
MariuszW

J'ai eu le même problème lors de l'appel d'un service WCF REST service à partir de l'application .NET où je dois attacher le certificat client; tout ce que j'avais à faire était de fournir l'accès au certificat dans le magasin de certificats [console mmc ] au "NETWORKSERVICE] bien sûr mon IIS pool était le pool par défaut qui indique qu'il utilise le compte utilisateur NETWORKService.

l'erreur que j'ai faite était, j'ai copié le certificat d'un autre magasin vers la machine locale -> magasin du personnel où le certificat était protégé par mot de passe. doit importer le certificat explicitement dans le magasin requis.

1
user3264937

Auparavant, chaque fois que je rencontrais ce problème, je devais supprimer le certificat de mon magasin de certificats de machine local et le réimporter. Ensuite, tout semble heureux. Je ne vois pas comment cela pourrait être un problème d'autorisations globales ou un certificat invalide si la simple réimportation résout le problème.

Comment j'ai finalement résolu le problème en utilisant l'outil winhttpcertcfg du Kit de ressources Windows pour accorder l'autorisation à l'utilisateur spécifique qui utilisait le certificat.

La syntaxe serait:

"C:\Program Files (x86)\Windows Resource Kits\Tools\winhttpcertcfg" -i cert.p12 -c LOCAL_MACHINE\My -a UserWhoUsesTheCert -p passwordforp12
1
NitrusCS

Je ne me souviens pas de cette erreur mais le certificat que vous créez n'est pas valide pour être utilisé pour SSL/TLS, y compris:

  • certificat v1 (pas v3);
  • extensions manquantes;
  • cN invalide;
  • ...

Il existe plusieurs RFC qui en parlent, notamment RFC5246 sur TLS (1.2).

Enfin, faire vos propres certificats n'est pas plus adapté que d'utiliser ceux créés par makecert (mais le dernier peut générer l'ensemble minimum pour être utilisable pour un certificat de serveur SSL/TLS).

Je fortement vous suggère d'acheter, auprès d'une autorité de certification (CA) bien connue, un certificat SSL/TLS pour production . Cela vous donnera un certificat de travail reconnu par la plupart des navigateurs et des outils.

0
poupou