Cryptographie asymétrique exemple en C#

J'ai besoin d'envoyer des données à un serveur sur une connexion TCP. J'ai fait beaucoup de recherches et je comprends la partie théorique. Basé sur ce que j'ai fait des recherches je veux faire ce qui suit:

Remarque il y a un client et un serveur: (nous supposons que les clés publiques de client ou de serveur peut être obtenue par n'importe qui)

  1. client crée sa clé publique et privée. Il est en mesure de chiffrer avec sa clé privée et de déchiffrer avec sa clé publique.

  2. serveur crée ses clés publiques et privées. la clé privée est utilisée pour déchiffrer les messages et la clé publique est utilisée pour chiffrer les messages. (remarque est l'inverse avec le client)

  3. le client est la clé publique du serveur. le client sera alors en mesure de chiffrer les messages avec cette clé, et le seul qui sera en mesure de déchiffrer le message serait la clé privée du serveur.

  4. depuis le serveur doit être certain que le message vient de ce client, le client va crypter son nom (signature) avec sa clé privée.

  5. de sorte que le client message contient des données: les données à envoyer au client à clé publique, le nom du client chiffré avec le client est la clé privée.

  6. le client va chiffrer le message avec la clé publique du serveur. le client devra ensuite envoyer le message au serveur.

  7. le serveur va décrypter le message qu'il vient de recevoir, avec sa clé privée.

  8. une fois que le message est déchiffré il contient les données (informations), signature cryptée, de la clé publique du client.

  9. enfin, le serveur déchiffre la signature du client avec la clé publique contenue dans le message pour vérifier que le message est à partir de ce client.


OK donc, c'est comment la cryptographie asymétrique œuvres. J'ai aussi fait des recherches sur les classes qui vous permettent de créer cette paires de clés avec le .NET framework. Les classes que j'ai fait des recherches qui vous permettent de vous faire créer cette publics et privés paires de clés sont:

System.Security.Cryptography.DES
System.Security.Cryptography.DSACryptoServiceProvider 
System.Security.Cryptography.ECDsa 
System.Security.Cryptography.ECDsaCng 
System.Security.Cryptography.ECDiffieHellman 
System.Security.Cryptography.ECDiffieHellmanCng 
System.Security.Cryptography.RSA 
System.Security.Cryptography.RSACryptoServiceProvider 

donc maintenant mes problèmes vient sur comment puis-je utiliser un de ces classes de le faire avec C#? Je comprends comment la partie théorique fonctionne, mais comment dois-je faire ce que je viens de décrire avec code. J'ai fait des recherches pour d'autres exemples, mais je vais avoir du mal à les comprendre.

voici un exemple que j'ai trouvé qui je crois n'est ce que j'ai décrit:

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
namespace Example
{
class Program
{
static CngKey aliceKey;
static CngKey bobKey;
static byte[] alicePubKeyBlob;
static byte[] bobPubKeyBlob;
static void Main()
{
CreateKeys();
byte[] encrytpedData = AliceSendsData("secret message");
BobReceivesData(encrytpedData);
Console.Read();
}
private static void CreateKeys()
{
aliceKey = CngKey.Create(CngAlgorithm.ECDiffieHellmanP256);
bobKey = CngKey.Create(CngAlgorithm.ECDiffieHellmanP256);
alicePubKeyBlob = aliceKey.Export(CngKeyBlobFormat.EccPublicBlob);
bobPubKeyBlob = bobKey.Export(CngKeyBlobFormat.EccPublicBlob);
}
private static byte[] AliceSendsData(string message)
{
Console.WriteLine("Alice sends message: {0}", message);
byte[] rawData = Encoding.UTF8.GetBytes(message);
byte[] encryptedData = null;
using (var aliceAlgorithm = new ECDiffieHellmanCng(aliceKey))
using (CngKey bobPubKey = CngKey.Import(bobPubKeyBlob,
CngKeyBlobFormat.EccPublicBlob))
{
byte[] symmKey = aliceAlgorithm.DeriveKeyMaterial(bobPubKey);
Console.WriteLine("Alice creates this symmetric key with " +
"Bobs public key information: {0}",
Convert.ToBase64String(symmKey));
using (var aes = new AesCryptoServiceProvider())
{
aes.Key = symmKey;
aes.GenerateIV();
using (ICryptoTransform encryptor = aes.CreateEncryptor())
using (MemoryStream ms = new MemoryStream())
{
//create CryptoStream and encrypt data to send
var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write);
//write initialization vector not encrypted
ms.Write(aes.IV, 0, aes.IV.Length);
cs.Write(rawData, 0, rawData.Length);
cs.Close();
encryptedData = ms.ToArray();
}
aes.Clear();
}
}
Console.WriteLine("Alice: message is encrypted: {0}",
Convert.ToBase64String(encryptedData)); ;
Console.WriteLine();
return encryptedData;
}
private static void BobReceivesData(byte[] encryptedData)
{
Console.WriteLine("Bob receives encrypted data");
byte[] rawData = null;
var aes = new AesCryptoServiceProvider();
int nBytes = aes.BlockSize >> 3;
byte[] iv = new byte[nBytes];
for (int i = 0; i < iv.Length; i++)
iv[i] = encryptedData[i];
using (var bobAlgorithm = new ECDiffieHellmanCng(bobKey))
using (CngKey alicePubKey = CngKey.Import(alicePubKeyBlob,
CngKeyBlobFormat.EccPublicBlob))
{
byte[] symmKey = bobAlgorithm.DeriveKeyMaterial(alicePubKey);
Console.WriteLine("Bob creates this symmetric key with " +
"Alices public key information: {0}",
Convert.ToBase64String(symmKey));
aes.Key = symmKey;
aes.IV = iv;
using (ICryptoTransform decryptor = aes.CreateDecryptor())
using (MemoryStream ms = new MemoryStream())
{
var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Write);
cs.Write(encryptedData, nBytes, encryptedData.Length - nBytes);
cs.Close();
rawData = ms.ToArray();
Console.WriteLine("Bob decrypts message to: {0}",
Encoding.UTF8.GetString(rawData));
}
aes.Clear();
}
}
}
}

