将Diffie Hellman会话密钥用于AES返回错误0x80090005

问题描述 投票:-1回答:1

我需要使用c ++创建服务器和客户端,到目前为止,xchange diffie hellman公共密钥和使用AES 256进行加密,我正在使用MSDN示例进行DH公共密钥创建https://docs.microsoft.com/en-us/windows/win32/seccrypto/diffie-hellman-keys,并且在两端都使用RC4可以很好地使用它(客户端和服务器) ),但是如果我将hSessionKey转换为AES 256,我会在客户端的EncryptDecrypt API上收到错误0x80090005(NET_BAD_DATA),但是如果客户端和服务器都在同一台计算机上运行(不是同一操作系统),结果就可以了!我真的迷路了。

任何帮助将不胜感激。

服务器端:

  #define WIN32_LEAN_AND_MEAN
# define _WINSOCK_DEPRECATED_NO_WARNINGS 

#include <Windows.h>
#include <wincrypt.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#pragma comment(lib, "Ws2_32.lib")
//#pragma comment(lib, "Msvsock.lib")
#pragma comment (lib , "AdvApi32.lib")
#pragma comment(lib, "crypt32.lib")



// The key size, in bits.
#define DHKEYSIZE 512
#define DEFAULT_BUFLEN 1024
// Prime in little-endian format.
static const BYTE g_rgbPrime[] =
{
    0x91, 0x02, 0xc8, 0x31, 0xee, 0x36, 0x07, 0xec,
    0xc2, 0x24, 0x37, 0xf8, 0xfb, 0x3d, 0x69, 0x49,
    0xac, 0x7a, 0xab, 0x32, 0xac, 0xad, 0xe9, 0xc2,
    0xaf, 0x0e, 0x21, 0xb7, 0xc5, 0x2f, 0x76, 0xd0,
    0xe5, 0x82, 0x78, 0x0d, 0x4f, 0x32, 0xb8, 0xcb,
    0xf7, 0x0c, 0x8d, 0xfb, 0x3a, 0xd8, 0xc0, 0xea,
    0xcb, 0x69, 0x68, 0xb0, 0x9b, 0x75, 0x25, 0x3d,
    0xaa, 0x76, 0x22, 0x49, 0x94, 0xa4, 0xf2, 0x8d
};

// Generator in little-endian format.
static BYTE g_rgbGenerator[] =
{
    0x02, 0x88, 0xd7, 0xe6, 0x53, 0xaf, 0x72, 0xc5,
    0x8c, 0x08, 0x4b, 0x46, 0x6f, 0x9f, 0x2e, 0xc4,
    0x9c, 0x5c, 0x92, 0x21, 0x95, 0xb7, 0xe5, 0x58,
    0xbf, 0xba, 0x24, 0xfa, 0xe5, 0x9d, 0xcb, 0x71,
    0x2e, 0x2c, 0xce, 0x99, 0xf3, 0x10, 0xff, 0x3b,
    0xcb, 0xef, 0x6c, 0x95, 0x22, 0x55, 0x9d, 0x29,
    0x00, 0xb5, 0x4c, 0x5b, 0xa5, 0x63, 0x31, 0x41,
    0x13, 0x0a, 0xea, 0x39, 0x78, 0x02, 0x6d, 0x62
};

BYTE g_rgbData[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };


