SOL9 2.0 Class: CryptServiceProvider

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

Source code

/*
 * CryptServiceProvider.h 
 * Copyright (c) 2011 Antillia.com TOSHIYUKI ARAI. ALL RIGHTS RESERVED. 
 */


// 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;

        while (true) {
            // 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, SizeOf(algName));
            strncpy(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: 1 Feb 2012

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