From 852dc2056835679e2beb4b1ee9bfe4385ab27bf2 Mon Sep 17 00:00:00 2001 From: open-license-manager <rillf@maildrop.cc> Date: 周一, 13 10月 2014 00:28:17 +0800 Subject: [PATCH] windows --- src/tools/base_lib/win/CryptoHelperWindows.cpp | 455 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 429 insertions(+), 26 deletions(-) diff --git a/src/tools/base_lib/win/CryptoHelperWindows.cpp b/src/tools/base_lib/win/CryptoHelperWindows.cpp index 1b7b40e..5fb1019 100644 --- a/src/tools/base_lib/win/CryptoHelperWindows.cpp +++ b/src/tools/base_lib/win/CryptoHelperWindows.cpp @@ -1,26 +1,429 @@ -/* - * 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-manager2++", + MS_ENHANCED_PROV, + PROV_RSA_FULL, //CRYPT_NEWKEYSET + 0)) { + } + else + { + throw exception("Error during CryptAcquireContext"); + } + + } + + + /** + 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(); + } + + 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) + 1; + HCRYPTHASH hHash; + + HCRYPTKEY hKey; + BYTE *pbKeyBlob; + BYTE *pbSignature; + DWORD dwSigLen; + DWORD dwBlobLen; + DWORD strLen; + + + //------------------------------------------------------------------- + // Acquire a cryptographic provider context handle. + + + //------------------------------------------------------------------- + // Get the public at signature key. This is the public key + // that will be used by the receiver of the hash to verify + // the signature. In situations where the receiver could obtain the + // sender's public key from a certificate, this step would not be + // needed. + + if (CryptGetUserKey( + m_hCryptProv, + AT_SIGNATURE, + &hKey)) + { + printf("The signature key has been acquired. \n"); + } + else + { + printf("Error during CryptGetUserKey for signkey. %d", GetLastError()); + } + + //------------------------------------------------------------------- + // Create the hash object. + + if (CryptCreateHash( + m_hCryptProv, + CALG_SHA1, + 0, + 0, + &hHash)) + { + printf("Hash object created. \n"); + } + else + { + throw logic_error(string("Error during CryptCreateHash.")); + } + //------------------------------------------------------------------- + // Compute the cryptographic hash of the buffer. + + if (CryptHashData( + hHash, + pbBuffer, + dwBufferLen, + 0)) + { + printf("The data buffer has been hashed.\n"); + } + 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 hash signature.\n"); + } + else + { + throw logic_error(string("Error during CryptSignHash.")); + } + //------------------------------------------------------------------- + // Destroy the hash object. + + if (hHash) + CryptDestroyHash(hHash); + + printf("The hash object has been destroyed.\n"); + printf("The signing phase of this program is completed.\n\n"); + + 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. + + if (pbSignature) + free(pbSignature); + + //------------------------------------------------------------------- + // Destroy the hash object. + + if (hHash) + CryptDestroyHash(hHash);*/ + + //------------------------------------------------------------------- + // Release the provider handle. + + /*if (hProv) + CryptReleaseContext(hProv, 0);*/ + return string(&buffer[0]); + } +} /* namespace license */ -- Gitblit v1.9.1