Dans ce programme, je crois que le client est Alice et le serveur est Bob. Je dois briser ce programme en deux parties. Je vais avoir du mal à le comprendre, et si je tente le plus probable, je vais le faire fonctionner. De toute façon comment puis-je diviser ce programme dans un code côté serveur et côté client code. Je sais comment envoyer des octets entre le serveur et le client. Mais je ne veux pas le faire fonctionner sans comprendre ce qui se passe. peut-être que les gars, vous pouvez me montrer un exemple facile.


MODIFIER

J'ai réussi à séparer le code: voici le code du serveur (adresse ip de mon ordinateur qui est arrivé à être 192.168.0.120) :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Security.Cryptography;
using System.IO;
namespace ServerListener
{
class Program
{
static TcpListener server;
//static CngKey aliceKey;
static CngKey bobKey;
static byte[] alicePubKeyBlob;
static byte[] bobPubKeyBlob;
static void Main(string[] args)
{
CreateKeys();
IPAddress ipAddress = IPAddress.Parse("192.168.0.120");
server = new TcpListener(ipAddress, 54540);
server.Start();
var client = server.AcceptTcpClient();
var stream = client.GetStream();
alicePubKeyBlob = new byte[bobPubKeyBlob.Length];
stream.Read(alicePubKeyBlob, 0, alicePubKeyBlob.Length);
stream.Write(bobPubKeyBlob, 0, bobPubKeyBlob.Length);
byte[] encrytpedData = new byte[32];
stream.Read(encrytpedData, 0, encrytpedData.Length);
BobReceivesData(encrytpedData);
}
private static void CreateKeys()
{
//aliceKey = CngKey.Create(CngAlgorithm.ECDiffieHellmanP256);
bobKey = CngKey.Create(CngAlgorithm.ECDiffieHellmanP256);
//alicePubKeyBlob = aliceKey.Export(CngKeyBlobFormat.EccPublicBlob);
bobPubKeyBlob = bobKey.Export(CngKeyBlobFormat.EccPublicBlob);
}
private static void BobReceivesData(byte[] encryptedData)
{
Console.WriteLine("Bob receives encrypted data");
byte[] rawData = null;
var aes = new AesCryptoServiceProvider();
int nBytes = aes.BlockSize >> 3;
byte[] iv = new byte[nBytes];
for (int i = 0; i < iv.Length; i++)
iv[i] = encryptedData[i];
using (var bobAlgorithm = new ECDiffieHellmanCng(bobKey))
using (CngKey alicePubKey = CngKey.Import(alicePubKeyBlob,
CngKeyBlobFormat.EccPublicBlob))
{
byte[] symmKey = bobAlgorithm.DeriveKeyMaterial(alicePubKey);
Console.WriteLine("Bob creates this symmetric key with " +
"Alices public key information: {0}",
Convert.ToBase64String(symmKey));
aes.Key = symmKey;
aes.IV = iv;
using (ICryptoTransform decryptor = aes.CreateDecryptor())
using (MemoryStream ms = new MemoryStream())
{
var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Write);
cs.Write(encryptedData, nBytes, encryptedData.Length - nBytes);
cs.Close();
rawData = ms.ToArray();
Console.WriteLine("Bob decrypts message to: {0}",
Encoding.UTF8.GetString(rawData));
}
aes.Clear();
}
}
}
}

