Заметка
Доступ к этой странице требует авторизации. Вы можете попробовать войти в систему или изменить каталог.
Доступ к этой странице требует авторизации. Вы можете попробовать сменить директорию.
Операция хэширования — это односторонняя операция, которая выполняется на блоке данных для создания уникального хэш-значения, представляющего содержимое данных. Независимо от того, когда выполняется хэш, то же алгоритм хэширования, выполняемый на одних и том же данных, всегда будет производить одно и то же хэш-значение. Если какой-либо из данных изменяется, хэш-значение изменится соответствующим образом.
Хэши не полезны для шифрования данных, так как они не предназначены для воспроизведения исходных данных из хэш-значения. Хэши наиболее полезны для проверки целостности данных при использовании с асимметричным алгоритмом подписи. Например, если вы хэшировали текстовое сообщение, подписали хэш и включили подписанное хэш-значение с исходным сообщением, получатель может проверить подписанный хэш, создать хэш-значение для полученного сообщения, а затем сравнить это хэш-значение с подписанным хэш-значением, включенным в исходное сообщение. Если два хэш-значения идентичны, получатель может быть достаточно уверен, что исходное сообщение не было изменено.
Размер хэш-значения фиксирован для определенного алгоритма хэширования. Это означает, что независимо от того, насколько велик или мал блок данных, хэш-значение всегда будет одинаковым. Например, алгоритм хэширования SHA256 имеет хэш-значение размером 256 бит.
- создание объекта хэширования
- создание повторно используемых объектов хэширования
- Копирование хэш-объекта
Создание хэш-объекта
Чтобы создать хэш с помощью CNG, выполните следующие действия.
Откройте поставщик алгоритмов, поддерживающий требуемый алгоритм. Типичные алгоритмы хэширования включают MD2, MD4, MD5, SHA-1 и SHA256. Вызовите функцию BCryptOpenAlgorithmProvider и укажите соответствующий идентификатор алгоритма в параметре pszAlgId. Функция возвращает дескриптор поставщику.
Выполните следующие действия, чтобы создать хэш-объект:
- Получите размер объекта, вызвав функцию BCryptGetProperty, чтобы получить свойство BCRYPT_OBJECT_LENGTH.
- Выделение памяти для хранения хэш-объекта.
- Создайте объект, вызвав функцию BCryptCreateHash.
Выполните хеширование данных. Это включает вызов функции BCryptHashData один или несколько раз. Каждый вызов добавляет указанные данные в хэш.
Выполните следующие действия, чтобы получить хэш-значение:
- Получите размер значения, вызвав функцию BCryptGetProperty, чтобы получить свойство BCRYPT_HASH_LENGTH.
- Выделите память для хранения значения.
- Получите хэш-значение, вызвав функцию BCryptFinishHash. После вызова этой функции хэш-объект больше не действителен.
Чтобы выполнить эту процедуру, необходимо выполнить следующие действия по очистке:
Закройте хэш-объект, передав хэш-дескриптор в функцию BCryptDestroyHash .
Освободит память, выделенную для хэш-объекта.
Если вы не планируете создавать больше хэш-объектов, закройте поставщика алгоритма, передав дескриптор поставщика в функцию BCryptCloseAlgorithmProvider.
Если вы собираетесь создавать большее количество хэш-объектов, мы рекомендуем повторно использовать поставщика алгоритмов, вместо того чтобы многократно создавать и уничтожать один и тот же тип поставщика алгоритмов.
Когда вы закончите использовать память для хэш-значения, освободите её.
В следующем примере показано, как создать хэш-значение с помощью CNG.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (C) Microsoft. All rights reserved.
/*++
Abstract:
Sample program for SHA 256 hashing using CNG
--*/
#include <windows.h>
#include <stdio.h>
#include <bcrypt.h>
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L)
static const BYTE rgbMsg[] =
{
0x61, 0x62, 0x63
};
void __cdecl wmain(
int argc,
__in_ecount(argc) LPWSTR *wargv)
{
BCRYPT_ALG_HANDLE hAlg = NULL;
BCRYPT_HASH_HANDLE hHash = NULL;
NTSTATUS status = STATUS_UNSUCCESSFUL;
DWORD cbData = 0,
cbHash = 0,
cbHashObject = 0;
PBYTE pbHashObject = NULL;
PBYTE pbHash = NULL;
UNREFERENCED_PARAMETER(argc);
UNREFERENCED_PARAMETER(wargv);
//open an algorithm handle
if(!NT_SUCCESS(status = BCryptOpenAlgorithmProvider(
&hAlg,
BCRYPT_SHA256_ALGORITHM,
NULL,
0)))
{
wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status);
goto Cleanup;
}
//calculate the size of the buffer to hold the hash object
if(!NT_SUCCESS(status = BCryptGetProperty(
hAlg,
BCRYPT_OBJECT_LENGTH,
(PBYTE)&cbHashObject,
sizeof(DWORD),
&cbData,
0)))
{
wprintf(L"**** Error 0x%x returned by BCryptGetProperty\n", status);
goto Cleanup;
}
//allocate the hash object on the heap
pbHashObject = (PBYTE)HeapAlloc (GetProcessHeap (), 0, cbHashObject);
if(NULL == pbHashObject)
{
wprintf(L"**** memory allocation failed\n");
goto Cleanup;
}
//calculate the length of the hash
if(!NT_SUCCESS(status = BCryptGetProperty(
hAlg,
BCRYPT_HASH_LENGTH,
(PBYTE)&cbHash,
sizeof(DWORD),
&cbData,
0)))
{
wprintf(L"**** Error 0x%x returned by BCryptGetProperty\n", status);
goto Cleanup;
}
//allocate the hash buffer on the heap
pbHash = (PBYTE)HeapAlloc (GetProcessHeap (), 0, cbHash);
if(NULL == pbHash)
{
wprintf(L"**** memory allocation failed\n");
goto Cleanup;
}
//create a hash
if(!NT_SUCCESS(status = BCryptCreateHash(
hAlg,
&hHash,
pbHashObject,
cbHashObject,
NULL,
0,
0)))
{
wprintf(L"**** Error 0x%x returned by BCryptCreateHash\n", status);
goto Cleanup;
}
//hash some data
if(!NT_SUCCESS(status = BCryptHashData(
hHash,
(PBYTE)rgbMsg,
sizeof(rgbMsg),
0)))
{
wprintf(L"**** Error 0x%x returned by BCryptHashData\n", status);
goto Cleanup;
}
//close the hash
if(!NT_SUCCESS(status = BCryptFinishHash(
hHash,
pbHash,
cbHash,
0)))
{
wprintf(L"**** Error 0x%x returned by BCryptFinishHash\n", status);
goto Cleanup;
}
wprintf(L"Success!\n");
Cleanup:
if(hAlg)
{
BCryptCloseAlgorithmProvider(hAlg,0);
}
if (hHash)
{
BCryptDestroyHash(hHash);
}
if(pbHashObject)
{
HeapFree(GetProcessHeap(), 0, pbHashObject);
}
if(pbHash)
{
HeapFree(GetProcessHeap(), 0, pbHash);
}
}
Создание повторно используемых объектов хэширования
Начиная с Windows 8 и Windows Server 2012, можно создать повторно используемый объект хэширования для сценариев, требующих вычисления нескольких хэшей или HMACs в быстром последовательном порядке. Это можно сделать, указав BCRYPT_HASH_REUSABLE_FLAG при вызове функции BCryptOpenAlgorithmProvider. Все поставщики хэш-алгоритмов Майкрософт поддерживают этот флаг. Хэш-объект, созданный с помощью этого флага, можно повторно использовать сразу после вызова BCryptFinishHash так же, как если бы он был создан с помощью вызова BCryptCreateHash. Выполните следующие действия, чтобы создать повторно используемый объект хэширования:
Откройте поставщик алгоритмов, поддерживающий требуемый алгоритм хэширования. Вызовите функцию BCryptOpenAlgorithmProvider и укажите соответствующий идентификатор алгоритма в параметре pszAlgId и BCRYPT_HASH_REUSABLE_FLAG в параметре dwFlags. Функция возвращает дескриптор поставщику.
Выполните следующие действия, чтобы создать хэш-объект:
- Получите размер объекта, вызвав функцию BCryptGetProperty, чтобы получить свойство BCRYPT_OBJECT_LENGTH.
- Выделение памяти для хранения хэш-объекта.
- Создайте объект, вызвав функцию BCryptCreateHash. Укажите BCRYPT_HASH_REUSABLE_FLAG в параметре dwFlags.
Хэш данных путем вызова функции BCryptHashData.
Выполните следующие действия, чтобы получить хэш-значение:
- Получите размер хэш-значения, вызвав функцию BCryptGetProperty, чтобы получить свойство BCRYPT_HASH_LENGTH.
- Выделите память для хранения значения.
- Получите хэш-значение, вызвав BCryptFinishHash.
Чтобы повторно использовать хэш-объект с новыми данными, перейдите к шагу 3.
Чтобы выполнить эту процедуру, необходимо выполнить следующие действия по очистке:
- Закройте объект хэша, передав дескриптор хэша в функцию BCryptDestroyHash.
- Освободит память, выделенную для хэш-объекта.
- Если вы не будете создавать более хэш-объекты, закройте поставщик алгоритма, передав дескри птор поставщика в функцию BCryptCloseAlgorithmProvider.
- Когда закончишь использование памяти для хэш-значения, освободи её.
Дублирование хэш-объекта
В некоторых случаях может быть полезно хэшировать некоторые общие данные, а затем создавать два отдельных хэш-объекта из общих данных. Для этого не нужно создавать два отдельных хэш-объекта и хэшировать общие данные дважды. Вы можете создать один хэш-объект и добавить все общие данные в хэш-объект. Затем можно использовать функцию BCryptDuplicateHash для создания дубликата исходного хэш-объекта. Повторяющийся хэш-объект содержит все те же сведения о состоянии и хэшированные данные, что и исходный, но это полностью независимый хэш-объект. Теперь вы можете добавить уникальные данные в каждый из хэш-объектов и получить хэш-значение, как показано в примере. Этот метод полезен при хэшировании возможного большого количества общих данных. Необходимо добавить общие данные только в исходный хэш один раз, а затем дублировать хэш-объект для получения уникального хэш-объекта.