int main()
{

    WSADATA wsaData;
    SOCKET ListenSocket;
    struct sockaddr_in client;
    int iResult;
    char * binaryBuffer = NULL;
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0)
    {
        printf("WSAStartup failed with error: %d\n", iResult);
        return 0;
    }
    BYTE* pubKeyBuffer;
    pubKeyBuffer = (BYTE*)malloc(1024);
    ZeroMemory(pubKeyBuffer, 1024);


    BOOL fReturn;
    HCRYPTPROV hProvParty1 = NULL;
    HCRYPTPROV hCryptProv = NULL;
    DATA_BLOB P;
    DATA_BLOB G;
    HCRYPTKEY hPrivateKey1 = NULL;
    //HCRYPTKEY hPrivateKey2 = NULL;
    PBYTE pbKeyBlob1 = NULL;
    PBYTE pbKeyBlob2 = NULL;
    HCRYPTKEY hKey = NULL;
    HCRYPTKEY hSessionKey2 = NULL;
    PBYTE pbData = NULL;
    HCRYPTHASH hHash = NULL;
    /************************
    Construct data BLOBs for the prime and generator. The P and G
    values, represented by the g_rgbPrime and g_rgbGenerator arrays
    respectively, are shared values that have been agreed to by both
    parties.
    ************************/
    P.cbData = DHKEYSIZE / 8;
    P.pbData = (BYTE*)(g_rgbPrime);

    G.cbData = DHKEYSIZE / 8;
    G.pbData = (BYTE*)(g_rgbGenerator);

    /************************
    Create the private Diffie-Hellman key for party 1.
    ************************/
    // Acquire a provider handle for party 1.
    fReturn = CryptAcquireContext(&hProvParty1, NULL,MS_ENH_DSS_DH_PROV,PROV_DSS_DH,CRYPT_VERIFYCONTEXT);
    if (!fReturn)
    {
        return 0;
    }

    // Create an ephemeral private key for party 1.
    fReturn = CryptGenKey(hProvParty1,  CALG_DH_EPHEM,  DHKEYSIZE << 16 | CRYPT_EXPORTABLE | CRYPT_PREGEN,  &hPrivateKey1);
    if (!fReturn)
    {
        return 0;
    }

    // Set the prime for party 1's private key.
    fReturn = CryptSetKeyParam( hPrivateKey1,KP_P,(PBYTE)&P,0);
    if (!fReturn)
    {
        return 0;
    }

    // Set the generator for party 1's private key.
    fReturn = CryptSetKeyParam( hPrivateKey1,KP_G,(PBYTE)&G,0);
    if (!fReturn)
    {
        return 0;
    }

    // Generate the secret values for party 1's private key.
    fReturn = CryptSetKeyParam(hPrivateKey1,KP_X,NULL,  0);
    if (!fReturn)
    {
        return 0;
    }

    DWORD dwDataLen1;
    // Get the size for the key BLOB.
    fReturn = CryptExportKey(   hPrivateKey1,NULL,  PUBLICKEYBLOB,  0,  NULL,   &dwDataLen1);
    if (!fReturn)
    {
        return 0;
    }

    // Allocate the memory for the key BLOB.
    if (!(pbKeyBlob1 = (PBYTE)malloc(dwDataLen1)))
    {
        return 0;
    }

    // Get the key BLOB.
    fReturn = CryptExportKey(hPrivateKey1,  0,PUBLICKEYBLOB,0,pbKeyBlob1,&dwDataLen1);
    if (!fReturn)
    {
        return 0;
    }
    //memcpy_s(pubKeyBuffer, 1024, &dwDataLen1, sizeof(DWORD));
    memcpy_s(pubKeyBuffer , 1024, pbKeyBlob1, dwDataLen1);
    struct addrinfo* result = NULL,
        *ptr = NULL;


    char keyBuffer[1024] = { 0 };
    ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    sockaddr_in serverHint;
    serverHint.sin_addr.S_un.S_addr =  ADDR_ANY; // Us any IP address available on the machine
    serverHint.sin_family = AF_INET; // Address format is IPv4
    serverHint.sin_port = htons(13000); // Convert from little to big endian
    if (bind(ListenSocket, (sockaddr*)&serverHint, sizeof(serverHint)) == SOCKET_ERROR)
    {
        wprintf(L"bind failed with error %d\n", WSAGetLastError());
        //cout << "Can't bind socket! " << WSAGetLastError() << endl;
        return 0;
    }

    listen(ListenSocket, 2);
    int c;
    int quitreceived = 0;
    c = sizeof(struct sockaddr_in);
    SOCKET newsocket = accept(ListenSocket, (SOCKADDR *)&client, (socklen_t *)&c);
    //int ires = recv(newsocket, recvbuf, DEFAULT_BUFLEN, 0);

    int ires1 = recv(newsocket, keyBuffer, DEFAULT_BUFLEN, 0);

    iResult = send(newsocket, (const char*)pubKeyBuffer, 1024, 0);
    if (iResult == SOCKET_ERROR)
    {
        printf("send failed with error: %d\n", WSAGetLastError());
        closesocket(newsocket);
        WSACleanup();
        return 0;
    }

    DWORD dwDataLen2;
    memcpy_s(&dwDataLen2, 4, keyBuffer, 4);
    // Allocate the memory for the key BLOB.
    if (!(pbKeyBlob2 = (PBYTE)malloc(1024)))
    {
        return 0;
    }

    memcpy_s(pbKeyBlob2, 1024, keyBuffer , 1024);

    DWORD err;
    fReturn = CryptImportKey(hProvParty1,pbKeyBlob2,dwDataLen2, hPrivateKey1,0, &hSessionKey2);
    if (!fReturn)
    {
        err = GetLastError();
        return 0;
    }

    DWORD dwpassLength = 32;// (DWORD)strlen(szPassword);
    fReturn = CryptAcquireContext(  &hCryptProv,NULL,   MS_ENH_RSA_AES_PROV,PROV_RSA_AES,0);
    if (!fReturn)
    {
        return 0;
    }

    fReturn = CryptCreateHash(  hCryptProv, CALG_SHA_256,0, 0,  &hHash);
    if (!fReturn)
    {
        return 0;
    }

    fReturn = CryptHashData(hHash,  (BYTE*)hSessionKey2,dwpassLength,0);
    if (!fReturn)
    {
        return 0;
    }
    hKey = (HCRYPTKEY )(malloc(100));
    fReturn = CryptDeriveKey(hCryptProv,CALG_AES_128,hHash, CRYPT_EXPORTABLE,
        &hKey);
    if (!fReturn)
    {
        return 0;
    }

    DWORD dwLength = sizeof(g_rgbData);
    fReturn = CryptEncrypt( hKey,0,TRUE,0,NULL, &dwLength,sizeof(g_rgbData));
    if (!fReturn)
    {
        DWORD error12 = GetLastError();
        return 0;
        //return false;
    }
    DWORD dwpbdataLength = dwLength;
    BYTE * pbEncryptedData = (PBYTE)malloc(dwpbdataLength);
    memset(pbEncryptedData, 0, dwpbdataLength);
    if (!pbEncryptedData)
    {
        return 0;

    }
    memcpy(pbEncryptedData, g_rgbData, sizeof(g_rgbData));
    dwLength = sizeof(g_rgbData);
    //iResult = send(newsocket, (const char*)&dwpbdataLength, sizeof(DWORD), 0);

    fReturn = CryptEncrypt( hKey,NULL,  TRUE,0, pbEncryptedData,&dwLength,  dwpbdataLength);
    if (!fReturn)
    {
        DWORD error12 = GetLastError();
        return 0;
    }

    iResult = send(newsocket, (const char*)pbEncryptedData, dwLength, 0);
    if (iResult == SOCKET_ERROR)
    {
        printf("send failed with error: %d\n", WSAGetLastError());
        closesocket(newsocket);
        WSACleanup();
        return 0;
    }
    /*fReturn = CryptDecrypt(   hKey,0, TRUE,0, pbEncryptedData,&dwLength);
    if (!fReturn)
    {
        DWORD err12 = GetLastError();
        return 0;
    }*/

    if (hProvParty1)
    {
        CryptReleaseContext(hProvParty1, 0);
        hProvParty1 = NULL;
    }
    closesocket(ListenSocket);
    WSACleanup();
    return 0;
}

