Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Podpisywanie danych nie chroni danych. Weryfikuje tylko integralność danych. Nadawca haszuje te dane i podpisuje (szyfruje) skrót używając klucza prywatnego. Zamierzony odbiorca przeprowadza weryfikację przez utworzenie skrótu odebranych danych, odszyfrowywanie podpisu w celu uzyskania oryginalnego skrótu i porównanie dwóch skrótów.
Gdy dane są podpisywane, nadawca tworzy wartość skrótu i podpisuje (szyfruje) skrót przy użyciu klucza prywatnego. Ten podpis jest następnie dołączany do danych i wysyłany w wiadomości do adresata. Algorytm tworzenia skrótu, który został użyty do utworzenia podpisu, musi być wcześniej znany przez adresata lub zidentyfikowany w wiadomości. To, jak to zrobić, zależy od protokołu wiadomości.
Aby zweryfikować podpis, adresat wyodrębnia dane i podpis z wiadomości. Następnie adresat tworzy kolejną wartość skrótu na podstawie danych, odszyfrowuje podpisany skrót przy użyciu klucza publicznego nadawcy i porównuje dwie wartości skrótu. Jeśli wartości są identyczne, podpis został zweryfikowany i przyjmuje się, że dane są niezniszczone.
Aby utworzyć podpis przy użyciu CNG
- Utwórz wartość skrótu dla danych przy użyciu funkcji tworzenia skrótów CNG. Aby uzyskać więcej informacji na temat tworzenia skrótu, zobacz Tworzenie skrótu za pomocą technologii CNG.
- Utwórz klucz asymetryczny, aby podpisać skrót. Możesz utworzyć klucz trwały przy użyciu funkcji magazynowania kluczy CNG lub klucz efemeryczny za pomocą kryptograficznych funkcji pierwotnych CNG .
- Użyj funkcji NCryptSignHash lub BCryptSignHash, aby podpisać (szyfrować) wartość skrótu. Ta funkcja podpisuje wartość skrótu przy użyciu klucza asymetrycznego.
- Połącz dane i podpis w wiadomości, którą można wysłać do zamierzonego adresata.
Aby zweryfikować podpis przy użyciu CNG
- Wyodrębnij dane i podpis z wiadomości.
- Utwórz wartość skrótu dla danych przy użyciu funkcji tworzenia skrótów CNG. Użyty algorytm tworzenia skrótu musi być tym samym algorytmem, który został użyty do podpisania skrótu.
- Uzyskaj publiczną część pary kluczy asymetrycznych, która została użyta do podpisania skrótu. Sposób uzyskiwania tego klucza zależy od sposobu tworzenia i utrwalania klucza. Jeśli klucz został utworzony lub załadowany przy użyciu funkcji magazynu kluczy CNG, użyjesz funkcji NCryptOpenKey do załadowania utrwalonego klucza. Jeśli klucz jest kluczem efemerycznym, konieczne byłoby zapisanie go w kluczowym obiekcie BLOB. Należy przekazać ten klucz BLOB do funkcji BCryptImportKeyPair lub NCryptImportKey.
- Przekaż nową wartość skrótu, podpis i uchwyt klucza do funkcji NCryptVerifySignature lub funkcji BCryptVerifySignature. Te funkcje przeprowadzają weryfikację przy użyciu klucza publicznego do odszyfrowania podpisu i porównywania odszyfrowanego skrótu do skrótu obliczonego w kroku 2. Funkcja BCryptVerifySignature zwróci STATUS_SUCCESS, jeśli podpis pasuje do skrótu lub STATUS_INVALID_SIGNATURE, jeśli sygnatura nie jest zgodna z skrótem. Funkcja NCryptVerifySignature zwróci STATUS_SUCCESS, jeśli podpis pasuje do skrótu lub NTE_BAD_SIGNATURE, jeśli sygnatura nie jest zgodna z skrótem.
Przykład podpisywania i weryfikowania danych
W poniższym przykładzie pokazano, jak używać kryptograficznych interfejsów API pierwotnych do podpisywania danych przy użyciu utrwalonego klucza i weryfikowania podpisu przy użyciu klucza efemerycznego.
// 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 ECDSA 256 signing using CNG
Example for use of BCrypt/NCrypt API
Persisted key for signing and ephemeral key for verification
--*/
#include <windows.h>
#include <stdio.h>
#include <bcrypt.h>
#include <ncrypt.h>
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L)
static const BYTE rgbMsg[] =
{
0x04, 0x87, 0xec, 0x66, 0xa8, 0xbf, 0x17, 0xa6,
0xe3, 0x62, 0x6f, 0x1a, 0x55, 0xe2, 0xaf, 0x5e,
0xbc, 0x54, 0xa4, 0xdc, 0x68, 0x19, 0x3e, 0x94,
};
void __cdecl wmain(
int argc,
__in_ecount(argc) LPWSTR *wargv)
{
NCRYPT_PROV_HANDLE hProv = NULL;
NCRYPT_KEY_HANDLE hKey = NULL;
BCRYPT_KEY_HANDLE hTmpKey = NULL;
SECURITY_STATUS secStatus = ERROR_SUCCESS;
BCRYPT_ALG_HANDLE hHashAlg = NULL,
hSignAlg = NULL;
BCRYPT_HASH_HANDLE hHash = NULL;
NTSTATUS status = STATUS_UNSUCCESSFUL;
DWORD cbData = 0,
cbHash = 0,
cbBlob = 0,
cbSignature = 0,
cbHashObject = 0;
PBYTE pbHashObject = NULL;
PBYTE pbHash = NULL,
pbBlob = NULL,
pbSignature = NULL;
UNREFERENCED_PARAMETER(argc);
UNREFERENCED_PARAMETER(wargv);
//open an algorithm handle
if(!NT_SUCCESS(status = BCryptOpenAlgorithmProvider(
&hHashAlg,
BCRYPT_SHA1_ALGORITHM,
NULL,
0)))
{
wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status);
goto Cleanup;
}
if(!NT_SUCCESS(status = BCryptOpenAlgorithmProvider(
&hSignAlg,
BCRYPT_ECDSA_P256_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(
hHashAlg,
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(
hHashAlg,
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(
hHashAlg,
&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;
}
//open handle to KSP
if(FAILED(secStatus = NCryptOpenStorageProvider(
&hProv,
MS_KEY_STORAGE_PROVIDER,
0)))
{
wprintf(L"**** Error 0x%x returned by NCryptOpenStorageProvider\n", secStatus);
goto Cleanup;
}
//create a persisted key
if(FAILED(secStatus = NCryptCreatePersistedKey(
hProv,
&hKey,
NCRYPT_ECDSA_P256_ALGORITHM,
L"my ecc key",
0,
0)))
{
wprintf(L"**** Error 0x%x returned by NCryptCreatePersistedKey\n", secStatus);
goto Cleanup;
}
//create key on disk
if(FAILED(secStatus = NCryptFinalizeKey(hKey, 0)))
{
wprintf(L"**** Error 0x%x returned by NCryptFinalizeKey\n", secStatus);
goto Cleanup;
}
//sign the hash
if(FAILED(secStatus = NCryptSignHash(
hKey,
NULL,
pbHash,
cbHash,
NULL,
0,
&cbSignature,
0)))
{
wprintf(L"**** Error 0x%x returned by NCryptSignHash\n", secStatus);
goto Cleanup;
}
//allocate the signature buffer
pbSignature = (PBYTE)HeapAlloc (GetProcessHeap (), 0, cbSignature);
if(NULL == pbSignature)
{
wprintf(L"**** memory allocation failed\n");
goto Cleanup;
}
if(FAILED(secStatus = NCryptSignHash(
hKey,
NULL,
pbHash,
cbHash,
pbSignature,
cbSignature,
&cbSignature,
0)))
{
wprintf(L"**** Error 0x%x returned by NCryptSignHash\n", secStatus);
goto Cleanup;
}
if(FAILED(secStatus = NCryptExportKey(
hKey,
NULL,
BCRYPT_ECCPUBLIC_BLOB,
NULL,
NULL,
0,
&cbBlob,
0)))
{
wprintf(L"**** Error 0x%x returned by NCryptExportKey\n", secStatus);
goto Cleanup;
}
pbBlob = (PBYTE)HeapAlloc (GetProcessHeap (), 0, cbBlob);
if(NULL == pbBlob)
{
wprintf(L"**** memory allocation failed\n");
goto Cleanup;
}
if(FAILED(secStatus = NCryptExportKey(
hKey,
NULL,
BCRYPT_ECCPUBLIC_BLOB,
NULL,
pbBlob,
cbBlob,
&cbBlob,
0)))
{
wprintf(L"**** Error 0x%x returned by NCryptExportKey\n", secStatus);
goto Cleanup;
}
if(!NT_SUCCESS(status = BCryptImportKeyPair(
hSignAlg,
NULL,
BCRYPT_ECCPUBLIC_BLOB,
&hTmpKey,
pbBlob,
cbBlob,
0)))
{
wprintf(L"**** Error 0x%x returned by BCryptImportKeyPair\n", status);
goto Cleanup;
}
if(!NT_SUCCESS(status = BCryptVerifySignature(
hTmpKey,
NULL,
pbHash,
cbHash,
pbSignature,
cbSignature,
0)))
{
wprintf(L"**** Error 0x%x returned by BCryptVerifySignature\n", status);
goto Cleanup;
}
wprintf(L"Success!\n");
Cleanup:
if(hHashAlg)
{
BCryptCloseAlgorithmProvider(hHashAlg,0);
}
if(hSignAlg)
{
BCryptCloseAlgorithmProvider(hSignAlg,0);
}
if (hHash)
{
BCryptDestroyHash(hHash);
}
if(pbHashObject)
{
HeapFree(GetProcessHeap(), 0, pbHashObject);
}
if(pbHash)
{
HeapFree(GetProcessHeap(), 0, pbHash);
}
if(pbSignature)
{
HeapFree(GetProcessHeap(), 0, pbSignature);
}
if(pbBlob)
{
HeapFree(GetProcessHeap(), 0, pbBlob);
}
if (hTmpKey)
{
BCryptDestroyKey(hTmpKey);
}
if (hKey)
{
NCryptDeleteKey(hKey, 0);
}
if (hProv)
{
NCryptFreeObject(hProv);
}
}