C# 中的非对称加密示例

2023-11-24

我需要通过 TCP 连接将机密数据发送到服务器。我做了很多研究并且理解了理论部分。根据我的研究,我想做以下事情:

注意有一个服务器和一个客户端:(我们假设客户端或服务器的公钥可以被任何人获取)

  1. 客户创建他的公钥和私钥。他能够用他的私钥加密并用他的公钥解密。

  2. 服务器创建他的公钥和私钥。私钥用于解密消息,公钥用于加密消息。 (注意与客户的情况相反)

  3. 客户端获取服务器的公钥。然后,客户端将能够使用该密钥加密消息,并且唯一能够解密该消息的密钥是服务器的私钥。

  4. 由于服务器需要确定消息来自该特定客户端,因此客户端将使用他的私钥加密他的名字(签名)。

  5. 因此客户端消息将包含:要发送的数据、客户端的公钥、使用客户端私钥加密的客户端名称。

  6. 客户端将使用来自服务器的公钥对消息进行加密。然后客户端将该消息发送到服务器。

  7. 服务器将用他的私钥解密刚刚收到的消息。

  8. 一旦消息被解密,它将包含数据(信息)、加密签名、来自客户端的公钥。

  9. 最后,服务器将使用消息中包含的公钥解密客户端签名,以验证该消息是否来自该客户端。


好的,这就是非对称加密的工作原理。我还研究了使您能够使用 .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();
            }
        }
    }
}

在这个程序中,我相信客户端是 Alice,服务器是 Bob。我必须把这个程序分成两部分。我很难理解它,如果我尝试一下,我很可能会成功。无论如何,我如何将该程序拆分为服务器端代码和客户端代码。我知道如何在服务器和客户端之间发送字节。但我不想在不了解发生了什么的情况下让它发挥作用。也许你们可以给我看一个更简单的例子。


EDIT

我设法分离了代码:这是服务器代码(我的计算机的IP地址恰好是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/任何其他工具)来解决此问题,而不是自己做错事。

我将借此机会指出你的草图的致命弱点。

3) 客户端获取服务器的公钥。

好的。如何?这是最重要的一步。整个系统的安全性依赖于这一步,而您已经完全掩盖了它是如何工作的。客户端如何获取服务器的公钥呢?什么可以阻止邪恶的人打电话给客户端并说“嘿客户端,我是服务器。这是我的公钥!”现在,客户端正在加密只能由作恶者解密的消息。作恶者拥有真实服务器的公钥,因此作恶者用真实的公钥重新加密消息并继续发送。您的整个系统因此受到损害。公钥密码系统是唯一安全的是否有安全的密钥交换机制。 (一个合理的问题是:如果您有一个安全的密钥交换机制,为什么不首先简单地使用它来交换消息呢?)

4)由于服务器需要确定消息来自该特定客户端,因此客户端将使用他的私钥对其名称(签名)进行加密。

客户端应该加密整个消息的哈希值作为签名,而不仅仅是消息的一部分。这样服务器就有证据表明整个消息来自客户端。

6) 客户端将使用来自服务器的公钥对消息进行加密。然后客户端将该消息发送到服务器。

This is 效率极低。更好的是服务器和客户端就对称密码系统的密钥达成一致。密钥可以使用公钥密码系统在服务器和客户端之间传输。服务器和客户端现在拥有可用于此通信会话的共享密钥。

9) 最后,服务器将使用消息中包含的公钥解密客户端签名,以验证该消息是否来自该客户端。