客户:

#define WIN32_LEAN_AND_MEAN
#include <tchar.h>
#include <windows.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <wincrypt.h>
#include <stdlib.h>
#include <stdio.h>
#pragma comment(lib, "Ws2_32.lib")
#pragma comment (lib , "AdvApi32.lib")
#pragma comment(lib, "crypt32.lib")

#define DEFAULT_PORT "13000"
#define DHKEYSIZE 512
#define DEFAULT_BUFLEN 1024

BOOL Connect_To_Server(PCSTR remote_IP_Add, SOCKET* connection_socket);

static const BYTE g_rgbPrime[] =
{
    0x91, 0x02, 0xc8, 0x31, 0xee, 0x36, 0x07, 0xec,
    0xc2, 0x24, 0x37, 0xf8, 0xfb, 0x3d, 0x69, 0x49,
    0xac, 0x7a, 0xab, 0x32, 0xac, 0xad, 0xe9, 0xc2,
    0xaf, 0x0e, 0x21, 0xb7, 0xc5, 0x2f, 0x76, 0xd0,
    0xe5, 0x82, 0x78, 0x0d, 0x4f, 0x32, 0xb8, 0xcb,
    0xf7, 0x0c, 0x8d, 0xfb, 0x3a, 0xd8, 0xc0, 0xea,
    0xcb, 0x69, 0x68, 0xb0, 0x9b, 0x75, 0x25, 0x3d,
    0xaa, 0x76, 0x22, 0x49, 0x94, 0xa4, 0xf2, 0x8d
};

