मुझे CNG (क्रिप्टोग्राफी एपीआई: अगला) का उपयोग करके मौजूदा सी कोड को संकलित करना होगा। जनरेशन) विंडोज एम्बेडेड कॉम्पैक्ट 2013 के लिए कार्य करता है। यह कोड BCryptDeriveKeyPBKDF2, जो कि विंडोज एम्बेडेड कॉम्पैक्ट 2013 के तहत उपलब्ध नहीं है।

इसका मतलब है कि मुझे RFC 2898 में परिभाषित PBKDF2 कुंजी व्युत्पत्ति एल्गोरिथ्म को लागू करने के लिए नीचे दिए गए फ़ंक्शन के प्रतिस्थापन की आवश्यकता है अनुभाग 5.2, लेकिन का उपयोग किए बिना BCryptDeriveKeyPBKDF2

मुझे कुछ सी कोड मिले जो CryptoAPI फ़ंक्शन का उपयोग कर रहे हैं यहां, लेकिन मैं दूसरे का उपयोग नहीं करना चाहता, यदि संभव हो तो बहिष्कृत एपीआई।

BOOL pbkdf2(
    PUCHAR pbPassword,  ULONG cbPassword,
    PUCHAR pbSalt, ULONG cbSalt,
    ULONGLONG cIterations,
    PUCHAR pbDerivedKey, ULONG cbDerivedKey)
{
    NTSTATUS status;
    BCRYPT_ALG_HANDLE hAlgorithm;

    status = BCryptOpenAlgorithmProvider(&hAlgorithm, BCRYPT_SHA1_ALGORITHM, NULL, BCRYPT_ALG_HANDLE_HMAC_FLAG);
    if (BCRYPT_SUCCESS(status))
    {
        status = BCryptDeriveKeyPBKDF2(hAlgorithm, pbPassword, cbPassword, pbSalt, cbSalt, cIterations, pbDerivedKey, cbDerivedKey, 0);
        BCryptCloseAlgorithmProvider(hAlgorithm, 0);
    }

    return BCRYPT_SUCCESS(status);
}
0
haide 3 सितंबर 2018, 20:24

2 जवाब

आप एल्गोरिदम को लागू करने के लिए सीएनजी आदिम जैसे BCryptCreateHash का उपयोग कर सकते हैं। BCryptOpenAlgorithmProvider में ध्वज BCRYPT_ALG_HANDLE_HMAC_FLAG का उपयोग करना सबसे महत्वपूर्ण है :

void pbkdf2()
{
    BCRYPT_ALG_HANDLE hAlg = NULL;
    BCRYPT_HASH_HANDLE hHash = NULL;
    std::vector<BYTE> pass = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
    std::vector<BYTE> salt = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
    std::vector<BYTE> derived_key(32);
    std::vector<BYTE> dig(32);
    byte t[] = { 0x00, 0x00, 0x00, 0x01 };
    DWORD itcount = 10000;

    SECURITY_STATUS status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_SHA256_ALGORITHM,
        nullptr, BCRYPT_ALG_HANDLE_HMAC_FLAG);
    if (status != ERROR_SUCCESS) {
        goto Exit;
    }

    status = BCryptCreateHash(hAlg, &hHash, nullptr, 0, pass.data(), pass.size(), 0);
    if (status != ERROR_SUCCESS) {
        goto Exit;
    }
    status = BCryptHashData(hHash, salt.data(), salt.size(), 0);
    if (status != ERROR_SUCCESS) {
        goto Exit;
    }
    status = BCryptHashData(hHash, t, 4, 0);
    if (status != ERROR_SUCCESS) {
        goto Exit;
    }
    status = BCryptFinishHash(hHash, dig.data(), dig.size(), 0);
    if (status != ERROR_SUCCESS) {
        goto Exit;
    }
    derived_key = dig;
    BCryptDestroyHash(hHash);

    for (DWORD i = 1; i < itcount; ++i)
    {
        status = BCryptCreateHash(hAlg, &hHash, nullptr, 0, pass.data(), pass.size(), 0);
        if (status != ERROR_SUCCESS) {
            goto Exit;
        }
        status = BCryptHashData(hHash, dig.data(), dig.size(), 0);
        if (status != ERROR_SUCCESS) {
            goto Exit;
        }
        status = BCryptFinishHash(hHash, dig.data(), dig.size(), 0);
        if (status != ERROR_SUCCESS) {
            goto Exit;
        }
        BCryptDestroyHash(hHash);
        for (DWORD j = 0; j < dig.size(); ++j) {
            derived_key[j] ^= dig[j];
        }
    }


Exit:
    if (hHash) {
        BCryptDestroyHash(hHash);
    }
    if (hAlg) {
        BCryptCloseAlgorithmProvider(hAlg, 0);
    }
    return;
}

संपादित करें: t[] का अर्थ स्पष्ट करने के लिए।
RFC (5.2) के अनुसार:

