open-license-manager
2014-09-13 1922d8c2cf7dcaacafd17394849577794b1f10eb
src/license-generator/win/LicenseSigner.cpp
@@ -1,148 +1,306 @@
/*
 * LicenseSigner.cpp
 *
 *  Created on: Apr 6, 2014
 *      Author: devel
 */
#include "LicenseSigner.h"
#include "private-key.h"
#include <stdexcept>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <iostream>
#include <cmath>
namespace license {
using namespace std;
LicenseSigner::LicenseSigner() {
   os_initialize();
}
LicenseSigner::LicenseSigner(const std::string& alternatePrimaryKey) {
   os_initialize();
}
string LicenseSigner::Opensslb64Encode(size_t slen, unsigned char* signature) {
   /*
    FILE*  stream = fmemopen(*buffer, encodedSize+1, "w");
    */
   //bio = BIO_new_fp(stdout, BIO_NOCLOSE);
   /*int encodedSize = 4 * ceil(slen / 3);
    char* buffer = (char*) (malloc(encodedSize + 1));
    memset(buffer,0,encodedSize+1);*/
   BIO* mem_bio = BIO_new(BIO_s_mem());
   BIO* b64 = BIO_new(BIO_f_base64());
   BIO* bio1 = BIO_push(b64, mem_bio);
   BIO_set_flags(bio1, BIO_FLAGS_BASE64_NO_NL);
   BIO_write(bio1, signature, slen);
   BIO_flush(bio1);
   char* charBuf;
   int sz = BIO_get_mem_data(mem_bio, &charBuf);
   string signatureStr;
   signatureStr.assign(charBuf, sz);
   BIO_free_all(bio1);
   return signatureStr;
}
string LicenseSigner::signString(const string& license) {
   size_t slen;
   unsigned char* signature;
   signature = NULL;
   /* Create the Message Digest Context */
   EVP_MD_CTX* mdctx = EVP_MD_CTX_create();
   if (!mdctx) {
      throw logic_error("Message digest creation context");
   }
   const char *private_key = PRIVATE_KEY
   ;
   BIO* bio = BIO_new_mem_buf((void*) (private_key), strlen(private_key));
   EVP_PKEY *pktmp = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
   BIO_free(bio);
   /*Initialise the DigestSign operation - SHA-256 has been selected
    * as the message digest function in this example */
   if (1 != EVP_DigestSignInit(mdctx, NULL, EVP_sha256(), NULL, pktmp)) {
      EVP_MD_CTX_destroy(mdctx);
   }
   /* Call update with the message */
   if (EVP_DigestSignUpdate(mdctx, license.c_str(), license.length()) != 1) {
      EVP_MD_CTX_destroy(mdctx);
      throw logic_error("Message signing exception");
   }
   /* Finalise the DigestSign operation */
   /* First call EVP_DigestSignFinal with a NULL sig parameter to obtain the length of the
    * signature. Length is returned in slen */
   if (EVP_DigestSignFinal(mdctx, NULL, &slen) != 1) {
      EVP_MD_CTX_destroy(mdctx);
      throw logic_error("Message signature finalization exception");
   }
   /* Allocate memory for the signature based on size in slen */
   if (!(signature = (unsigned char *) OPENSSL_malloc(
         sizeof(unsigned char) * slen))) {
      EVP_MD_CTX_destroy(mdctx);
      throw logic_error("Message signature memory allocation exception");
   }
   /* Obtain the signature */
   if (1 != EVP_DigestSignFinal(mdctx, signature, &slen)) {
      OPENSSL_free(signature);
      EVP_MD_CTX_destroy(mdctx);
      throw logic_error("Message signature exception");
   }
   /*
    FILE*  stream = fmemopen(*buffer, encodedSize+1, "w");
    */
   //bio = BIO_new_fp(stdout, BIO_NOCLOSE);
   /*int encodedSize = 4 * ceil(slen / 3);
    char* buffer = (char*) (malloc(encodedSize + 1));
    memset(buffer,0,encodedSize+1);*/
   string signatureStr = Opensslb64Encode(slen, signature);
   /*
    * BIO *bio, *b64;
    char message[] = "Hello World \n";
    b64 = BIO_new(BIO_f_base64());
    bio = BIO_new_fp(stdout, BIO_NOCLOSE);
    bio = BIO_push(b64, bio);
    BIO_write(bio, message, strlen(message));
    BIO_flush(bio);
    BIO_free_all(bio);
    Read Base64 encoded data from standard input and write the decoded data to standard output:
    BIO *bio, *b64, *bio_out;
    char inbuf[512];
    int inlen;
    b64 = BIO_new(BIO_f_base64());
    bio = BIO_new_fp(stdin, BIO_NOCLOSE);
    bio_out = BIO_new_fp(stdout, BIO_NOCLOSE);
    bio = BIO_push(b64, bio);
    while((inlen = BIO_read(bio, inbuf, 512)) > 0)
    BIO_write(bio_out, inbuf, inlen);
    BIO_free_all(bio);
    */
   /* Clean up */
   //free(buffer);
   if (pktmp)
      EVP_PKEY_free(pktmp);
   if (signature)
      OPENSSL_free(signature);
   if (mdctx)
      EVP_MD_CTX_destroy(mdctx);
   return signatureStr;
}
void LicenseSigner::signLicense(FullLicenseInfo& licenseInfo) {
   string license = licenseInfo.printForSign();
   string signature = signString(license);
   licenseInfo.license_signature = signature;
}
LicenseSigner::~LicenseSigner() {
}
} /* namespace license */
/*
 * LicenseSigner.cpp (Windows)
 *
 *  Created on: Apr 6, 2014
 *      Author: devel
 */