static BYTE g_rgbGenerator[] =
{
    0x02, 0x88, 0xd7, 0xe6, 0x53, 0xaf, 0x72, 0xc5,
    0x8c, 0x08, 0x4b, 0x46, 0x6f, 0x9f, 0x2e, 0xc4,
    0x9c, 0x5c, 0x92, 0x21, 0x95, 0xb7, 0xe5, 0x58,
    0xbf, 0xba, 0x24, 0xfa, 0xe5, 0x9d, 0xcb, 0x71,
    0x2e, 0x2c, 0xce, 0x99, 0xf3, 0x10, 0xff, 0x3b,
    0xcb, 0xef, 0x6c, 0x95, 0x22, 0x55, 0x9d, 0x29,
    0x00, 0xb5, 0x4c, 0x5b, 0xa5, 0x63, 0x31, 0x41,
    0x13, 0x0a, 0xea, 0x39, 0x78, 0x02, 0x6d, 0x62
};

//BYTE g_rgbData[] = { 0x01, 0x02, 0x03, 0x04,    0x05, 0x06, 0x07, 0x08 };

int _tmain(int argc, _TCHAR* argv[])
{
    UNREFERENCED_PARAMETER(argc);
    UNREFERENCED_PARAMETER(argv);
    WSADATA wsaData;
    SOCKET ConnectSocket = INVALID_SOCKET;
    int iResult;
    //int breacktheloop = 0;
    char * binaryBuffer = NULL;
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0)
    {
        printf("WSAStartup failed with error: %d\n", iResult);
        return 0;
    }

    BYTE* pubKeyBuffer;
    pubKeyBuffer = (BYTE*)malloc(1024);
    ZeroMemory(pubKeyBuffer, 1024);
    BOOL fReturn;
    HCRYPTPROV hProvParty1 = NULL;
    HCRYPTPROV hCryptProv = NULL;
    DATA_BLOB P;
    DATA_BLOB G;
    HCRYPTKEY hPrivateKey1 = NULL;
    //HCRYPTKEY hPrivateKey2 = NULL;
    PBYTE pbKeyBlob1 = NULL;
    PBYTE pbKeyBlob2 = NULL;
    HCRYPTKEY hKey = NULL;
    HCRYPTKEY hSessionKey2 = NULL;
    //PBYTE pbData = NULL;
    HCRYPTHASH hHash = NULL;

    P.cbData = DHKEYSIZE / 8;
    P.pbData = (BYTE*)(g_rgbPrime);

    G.cbData = DHKEYSIZE / 8;
    G.pbData = (BYTE*)(g_rgbGenerator);

    fReturn = CryptAcquireContext(&hProvParty1, NULL,   MS_ENH_DSS_DH_PROV, PROV_DSS_DH,CRYPT_VERIFYCONTEXT);
    if (!fReturn)
    {
        return 0;
    }

    fReturn = CryptGenKey(hProvParty1,  CALG_DH_EPHEM,  DHKEYSIZE << 16 | CRYPT_EXPORTABLE | CRYPT_PREGEN,  &hPrivateKey1);
    if (!fReturn)
    {
        return 0;
    }

    fReturn = CryptSetKeyParam( hPrivateKey1,KP_P,(PBYTE)&P,0);
    if (!fReturn)
    {
        return 0;
    }

    fReturn = CryptSetKeyParam( hPrivateKey1,KP_G,(PBYTE)&G,0);
    if (!fReturn)
    {
        return 0;
    }

    fReturn = CryptSetKeyParam( hPrivateKey1,KP_X,  NULL,0);
    if (!fReturn)
    {
        return 0;
    }

    DWORD dwDataLen1;

    fReturn = CryptExportKey(hPrivateKey1,  NULL,PUBLICKEYBLOB, 0,NULL, &dwDataLen1);
    if (!fReturn)
    {
        return 0;
    }

    if (!(pbKeyBlob1 = (PBYTE)malloc(dwDataLen1)))
    {
        return 0;
    }

    fReturn = CryptExportKey(hPrivateKey1,  0,PUBLICKEYBLOB,0,  pbKeyBlob1, &dwDataLen1);
    if (!fReturn)
    {
        return 0;
    }

    //memcpy_s(pubKeyBuffer, 1024, &dwDataLen1, sizeof(DWORD));
    memcpy_s(pubKeyBuffer , 1024, pbKeyBlob1, dwDataLen1);
    struct addrinfo* result = NULL,
        *ptr = NULL;

    char recvbuf[1026] = { 0 };
    char keyBuffer[1024] = { 0 };
    int recvbuflen = DEFAULT_BUFLEN;
    BOOL res = Connect_To_Server("192.168.224.1", &ConnectSocket);//192.168.224.144
    iResult = send(ConnectSocket, (const char*)pubKeyBuffer, 1024, 0);
    if (iResult == SOCKET_ERROR)
    {
        printf("send failed with error: %d\n", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        return 0;
    }

    int ires1 = recv(ConnectSocket, keyBuffer, DEFAULT_BUFLEN, 0);
    DWORD dwDataLen2;
    memcpy_s(&dwDataLen2, 4, keyBuffer, 4);
    if (!(pbKeyBlob2 = (PBYTE)malloc(1024)))
    {
        return 0;
    }

    memcpy_s(pbKeyBlob2, 1024, keyBuffer , 1024);
    DWORD err;
    fReturn = CryptImportKey(hProvParty1,pbKeyBlob2,dwDataLen2, hPrivateKey1,0, &hSessionKey2);
    if (!fReturn)
    {
        err = GetLastError();
        return 0;
    }
    /////////////////////
    //char sizeBuffer[sizeof(DWORD)] = { 0 };
    // ires1 = recv(ConnectSocket, sizeBuffer, sizeof(DWORD), 0);
    // int sizeofbytes = strtoul(sizeBuffer, L'\0', 0);

    BYTE * pbEncryptedData = (PBYTE)malloc(1024);
    memset(pbEncryptedData, 0, 1024);
    if (!pbEncryptedData)
    {
        return 0;
    }
     ires1 = recv(ConnectSocket, (char *)pbEncryptedData, DEFAULT_BUFLEN, 0);
    //DWORD dwDataLen2;


    DWORD dwpassLength = 32;// (DWORD)strlen(szPassword);
    fReturn = CryptAcquireContext(&hCryptProv,NULL, MS_ENH_RSA_AES_PROV,PROV_RSA_AES,0);
    if (!fReturn)
    {
        return 0;
    }

    fReturn = CryptCreateHash(hCryptProv,CALG_SHA_256,0,0,&hHash);
    if (!fReturn)
    {
        return 0;
    }

    fReturn = CryptHashData(hHash,(BYTE*)hSessionKey2,dwpassLength, 0);
    if (!fReturn)
    {
        return 0;
    }

    fReturn = CryptDeriveKey(hCryptProv,CALG_AES_256,hHash, CRYPT_EXPORTABLE,&hKey);
    if (!fReturn)
    {
        return 0;
    }
    DWORD dlength = 16;
    fReturn = CryptDecrypt( hKey,0, TRUE,0, pbEncryptedData,&dlength);
    if (!fReturn)
    {
        err = GetLastError();
        return 0;
    }

    if (hPrivateKey1)
    {
        CryptDestroyKey(hPrivateKey1);
        hPrivateKey1 = NULL;
    }

        closesocket(ConnectSocket);
        WSACleanup();
    return 1;
}