व्युत्पन्न कुंजी के प्रत्येक ब्लॉक के लिए पासवर्ड पी, नमक एस, पुनरावृत्ति गणना सी, और ब्लॉक की गणना करने के लिए ब्लॉक इंडेक्स के नीचे परिभाषित फ़ंक्शन एफ लागू करें:

               T_1 = F (P, S, c, 1) ,
               T_2 = F (P, S, c, 2) ,
               ...
               T_l = F (P, S, c, l) ,

     where the function F is defined as the exclusive-or sum of the
     first c iterates of the underlying pseudorandom function PRF
     applied to the password P and the concatenation of the salt S
     and the block index i:  F (P, S, c, i) = U_1 \xor U_2 \xor ... \xor U_c

     where

               U_1 = PRF (P, S || INT (i)) ,
               U_2 = PRF (P, U_1) ,
               ...
               U_c = PRF (P, U_{c-1}) .

     Here, INT (i) is a four-octet encoding of the integer i, most
     significant octet first.

तो, मेरे कोड में t[] - पूर्णांक 1 का चार-ऑक्टेट एन्कोडिंग है (पहले पुनरावृत्ति के लिए), सबसे महत्वपूर्ण ऑक्टेट पहले।

0
plstryagain 4 सितंबर 2018, 16:31
Plstryagain, आपके उत्तर के लिए धन्यवाद। आपके कोड में t[] का उद्देश्य क्या है? मैंने चीजों को स्पष्ट करने के लिए उपरोक्त मेरी पोस्ट संपादित की
 – 
haide
4 सितंबर 2018, 15:15
आपकी मदद के लिए फिर से धन्यवाद, मैंने आपके उत्तर को उपयोगी के रूप में चिह्नित किया है, लेकिन दुर्भाग्य से इसकी गिनती नहीं है क्योंकि मेरी प्रतिष्ठा कम है। मेरे लिए मौजूदा कोड को परिवर्तित करना आसान था (नीचे मेरा उत्तर देखें), क्योंकि मैं इस क्रिप्टोग्राफी सामग्री के बारे में कुल नौसिखिया हूं।
 – 
haide
4 सितंबर 2018, 20:25

मैंने यह कोड लिया, पदावनत विनक्रिप्ट कॉल को नए में बदल दिया CNG API, इसे फिर से तैयार किया और उस सामान को हटा दिया जो मुझे जरूरत नहीं है।

हालांकि मुझे समझ में नहीं आता कि कोड क्या कर रहा है, ऐसा लगता है कि यह मेरे प्रश्न में फ़ंक्शन की तुलना में वही परिणाम दे रहा है जो BCryptDeriveKeyPBKDF2

#define NOCRYPT

#include <windows.h>
#include <bcrypt.h>
#include <math.h>
#include <assert.h>

#define DIGEST_SIZE 20
#define BLOCK_SIZE 64

typedef struct
{
    BCRYPT_ALG_HANDLE hAlgorithm;
    BCRYPT_HASH_HANDLE hInnerHash;
    BCRYPT_HASH_HANDLE hOuterHash;
} PRF_CTX;

static void hmacFree(PRF_CTX* pContext)
{
    if (pContext->hOuterHash) BCryptDestroyHash(pContext->hOuterHash);
    if (pContext->hInnerHash) BCryptDestroyHash(pContext->hInnerHash);
    if (pContext->hAlgorithm) BCryptCloseAlgorithmProvider(pContext->hAlgorithm, 0);
}

static BOOL hmacPrecomputeDigest(BCRYPT_HASH_HANDLE hHash, PUCHAR pbPassword, DWORD cbPassword, BYTE mask)
{
    BYTE buffer[BLOCK_SIZE];
    DWORD i;
    assert(cbPassword <= BLOCK_SIZE);

    memset (buffer, mask, sizeof(buffer));

    for (i = 0; i < cbPassword; ++i)
    {
        buffer[i] = (char) (pbPassword[i] ^ mask);
    }

    return BCRYPT_SUCCESS(BCryptHashData(hHash, buffer, sizeof(buffer), 0));
}

