{"id":18246380,"url":"https://github.com/tuanlh/private-chat-diffiehellman","last_synced_at":"2025-06-12T08:33:15.158Z","repository":{"id":127301075,"uuid":"131103915","full_name":"tuanlh/private-chat-diffiehellman","owner":"tuanlh","description":"Ứng dụng chat TCP dạng Client - Server có sử dụng mã hóa AES và phương thức trao đổi khóa ECDiffie Hellman bằng C#","archived":false,"fork":false,"pushed_at":"2018-05-10T15:04:57.000Z","size":1101,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-04-08T19:28:13.454Z","etag":null,"topics":["aes","chat","csharp","diffie-hellman","tcp-socket"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tuanlh.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-04-26T05:21:20.000Z","updated_at":"2019-08-06T13:27:20.000Z","dependencies_parsed_at":null,"dependency_job_id":"3b230d04-e86e-4561-9235-eff7a39fbdbb","html_url":"https://github.com/tuanlh/private-chat-diffiehellman","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/tuanlh/private-chat-diffiehellman","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tuanlh%2Fprivate-chat-diffiehellman","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tuanlh%2Fprivate-chat-diffiehellman/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tuanlh%2Fprivate-chat-diffiehellman/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tuanlh%2Fprivate-chat-diffiehellman/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tuanlh","download_url":"https://codeload.github.com/tuanlh/private-chat-diffiehellman/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tuanlh%2Fprivate-chat-diffiehellman/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259430176,"owners_count":22856199,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aes","chat","csharp","diffie-hellman","tcp-socket"],"created_at":"2024-11-05T09:25:44.523Z","updated_at":"2025-06-12T08:33:15.142Z","avatar_url":"https://github.com/tuanlh.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Sản phẩm có gì?\n* Tính năng cơ bản của sản phẩm là cho phép Client và Server chat với nhau.\n* Các thông điệp được mã hóa bằng AES, và khóa được sử dụng trong thuật toán AES được trao đổi qua lại giữa Client và Server bằng phương thức Diffie Hellman.\n# Sử dụng làm sao?\nThật sự không quá khó khăn để sử dụng một ứng dụng GUI với giao diện đơn giản trực quan.\n\nĐể mô tả rõ hơn cách sử dụng phần mềm, ta sử dụng hai máy ảo là Windows 7 có IP là **10.0.0.2** và Windows 8.1 có IP là **10.0.0.16**, hai máy đều sử dụng chung card mạng là Host-only. Ta chọn máy Windows 8.1 là Server.\n\nSản phẩm được chia ra 2 phần là Server và Client với file thực thi và thư viện kèm theo (lưu ý là phải có file thư viện MessageLib.dll kèm theo). File thực thi và thư viện nằm trong thư mục [Release](https://github.com/arituan/private-chat-diffiehellman/tree/master/Release)\n\n- Đầu tiên là chạy **Server.exe** lên ta có giao diện như sau:\n\t\n\t![Giao diện Server](https://github.com/arituan/private-chat-diffiehellman/raw/master/man-server.PNG)\n\n\tTa tiến hành chọn IP và Port để lắng nghe các kết nối từ phía client (Danh sách IP được tạo dựa vào các Interface network trên máy), Ở đây ta chọn IP 10.0.0.16 với port là 42018. Sau đó nhấn nút **Mở kết nối** để bắt đầu lắng nghe.\n\n- Tiếp theo khởi chạy file **Client.exe** ta được giao diện như hình sau:\n\t\n\t![Giao diện Client](https://github.com/arituan/private-chat-diffiehellman/raw/master/man-client.PNG)\n\n\tĐiền IP và Port của Server và ấn **Kết nối**.\n\t\n- Sau khi 2 bên tạo kết nối thành công, ta bắt đầu trò chuyện giữa Client và Server. Lưu ý trước khi tạo kết nối ta nên bật wireshark để theo dõi quá trình trao đổi giữa Client và Server.\n\t\n\tKết quả màn hình tại Server:\n\t\n\t![Kết quả tại Server](https://github.com/arituan/private-chat-diffiehellman/raw/master/server-capture.PNG)\n\t\n\tKết quả màn hình tại Client:\n\t\n\t![Kết quả tại Client](https://github.com/arituan/private-chat-diffiehellman/raw/master/client-capture.PNG)\n\n- Kết quả Wireshark bắt được:\n\t\n\t![Kết quả Wireshark](https://github.com/arituan/private-chat-diffiehellman/raw/master/wireshark-capture.PNG)\n\n\tTừ kết quả Wireshark bắt được, ta chỉ nhìn được cấu trúc của các message chứ không đọc được nội dung cụ thể bên trong, vì nó đã được mã hóa.\n\n# Làm như thế nào để viết được?\nProject được thực hiện trên Visual Studio 2015.\n\nQuá trình trao đổi giữa client và server sử dụng thư viện **System.Net.Socket** (tham khảo thêm tại: https://msdn.microsoft.com/en-us/library/system.net.sockets(v=vs.110).aspx)\n\nSau khi tạo kết nối thành công, giữa client và server sẽ diễn ra quá trình trao đổi khóa với nhau bằng phương thức Diffie Hellman, ở đây sử dụng thư viện có sẵn trong .NET là **System.Security.Cryptography**, trong thư viện này cung cấp cho chúng ta Class **ECDiffieHellmanCng**, class này sử dụng lí thuyết đường cong Elliptic. Cũng là ý tưởng trao đổi khóa Diffie Hellman nhưng với **Elliptic Curve Diffie Hellman** thì chỉ khác nhau ở việc sinh G so với Diffie Hellman truyền thống:\n\n* Alice và Bob thống nhất với nhau một điểm **P** nằm trên đường cong **E** thuộc trường trường **F**\u003csub\u003eq\u003c/sub\u003e. Điểm **P** ở đây đóng vai trò như số sinh g trong Diffie Hellman truyền thống.\n* Alice sẽ sinh ngẫu nhiên một số bí mật k\u003csub\u003eA\u003c/sub\u003e, và tính giá trị P\u003csub\u003eA\u003c/sub\u003e=k\u003csub\u003eA\u003c/sub\u003eP\n* Bob sẽ sinh ngẫu nhiên một số bí mật k\u003csub\u003eB\u003c/sub\u003e, và tính giá trị P\u003csub\u003eB\u003c/sub\u003e=k\u003csub\u003eB\u003c/sub\u003eP\n* Alice và Bob trao đổi cho nhau P\u003csub\u003eA\u003c/sub\u003e và P\u003csub\u003eB\u003c/sub\u003e.\n* Alice và Bob sẽ có chung giá trị P\u003csub\u003eAB\u003c/sub\u003e = k\u003csub\u003eA\u003c/sub\u003eP\u003csub\u003eB\u003c/sub\u003e = k\u003csub\u003eB\u003c/sub\u003eP\u003csub\u003eA\u003c/sub\u003e = k\u003csub\u003eA\u003c/sub\u003ek\u003csub\u003eB\u003c/sub\u003eP.\n\t\n\tCác số bí mật k\u003csub\u003eA\u003c/sub\u003e và k\u003csub\u003eB\u003c/sub\u003e được sinh ngẫu nhiên trong khoảng {1, ..., n-1}, trong đó n là thứ tự nhóm được sinh ra bởi P.\n\nAlice và Bob lúc nãy đã có khóa bí mật để dùng chung, ta sẽ dùng khóa này vào một thuật toán mã hóa đối xứng, trong project sử dụng AES để mã hóa. Mã hóa AES cũng có sẵn trong thư viện **System.Security.Cryptography**. Hiện thực hóa quá trình trao đổi khóa và mã hóa qua ví dụ tại: https://msdn.microsoft.com/en-us/library/system.security.cryptography.ecdiffiehellmancng(v=vs.110).aspx\n\nTa nhìn ví dụ trong link sẽ thấy khi thực hiện mã hóa AES sẽ sinh ra một **IV**, IV này sẽ được kèm theo thông điệp và gửi qua cho đối phương. Một vấn đề ta cần giải quyết là làm sao tích hợp được IV vào thông điệp. Để giải quyết vấn đề đó thì cần tạo một cấu trúc cho thông điệp và sử dụng Serialization để gói gọn cấu trúc đó thành các bytes và truyền đi.\n\nĐến đây thì một vấn đề nữa xảy ra là làm sao để phân biệt gói tin nào là gói tin trao đổi khóa, gói nào là gói thông điệp bình thường. Vậy ta cần thêm một thuộc tính là mode vào trong cấu trúc thông điệp. Cấu trúc của thông điệp như sau:\n\n````Csharp\nusing System;\nusing System.IO;\nusing System.Runtime.Serialization;\nusing System.Security.Cryptography;\nusing System.Text;\n\n/*\n* Structure a Message\n* Attributes\n*      byte[] msg: contain message or public key\n*      exData: IV in AES\n*      mode: 0 - KeyExchange, 1 - SendMsg\n*/\n\nnamespace MessageLib\n{\n\n\tpublic class MsgStruct : ISerializable\n\t{\n\t\t\n\t\tprivate byte[] _msg;\n\t\tprivate int _mode;\n\t\tprivate byte[] _extData; //IV or Public key exchange\n\t\t\n\t\tpublic MsgStruct()\n\t\t{\n\t\t\tmsg = null;\n\t\t\textData = null;\n\t\t\tmode = 1;\n\t\t\t\n\t\t}\n\t\t\n\t\tpublic MsgStruct(byte[] txt, int mode)\n\t\t{\n\t\t\tthis.msg = txt;\n\t\t\tthis.mode = mode;\n\t\t}\n\t\t\n\t\tpublic MsgStruct(string msg)\n\t\t{\n\t\t\tif (msg != null)\n\t\t\tthis.msg = Encoding.UTF8.GetBytes(msg);\n\t\t}\n\t\t\n\t\tpublic void Encrypt(byte[] key)\n\t\t{\n\t\t\tusing (Aes aes = new AesCryptoServiceProvider())\n\t\t\t{\n\t\t\t\taes.Key = key;\n\t\t\t\textData = aes.IV;\n\t\t\t\t// Encrypt the message\n\t\t\t\tusing (MemoryStream ciphertext = new MemoryStream())\n\t\t\t\tusing (CryptoStream cs = new CryptoStream(ciphertext, aes.CreateEncryptor(), CryptoStreamMode.Write))\n\t\t\t\t{\n\t\t\t\t\tcs.Write(msg, 0, msg.Length);\n\t\t\t\t\tcs.Close();\n\t\t\t\t\tmsg = ciphertext.ToArray();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\tpublic void Decrypt(byte[] key)\n\t\t{\n\t\t\tusing (Aes aes = new AesCryptoServiceProvider())\n\t\t\t{\n\t\t\t\taes.Key = key;\n\t\t\t\taes.IV = extData;\n\t\t\t\t\n\t\t\t\t// Decrypt the message\n\t\t\t\tusing (MemoryStream plaintext = new MemoryStream())\n\t\t\t\t{\n\t\t\t\t\tusing (CryptoStream cs = new CryptoStream(plaintext, aes.CreateDecryptor(), CryptoStreamMode.Write))\n\t\t\t\t\t{\n\t\t\t\t\t\tcs.Write(msg, 0, msg.Length);\n\t\t\t\t\t\tcs.Close();\n\t\t\t\t\t\tmsg = plaintext.ToArray();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\tpublic string GetString()\n\t\t{\n\t\t\treturn Encoding.UTF8.GetString(msg);\n\t\t}\n\t\t\n\t\tpublic byte[] msg\n\t\t{\n\t\t\tget { return _msg; }\n\t\t\tset { _msg = value; }\n\t\t}\n\t\t\n\t\tpublic int mode\n\t\t{\n\t\t\tget { return _mode; }\n\t\t\tset { _mode = value; }\n\t\t}\n\t\t\n\t\tpublic byte[] extData\n\t\t{\n\t\t\tget { return _extData; }\n\t\t\tset { _extData = value; }\n\t\t}\n\t}\n}\n````\n\nCấu trúc thông điệp cũng đã được tích hợp luôn hàm ``Encrypt()`` và ``Decrypt()`` vào, trước khi gửi thông điệp đi thì ta cần gọi hàm ``Encrypt()`` và sau khi nhận thông điệp thì ta cần gọi hàm ``Decrypt()``.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftuanlh%2Fprivate-chat-diffiehellman","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftuanlh%2Fprivate-chat-diffiehellman","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftuanlh%2Fprivate-chat-diffiehellman/lists"}