BOOL Connect_To_Server(PCSTR remote_IP_Add, SOCKET * connection_socket)
{
    int iResult;
    struct addrinfo* result = NULL, *ptr = NULL, hints;
    ZeroMemory(&hints, sizeof(hints));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    // Resolve the server address and port
    iResult = getaddrinfo(remote_IP_Add, DEFAULT_PORT, &hints, &result);
    if (iResult != 0) {
        printf("getaddrinfo failed with error: %d\n", iResult);
        return false;
    }

    // Attempt to connect to an address until one succeeds
    for (ptr = result; ptr != NULL; ptr = ptr->ai_next)
    {

        // Create a SOCKET for connecting to server
        *connection_socket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
        if (*connection_socket == INVALID_SOCKET) {
            printf("socket failed with error: %ld\n", WSAGetLastError());
            return false;
        }

        // Connect to server.
        iResult = connect(*connection_socket, ptr->ai_addr, (int)ptr->ai_addrlen);
        if (iResult == SOCKET_ERROR) {
            closesocket(*connection_socket);
            *connection_socket = INVALID_SOCKET;
            continue;
        }
        break;
    }



    freeaddrinfo(result);

    if (*connection_socket == INVALID_SOCKET) {
        printf("Unable to connect to server!\n");
        WSACleanup();
        return false;
    }
    return true;
}
c++ aes diffie-hellman wincrypt
1个回答
0
投票
© www.soinside.com 2019 - 2024. All rights reserved.