如何解决Windows 上 C# 和 C++ 之间的 Diffie Hellman 密钥交换
我想使用 Diffie Hellman
算法在 C++
服务器和 C#
客户端之间安全地交换密钥,这两个客户端都在 Windows
上运行。我尝试在 ECDiffieHellmanCng
中使用 C#
生成公钥,如下所示:
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++
交互。
是否有任何与 C++
兼容的 ECDiffieHellmanCng
库或代码?我查看了 Crypto++
but it wants me to generate a p
,q
,and g
as well as the public key size being 128
bytes,它看起来与我的 C#
密钥交换方法不兼容。
欢迎提供任何其他用于执行密钥交换的建议或代码示例。
解决方法
因为我只是想要一个加密连接,所以使用 OpenSSL
是可行的方法。
也许这会对你有所帮助?
#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;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。