static BOOL hmacInit(PRF_CTX* pContext, PUCHAR pbPassword, DWORD cbPassword)
{
    BCRYPT_HASH_HANDLE hHash = NULL;
    BOOL bStatus = FALSE;
    BYTE key[DIGEST_SIZE];

    if (!BCRYPT_SUCCESS(BCryptOpenAlgorithmProvider(&pContext->hAlgorithm, BCRYPT_SHA1_ALGORITHM, NULL, 0)) ||
        !BCRYPT_SUCCESS(BCryptCreateHash(pContext->hAlgorithm, &pContext->hInnerHash, NULL, 0, NULL, 0, 0)) ||
        !BCRYPT_SUCCESS(BCryptCreateHash(pContext->hAlgorithm, &pContext->hOuterHash, NULL, 0, NULL, 0, 0)))
    {
        goto hmacInit_end;
    }

    if (cbPassword > BLOCK_SIZE)
    {
        ULONG cbResult;
        if (!BCRYPT_SUCCESS(BCryptCreateHash(pContext->hAlgorithm, &hHash, NULL, 0, NULL, 0, 0)) ||
            !BCRYPT_SUCCESS(BCryptHashData(hHash, pbPassword, cbPassword, 0)) ||
            !BCRYPT_SUCCESS(BCryptGetProperty(hHash, BCRYPT_HASH_LENGTH, (PUCHAR)&cbPassword, sizeof(cbPassword), &cbResult, 0)) ||
            !BCRYPT_SUCCESS(BCryptFinishHash(hHash, key, cbPassword, 0)))
        {
            goto hmacInit_end;
        }

        pbPassword = key;
    }

    bStatus =
        hmacPrecomputeDigest(pContext->hInnerHash, pbPassword, cbPassword, 0x36) &&
        hmacPrecomputeDigest(pContext->hOuterHash, pbPassword, cbPassword, 0x5C);

hmacInit_end:

    if (hHash) BCryptDestroyHash(hHash);
    if (bStatus == FALSE) hmacFree(pContext);

    return bStatus;
}

static BOOL hmacCalculateInternal(BCRYPT_HASH_HANDLE hHashTemplate, PUCHAR pbData, DWORD cbData, PUCHAR pbOutput, DWORD cbOutput)
{
    BOOL success = FALSE;
    BCRYPT_HASH_HANDLE hHash = NULL;

    if (BCRYPT_SUCCESS(BCryptDuplicateHash(hHashTemplate, &hHash, NULL, 0, 0)))
    {
        success =
            BCRYPT_SUCCESS(BCryptHashData(hHash, pbData, cbData, 0)) &&
            BCRYPT_SUCCESS(BCryptFinishHash(hHash, pbOutput, cbOutput, 0));

        BCryptDestroyHash(hHash);
    }

    return success;
}

static BOOL hmacCalculate(PRF_CTX* pContext, PUCHAR pbData, DWORD cbData, PUCHAR pbDigest)
{
    return
        hmacCalculateInternal(pContext->hInnerHash, pbData, cbData, pbDigest, DIGEST_SIZE) &&
        hmacCalculateInternal(pContext->hOuterHash, pbDigest, DIGEST_SIZE, pbDigest, DIGEST_SIZE);
}

static void xor(LPBYTE ptr1, LPBYTE ptr2, DWORD dwLen)
{
    while (dwLen--)
        *ptr1++ ^= *ptr2++;
}

BOOL pbkdf2(
    PUCHAR pbPassword, ULONG cbPassword,
    PUCHAR pbSalt, ULONG cbSalt,
    DWORD cIterations,
    PUCHAR pbDerivedKey, ULONG cbDerivedKey)
{
    BOOL bStatus = FALSE;
    DWORD l, r, dwULen, i, j;
    BYTE Ti[DIGEST_SIZE];
    BYTE V[DIGEST_SIZE];
    LPBYTE U = malloc(max((cbSalt + 4), DIGEST_SIZE));
    PRF_CTX prfCtx = { 0 };

    assert(pbPassword != NULL && cbPassword != 0 && pbSalt != NULL && cbSalt != 0);
    assert(cIterations > 0 && pbDerivedKey > 0 && cbDerivedKey > 0);

    if (!hmacInit(&prfCtx, pbPassword, cbPassword))
    {
        goto PBKDF2_end;
    }

    l = (DWORD) ceil((double) cbDerivedKey / (double) DIGEST_SIZE);
    r = cbDerivedKey - (l - 1) * DIGEST_SIZE;

    for (i = 1; i <= l; i++)
    {
        ZeroMemory(Ti, DIGEST_SIZE);
        for (j = 0; j < cIterations; j++)
        {
            if (j == 0)
            {
                // construct first input for PRF
                memcpy(U, pbSalt, cbSalt);
                U[cbSalt] = (BYTE) ((i & 0xFF000000) >> 24);
                U[cbSalt + 1] = (BYTE) ((i & 0x00FF0000) >> 16);
                U[cbSalt + 2] = (BYTE) ((i & 0x0000FF00) >> 8);
                U[cbSalt + 3] = (BYTE) ((i & 0x000000FF));
                dwULen = cbSalt + 4;
            }
            else
            {
                memcpy(U, V, DIGEST_SIZE);
                dwULen = DIGEST_SIZE;
            }

            if (!hmacCalculate(&prfCtx, U, dwULen, V))
            {
                goto PBKDF2_end;
            }

            xor(Ti, V, DIGEST_SIZE);
        }

        if (i != l)
        {
            memcpy(&pbDerivedKey[(i-1) * DIGEST_SIZE], Ti, DIGEST_SIZE);
        }
        else
        {
            // Take only the first r bytes
            memcpy(&pbDerivedKey[(i-1) * DIGEST_SIZE], Ti, r);
        }
    }

    bStatus = TRUE;

PBKDF2_end:

    hmacFree(&prfCtx);
    free(U);
    return bStatus;
}
0
haide 4 सितंबर 2018, 20:22