安全隨機數

 

隨機數出問題了, 分裝了一個

#include <Wincrypt.h>
#include <Realtimeapiset.h>
#include <tchar.h>
#pragma comment(lib,"Advapi32.lib")
class CryptRandom{
    CRITICAL_SECTION __lock;
    HCRYPTPROV hDefaultProvidor;
    std::set<__int64> __szBuffer;
    static CryptRandom __instance;
    static int iEndTimes;

public:
    CryptRandom() throw(){
        InitializeCriticalSectionAndSpinCount(&__lock,4000);
        ::CryptAcquireContext(&hDefaultProvidor, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT);

    }
    ~CryptRandom(){
        DeleteCriticalSection(&__lock);
        ::CryptReleaseContext(hDefaultProvidor, 0);
    }

    static CryptRandom& getInstance(){
        return __instance;
    }

    //獲取隨機數, 隨便使用
    template <typename T>
    T getRandomNumer(bool bUseDefaultProvider = true){
        EnterCriticalSection(&__lock);
        const int iLen = sizeof(T);
        unsigned char buffer [iLen] = {0};
        int (CryptRandom::*__pFunc)(void * const , const int ) = NULL;

        if(bUseDefaultProvider)
            __pFunc = &CryptRandom::GetRandBytesWithDefaultProvider;
        else
            __pFunc = &CryptRandom::GetRandBytes;


        if(0 == (this->*__pFunc)(buffer, iLen) ){
            T res = *(T*)buffer;
            LeaveCriticalSection(&__lock);
            return res;
        }

        __int64 res = getCpuCount();
        LeaveCriticalSection(&__lock);
        return res;
    }

    //獲取隨機種子 , srand 使用
    template <typename T>
    T getRandomSeed(bool bUseDefaultProvider = true){
        EnterCriticalSection(&__lock);
        const int iLen = sizeof(T);
        unsigned char buffer [iLen] = {0};
        int (CryptRandom::*__pFunc)(void * const , const int ) = NULL;

        if(bUseDefaultProvider)
            __pFunc = &CryptRandom::GetRandBytesWithDefaultProvider;
        else
            __pFunc = &CryptRandom::GetRandBytes;

        T res = 0;


        if(0 != (this->*__pFunc)(buffer, iLen) ){
            res = getNumberWhenFailed();
            LeaveCriticalSection(&__lock);
            return res;
        }

        std::set<__int64>::iterator iter ;
        res = *(T*)buffer;
        int iTryTimes = 0;
        while(1){
            iter = __szBuffer.find(res);
            if(iter == __szBuffer.end()){
                __szBuffer.insert(res);
                break;
            }

            if(++iTryTimes == iEndTimes){
                res = getNumberWhenFailed();
                break;
            }

            memset(buffer,0,iLen);
            if( 0 != (this->*__pFunc)(buffer,iLen) ){
                 res = getNumberWhenFailed();
                break;
            }

            res =  *(T*)buffer;
        }



        LeaveCriticalSection(&__lock);
        return res;
    }



    __int64 getCpuCount(){
        EnterCriticalSection(&__lock);
        LARGE_INTEGER li;
        QueryPerformanceCounter(&li);
        __int64 res = li.QuadPart;
        LeaveCriticalSection(&__lock);
        return res;
    }

    // 沒有任何需求, 也可調用此函數;
    void GetRandom2(){
            FILETIME  tmCreation = {0};
            FILETIME  tmExit = { 0 };
            FILETIME  tmKernel = { 0 };
            FILETIME  tmUser = { 0 };
            SYSTEMTIME  tmSys = { 0 };

            GetThreadTimes(GetCurrentThread(), &tmCreation,&tmExit,&tmKernel,&tmUser);
            ULARGE_INTEGER tm_total_1 = { 0 };
            ULARGE_INTEGER tm_total_2 = { 0 };
            FileTimeToLocalFileTime(&tmKernel, &tmKernel);
            FileTimeToLocalFileTime(&tmUser, &tmUser);
    //        FileTimeToSystemTime(&tmCreation, &tmSys);

            tm_total_1.HighPart = tmKernel.dwHighDateTime + tmUser.dwHighDateTime;
            tm_total_1.LowPart = tmKernel.dwLowDateTime + tmUser.dwLowDateTime;

            const uint32_t kPrime1 = 61631;
            const uint32_t kPrime2 = 64997;
            const uint32_t kPrime3 = 111857;
            unsigned int d =  kPrime1 * static_cast<uint32_t>(GetCurrentThreadId())
                 + kPrime2 * static_cast<uint32_t>(tm_total_1.HighPart )
                 + kPrime3 * static_cast<uint32_t>(tm_total_1.LowPart  );

    }
private:
    int GetRandBytes(void * const buffer, const int iLen){
        if(NULL == buffer || 0 == iLen )
            return -1;

        HCRYPTPROV hProvider = 0;
        DWORD dwRes =::CryptAcquireContext(&hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT);

        if(dwRes == FALSE)
            return -1;

         dwRes = ::CryptGenRandom(hProvider, iLen, (unsigned char*)buffer);
         if(dwRes == FALSE)
             return -1;

         ::CryptReleaseContext(hProvider, 0);
        return 0;
    }

    int GetRandBytesWithDefaultProvider(void * const buffer, const int iLen){

        DWORD dwRes = 0;
         dwRes = ::CryptGenRandom(hDefaultProvidor, iLen, (unsigned char*)buffer);
         if(dwRes == FALSE)
             return -1;

        return 0;
    }

    __int64 getNumberWhenFailed(){
        __int64 res = 0;
        std::set<__int64>::iterator iter ;
        while(1){
            res = getCpuCount();
            iter = __szBuffer.find(res);
            if(iter == __szBuffer.end()){
                __szBuffer.insert(res);
                break;
            }
        }
        return res;
    }
};

CryptRandom CryptRandom::__instance;
int CryptRandom::iEndTimes = 3;

int main(int argc, char* argv[])
{

        CryptRandom & instance = CryptRandom::getInstance();
        for(int i = 0; i < 10 ; ++i)
            cout << instance.getRandomNumer<unsigned int>() << ":" << instance.getRandomSeed<unsigned int>() << endl;;


    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章