#include <stdexcept>
#include <string.h>
#include <iostream>
#include <cmath>
#pragma comment(lib, "crypt32.lib")
#include <stdio.h>
#include <windows.h>
#include <Wincrypt.h>
#define MY_ENCODING_TYPE  (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
#include "../private-key.h"
#include "../LicenseSigner.h"
#include "../../library/base/logger.h"
namespace license {
   using namespace std;
   LicenseSigner::LicenseSigner() {
      os_initialize();
      if (CryptAcquireContext(
         &hProv,
         "license-manager2++",
         MS_ENHANCED_PROV,
         PROV_RSA_FULL, //CRYPT_NEWKEYSET
         0))   {
         LOG_DEBUG("CSP context acquired.");
      }
      else
      {
         LOG_ERROR("Error during CryptAcquireContextc %d.",GetLastError());
         throw exception();
      }
      if (CryptImportKey(
         hProv,
         PRIVATE_KEY,
         sizeof(PRIVATE_KEY),
         0,
         0,
         &hPubKey))
      {
         LOG_DEBUG("The key has been imported.\n");
      }
      else
      {
         LOG_ERROR("Private key import failed.\n");
         throw exception();
      }
   }
   LicenseSigner::LicenseSigner(const std::string& alternatePrimaryKey) {
      os_initialize();
   }
   string LicenseSigner::Opensslb64Encode(size_t slen, unsigned char* signature) {
      return NULL;
   }
   string LicenseSigner::signString(const string& license) {
      //-------------------------------------------------------------------
      // Declare and initialize variables.
      BYTE *pbBuffer = (BYTE *)license.c_str();
      DWORD dwBufferLen = strlen((char *)pbBuffer) + 1;
      HCRYPTHASH hHash;
      HCRYPTKEY hKey;
      BYTE *pbKeyBlob;
      BYTE *pbSignature;
      DWORD dwSigLen;
      DWORD dwBlobLen;
      //-------------------------------------------------------------------
      // 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(
         hProv,
         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(
         hProv,
         CALG_SHA1,
         0,
         0,
         &hHash))
      {
         printf("Hash object created. \n");
      }
      else
      {
         LOG_ERROR("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
      {
         LOG_ERROR("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
      {
         LOG_ERROR("Error during CryptSignHash.");
      }
      //-------------------------------------------------------------------
      // Allocate memory for the signature buffer.
      if (pbSignature = (BYTE *)malloc(dwSigLen))
      {
         printf("Memory allocated for the signature.\n");
      }
      else
      {
         LOG_ERROR("Out of memory.");
      }
      //-------------------------------------------------------------------
      // Sign the hash object.
      if (CryptSignHash(
         hHash,
         AT_SIGNATURE,
         NULL,
         0,
         pbSignature,
         &dwSigLen))
      {
         printf("pbSignature is the hash signature.\n");
      }
      else
      {
         LOG_ERROR("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");
      //-------------------------------------------------------------------
      // 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("");
   } //  End of main
   void LicenseSigner::signLicense(FullLicenseInfo& licenseInfo) {
      string license = licenseInfo.printForSign();
      string signature = signString(license);
      licenseInfo.license_signature = signature;
   }
   LicenseSigner::~LicenseSigner() {
   }
} /* namespace license */