【问题标题】:Diffie Hellman key exchange between C# and C++ on WindowsWindows 上 C# 和 C++ 之间的 Diffie Hellman 密钥交换
【发布时间】:2021-08-07 00:18:56
【问题描述】:

我想使用Diffie Hellman 算法在C++ 服务器和C# 客户端之间安全地交换密钥,这两个客户端都在Windows 上运行。我尝试在C# 中使用ECDiffieHellmanCng 生成公钥,如下所示:

ECDiffieHellmanCng diffieHellman = new ECDiffieHellmanCng
{
    KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash,
    HashAlgorithm = CngAlgorithm.Sha256
};

byte[] publicKey = diffieHellman.PublicKey.ToByteArray(); // 140 bytes

此外,我正在使用以下代码派生AES key

var cngKey = CngKey.Import(publicKey, CngKeyBlobFormat.EccPublicBlob);
var aesKey = diffieHellman.DeriveKeyMaterial(cngKey); // 32 bytes

这在 C# 上下文中运行良好,但我需要它与 C++ 交互。

是否有任何与ECDiffieHellmanCng 兼容的C++ 库或代码?我查看了Crypto++but it wants me to generate a p, q, and g as well as the public key size being 128 bytes,它看起来与我的C# 密钥交换方法不兼容。

欢迎提供任何其他有关执行密钥交换的建议或代码示例。

【问题讨论】:

  • 1) 您真的需要为每个客户端即时生成服务器密钥吗? 这对我来说不合适。客户端在连接时应该以某种方式信任服务器的公钥(要么有硬编码的 pub 密钥,要么使用第三方渠道来检查它),对吗? 2) 你不能只使用 TLS 并避免干预低级别的东西吗?
  • @MaximSagaydachny:我真的不需要,但我认为用AES 实现Diffie-Hellman 就很容易了,显然不是。也许为服务器和客户端设置TLS 更加可行和标准。我也会尝试这个,但由于不同的技术必须交互,它可能是另一种蠕虫。

标签: c# c++ windows diffie-hellman public-key-exchange


【解决方案1】:

因为我只是想要一个加密连接,所以使用OpenSSL 是最好的选择。

【讨论】:

    【解决方案2】:

    也许这会对你有所帮助?

    #pragma warning(disable : 4996)
    
    #include <stdio.h>
    #include <iostream>
    #include <string>
    #include <sstream>
    #include "openssl/dh.h"
    #include "openssl/bn.h"
    #include "openssl/pem.h";
    using namespace std;
    
    DH *dhp = NULL;
    
    static const std::string base64_chars =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "abcdefghijklmnopqrstuvwxyz"
    "0123456789+/";
    
    static inline bool is_base64(unsigned char c) {
        return (isalnum(c) || (c == '+') || (c == '/'));
    }
    
    std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) {
        std::string ret;
        int i = 0;
        int j = 0;
        unsigned char char_array_3[3];
        unsigned char char_array_4[4];
    
        while (in_len--) {
            char_array_3[i++] = *(bytes_to_encode++);
            if (i == 3) {
                char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
                char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
                char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
                char_array_4[3] = char_array_3[2] & 0x3f;
    
                for (i = 0; (i < 4); i++)
                    ret += base64_chars[char_array_4[i]];
                i = 0;
            }
        }
    
        if (i)
        {
            for (j = i; j < 3; j++)
                char_array_3[j] = '\0';
    
            char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
            char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
            char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
            char_array_4[3] = char_array_3[2] & 0x3f;
    
            for (j = 0; (j < i + 1); j++)
                ret += base64_chars[char_array_4[j]];
    
            while ((i++ < 3))
                ret += '=';
    
        }
    
        return ret;
    
    }
    std::string base64_decode(std::string const& encoded_string) {
        int in_len = encoded_string.size();
        int i = 0;
        int j = 0;
        int in_ = 0;
        unsigned char char_array_4[4], char_array_3[3];
        std::string ret;
    
        while (in_len-- && (encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
            char_array_4[i++] = encoded_string[in_]; in_++;
            if (i == 4) {
                for (i = 0; i < 4; i++)
                    char_array_4[i] = base64_chars.find(char_array_4[i]);
    
                char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
                char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
                char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
    
                for (i = 0; (i < 3); i++)
                    ret += char_array_3[i];
                i = 0;
            }
        }
    
        if (i) {
            for (j = i; j < 4; j++)
                char_array_4[j] = 0;
    
            for (j = 0; j < 4; j++)
                char_array_4[j] = base64_chars.find(char_array_4[j]);
    
            char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
            char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
            char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
    
            for (j = 0; (j < i - 1); j++) ret += char_array_3[j];
        }
    
        return ret;
    }
    
    int main(int argc, char *argv[])
    {
        BIGNUM* priv_key = NULL;
        BIGNUM* apub_key = NULL;
        BIGNUM* p = NULL;
        BIGNUM* g = NULL;
        std::string userPubKey;
        std::string prime;
        std::string generator;
    
        if (argc < 6) {
            printf("%s", "Missing parameters: -p, -key -g");
            return -1;
        }
    
        //Process parameters
        int count;
        for (count = 1; count < argc; count+=2)
        {
            std::string param = (string)argv[count];
    
            if (strcmpi(param.c_str(), "-p") == 0) {
                prime = (string)argv[count+1];
            }
            else if (strcmpi(param.c_str(), "-key") == 0) {
                userPubKey = (string)argv[count + 1];
            }
            else if (strcmpi(param.c_str(), "-g") == 0) {
                generator = (string)argv[count+1];
            }
        }
    
        //Set public key of remote User
        BN_hex2bn(&apub_key, userPubKey.c_str());
    
        DH *dhp = DH_new();
        if (dhp == NULL) {
            return -1;
        }
        
        //Set Prime and Generator
        BN_hex2bn(&p, prime.c_str());
        BN_dec2bn(&g, generator.c_str());
        DH_set0_pqg(dhp, p, NULL, g);
    
        if (DH_generate_key(dhp) != 1) {
            printf("%s", "Error generating keys.");
            return -1;
        }
    
        //Print Public Key as Hex
        const BIGNUM* exportPublic = DH_get0_pub_key(dhp);
        printf("Public Key: %s\r\n", BN_bn2hex(exportPublic));
    
        //Calculate secret
        char buf[256] = { 0 };
        unsigned char* abuf = NULL;
        int alen = DH_size(dhp);
        abuf = (unsigned char*)OPENSSL_malloc(alen);
    
        int aout = DH_compute_key(abuf, apub_key, dhp);
        printf("\r\nThe shared secret is:\r\n");
        std::string encoded = base64_encode(abuf, aout);
        printf("%s\r\n", encoded.c_str());
    
        DH_free(dhp);
        p = NULL;
        g = NULL;
        abuf = NULL;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-19
      • 1970-01-01
      • 2014-05-13
      • 2023-03-03
      • 1970-01-01
      • 2019-05-24
      相关资源
      最近更新 更多