SOL9 2.0 Class: CryptServiceProvider

 SOL9 C++ Class Library  SOL9 Samples  SOL9 Tutorial  SOL9 FAQ  SOL9 ClassTree  SOL9 ClassList 

Source code

/******************************************************************************
 *
 * Copyright (c) 2009 Antillia.com TOSHIYUKI ARAI. ALL RIGHTS RESERVED.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions, and the following disclaimer.
 *  
 * 2. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *
 *  CryptServiceProvider.h
 *
 *****************************************************************************/

// SOL9
// 2009/02/17
// 2009/03/04 Modified getProviderName
// 2009/03/15 Added two methods exportPublicKeyInfo, importPublicKeyInfo
// 2003/03/23 Added a method hashPublicKeyInfo.

#pragma once

#include <sol/Object.h>
#include <sol/Exception.h>
#include <sol/String.h>
#include <sol/SmartPtrs.h>
#include <wincrypt.h>
#include <sol/crypt/CryptError.h>

namespace SOL {

class CryptServiceProvider :public Object {

private:
  HCRYPTPROV hCryptProv;


public:
  /**
   * Constructor
   * @param type
    PROV_RSA_AES;    //RC2,RC4,AES
    PROV_RSA_SCHANNEL;  //RC4,DES,TripleDES
    PROV_DSS;      //2009/03/04
    PROV_DSS_DH;    //CYLINK_MEK,
    PROV_DH_SCHANNEL;  //DES,Triple DES
   */
  CryptServiceProvider(__in const DWORD type=PROV_RSA_AES)
  :hCryptProv(NULL) {

    TCHAR* name = _T("");

    getProviderName(type, &name);

    if (!CryptAcquireContext(
      &hCryptProv, 
      NULL,      // Container name
      name,  // Provider name
      type,  // Provider type
      CRYPT_VERIFYCONTEXT))  {
      //CRYPT_NEWKEYSET))  {
  
      throw Exception(GetLastError(),
        "CryptServiceProvider#CryptServiceProvider,1,CryptAcquireContext failed");
    
    } 
  }

public:
  /**
   * Constructor
   * @param type
    PROV_RSA_AES;    //RC2,RC4,AES
    PROV_RSA_SCHANNEL;  //RC4,DES,TripleDES
    PROV_DSS;      //2009/03/04
    PROV_DSS_DH;    //CYLINK_MEK,
    PROV_DH_SCHANNEL;  //DES,Triple DES
   */
  CryptServiceProvider(__in const TCHAR* container, 
        __in const DWORD type=PROV_RSA_FULL, 
        __in const TCHAR* name=NULL)
  :hCryptProv(NULL) {

    if (!CryptAcquireContext(
      &hCryptProv,
      container,    // Container name 
      name,  // Provider name
      type,  // Provider type
      CRYPT_MACHINE_KEYSET))  {

      //DWORD rc = GetLastError();
      //if (rc == NTE_BAD_KEYSET) {
  
        if (!CryptAcquireContext(
          &hCryptProv, 
          container, 
          name,
          type,  
          CRYPT_MACHINE_KEYSET|CRYPT_NEWKEYSET)) {

          //
          throw Exception(GetLastError(),
            "CryptServiceProvider#CryptServiceProvider,1,CryptAcquireContext failed");
         
        }
      //}
    }
  }

public:
  //Destructor
  ~CryptServiceProvider() {
    if (hCryptProv) {
      CryptReleaseContext(hCryptProv, 0);
      hCryptProv = NULL;
    }
  }

public:
  // Get the name of the CSP.
  int  getProviderName(__out String& string){
    int size = 0;
    int rc = NO_ERROR;
    
    CryptGetProvParam(
      hCryptProv, 
      PP_NAME, 
      NULL, 
      (DWORD*)&size, 0);
    if (size > 0) {
      SmartPtrs<char> name = new char[size+1];
      if (!CryptGetProvParam(
        hCryptProv, 
        PP_NAME, 
        (BYTE*)(const char*)name, 
        (DWORD*)&size, 0)) {
        string = "";
        rc = GetLastError();
      } else {
        string = (const char*)name;  
      }
    }
    return rc;
  }


public:
  // Get the name of the KeyContainer.
  int  getKeyContainer(__out String& string) {
    int size = 0;
    int rc = NO_ERROR;
    
    CryptGetProvParam(
      hCryptProv, 
      PP_CONTAINER, 
      NULL, 
      (DWORD*)&size, 0);
    if (size > 0) {
      SmartPtrs<char> name = new char[size+1];
      if (!CryptGetProvParam(
        hCryptProv, 
        PP_CONTAINER, 
        (BYTE*)(const char*)name, 
        (DWORD*)&size, 0)) {
        string = "";
        rc = GetLastError();
      } else {
        string = (const char*)name;  
      }
    }
    return rc;
  }


public:
  HCRYPTPROV getProviderHandle() {
    return this->hCryptProv;
  }


private:
  static bool getProviderName(__in const DWORD type, TCHAR** name)
  {
    bool rc = true;

    switch (type) {
    case PROV_RSA_AES:
      *name = MS_ENH_RSA_AES_PROV;
      break;

    case PROV_RSA_SCHANNEL:
      *name = MS_DEF_RSA_SCHANNEL_PROV;
      break;

    case PROV_DSS_DH:
      *name = MS_DEF_DSS_DH_PROV;
      break;

    case PROV_DH_SCHANNEL:
      *name = MS_DEF_DH_SCHANNEL_PROV;
      break;

      //2009/03/04
    case PROV_DSS:
      *name = MS_DEF_DSS_PROV;
      break;

    default:
      rc = false;
      break;
    }
    return rc;
  }

public:
  int stat()
  {
    int rc = 0;
    BYTE pbData[1000];
    //First time only    
    DWORD dwFlags =CRYPT_FIRST;

    DWORD dwDataLen = 1000;
    bool looping = true;
    while (looping) {
      // Enumerate the supported algorithms.
      CryptGetProvParam(this->hCryptProv, PP_ENUMALGS, pbData, &dwDataLen, dwFlags);
      rc= GetLastError();
      if (rc == ERROR_NO_MORE_ITEMS){
        break;
      }
      dwFlags = 0;

      // Extract algorithm information from 'pbData'.
      BYTE *ptr = pbData;
      ALG_ID algid = *(ALG_ID *)ptr;
      ptr += sizeof(ALG_ID);
      DWORD dwBits = *(DWORD *)ptr;
      ptr += sizeof(DWORD);

      DWORD dwNameLen = *(DWORD *)ptr;
      ptr += sizeof(DWORD);
      char algName[256];
      memset(algName, 0, CountOf(algName));
      strncpy_s(algName, CountOf(algName), (char*)ptr, dwNameLen);
      TCHAR* algType = NULL;

      switch (GET_ALG_CLASS(algid)) {
      case ALG_CLASS_DATA_ENCRYPT:
        algType = _T("Encrypt  ");
        break;
      case ALG_CLASS_HASH:
        algType = _T("Hash     ");
        break;
      case ALG_CLASS_KEY_EXCHANGE:
        algType = _T("Exchange ");
        break;
      case ALG_CLASS_SIGNATURE:
        algType = _T("Signature");
        break;
      default:
        algType = _T("Unknown  ");
        break;
      }
      String algorithm = algName;
      //2009/11/10
      _tprintf(_T("Name:%-14s Type:%s  Bits:%-4d AlgId:0x%8.8x\n"),
        (const TCHAR*)algorithm, algType, dwBits, algid);
    
    }

    return rc;
  }

public:
  // 2009/03/15
  int exportPublicKeyInfo(__in DWORD keySpec, 
        __in DWORD encodingType, 
        __out PCERT_PUBLIC_KEY_INFO* ppKeyInfo)
  {
    int rc = NO_ERROR;

    DWORD size = 0;
    if (CryptExportPublicKeyInfo(hCryptProv, keySpec, encodingType, //X509_ASN_ENCODING, 
      NULL, &size)) {
      PCERT_PUBLIC_KEY_INFO pKeyInfo = (PCERT_PUBLIC_KEY_INFO)new BYTE[size];

      if (CryptExportPublicKeyInfo(hCryptProv, keySpec, encodingType, 
          pKeyInfo, &size)) {
        *ppKeyInfo = pKeyInfo;
      } else {
        delete pKeyInfo;
        rc = GetLastError();
      }
      
    } else {
      rc = GetLastError();
    }
    return rc;
  }

public:
  // 2009/03/15
  int importPublicKeyInfo(__in DWORD encodingType, 
        __in PCERT_PUBLIC_KEY_INFO pInfo,
        __out HCRYPTKEY *phKey) 
  {
    int rc = NO_ERROR;
    HCRYPTKEY hKey = NULL;
    if (CryptImportPublicKeyInfo(
      hCryptProv,
      encodingType,
      pInfo,
      &hKey)) {
      //OK
      *phKey = hKey;  
    } else {
      rc = GetLastError();
    }

    return rc;
  }


/*
BOOL WINAPI CryptSignAndEncodeCertificate(
  HCRYPTPROV hCryptProv,
  DWORD dwKeySpec,
  DWORD dwCertEncodingType,
  LPCSTR lpszStructType,
  const void *pvStructInfo,
  PCRYPT_ALGORITHM_IDENTIFIER pSignatureAlgorithm,
  const void *pvHashAuxInfo,
  PBYTE pbEncoded,
  DWORD *pcbEncoded
);
*/

public:
  // 2009/03/17
  int signAndEncodeCertificate(
      __in PCERT_INFO certInfo,
      __in DWORD keySpec,
      __in DWORD encodingType,

      __out BYTE** encData,
      __out DWORD *encDataSize)
  {
    int rc = NO_ERROR;

    DWORD size = 0;
    if (CryptSignAndEncodeCertificate(hCryptProv, 
        keySpec, 
        encodingType,    //X509_ASN_ENCODING, 
        (LPSTR)X509_CERT_TO_BE_SIGNED, 
        certInfo, 
        &(certInfo->SignatureAlgorithm), 
        NULL, 
        NULL, 
        &size)) {

      BYTE* data = new BYTE[size];
      if (CryptSignAndEncodeCertificate(hCryptProv, 
                keySpec, 
                encodingType,    //X509_ASN_ENCODING, 
                (LPSTR)X509_CERT_TO_BE_SIGNED, 
                certInfo, 
                &(certInfo->SignatureAlgorithm), 
                NULL, 
                data, 
                &size)) {

        *encData = data;
        *encDataSize = size;
      } else {

        delete [] data;
        rc = GetLastError();
      }
    } else {
      rc = GetLastError();
    }

    return rc;
  }

public:
  /**
   * @param hashAlg  A hash alogorithm (Ex. CALG_SHA1 CALG_MD5,...)
   * @param dwKeySpec A keyspec (AT_SIGNATURE or AT_KEYEXCHANGE)
   * @param ppHashData  A pointer to pointer to a hash byte array.
   * @param pHashDataSize A pointer to DWORD to return byte size of hash-data.
   */
  //2003/03/23
  int hashPublicKeyInfo(__in DWORD hashAlg, __in DWORD dwKeySpec, 
      __out BYTE** ppHashData, 
      __out DWORD* pHashDataSize)
  {
    int rc = NO_ERROR;
    DWORD dwSize = 0;
    DWORD encodingType = X509_ASN_ENCODING;

    if (!CryptExportPublicKeyInfo(hCryptProv, dwKeySpec, encodingType, NULL, &dwSize)) {
      return GetLastError();
    }
      
    PCERT_PUBLIC_KEY_INFO publicKeyInfo = (PCERT_PUBLIC_KEY_INFO)new BYTE[dwSize];
    if (!CryptExportPublicKeyInfo(hCryptProv, dwKeySpec, encodingType, publicKeyInfo, &dwSize)) {
      delete publicKeyInfo;
      return GetLastError(); 
    }

    dwSize = 0;
    if (!CryptHashPublicKeyInfo(hCryptProv, hashAlg, 0, encodingType, publicKeyInfo, NULL, &dwSize)) {
      delete publicKeyInfo;
      return GetLastError();     
    }

    BYTE* publicKeyHash =  new BYTE[dwSize];

    if (CryptHashPublicKeyInfo(hCryptProv, hashAlg, 0, encodingType, publicKeyInfo, publicKeyHash, &dwSize)) {
      *ppHashData = publicKeyHash;
      *pHashDataSize = dwSize;

    } else {
      delete [] publicKeyHash; 
      rc = GetLastError();
    }
    delete publicKeyInfo;
    return rc;
    
  }
};

}

Last modified: 5 May 2019

Copyright (c) 2009-2019 Antillia.com ALL RIGHTS RESERVED.