IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

SSL gestion des certificats


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre extrêmement actif Avatar de petitours
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Février 2003
    Messages
    2 037
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 2 037
    Par défaut SSL gestion des certificats
    Bonjour

    Je débute en SSL et après de longues heures de lecture j'ai pu faire un client et un serveur TCP qui communiquent en TLS.
    Il me reste quelques questions sur SSL que j'ai posé sur le forum sécurité http://www.developpez.net/forums/d15...certification/ mais globalement j'ai compris les principes.

    Pour mon appli je ne demande pas le certificat au client mais il reste la gestion du certificat du serveur.
    Ça fonctionne en créant un certificat auto signé via la console MMC puis en faisant un export d'un fichier .pfx que j'ai cru comprendre être la clé privée, protégée par un mot de passe à l'export. Je place ce fichier pfx à coté du .exe et hop ca fonctionne avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    String fileName = "MonCertif.pfx" ;
    X509Certificate2 certificate = new X509Certificate2(fileName,"password");
    Plusieurs questions :
    1) ce mot de passe qui est demandé à l'export du certificat protège quoi ? parce que pour le moment j'ai un mot de passe en clair qui est donc super pas sécur puisque le code est super facile à lire pour quiconque et a ma connaissance le seul moyen de le rendre sécur serait de demander le mot de passe à l'utilisateur et de le comparer à un hash...un peu pénible pour l'utilisateur, surtout si je sais pas lui dire à quoi il sert ! :-)
    2) Y a t-il un moyen de pointer directement sur les certificats que l'on gère avec MMC ?
    3) pour le déploiement de l'application chez des clients, comment doit on procéder pour l'installation du certificat que l'on va du coup devoir fournir au client avec l'appli ? (perso j'utilise innoSetup)

    Merci par avance

    pour info, voici le code complet du serveur (code largement inspiré par d'autres...)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    using System;
    using System.Configuration;
    using System.Net;
    using System.Net.Security;
    using System.Net.Sockets;
    using System.Security.Authentication;
    using System.Security.Cryptography.X509Certificates;
    using System.Text;
     
     
    namespace MutualSslDemo.Server
    {
        class Program
        {
            static void Main(string[] args)
            {
                //  port
                UInt16 port = 0;
                string UserEntry = "";
                bool IsOk = false;
                do
                {
                    Console.WriteLine("Saisir le numéro de port à surveiller : ");
                    UserEntry = Console.ReadLine();
                    IsOk = UInt16.TryParse(UserEntry, out port);
                } while (!IsOk );
     
                //  certificate and password
                var fileName = "MonCertif.pfx"; 
     
                X509Certificate2 certificate = new X509Certificate2(fileName,"password");
     
     
                ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(OnRemoteCertificateValidationCallback);
                SslTcpServer.RunServer((int)port, certificate);
            }
     
            static bool OnRemoteCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
            {
                return (sslPolicyErrors == SslPolicyErrors.None);
            }
     
            public sealed class SslTcpServer
            {
                // The certificate parameter specifies the name of the file 
                // containing the machine certificate.
                public static void RunServer(int serverPort, X509Certificate2 certificate)
                {
                    // Create a TCP/IP (IPv4) socket and listen for incoming connections.
                    var listener = new TcpListener(IPAddress.Any, serverPort);
                    listener.Start();
     
     
                    while (true)
                    {
                        Console.WriteLine("Waiting for a client to connect...");
                        // Application blocks while waiting for an incoming connection.
                        // Type CNTL-C to terminate the server.
                        var client = listener.AcceptTcpClient();
                        ProcessClient(client, certificate);
                    }
                }
     
                static void ProcessClient(TcpClient client, X509Certificate certificate)
                {
                    // A client has connected. Create the SslStream using the client's network stream.
                    var sslStream = new SslStream(client.GetStream(), false);
     
                    try
                    {
                        // Authenticate the server and NOT requires the client to authenticate.
                        sslStream.AuthenticateAsServer(certificate, false, SslProtocols.Default, true);
     
                        // Authenticate the server and requires the client to authenticate.
    //sslStream.AuthenticateAsServer(certificate, true, SslProtocols.Default, true);
     
     
                        // Display the properties and settings for the authenticated stream.
                        DisplaySecurityLevel(sslStream);
                        DisplaySecurityServices(sslStream);
                        DisplayCertificateInformation(sslStream);
                        DisplayStreamProperties(sslStream);
     
                        // Set timeouts for the read and write to 5 seconds.
                        sslStream.ReadTimeout = 5000;
                        sslStream.WriteTimeout = 5000;
                        // Read a message from the client.   
                        Console.WriteLine("Waiting for client message...");
                        string messageData = ReadMessage(sslStream);
                        Console.ForegroundColor = ConsoleColor.Yellow;
                        Console.WriteLine("Received: {0}", messageData);
                        Console.ResetColor();
     
                        // Write a message to the client.
                        byte[] message = Encoding.UTF8.GetBytes("Hello from the server.<EOF>");
                        Console.WriteLine("Sending hello message.");
                        sslStream.Write(message);
                    }
                    catch (AuthenticationException e)
                    {
                        Console.WriteLine("Exception: {0}", e.Message);
                        if (e.InnerException != null)
                        {
                            Console.WriteLine("Inner exception: {0}", e.InnerException.Message);
                        }
                        Console.WriteLine("Authentication failed - closing the connection.");
                        sslStream.Close();
                        client.Close();
                        return;
                    }
                    finally
                    {
                        // The client stream will be closed with the sslStream
                        // because we specified this behavior when creating
                        // the sslStream.
                        sslStream.Close();
                        client.Close();
                    }
                }
     
                static string ReadMessage(SslStream sslStream)
                {
                    // Read the  message sent by the client.
                    // The client signals the end of the message using the
                    // "<EOF>" marker.
                    byte[] buffer = new byte[2048];
                    StringBuilder messageData = new StringBuilder();
                    int bytes = -1;
                    do
                    {
                        // Read the client's test message.
                        bytes = sslStream.Read(buffer, 0, buffer.Length);
     
                        // Use Decoder class to convert from bytes to UTF8
                        // in case a character spans two buffers.
                        Decoder decoder = Encoding.UTF8.GetDecoder();
                        char[] chars = new char[decoder.GetCharCount(buffer, 0, bytes)];
                        decoder.GetChars(buffer, 0, bytes, chars, 0);
                        messageData.Append(chars);
                        // Check for EOF or an empty message.
                        if (messageData.ToString().IndexOf("<EOF>") != -1)
                        {
                            break;
                        }
                    } while (bytes != 0);
     
                    return messageData.ToString();
                }
     
                static void DisplaySecurityLevel(SslStream stream)
                {
                    Console.WriteLine("Cipher: {0} strength {1}", stream.CipherAlgorithm, stream.CipherStrength);
                    Console.WriteLine("Hash: {0} strength {1}", stream.HashAlgorithm, stream.HashStrength);
                    Console.WriteLine("Key exchange: {0} strength {1}", stream.KeyExchangeAlgorithm, stream.KeyExchangeStrength);
                    Console.WriteLine("Protocol: {0}", stream.SslProtocol);
                }
     
                static void DisplaySecurityServices(SslStream stream)
                {
                    Console.WriteLine("Is authenticated: {0} as server? {1}", stream.IsAuthenticated, stream.IsServer);
                    Console.WriteLine("IsSigned: {0}", stream.IsSigned);
                    Console.WriteLine("Is Encrypted: {0}", stream.IsEncrypted);
                }
     
                static void DisplayStreamProperties(SslStream stream)
                {
                    Console.WriteLine("Can read: {0}, write {1}", stream.CanRead, stream.CanWrite);
                    Console.WriteLine("Can timeout: {0}", stream.CanTimeout);
                }
     
                static void DisplayCertificateInformation(SslStream stream)
                {
                    Console.WriteLine("Certificate revocation list checked: {0}", stream.CheckCertRevocationStatus);
     
                    X509Certificate localCertificate = stream.LocalCertificate;
                    if (stream.LocalCertificate != null)
                    {
                        Console.WriteLine("Local cert was issued to {0} and is valid from {1} until {2}.",
                            localCertificate.Subject,
                            localCertificate.GetEffectiveDateString(),
                            localCertificate.GetExpirationDateString());
                    }
                    else
                    {
                        Console.WriteLine("Local certificate is null.");
                    }
                    // Display the properties of the client's certificate.
                    X509Certificate remoteCertificate = stream.RemoteCertificate;
                    if (remoteCertificate != null)
                    {
                        Console.WriteLine("Remote cert was issued to {0} and is valid from {1} until {2}.",
                            remoteCertificate.Subject,
                            remoteCertificate.GetEffectiveDateString(),
                            remoteCertificate.GetExpirationDateString());
                    }
                    else
                    {
                        Console.WriteLine("Remote certificate is null.");
                    }
                }
            }
        }
    }

  2. #2
    Expert confirmé

    Avatar de François DORIN
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2016
    Messages
    2 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2016
    Messages : 2 761
    Billets dans le blog
    21
    Par défaut
    Bonjour,

    Dans l'ordre :
    1) le mot de passe protège la clé privé qui est contenu au sein du certificat ;
    2) Je pense que la classe X509Store peut répondre à tes besoins ;
    3) Si le certificat que tu veux distribuer à tes clients sert juste à pouvoir vérifier le certificat serveur, (qu'il ne sert donc pas à l'identification des clients) et qu'il est le même pour tout les clients, tu peux l'embarquer directement au sein de ton programme. Par exemple, en tant que ressource embarquée.

    A propos, au niveau du serveur, il se peut que tu aies des problèmes lors du chargement d'un certificat (une exception style Opération non autorisé). Cela peut venir que par défaut, quand tu charges un certificat (même depuis un fichier), il est stocké temporairement dans le magasin de l'utilisateur. En fonction de comment est configuré ton application, il se peut que tu ne puisses pas avoir accès à ce magasin. Dans ce cas, il faut utiliser le magasin de la machine via le flag X509KeyStorageFlags.MachineKeySet lors de la création de ton certificat.

  3. #3
    Membre extrêmement actif Avatar de petitours
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Février 2003
    Messages
    2 037
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 2 037
    Par défaut
    Bonjour et merci

    Le fait de travailler avec un certificat placé dans un magasin dispense de faire appel au mot de passe ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     X509Certificate2 certificate = new X509Certificate2(fileName,"password");
    Mon appli intègre un serveur TCP qui reçoit des données envoyées par des cartes électroniques il faut que mon appli (windowsform) gère un certificat serveur pour que les cartes électroniques puissent crypter les données en étant certaines qu'elles parlent bien au bon serveur.
    Si je devais demander à un opérateur de taper un mot de passe ce serait la misère...

    Si je comprends l'idée du 3) :
    -j'intègre un .pfx à ma solution
    -Avec X509Store je place ce certificat dans un magasin (pas besoin de mot de passe pour ca non plus ?)
    -Le serveur de l'appli fait ensuite appel à ce magasin pour avoir accès au certificat qui peut être appelé sans mot de passe puisque géré dans le magasin

    C'est ça?

    Merci

  4. #4
    Expert confirmé

    Avatar de François DORIN
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2016
    Messages
    2 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2016
    Messages : 2 761
    Billets dans le blog
    21
    Par défaut
    Je pense qu'il est nécessaire de bien distinguer le côté client du côté serveur, aussi bien dans la manière de programmer que dans la manière de générer les certificats. Tout d'abord, il va te falloir non pas un, mais deux certificats. Un qui sera utilisé côté serveur (et uniquement côté serveur), qui contiendra à la fois la clé publique et la clé privée et qui sera protégé par mot de passe. Ensuite, un autre certificat, qui sera distribué avec les clients et qui ne contiendra que la clé publique. Ce certificat n'aura pas besoin d'être protégé par mot de passe.

    Ensuite, côté client, il s'agit de vérifier que le certificat émis par le serveur est le bon. Pour cela, comme le certificat est autosigné, tu ne peux pas utiliser une chaîne de certification. Tu vas donc avoir besoin de faire cette vérification manuellement, par exemple, en comparant les clés publiques.

    Pour la distribution du certificat coté client, comme je le disais, je pense qu'inclure le certificat en tant que ressources internes est une bonne idée. Ainsi, tu n'auras pas de problème de déploiement.

    [edit]
    Si je comprends l'idée du 3) :
    -j'intègre un .pfx à ma solution
    -Avec X509Store je place ce certificat dans un magasin (pas besoin de mot de passe pour ca non plus ?)
    -Le serveur de l'appli fait ensuite appel à ce magasin pour avoir accès au certificat qui peut être appelé sans mot de passe puisque géré dans le magasin
    Non, car là tu supposes que ton client et ton serveur sont sur la même machine. Ce qui ne sera très certainement pas le cas. Il faut bien avoir en tête qu'en général, une architecture client/serveur est constituée de plusieurs machines : une (ou parfois plusieurs) pour le serveur / plusieurs (rarement une) pour les clients.
    [/edit]

  5. #5
    Membre extrêmement actif Avatar de petitours
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Février 2003
    Messages
    2 037
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 2 037
    Par défaut
    justement mon appli winform n'est pas le coté client mais le coté serveur ; serveur sur le quel les cartes électronique ( clientes) viennent se connecter.
    C'est donc bien un certificat "serveur" que je veux déployer avec mon appli.

    Les cartes arrivent très bien à traiter le certificats autosigné que mon appli leur envoi, même si le boulot est surement pas fini puisque je ne leur ai pas donné de certificat de référence et donc elles ne doivent pas vérifier l'authenticité du certificat du serveur à priori.

  6. #6
    Expert confirmé

    Avatar de François DORIN
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2016
    Messages
    2 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2016
    Messages : 2 761
    Billets dans le blog
    21
    Par défaut
    Hmm, d'accord. On est donc dans un cas un peu particulier (forcément, sinon, ce serait trop simple).

    A priori, tu n'as pas forcément besoin d'une sécurité forte au niveau des certificats dans ta situation. Aussi, il est tout à fait possible d'exporter ton certificat sans le protéger par mot de passe. Ou en mettre un et le coder en dur, je ne suis pas sur que cela ait une grande incidence dans ton cas (surtout que les cartes ne semblent pas vérifier le certificat !).

    Pour en revenir à tes questions initiales, je reste sur la distribution du certificat en tant que ressources incluses dans ton programme (et tu y accèdes via réflexion). Eventuellement protégé par un mot de passe (dans ce cas, tu le codes en dur. Tu peux éventuellement regarder du côté de SecureString afin d'avoir un mot de passe plus sécurisé).

    Ainsi, tu ne devrais pas avoir de problème de déploiement.

Discussions similaires

  1. [Débutant] Je crois que j'ai cassé mon IIS Express (gestion des certificats ssl)
    Par Nadinette dans le forum ASP.NET MVC
    Réponses: 4
    Dernier message: 16/06/2016, 09h03
  2. Gestion des certificats dans une application client/serveur j2ee
    Par alexandre.granier dans le forum Java EE
    Réponses: 2
    Dernier message: 26/06/2013, 12h11
  3. gestion des certificats
    Par Jeecer dans le forum Visual Studio
    Réponses: 4
    Dernier message: 04/01/2012, 16h44
  4. Gestion des certificats pour HTTPS
    Par OjBarbare dans le forum C#
    Réponses: 3
    Dernier message: 21/09/2011, 05h26
  5. [ C# / CryptoAPI ] Gestion des certificats
    Par Endy dans le forum C#
    Réponses: 5
    Dernier message: 29/07/2008, 11h36

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo