+7(960) 250-82-68 sergey@mirossa.ru


button
button
button
button
button


 
Статьи
 
mingw-w64
#include <windows.h>
#include <stdio.h>
#include <bcrypt.h>
#include <ncrypt.h>

//CMD.exe
//cd "C:\Program Files (x86)\mingw-w64\i686-8.1.0-win32-dwarf-rt_v6-rev0\mingw32\bin"
// i686-w64-mingw32-gcc.exe -I"C:\Program Files (x86)\Windows Kits\8.0\Cryptographic Provider Development Kit\Include" test_crypt.c -L"C:\Program Files (x86)\Windows Kits\8.0\Cryptographic Provider Development Kit\Lib\win8\x64" -lbcrypt_provider -lcng_provider -lncrypt_provider -o test_crypt.exe // -mwindows
// !!! i686-w64-mingw32-gcc.exe -I"C:\Program Files (x86)\Windows Kits\8.0\Cryptographic Provider Development Kit\Include" test_crypt.c -L"C:\Program Files (x86)\Windows Kits\8.0\Cryptographic Provider Development Kit\Lib\win8\x86" -lbcrypt_provider -lcng_provider -lncrypt_provider -o test_crypt.exe // -mwindows


//https://docs.microsoft.com/en-us/windows/desktop/seccng/cng-portal
//https://docs.microsoft.com/en-us/windows/desktop/seccng/encrypting-data-with-cng
//https://docs.microsoft.com/en-us/windows/desktop/seccng/signing-data-with-cng

// What is the difference between encrypting and signing in asymmetric encryption?
// When encrypting, you use their public key to write message and they use their private key to read it.
// When signing, you use your private key to write message's signature, and they use your public key to check if it's really yours.

//If you are developing a CNG cryptographic algorithm provider or key storage provider, you must download the Cryptographic Provider Development Kit (or here )from Microsoft.

//HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Defaults\Provider

// https://xakep.ru/2008/03/06/42665/

// ----------------------------------
// CNG Token Binding Functions (https://docs.microsoft.com/ru-ru/windows/desktop/SecCNG/cng-token-binding-functions)
// Cryptography API: Next Generation (CNG) defines the following functions which are used to perform CNG Token Binding operations.

// TokenBindingDeleteBinding
// TokenBindingGenerateBinding
// TokenBindingGenerateMessage
// TokenBindingGetKeyTypesClient
// TokenBindingGetKeyTypesServer
// TokenBindingVerifyMessage
// Эти функции находятся в Windows 10 SDK в tokenbinding.h и Tokenbinding.lib.
// Архив Windows SDK и эмуляторов
// ----------------------------------

#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L)

// void __cdecl wmain(
// int argc,
// __in_ecount(argc) LPWSTR *wargv)
// {

int main()
{
SetConsoleCP(1251); // На ввод
SetConsoleOutputCP(1251); //На вывод.

wprintf(L"ok\n");

// 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;

NCRYPT_PROV_HANDLE hProv;
PUCHAR rgbMsg;
NCRYPT_KEY_HANDLE hKey;

// 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;
}

//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);
}

return 0;


}

to be continued...