English 中文(简体)
C#中的不对称加密法
原标题:Asymmetric cryptography example in C#

我需要将机密数据发送到一个服务器,以了解与肺结核有关的联系。 我做了很多研究,我理解理论部分。 根据我研究的情况,我想做以下工作:

注 有一个服务器和一个客户:(我们假定客户或服务器的公用钥匙可由任何人获得)。

  1. 客户创建自己的公共和私人钥匙。 他能够与他的私人钥匙进行加密,并与他的公用钥匙进行加密。

  2. 服务器创建他的公共和私人钥匙。 私人钥匙被用于加密信息,公用钥匙被用于加密信息。 (单位:千美元)

  3. 客户获得服务器的公用钥匙。 然后,客户将能够用该钥匙和唯一能够加密的钥匙加密电文,即电文是服务器的私人钥匙。

  4. 由于服务器需要确定该信息来自该特定客户,客户将把其姓名(签名)与私人钥匙加以加密。

  5. 因此,客户信息将包含:要发送的数据、客户的公用钥匙、客户名称与客户的私人钥匙加密。

  6. 客户将把电文与服务器的公用钥匙加密。 然后,客户将向服务器发出这一信息。

  7. 服务器将把刚刚收到的电文与他的私人钥匙隔开。

  8. 一旦电文被加密,该电文将包含数据(info)、加密签名、客户的公用钥匙。

  9. finally, the server will decrypt the client signature with the public key that was contained on the message to verify that the message is from that client.


因此,是不对称加密法如何发挥作用。 我也研究了使你能够创造这一关键楼梯的课堂。 NET框架。 我所研究的使你能够创造这种公共和私人钥匙的课堂是:

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 

现在我的问题是,我如何利用这几类人与C#做这件事? 我理解理论部分是如何运作的,但我如何做我刚才描述的法典。 我已经研究了一些例子,但我很难理解这些例子。

这里我发现的一个例子是,我相信我所说的话:

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();
            }
        }
    }
}

In this program I believe the client is Alice and the server is Bob. I have to split this program into two parts. I am having a hard time understanding it and if I give it a try most likely I will make it work. Anyways how can I split this program into a server side code and client side code. I know how to send bytes between server and client. But I don t want to make it work without understanding what is going on. maybe you guys can show me an easier example.


EDIT

I managed to separate the code: here is the server code (the ip address of my computer happened to be 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();
            }
        }
    }
}

这里是客户守则:

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;
        }
    }
}

我认为,这很安全。 每当它派一个不同的旁观阵列,尽管它发送了同样的信息!

最佳回答

阁下指出,你是加密的开端人。 如果这是一声不响的项目,了解大的加密。 如果这是真正的生产法典,你将无保障地予以执行。 你们应当使用诸如SSL/HTTPS/what等现成工具来解决这一问题,而不是错失。

I ll take this opportunity to point out areas where your sketch is fatally weak.

3) the client get s the server s public key.

OK。 如何? www.un.org/Depts/DGACM/index_spanish.htm 这是最重要的一步。 整个系统的安全取决于这一步骤,而且你在如何运作方面完全感到疲.。 客户是否获得服务器的公用钥匙? 谁阻止一个邪恶的人打电话给客户,说“客人,我是服务器”。 我的公用钥匙 现在客户正在加密信息,只能由邪恶者加密。 邪恶者拥有真正的服务器,具有公用钥匙,因此邪恶者将电文重新贴上真正的公用钥匙并发送。 因此,你的整个系统受到破坏。 如果有一个可靠的关键交换机制<>,公用钥匙加密系统就只能是安全的。 (一个合理的问题是:如果你有一个可靠的关键交换机制,为什么不简单地利用这一机制交换信息?)

4) 由于服务器需要确定电文来自该特定客户,客户将将其姓名(签名)与私人钥匙加密。

客户应当把整个电文的散射作为签名,而不仅仅是电文的一部分。 这样,服务器就能够证明整个信息来自客户。

6)客户将把电文与服务器的公用钥匙加密。 然后,客户将向服务器发出这一信息。

页: 1 更好的是,服务器和客户商定一个对称加密系统的关键。 钥匙可在服务器与使用公用钥匙加密系统的客户之间传送。 服务器和客户现在拥有共同的秘密钥匙,可以用于本次通信会议。

(9) 最后,服务器将把客户签名与电文中所载的公用钥匙加密,以核实电文来自该客户。

地球如何帮助任何东西? 我想向你发出一个信息。 你们想知道来自谁。 因此,我向您发送了我的驾驶执照复印件,以便你能够将许可证上的签名与电文上的签名进行比较。 你们怎样知道我寄给你my的驾驶执照,而不是他人的复印件? www.un.org/Depts/DGACM/index_spanish.htm 这根本无法解决客户认证问题。 同样,you需要解决主要分配问题。 这一制度取决于是否有安全的关键分配基础设施,而你没有具体说明。

问题回答

作为答案,因为发表评论的时间太长,因此没有具体回答你的问题。

正如德赖斯在评论中提到的那样,你应当真正依靠被视为安全的现有解决办法。 尽管如此,你的议定书确实有安全问题:

  • 通信通常是双向的,但你似乎只处理单向通信(服务器的客户)。 这并不重要,因为你说,你会再次使用肺结核,因为它本身就是双向议定书。

  • 第4和第5步是 b的:由于你将客户的公用钥匙寄到电文内,任何人都可能产生一种搭乘机,并用这种平子对客户的身份进行加密。 从您的描述来看,服务器对客户钥匙没有事先了解,因此这一签名只能确保电文的完整性,具体地说,根本不能使客户的身份证明可信。

为了适当识别,你确实有其他先决条件;服务器必须事先了解客户的公用钥匙,或者必须能够利用信任的第三人相信客户的自称。 这就是证书和证书信托链的内容:如果该客户出示第三当事人X和服务器X出具的证明,那么他可以假定客户是谁。

国家安全局基本上支持两种方式:

  • 不仅对服务器的身份进行了核实,而且任何客户都可以与服务器进行通信;客户的身份未经核实,而且只有(经过联系谈判后)客户总是与服务器通信的客户相同。 这是网上购物的典型用法,即(作为客户)相信服务器并创建可信赖的联系,但服务器不知道是谁。

  • 可通过使用客户证书进行双向认证。 服务器必须直接了解并信任客户证书或客户证书签发人,以便成功谈判联系。 在这种情况下,服务器确实知道客户是谁,但必须满足上述先决条件。





相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...