Domanda

ho bisogno di fornire una comunicazione sicura tra i vari processi che stanno utilizzando socket TCP / IP per la comunicazione. Voglio sia l'autenticazione e la crittografia. Invece di reinventare la ruota mi piacerebbe davvero per utilizzare SSL e la classe SslStream e certificati autofirmati. Quello che voglio fare è convalidare il certificato del processo remoto contro una copia conosciuta nella mia applicazione locale. (Ci non ha bisogno di essere un'autorità di certificazione perché intendo per i certificati da copiare in tutto manualmente).

Per fare questo, voglio che l'applicazione sia in grado di generare automaticamente un nuovo certifiate la prima volta che viene eseguito. Oltre a Makecert.exe, sembra questo link mostra un modo per generare automaticamente i certificati autofirmati, in modo che è un inizio.

Ho guardato i metodi AuthenticateAsServer e AuthenticateAsClient di SslStream. È possibile fornire call-back per la verifica, così sembra che sia possibile. Ma ora che sono nei dettagli di essa, io davvero non credo sia possibile farlo.

Sto andando nella direzione giusta? C'è un'alternativa migliore? Qualcuno ha fatto niente di simile prima (SSL sostanzialmente peer-to-peer, piuttosto che client-server)?

È stato utile?

Soluzione

Passaggio 1: Generazione di un certificato autofirmato:

  • Ho scaricato il class Certificate.cs pubblicato da Doug Cook
  • Ho usato questo codice per generare un file di certificato .pfx:

    byte[] c = Certificate.CreateSelfSignCertificatePfx(
            "CN=yourhostname.com", //host name
            DateTime.Parse("2000-01-01"), //not valid before
            DateTime.Parse("2010-01-01"), //not valid after
            "mypassword"); //password to encrypt key file
    
        using (BinaryWriter binWriter = new BinaryWriter(
            File.Open(@"testcert.pfx", FileMode.Create)))
        {
            binWriter.Write(c);
        }
    

Passaggio 2: Caricamento del certificato

    X509Certificate cert = new X509Certificate2(
                            @"testcert.pfx", 
                            "mypassword");

Passaggio 3: Mettere insieme

  • Ho basato su questo esempio molto semplice SslStream
  • Si otterrà un errore di compilazione sull'enumerazione SslProtocolType. Basta cambiare che da SslProtocolType.Default a SslProtocols.Default
  • Ci sono stati 3 avvertimenti sulle funzioni deprecate. Li ho sostituiti con tutte le sostituzioni suggerite.
  • ho sostituito questa riga nel file server Program.cs con la linea dal punto 2:

    X509Certificate CERT = getServerCert ();

  • Nel file client Program.cs, assicuratevi di impostare serverName = yourhostname.com (e che corrisponde al nome nel certificato)

  • Nel Program.cs client, la funzione CertificateValidationCallback fallisce perché sslPolicyErrors contiene un RemoteCertificateChainErrors. Se si scava un po 'più profonda, questo è perché l'autorità di emissione che ha firmato il certificato non è una fonte attendibile.
  • I don `t vuole ottenere in avere i certificati di importazione utente nell'archivio principale, ecc, così ho fatto un caso speciale per questo, e controllare che certificate.GetPublicKeyString () è uguale alla chiave pubblica che ho avere in archivio per quel server. Se corrisponde, torno vera da quella funzione. Che sembra funzionare.

Passo 4: di autenticazione client

Ecco come il mio client autentica (è un po 'diverso da quello del server):

TcpClient client = new TcpClient();
client.Connect(hostName, port);

SslStream sslStream = new SslStream(client.GetStream(), false,
    new RemoteCertificateValidationCallback(CertificateValidationCallback),
    new LocalCertificateSelectionCallback(CertificateSelectionCallback));

bool authenticationPassed = true;
try
{
    string serverName = System.Environment.MachineName;

    X509Certificate cert = GetServerCert(SERVER_CERT_FILENAME, SERVER_CERT_PASSWORD);
    X509CertificateCollection certs = new X509CertificateCollection();
    certs.Add(cert);

    sslStream.AuthenticateAsClient(
        serverName,
        certs,
        SslProtocols.Default,
        false); // check cert revokation
}
catch (AuthenticationException)
{
    authenticationPassed = false;
}
if (authenticationPassed)
{
    //do stuff
}

Il CertificateValidationCallback è la stessa come nel caso del server, ma è da notare come AuthenticateAsClient prende una raccolta di certificati, non solo un certificato. Quindi, si deve aggiungere un LocalCertificateSelectionCallback, come questo (in questo caso, ho solo un client cert quindi ho solo restituisce il primo della collezione):

static X509Certificate CertificateSelectionCallback(object sender,
    string targetHost,
    X509CertificateCollection localCertificates,
    X509Certificate remoteCertificate,
    string[] acceptableIssuers)
{
    return localCertificates[0];
}

Altri suggerimenti

si può guardare anche questo esempio Esempio client asincroni SslStream / implementazione del server http: // blogs.msdn.com/joncole/archive/2007/06/13/sample-asynchronous-sslstream-client-server-implementation.aspx

se il certificato non è prodotto correttamente è possibile ottenere un'eccezione Lo SSL modalità server deve utilizzare un certificato con la chiave privata associata.

esempio di base certificato

makecert -sr LocalMachine -ss mio -n CN = Test di cambio-Sky -sk 123456

o

come file esterno

makecert -sr LocalMachine -ss mio -n CN = Test di cambio-Sky -sk 123456 c: \ Test.cer

Certificato Creation Tool (Makecert.exe)
http://msdn.microsoft.com/en- us / library / bfsktky3% 28VS.80% 29.aspx

Che cosa si sta proponendo suona bene a me, se non che suona come stai cercando di attendere che il callback viene invocata al fine di generare il certificato. Non credo che che volerà; Per quanto ne so, hai avuto modo di fornire un certificato valido quando si richiama AuthenticateAsX.

Tuttavia, queste classi sono override; quindi in teoria, è possibile creare una classe derivata, che prima controlla per vedere se un certificato deve essere generato, genera, se necessario, quindi richiama il metodo genitore AuthenticateAsX.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top