Как надежно получить неотрицательный серийный номер из хэша SHA1?

Я использую CNG для генерации серийных номеров для сертификатов. Мой алгоритм берет общее имя центра сертификации, добавляет 10 случайных байтов, а затем вычисляет хэш SHA1. Длина хеша SHA1 составляет 20 байт, и я использую его как серийный номер.

Эта проблема! Я не получаю надежных положительных чисел от этого алгоритма, что касается OpenSSL. Отрицательные серийные номера вызывают проблемы для OpenSSL. Итак, как мне убедиться, что мои 20 байтов всегда рассматриваются OpenSSL как «положительный» серийный номер?

Например, эти серийные номера:

da7db14cbc79401b642fd77806b54e21b012bbe1 f67604707a861fac55fbef8a5571ab8284e761bd 7d8df1b0b62c284ad12fd1eaadfb18dd4c9c91ba 8588ea1034c6c5a23b1f5cf9689e63baf10775a9 169ad01b41f6e5108d64d70bb8de25da475e02b5 89ff69bc06ec5a93c9e11e71a990f7e8ee0a9d3d 6dbd23a8655c9627a8d241d48a909aec7823dc1c

Создайте этот вывод, когда я помещу их в список отзыва сертификатов, что неприемлемо:

Отменено сертификаты: серийный номер: -25824EB34386BFE49BD02887F94AB1DE4FED441F Дата отзыва: 14 марта 21:47:02 2018 GMT Serial Number: -0989F8F8579E053AA041075AA8E547D7F8579E053AA041075AA8E547D7F8579E053AA041075A8E547D7F8579E053AA041075A8. 02 2018 GMT Serial Number: -7A7715EFCB393A5DC4E0A30697619C450EF88A57 Revocation Date: Mar 14 21:47:02 2018 GMT Serial Number: 169AD01B41F6E5108D64D70BB8DE25DA475E02B5 Revocation Date: Mar 14 21:47:02 2018 GMT Serial Number: -76009643F913A56C361EE18E566F081711F562C3 Revocation Date: Mar 14 21:47: 02 2018 GMT Серийный номер: 6DBD23A8655C9627A8D241D48A909AEC7823DC1C Дата отзыва: 14 марта 21:47:02 2018 GMT

Есть ли способ замаскировать часть одного байта, чтобы он всегда был положительным? Кроме того, есть ли причина, по которой третий серийный номер интерпретируется как ноль?

Пример кода для генерации серийного номера:

void CERTSTORE::GetSerialNumber(
eAction eActionTaken,
std::string sCACN, 
std::vector<BYTE> & vSerialNumber
)
{
    NTSTATUS statusBCryptOpenAlgorithmProvider_Hash;
    NTSTATUS statusBCryptOpenAlgorithmProvider_RNG;
    NTSTATUS statusBCryptGenRandom;
    NTSTATUS statusBCryptHash;
    BCRYPT_ALG_HANDLE hRandNumAlg;
    BCRYPT_ALG_HANDLE hHashAlg;
    DWORD dwHash = 20;
    BYTE bRandomBytes[10];
    std::vector<BYTE> vBytesToBeHashed(
        (BYTE)sCACN.c_str(),
        sCACN.length()
    );

    //open algorithm provider to get random number generator
    statusBCryptOpenAlgorithmProvider_RNG = BCryptOpenAlgorithmProvider(
        &hRandNumAlg,
        BCRYPT_RNG_ALGORITHM,
        MS_PRIMITIVE_PROVIDER,
        0
    );

    if (0 != statusBCryptOpenAlgorithmProvider_RNG)
    {
        throw ERRORSTRING(
            eActionTaken,
            eSubAction::eSubAction_OPENALGPROV,
            eMajorErrorCode::eMajorErrorCode_RUNTIMEERROR,
            eMinorErrorCode::eMinorErrorCode_UKNNTSTATUS,
            statusBCryptOpenAlgorithmProvider_RNG
        );
    }

    statusBCryptGenRandom = BCryptGenRandom(
        hRandNumAlg,
        bRandomBytes,
        sizeof(bRandomBytes),
        0
    );

    if (0 != statusBCryptGenRandom)
    {
        BCryptCloseAlgorithmProvider(hRandNumAlg, 0);
        throw ERRORSTRING(
            eActionTaken,
            eSubAction::eSubAction_GENRANDOM,
            eMajorErrorCode::eMajorErrorCode_RUNTIMEERROR,
            eMinorErrorCode::eMinorErrorCode_UKNNTSTATUS,
            statusBCryptGenRandom
        );
    }

    BCryptCloseAlgorithmProvider(hRandNumAlg, 0);

    for (int iRandByteCounter = 0; iRandByteCounter < sizeof(bRandomBytes); iRandByteCounter++)
    {
        vBytesToBeHashed.push_back(
            bRandomBytes[iRandByteCounter]
        );
    }

    statusBCryptOpenAlgorithmProvider_Hash = BCryptOpenAlgorithmProvider(
        &hHashAlg,
        BCRYPT_SHA1_ALGORITHM,
        MS_PRIMITIVE_PROVIDER,
        0
    );

    if (0 != statusBCryptOpenAlgorithmProvider_Hash)
    {
        throw ERRORSTRING(
            eActionTaken,
            eSubAction::eSubAction_OPENALGPROV,
            eMajorErrorCode::eMajorErrorCode_RUNTIMEERROR,
            eMinorErrorCode::eMinorErrorCode_UKNNTSTATUS,
            statusBCryptOpenAlgorithmProvider_Hash
        );
    }

    try
    {
        vSerialNumber.assign(
            dwHash,
            NULL
        );
    }
    catch (std::exception & ex)
    {
        throw ERRORSTRING(
            eActionTaken,
            eSubAction::eSubAction_CRYPTHASH,
            eMajorErrorCode::eMajorErrorCode_RUNTIMEERROR,
            eMinorErrorCode::eMinorErrorCode_MEMORYALLOCATION,
            0
        );
    }

    statusBCryptHash = BCryptHash(
        hHashAlg,
        NULL,
        0,
        &vBytesToBeHashed[0],
        vBytesToBeHashed.size(),
        &vSerialNumber[0],
        dwHash
    );

    if (0 != statusBCryptHash)
    {
        BCryptCloseAlgorithmProvider(hHashAlg, 0);
        throw ERRORSTRING(
            eActionTaken,
            eSubAction::eSubAction_CRYPTHASH,
            eMajorErrorCode::eMajorErrorCode_RUNTIMEERROR,
            eMinorErrorCode::eMinorErrorCode_UKNNTSTATUS,
            statusBCryptHash
        );
    }

    BCryptCloseAlgorithmProvider(hHashAlg, 0);
}

person Timothy John Laird    schedule 14.03.2018    source источник


Ответы (1)


В зависимости от того, какой API вы используете после этой точки, 20 байтов имеют либо прямой, либо прямой порядок байтов. Поскольку вы говорите, что третий оказался отрицательным, он кажется прямым порядком байтов.

Исправление прямого порядка байтов:

vSerialNumber[19] &= 0x7F

Исправление обратного порядка байтов:

vSerialNumber[0] &= 0x7F;

«Эх, просто работай» Исправление:

vSerialNumber[0] &= 0x7F;
vSerialNumber[19] &= 0x7F

Вы уменьшили свою энтропию на один (или два) бита, но все еще находитесь в безопасном диапазоне.

person bartonjs    schedule 15.03.2018