这到底有什么帮助呢?我想给你发消息。你想知道它来自谁。因此,我向您发送了我的驾驶执照的复印件,以便您可以将执照上的签名与消息上的签名进行比较。你怎么知道我发给你的my驾驶执照而不是别人的复印件?这根本不能解决客户端身份验证问题。 Again, 你需要解决密钥分配问题。该系统依赖于安全的密钥分发基础设施,而您尚未指定该基础设施。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C# 中的非对称加密示例 的相关文章

  • 添加 Nullable int 时保持 null?

    我想添加可为空的int 并保留null当所有值都是null 我想要这个结果 1 2 3 1 null 1 null null null O null 0 问题是 如果我将一个值与 null 相加 结果为 null int i1 1 int
  • 如何在另一个应用程序中挂钩 api 调用

    我正在尝试挂钩另一个应用程序的 ExtTextOut 和 DrawTextExt GDI 方法调用 我知道我需要使用 GetProcAddress 来查找 gdi32 dll 中那些方法的地址 并用我的函数的地址覆盖我想要挂钩的进程中的地址
  • 在 OnModelCreating 期间设置列名称

    Issue 我目前正在尝试通过设置的属性为我的表及其列添加前缀 我正在使用实体框架核心 我已经正确地为表名添加了前缀 但我似乎无法弄清楚列的前缀 我有一种感觉 我需要使用反射 我已经留下了我的 可能很糟糕的 反思尝试 有人有办法在实体中设置
  • std::call_once 可重入且线程安全吗?

    std call once http en cppreference com w cpp thread call once是线程安全的 但它也是可重入的吗 我使用 VS2012 调试和发布 进行的测试表明 调用std call once从单
  • 为什么'enable_if'不能用于禁用这里声明

    include
  • 将接口转换为其具体实现对象,反之亦然?

    在 C 中 当我有一个接口和几个具体实现时 我可以将接口强制转换为具体类型 还是将具体类型强制转换为接口 这种情况下的规则是什么 Java 和 C 中都允许这两个方向 向下转型需要显式转型 如果对象类型不正确 可能会抛出异常 然而 向上转换
  • UI 函数在快速事件完成之前触发

    我有一个停靠在 Silverlight 应用程序中的 Web 浏览器框架 有时会在其上弹出全窗口 XAML Silverlight UI 元素 我已经或多或少修复了一个老问题 即 Web 框架的内容似乎与 Silverlight 内容不能很
  • 如何对 NServiceBus.Configure.WithWeb() 进行单元测试?

    我正在构建一个 WCF 服务 该服务接收外部 IP 上的请求并将其转换为通过 NServiceBus 发送的消息 我的单元测试之一调用Global Application Start 它执行应用程序的配置 然后尝试将 Web 服务解析为 验
  • 析构函数中的异步操作

    尝试在类析构函数中运行异步操作失败 这是代码 public class Executor public static void Main var c1 new Class1 c1 DoSomething public class Class
  • 在 asp.net MVC 中使用活动目录进行身份验证

    我想使用活动目录对我的 asp net mvc 项目中的用户进行身份验证 在网上冲浪了几个小时后 我没有找到任何对我有用的东西 我已经看到了所有结果 但什么也没有 我尝试按照许多帖子的建议编辑我的 web config 如果有人可以帮助我提
  • 搜索实体的所有字段

    我正在尝试在客户数据库上实现 多功能框 类型的搜索 其中单个查询应尝试匹配客户的任何属性 这是一些示例数据来说明我想要实现的目标 FirstName LastName PhoneNumber ZipCode Mary Jane 12345
  • 英文日期差异

    接近重复 如何计算相对时间 https stackoverflow com questions 11 how do i calculate relative time 如何在 C 中计算某人的年龄 https stackoverflow c
  • Linux mremap 不释放旧映射?

    我需要一种方法将页面从一个虚拟地址范围复制到另一个虚拟地址范围 而无需实际复制数据 范围很大 延迟很重要 mremap 可以做到这一点 但问题是它也会删除旧的映射 由于我需要在多线程环境中执行此操作 因此我需要旧映射能够同时使用 因此稍后当
  • 选择查询不适用于使用Parameters.AddWithValue 的参数

    C 中的以下查询不起作用 但我看不出问题所在 string Getquery select from user tbl where emp id emp id and birthdate birthdate cmdR Parameters
  • C++ 中 void(*)() 和 void(&)() 之间的区别[重复]

    这个问题在这里已经有答案了 在此示例代码中 func1是类型void int double and funky是类型void int double include
  • 通过 Tab 键浏览 XML 文档字段

    In VB NET you can move through the fields in the XML member documentation with the Tab key 这在 C 中不起作用 还有其他方法吗 除了用鼠标将光标放在
  • 为什么以下 C 程序会出现总线错误?

    我认为这是第一个失败的 strtok 调用 好久没写C了 有点不知所措 非常感谢 include
  • 如何得知客户端从服务器的下载速度?

    根据客户的下载速度 我想以低质量或高质量显示视频 任何 Javascript 或 C 解决方案都是可以接受的 Thanks 没有任何办法可以确定 您只能测量向客户端发送数据的速度 如果没有来自客户端的任何类型的输入来表明其获取信息的速度 您
  • 使用 using 声明时,非限定名称查找如何工作?

    根据 C 标准 这是格式错误还是格式良好 namespace M struct i namespace N static int i 1 using M i using N i int main sizeof i Clang 拒绝它 GCC
  • 结构化绑定的用例有哪些?

    C 17 标准引入了新的结构化绑定 http en cppreference com w cpp language structured binding功能 最初是proposed http www open std org jtc1 sc

