From 62258ba3b4737432a95c3af8d0e03ed3fb7953e7 Mon Sep 17 00:00:00 2001 From: open-license-manager <rillf@maildrop.cc> Date: 周一, 13 10月 2014 05:05:37 +0800 Subject: [PATCH] windows ok --- src/tools/base_lib/win/CryptoHelperWindows.cpp | 480 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 454 insertions(+), 26 deletions(-) diff --git a/src/tools/base_lib/win/CryptoHelperWindows.cpp b/src/tools/base_lib/win/CryptoHelperWindows.cpp index 1b7b40e..e2d8cff 100644 --- a/src/tools/base_lib/win/CryptoHelperWindows.cpp +++ b/src/tools/base_lib/win/CryptoHelperWindows.cpp @@ -1,26 +1,454 @@ -/* - * CryptoHelperWindows.cpp - * - * Created on: Sep 14, 2014 - * - */ - -#include "CryptoHelperWindows.h" -// The RSA public-key key exchange algorithm -#define ENCRYPT_ALGORITHM CALG_RSA_SIGN -// The high order WORD 0x0200 (decimal 512) -// determines the key length in bits. -#define KEYLENGTH 0x02000000 - -namespace license { - -CryptoHelperWindows::CryptoHelperWindows() { - // TODO Auto-generated constructor stub - -} - -CryptoHelperWindows::~CryptoHelperWindows() { - // TODO Auto-generated destructor stub -} - -} /* namespace license */ +/* + * CryptoHelperWindows.cpp + * + * Created on: Sep 14, 2014 + * + */ + +#include "CryptoHelperWindows.h" +#include <sstream> +#include <vector> +// The RSA public-key key exchange algorithm +#define ENCRYPT_ALGORITHM CALG_RSA_SIGN +// The high order WORD 0x0200 (decimal 512) +// determines the key length in bits. +#define KEYLENGTH 0x02000000 +#pragma comment(lib, "crypt32.lib") + +namespace license { + + CryptoHelperWindows::CryptoHelperWindows() { + m_hCryptProv = NULL; + m_hCryptKey = NULL; + if (!CryptAcquireContext( + &m_hCryptProv, + "license++sign", + MS_ENHANCED_PROV, + PROV_RSA_FULL, + 0)) + { + // If the key container cannot be opened, try creating a new + // container by specifying a container name and setting the + // CRYPT_NEWKEYSET flag. + printf("Error in AcquireContext 0x%08x \n", GetLastError()); + if (NTE_BAD_KEYSET == GetLastError()) + { + if (!CryptAcquireContext( + &m_hCryptProv, + "license++sign", + MS_ENHANCED_PROV, + PROV_RSA_FULL, + CRYPT_NEWKEYSET)) + { + printf("Error in AcquireContext 0x%08x \n", + GetLastError()); + throw logic_error(""); + } + } + else + { + printf(" Error in AcquireContext 0x%08x \n", GetLastError()); + throw logic_error(""); + } + } + + } + + + /** + This method calls the CryptGenKey function to get a handle to an + + exportable key-pair. The key-pair is generated with the RSA public-key + key exchange algorithm using Microsoft Enhanced Cryptographic Provider. + */ + void CryptoHelperWindows::generateKeyPair() + { + HRESULT hr = S_OK; + DWORD dwErrCode; + // If the handle to key container is NULL, fail. + if (m_hCryptProv == NULL) + throw logic_error("Cryptocontext not correctly initialized"); + // Release a previously acquired handle to key-pair. + if (m_hCryptKey) + m_hCryptKey = NULL; + // Call the CryptGenKey method to get a handle + // to a new exportable key-pair. + if (!CryptGenKey(m_hCryptProv, + ENCRYPT_ALGORITHM, + KEYLENGTH | CRYPT_EXPORTABLE, + &m_hCryptKey)) + { + dwErrCode = GetLastError(); + throw logic_error(string("Error generating keys ") + to_string(dwErrCode)); + } + } + + /* This method calls the CryptExportKey function to get the Public key + in a string suitable for C source inclusion. + */ + const string CryptoHelperWindows::exportPublicKey() const + { + HRESULT hr = S_OK; + DWORD dwErrCode; + DWORD dwBlobLen; + BYTE *pbKeyBlob = NULL; + stringstream ss; + // If the handle to key container is NULL, fail. + if (m_hCryptKey == NULL) + throw logic_error("call GenerateKey first."); + // This call here determines the length of the key + // blob. + if (!CryptExportKey( + m_hCryptKey, + NULL, + PUBLICKEYBLOB, + 0, + NULL, + &dwBlobLen)) + { + dwErrCode = GetLastError(); + throw logic_error(string("Error calculating size of public key ") + to_string(dwErrCode)); + } + // Allocate memory for the pbKeyBlob. + if ((pbKeyBlob = new BYTE[dwBlobLen]) == NULL) + { + throw logic_error(string("Out of memory exporting public key ")); + } + // Do the actual exporting into the key BLOB. + if (!CryptExportKey( + m_hCryptKey, + NULL, + PUBLICKEYBLOB, + 0, + pbKeyBlob, + &dwBlobLen)) + { + delete pbKeyBlob; + dwErrCode = GetLastError(); + throw logic_error(string("Error exporting public key ") + to_string(dwErrCode)); + } + else + { + ss << "\t"; + for (unsigned int i = 0; i < dwBlobLen; i++){ + if (i != 0){ + ss << ", "; + if (i % 10 == 0){ + ss << "\\" << endl << "\t"; + } + } + ss << to_string(pbKeyBlob[i]); + } + delete pbKeyBlob; + } + return ss.str(); + } + + CryptoHelperWindows::~CryptoHelperWindows() { + if (m_hCryptProv) + { + CryptReleaseContext(m_hCryptProv, 0); + m_hCryptProv = NULL; + } + if (m_hCryptKey) + m_hCryptKey = NULL; + } + + //-------------------------------------------------------------------- + // This method calls the CryptExportKey function to get the Private key + // in a byte array. The byte array is allocated on the heap and the size + // of this is returned to the caller. The caller is responsible for releasing // this memory using a delete call. + //-------------------------------------------------------------------- + const string CryptoHelperWindows::exportPrivateKey() const + { + HRESULT hr = S_OK; + DWORD dwErrCode; + DWORD dwBlobLen; + BYTE *pbKeyBlob; + stringstream ss; + // If the handle to key container is NULL, fail. + if (m_hCryptKey == NULL) + throw logic_error(string("call GenerateKey first.")); + // This call here determines the length of the key + // blob. + if (!CryptExportKey( + m_hCryptKey, + NULL, + PRIVATEKEYBLOB, + 0, + NULL, + &dwBlobLen)) + { + dwErrCode = GetLastError(); + throw logic_error(string("Error calculating size of private key ") + to_string(dwErrCode)); + } + // Allocate memory for the pbKeyBlob. + if ((pbKeyBlob = new BYTE[dwBlobLen]) == NULL) + { + throw logic_error(string("Out of memory exporting private key ")); + } + + // Do the actual exporting into the key BLOB. + if (!CryptExportKey( + m_hCryptKey, + NULL, + PRIVATEKEYBLOB, + 0, + pbKeyBlob, + &dwBlobLen)) + { + delete pbKeyBlob; + dwErrCode = GetLastError(); + throw logic_error(string("Error exporting private key ") + to_string(dwErrCode)); + } + else + { + ss << "\t"; + for (unsigned int i = 0; i < dwBlobLen; i++){ + if (i != 0){ + ss << ", "; + if (i % 15 == 0){ + ss << "\\" << endl << "\t"; + } + } + ss << to_string(pbKeyBlob[i]); + } + delete pbKeyBlob; + } + return ss.str(); + } + + void CryptoHelperWindows::printHash(HCRYPTHASH* hHash) const { + BYTE *pbHash; + DWORD dwHashLen; + DWORD dwHashLenSize = sizeof(DWORD); + char* hashStr; + int i; + + if (CryptGetHashParam(*hHash, HP_HASHSIZE, (BYTE *)&dwHashLen, &dwHashLenSize, 0)) + { + pbHash = (BYTE*)malloc(dwHashLen); + hashStr = (char*)malloc(dwHashLen * 2 + 1); + if (CryptGetHashParam(*hHash, HP_HASHVAL, pbHash, &dwHashLen, 0)) { + for (i = 0; i < dwHashLen; i++) { + sprintf(&hashStr[i * 2], "%02x", pbHash[i]); + } + printf("hash To be signed: %s \n", hashStr); + } + free(pbHash); + free(hashStr); + } + } + + const string CryptoHelperWindows::signString(const void* privateKey, size_t pklen, + const string& license) const{ + BYTE *pbBuffer = (BYTE *)license.c_str(); + DWORD dwBufferLen = strlen((char *)pbBuffer); + HCRYPTHASH hHash; + + HCRYPTKEY hKey; + BYTE *pbKeyBlob; + BYTE *pbSignature; + DWORD dwSigLen; + DWORD dwBlobLen; + DWORD strLen; + + + //------------------------------------------------------------------- + // Acquire a cryptographic provider context handle. + + if (!CryptImportKey(m_hCryptProv, (const BYTE *) privateKey, pklen, 0, 0, &hKey)) + { + throw logic_error(string("Error in importing the PrivateKey ") + to_string(GetLastError())); + } + + //------------------------------------------------------------------- + // Create the hash object. + + if (CryptCreateHash( + m_hCryptProv, + CALG_SHA1, + 0, + 0, + &hHash)) + { + printf("Hash object created. \n"); + } + else + { + CryptDestroyKey(hKey); + throw logic_error(string("Error during CryptCreateHash.")); + } + //------------------------------------------------------------------- + // Compute the cryptographic hash of the buffer. + + if (CryptHashData(hHash,pbBuffer,dwBufferLen, 0)) + { +#ifdef _DEBUG + printf("Length of data to be hashed: %d \n", dwBufferLen); + printHash(&hHash); +#endif + } + else + { + throw logic_error(string("Error during CryptHashData.")); + } + //------------------------------------------------------------------- + // Determine the size of the signature and allocate memory. + + dwSigLen = 0; + if (CryptSignHash( + hHash, + AT_SIGNATURE, + NULL, + 0, + NULL, + &dwSigLen)) + { + printf("Signature length %d found.\n", dwSigLen); + } + else + { + throw logic_error(string("Error during CryptSignHash.")); + } + //------------------------------------------------------------------- + // Allocate memory for the signature buffer. + + if (pbSignature = (BYTE *)malloc(dwSigLen)) + { + printf("Memory allocated for the signature.\n"); + } + else + { + throw logic_error(string("Out of memory.")); + } + //------------------------------------------------------------------- + // Sign the hash object. + + if (CryptSignHash( + hHash, + AT_SIGNATURE, + NULL, + 0, + pbSignature, + &dwSigLen)) + { + printf("pbSignature is the signature length. %d\n", dwSigLen); + } + else + { + throw logic_error(string("Error during CryptSignHash.")); + } + //------------------------------------------------------------------- + // Destroy the hash object. + + + CryptDestroyHash(hHash); + CryptDestroyKey(hKey); + + CryptBinaryToString(pbSignature,dwSigLen, + CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, NULL, &strLen); + vector<char> buffer(strLen); + CryptBinaryToString(pbSignature, dwSigLen, + CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, &buffer[0], &strLen); + + //------------------------------------------------------------------- + // In the second phase, the hash signature is verified. + // This would most often be done by a different user in a + // separate program. The hash, signature, and the PUBLICKEYBLOB + // would be read from a file, an email message, + // or some other source. + + // Here, the original pbBuffer, pbSignature, szDescription. + // pbKeyBlob, and their lengths are used. + + // The contents of the pbBuffer must be the same data + // that was originally signed. + + //------------------------------------------------------------------- + // Get the public key of the user who created the digital signature + // and import it into the CSP by using CryptImportKey. This returns + // a handle to the public key in hPubKey. + + /*if (CryptImportKey( + hProv, + pbKeyBlob, + dwBlobLen, + 0, + 0, + &hPubKey)) + { + printf("The key has been imported.\n"); + } + else + { + MyHandleError("Public key import failed."); + } + //------------------------------------------------------------------- + // Create a new hash object. + + if (CryptCreateHash( + hProv, + CALG_MD5, + 0, + 0, + &hHash)) + { + printf("The hash object has been recreated. \n"); + } + else + { + MyHandleError("Error during CryptCreateHash."); + } + //------------------------------------------------------------------- + // Compute the cryptographic hash of the buffer. + + if (CryptHashData( + hHash, + pbBuffer, + dwBufferLen, + 0)) + { + printf("The new hash has been created.\n"); + } + else + { + MyHandleError("Error during CryptHashData."); + } + //------------------------------------------------------------------- + // Validate the digital signature. + + if (CryptVerifySignature( + hHash, + pbSignature, + dwSigLen, + hPubKey, + NULL, + 0)) + { + printf("The signature has been verified.\n"); + } + else + { + printf("Signature not validated!\n"); + } + //------------------------------------------------------------------- + // Free memory to be used to store signature. + + + + //------------------------------------------------------------------- + // Destroy the hash object. + + + + //------------------------------------------------------------------- + // Release the provider handle. + + /*if (hProv) + CryptReleaseContext(hProv, 0);*/ + if (pbSignature) + free(pbSignature); + return string(&buffer[0]); + } +} /* namespace license */ -- Gitblit v1.9.1