et voici le code de client:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Security.Cryptography;
using System.IO;
namespace ClientAlice
{
class Program
{
static CngKey aliceKey;
//static CngKey bobKey;
static byte[] alicePubKeyBlob;
static byte[] bobPubKeyBlob;
static void Main(string[] args)
{
CreateKeys();
bobPubKeyBlob = new byte[alicePubKeyBlob.Length];
TcpClient alice = new TcpClient("192.168.0.120", 54540);
var stream = alice.GetStream();
stream.Write(alicePubKeyBlob, 0, alicePubKeyBlob.Length);
stream.Read(bobPubKeyBlob, 0, bobPubKeyBlob.Length);
byte[] encrytpedData = AliceSendsData(":)");
stream.Write(encrytpedData, 0, encrytpedData.Length);
}
private static void CreateKeys()
{
aliceKey = CngKey.Create(CngAlgorithm.ECDiffieHellmanP256);
//bobKey = CngKey.Create(CngAlgorithm.ECDiffieHellmanP256);
alicePubKeyBlob = aliceKey.Export(CngKeyBlobFormat.EccPublicBlob);
//bobPubKeyBlob = bobKey.Export(CngKeyBlobFormat.EccPublicBlob);
}
private static byte[] AliceSendsData(string message)
{
Console.WriteLine("Alice sends message: {0}", message);
byte[] rawData = Encoding.UTF8.GetBytes(message);
byte[] encryptedData = null;
using (var aliceAlgorithm = new ECDiffieHellmanCng(aliceKey))
using (CngKey bobPubKey = CngKey.Import(bobPubKeyBlob,
CngKeyBlobFormat.EccPublicBlob))
{
byte[] symmKey = aliceAlgorithm.DeriveKeyMaterial(bobPubKey);
Console.WriteLine("Alice creates this symmetric key with " +
"Bobs public key information: {0}",
Convert.ToBase64String(symmKey));
using (var aes = new AesCryptoServiceProvider())
{
aes.Key = symmKey;
aes.GenerateIV();
using (ICryptoTransform encryptor = aes.CreateEncryptor())
using (MemoryStream ms = new MemoryStream())
{
//create CryptoStream and encrypt data to send
var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write);
//write initialization vector not encrypted
ms.Write(aes.IV, 0, aes.IV.Length);
cs.Write(rawData, 0, rawData.Length);
cs.Close();
encryptedData = ms.ToArray();
}
aes.Clear();
}
}
Console.WriteLine("Alice: message is encrypted: {0}",
Convert.ToBase64String(encryptedData)); ;
Console.WriteLine();
return encryptedData;
}
}
}

Je pense que c'est assez sécurisé. Chaque fois qu'il envoie un autre tableau d'octets, même si l'envoi de la même info!

  • Il semble que vous être en train de réinventer le protocole SSL (ou au moins, votre tâche pourrait être accomplie à l'aide de SSL). Une raison quelconque vous ne voulez pas utiliser SSL ?
  • Je ne sais pas, il sera bon de savoir comment utiliser les clés privées et publiques avec le code pas seulement à comprendre la partie théorique... Peut-être que vous avez raison, je devrais utiliser ssl mais je n'ai jamais utilisé ce feather. Je suis nouveau dans le monde de la cryptographie...
  • Je ne veux pas vous les gars pour modifier cet exemple. Il sera agréable de recevoir un sassier exemple. J'ai posté cet exemple juste pour vous montrer ce que je cherchais. Je veux juste comprendre comment cela fonctionne et de le faire fonctionner avec le code c'est ça...
  • Vote pour fermer ce qu'il n'a pas vraiment poser une question. Peut-être que le code pourrait être publié sur la revue de code site. Mais comme il est la seule réponse possible est d'expliquer totalement la cryptographie asymétrique (y compris la façon d'orthographier correctement) et de la sécurité des transports.
  • Je veux dire: "Étape 1: le client crée sa clé publique et privée. Il est en mesure de chiffrer avec sa clé privée et de déchiffrer avec sa clé publique." grande, ce qui est totalement faux déjà. Ne pas utiliser le texte ci-dessus à titre d'exemple.
InformationsquelleAutor Tono Nam | 2011-09-24