随机推荐

  • 仅锁定 ID

    我有一个方法需要专门运行一段代码 但我只想在确实需要时添加此限制 根据 Id 值 Int32 我将加载 修改不同的对象 因此锁定所有线程的访问没有意义 这是这样做的第一次尝试 private static readonly Concurre
  • 直接输入地址栏时,您必须使用 API 密钥来验证对 Google Maps Platform API 的每个请求

    我收到这样的错误 error message This API project is not authorized to use this API results status REQUEST DENIED 每当我运行这个 https ma
  • Web api 从处理程序内部获取路由模板

    在将问题放在这里之前 我进行了很多搜索 但搜索得越多 我就越感到困惑 所以我创建了一个处理程序 我试图获取这样的路线 public class ExecutionDelegatingHandler DelegatingHandler pro
  • 扩展模块中的类方法

    我正在研究 ruby 的元编程功能 我发现它有点棘手 我正在尝试使用模块包装方法调用 目前 我正在这样做 module Bar module ClassMethods def wrap method class eval do old me
  • 如何让 只接受图像文件?

    我只需要通过上传图像文件
  • Android:位图允许的最大宽度和高度

    我正在创建一个应用程序 需要将大图像解码为位图以显示在 ImageView 中 如果我只是尝试将它们直接解码为位图 我会收到以下错误 位图太大 无法上传到纹理中 1944x2592 最大 2048x2048 因此 为了能够显示太高分辨率的图
  • 将数组键从下划线大小写递归转换为驼峰大小写

    我必须想出一种方法将使用下划线 下划线大小写 的数组键转换为驼峰命名法 这必须递归完成 因为我不知道哪些数组将被输入到该方法中 我想出了这个 private function convertKeysToCamelCase apiRespon
  • 从C#到SQL Server的批量插入策略

    在我们当前的项目中 客户将向我们的系统发送复杂 嵌套消息的集合 这些消息的频率约为 1000 2000 条消息 每秒 这些复杂对象包含交易数据 待添加 以及主数据 如果找不到 将添加 但客户不传递主数据的 ID 而是传递 名称 列 系统检查
  • 在命令上设置 git 默认标志

    我想知道是否有办法为 git 命令默认设置标志 具体来说 我想设置 abbrev commit标志以便在执行时git log 我要执行git log abbrev commit 与问题不同 有没有办法为 git 命令默认设置一个标志 显然没
  • 如何使基本类型属性可选?

    我想在我的 JSONModel 类中创建一些原始属性选项 请参阅下面的代码 import JSONModel h protocol GreenModel
  • 悬停时颜色转灰度在 IE11 中不起作用

    我在用着Gray网站上的一些元素 但是 我无法让它在 IE11 中工作 例如 在下面的小提琴中 我使用 JS 添加grayscale and grayscale fade类 以便图像在悬停时从彩色渐变为灰度 我如何让它在 IE11 中工作
  • 在ggplot2中创建堆积密度图

    我正在尝试在 ggplot2 中创建堆积密度图 并且我还试图了解 qplot 相对于 ggplot 的工作原理 我在网上找到了下面的例子 qplot depth density data diamonds geom density fill
  • 为什么我的自定义控件的 Text 属性不会显示在“属性”窗口中?

    我有一个继承自 UserControl 的用户控件 这是一个按钮 因此我尝试使用像真实按钮一样的 Text 属性来更改按钮中的文本 而不是像 Text 这样命名我自己的文本 我有以下代码 但它不起作用 即它没有显示在属性窗口中 标签的名称是
  • 架构 i386 的未定义符号,为 iOS 构建?

    我已经下载了 iProcessing 框架 允许您为 iPhone 构建本机 javascript 应用程序 当我尝试编译时 我得到 Undefined symbols for architecture i386 ADBannerConte
  • 在计算机之间导入/导出 Chrome devtools 断点和设置

    Quoting 最初的想法 我遇到了一个问题 我需要将所有调试器断点共享给我的同事 以便在他结束时调试问题 因此考虑实施诸如从一个系统导出调试器点并在另一系统导入之类的东西 由于 devtools 不提供内置的导入 导出功能 还有其他方法吗
  • 将远程图像保存到隔离存储中

    我尝试使用此代码下载图像 void downloadImage WebClient client new WebClient client DownloadStringCompleted new DownloadStringComplete
  • 如何防止 URLDownloadToFile 从缓存中检索?

    我正在使用 URLDownloadToFile 从网站检索文件 后续调用将返回原始文件而不是更新版本 我假设它正在检索缓存的版本 在调用 URLDownloadToFile 之前使用相同的 URL 调用 DeleteUrlCacheEntr
  • invalidateList 和 invalidateDisplayList 有什么区别?

    我有一个 DataGrid 其中填充有 ArrayCollection 中的对象 更新对象的字段之一后 我希望屏幕更新 数据源不可绑定 因为我是在运行时构建它的 而且我还不知道如何使其可动态绑定 这是另一个问题 在这种情况下 如果我在网格上
  • 清理 Mercurial 存储库

    我的 hg 存储库的历史记录中有一堆文件已被删除 它们导致存储库变得相当大 其中一些是图像 以及项目早期的 sql 转储 以及其他一开始就不应该提交的东西 我如何让 Mercurial 忘记这些东西并再次将我的存储库缩小到合理的大小 我是否
  • C# 中的非对称加密示例

    我需要通过 TCP 连接将机密数据发送到服务器 我做了很多研究并且理解了理论部分 根据我的研究 我想做以下事情 注意有一个服务器和一个客户端 我们假设客户端或服务器的公钥可以被任何人获取 客户创建他的公钥和私钥 他能够用他的私钥加密并用他的