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/bootstrap/CMakeLists.txt | 1 src/library/os/win/os-win.c | 8 src/tools/base_lib/win/CryptoHelperWindows.h | 80 ++++--- src/tools/base_lib/CryptoHelper.cpp | 2 src/library/os/win/os-win.cpp | 7 src/tools/base_lib/CryptoHelper.h | 5 src/tools/base_lib/win/CryptoHelperWindows.cpp | 455 ++++++++++++++++++++++++++++++++++++++++++-- 7 files changed, 487 insertions(+), 71 deletions(-) diff --git a/src/library/os/win/os-win.c b/src/library/os/win/os-win.c index 6fd115d..a241734 100644 --- a/src/library/os/win/os-win.c +++ b/src/library/os/win/os-win.c @@ -161,4 +161,12 @@ *adapter_info_size = i; return result; } +FUNCTION_RETURN getModuleName(char buffer[MAX_PATH]) { + FUNCTION_RETURN result=FUNC_RET_OK; + DWORD wres = GetModuleFileName(NULL, buffer, MAX_PATH); + if (wres == 0){ + result = FUNC_RET_ERROR; + } + return result; +} diff --git a/src/library/os/win/os-win.cpp b/src/library/os/win/os-win.cpp index 22bb486..9eff973 100644 --- a/src/library/os/win/os-win.cpp +++ b/src/library/os/win/os-win.cpp @@ -6,13 +6,6 @@ using namespace std; -string OsFunctions::getModuleName() { - char lpFilename[MAX_PATH]; - DWORD result = GetModuleFileName(NULL,lpFilename,MAX_PATH); - return string(lpFilename); -} - - bool OsFunctions::verifySignature(const char* stringToVerify, const char* signatureB64) { diff --git a/src/tools/base_lib/CryptoHelper.cpp b/src/tools/base_lib/CryptoHelper.cpp index baa7e8f..07d0348 100644 --- a/src/tools/base_lib/CryptoHelper.cpp +++ b/src/tools/base_lib/CryptoHelper.cpp @@ -13,7 +13,7 @@ #ifdef __unix__ unique_ptr<CryptoHelper> ptr((CryptoHelper*) new CryptoHelperLinux()); #else - unique_ptr<CryptoHelper> ptr((CryptoHelper*) new CryptpHelperWindows()); + unique_ptr<CryptoHelper> ptr((CryptoHelper*) new CryptoHelperWindows()); #endif return ptr; } diff --git a/src/tools/base_lib/CryptoHelper.h b/src/tools/base_lib/CryptoHelper.h index 545c6ab..c1751f8 100644 --- a/src/tools/base_lib/CryptoHelper.h +++ b/src/tools/base_lib/CryptoHelper.h @@ -3,6 +3,7 @@ #include <memory> #include <cstddef> +#include <string> namespace license { using namespace std; @@ -20,7 +21,7 @@ class CryptoHelper { protected: - CryptoHelper(); + inline CryptoHelper(){}; public: virtual void generateKeyPair() = 0; @@ -30,7 +31,7 @@ virtual const string signString(const void* privateKey, size_t pklen, const string& license) const = 0; static unique_ptr<CryptoHelper> getInstance(); - virtual ~CryptoHelper(); + inline virtual ~CryptoHelper(){}; }; } #endif 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 */ diff --git a/src/tools/base_lib/win/CryptoHelperWindows.h b/src/tools/base_lib/win/CryptoHelperWindows.h index 293f4e9..e0e8753 100644 --- a/src/tools/base_lib/win/CryptoHelperWindows.h +++ b/src/tools/base_lib/win/CryptoHelperWindows.h @@ -1,35 +1,45 @@ -/* - * CryptoHelperWindows.h - * - * Created on: Sep 14, 2014 - * - */ - -#ifndef CRYPTOHELPERWINDOWS_H_ -#define CRYPTOHELPERWINDOWS_H_ - -#define _WIN32_WINNT 0x0400 -#include <windows.h> -#include <wincrypt.h> -#include <tchar.h> -#include "../CryptoHelper.h" - -namespace license { - -class CryptoHelperWindows: public CryptoHelper { -public: - CryptoHelperWindows(); - - virtual void generateKeyPair(); - virtual const string exportPrivateKey() const; - virtual const string exportPublicKey() const; - - virtual string signString(const void* privateKey, size_t pklen, - const string& license) const; - - virtual ~CryptoHelperWindows(); -}; - -} /* namespace license */ - -#endif /* CRYPTOHELPERWINDOWS_H_ */ +/* + * CryptoHelperWindows.h + * + * Created on: Sep 14, 2014 + * + */ + +#ifndef CRYPTOHELPERWINDOWS_H_ +#define CRYPTOHELPERWINDOWS_H_ + +//#define _WIN32_WINNT 0x0400 +#include <windows.h> +#include <wincrypt.h> +#include <tchar.h> +#include <string> +#include "../CryptoHelper.h" + + + +namespace license { +using namespace std; + +class CryptoHelperWindows: public CryptoHelper { +private : + void acquireContext(); + // Handle to the cryptography provider. + HCRYPTPROV m_hCryptProv; + // Handle to the cryptography key. + HCRYPTKEY m_hCryptKey; +public: + CryptoHelperWindows(); + + virtual void generateKeyPair(); + virtual const string exportPrivateKey() const; + virtual const string exportPublicKey() const; + + virtual const string signString(const void* privateKey, size_t pklen, + const string& license) const; + + virtual ~CryptoHelperWindows(); +}; + +} /* namespace license */ + +#endif /* CRYPTOHELPERWINDOWS_H_ */ diff --git a/src/tools/bootstrap/CMakeLists.txt b/src/tools/bootstrap/CMakeLists.txt index a47eecb..1e55e6a 100644 --- a/src/tools/bootstrap/CMakeLists.txt +++ b/src/tools/bootstrap/CMakeLists.txt @@ -16,6 +16,7 @@ add_custom_command ( OUTPUT "${CMAKE_BINARY_DIR}/private-key.h" "${CMAKE_BINARY_DIR}/public-key.h" COMMAND bootstrap "${CMAKE_BINARY_DIR}/private-key.h" "${CMAKE_BINARY_DIR}/public-key.h" + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} DEPENDS bootstrap ) -- Gitblit v1.9.1