c++ - Can Microsoft Cryptographic API allow creation of ECDSA keys from a stream of bytes? -
so pondering cryptographic c++ library use (i figured out how equivalent in c#) verification of licence file signed hash.
reading microsoft documentation cng seems not possible generate ecdsa key in code stream of bytes despite being possible rsa key (i think, not 100% sure).
because wanted in code byte stream generation, looked @ crypto++ , managed test suite compiled cryptolib.lib outsize 90 megabytes , facing slew of link errors trying basic. less keen in crypto++ now.
so want turn using shipped microsoft in desktop windows os original problem of no in code bytestream generated keys.
can expert confirm isn't possible? also, can suggest alternative, happy fall rsa long (2048?) key.
the following code compiles , runs me. can found @ msdn article - signing data cng. wondering if adapted. code (a) create ecdsa key on fly (b) sign hash (c) save key certificate store (d) retrieve key , verify signed hash. if guess it's demo code. need example of hard coded ecdsa key not 1 created on fly.
// cngecdsa.cpp : defines entry point console application. // based on https://msdn.microsoft.com/en-us/library/windows/desktop/aa376304(v=vs.85).aspx #include "stdafx.h" #include <windows.h> #include <stdint.h> #include <bcrypt.h> #include <ncrypt.h> #pragma comment(lib, "bcrypt") #pragma comment(lib, "ncrypt") #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, }; byte value[] = { 0x02,0x00,0x00,0x00 }; 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 algorithm handle if (!nt_success(status = bcryptopenalgorithmprovider( &hhashalg, bcrypt_sha1_algorithm, null, 0))) { wprintf(l"**** error 0x%x returned bcryptopenalgorithmprovider\n", status); goto cleanup; } if (!nt_success(status = bcryptopenalgorithmprovider( &hsignalg, bcrypt_ecdsa_p256_algorithm, null, 0))) { wprintf(l"**** error 0x%x returned bcryptopenalgorithmprovider\n", status); goto cleanup; } //calculate size of buffer hold hash object if (!nt_success(status = bcryptgetproperty( hhashalg, bcrypt_object_length, (pbyte)&cbhashobject, sizeof(dword), &cbdata, 0))) { wprintf(l"**** error 0x%x returned bcryptgetproperty\n", status); goto cleanup; } //allocate hash object on heap pbhashobject = (pbyte)heapalloc(getprocessheap(), 0, cbhashobject); if (null == pbhashobject) { wprintf(l"**** memory allocation failed\n"); goto cleanup; } //calculate length of hash if (!nt_success(status = bcryptgetproperty( hhashalg, bcrypt_hash_length, (pbyte)&cbhash, sizeof(dword), &cbdata, 0))) { wprintf(l"**** error 0x%x returned bcryptgetproperty\n", status); goto cleanup; } //allocate hash buffer on heap pbhash = (pbyte)heapalloc(getprocessheap(), 0, cbhash); if (null == pbhash) { wprintf(l"**** memory allocation failed\n"); goto cleanup; } //create hash if (!nt_success(status = bcryptcreatehash( hhashalg, &hhash, pbhashobject, cbhashobject, null, 0, 0))) { wprintf(l"**** error 0x%x returned bcryptcreatehash\n", status); goto cleanup; } //hash data if (!nt_success(status = bcrypthashdata( hhash, (pbyte)rgbmsg, sizeof(rgbmsg), 0))) { wprintf(l"**** error 0x%x returned bcrypthashdata\n", status); goto cleanup; } //close hash if (!nt_success(status = bcryptfinishhash( hhash, pbhash, cbhash, 0))) { wprintf(l"**** error 0x%x returned bcryptfinishhash\n", status); goto cleanup; } //open handle ksp if (failed(secstatus = ncryptopenstorageprovider( &hprov, ms_key_storage_provider, 0))) { wprintf(l"**** error 0x%x returned ncryptopenstorageprovider\n", secstatus); goto cleanup; } //create persisted key if (failed(secstatus = ncryptcreatepersistedkey( hprov, &hkey, ncrypt_ecdsa_p256_algorithm, l"my ecc key", 0, 0))) { wprintf(l"**** error 0x%x returned ncryptcreatepersistedkey\n", secstatus); goto cleanup; } //create key on disk if (failed(secstatus = ncryptfinalizekey(hkey, 0))) { wprintf(l"**** error 0x%x returned ncryptfinalizekey\n", secstatus); goto cleanup; } //sign hash if (failed(secstatus = ncryptsignhash( hkey, null, pbhash, cbhash, null, 0, &cbsignature, 0))) { wprintf(l"**** error 0x%x returned ncryptsignhash\n", secstatus); goto cleanup; } //allocate 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 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 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 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 bcryptimportkeypair\n", status); goto cleanup; } if (!nt_success(status = bcryptverifysignature( htmpkey, null, pbhash, cbhash, pbsignature, cbsignature, 0))) { wprintf(l"**** error 0x%x returned 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); } } just clear, aiming @ 384 bit , compatibility openssl , c# curvename nist recommended curve secp384r1 – {1.3.132.0.34} , using sha256 hash twice (just bitcoin).
does code (a) create ecdsa key on fly (b) sign hash (c) save key certificate store (d) retrieve key , verify signed hash. if guess it's demo code.
a) yes.
b) yes.
c) yes. saves key persisted object named "my ec key". since never asked name again, nullptr/null have been passed make ephemeral key. (and saved "key store", not "certificate store".
d) yes verify, no retrieve.
getting publickey data (this output of openssl ec -in eckey.pem -pubout -outform der | xxd -g1 translated c array) , signature (in ieee p1363 format) exercise left reader.
static const byte data[] = { '1', '2', '3', '4', }; static const byte publickey[] = { 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x23, 0x63, 0xdd, 0x13, 0x1d, 0xa6, 0x5e, 0x89, 0x9a, 0x2e, 0x63, 0xe9, 0xe0, 0x5e, 0x50, 0xc8, 0x30, 0xd4, 0x99, 0x46, 0x62, 0xff, 0xe8, 0x83, 0xdb, 0x2b, 0x9a, 0x76, 0x7d, 0xcc, 0xab, 0xa2, 0xf0, 0x70, 0x81, 0xb5, 0x71, 0x1b, 0xe1, 0xde, 0xe9, 0x0d, 0xfc, 0x8d, 0xe1, 0x79, 0x70, 0xc2, 0xd9, 0x37, 0xa1, 0x6c, 0xd3, 0x45, 0x81, 0xf5, 0x2b, 0x8d, 0x59, 0xc9, 0xe9, 0x53, 0x2d, 0x13, }; static const byte signature[] = { // r 0xc6, 0x4c, 0x14, 0x55, 0xfe, 0xc0, 0x2f, 0xe7, 0x4a, 0x25, 0x87, 0xe7, 0x0c, 0x10, 0x4e, 0x73, 0xf0, 0x28, 0x86, 0x18, 0x28, 0xae, 0xef, 0x4f, 0xe5, 0xa0, 0xcc, 0x7a, 0xa8, 0xe4, 0x1f, 0xbf, // s 0x35, 0x9f, 0x23, 0xfd, 0xc3, 0xd6, 0x33, 0xfb, 0x52, 0x47, 0x9b, 0xef, 0x2b, 0x2a, 0x48, 0xa8, 0x6f, 0x37, 0x04, 0xd0, 0x8c, 0xc3, 0x49, 0x04, 0x21, 0x53, 0xb8, 0x3c, 0x9d, 0x8c, 0x6c, 0xf5, }; #define nt_success(status) (((ntstatus)(status)) >= 0) int main() { ntstatus status = nte_bad_data; int exitcode = error_invalid_function; bcrypt_key_handle importedpublickey = nullptr; pcert_public_key_info subjectpublickeyinfo = (pcert_public_key_info)localalloc(0, 2048); bcrypt_alg_handle sha256 = nullptr; bcrypt_hash_handle hhash = nullptr; byte datahash[256 >> 3]; dword structsize = 2048; if (!cryptdecodeobject( x509_asn_encoding, x509_public_key_info, publickey, sizeof(publickey), 0, subjectpublickeyinfo, &structsize)) { wprintf(l"**** error 0x%x returned cryptdecodeobject\n", getlasterror()); goto cleanup; } if (!cryptimportpublickeyinfoex2( x509_asn_encoding, subjectpublickeyinfo, 0, nullptr, &importedpublickey)) { wprintf(l"**** error 0x%x returned cryptimportpublickeyinfoex2\n", getlasterror()); goto cleanup; } if (!nt_success(status = bcryptopenalgorithmprovider(&sha256, bcrypt_sha256_algorithm, nullptr, 0))) { wprintf(l"**** error 0x%x returned bcryptopenalgorithmprovider\n", status); goto cleanup; } if (!nt_success(status = bcryptcreatehash(sha256, &hhash, nullptr, 0, nullptr, 0, 0))) { wprintf(l"**** error 0x%x returned bcryptcreatehash\n", status); goto cleanup; } if (!nt_success(status = bcrypthashdata(hhash, (puchar)data, sizeof(data), 0))) { wprintf(l"**** error 0x%x returned bcrypthashdata\n", status); goto cleanup; } if (!nt_success(status = bcryptfinishhash(hhash, (puchar)datahash, sizeof(datahash), 0))) { wprintf(l"**** error 0x%x returned bcryptfinishhash\n", status); goto cleanup; } status = bcryptverifysignature( importedpublickey, nullptr, (puchar)datahash, sizeof(datahash), (puchar)signature, sizeof(signature), 0); switch (status) { case status_success: wprintf(l"signature verified successfully\n"); exitcode = error_success; break; case status_invalid_signature: wprintf(l"signature did not verify\n"); exitcode = error_invalid_data; break; default: wprintf(l"**** error 0x%x returned bcryptverifysignature\n", status); goto cleanup; } cleanup: if (hhash != nullptr) bcryptdestroyhash(hhash); if (sha256 != nullptr) bcryptclosealgorithmprovider(sha256, 0); if (importedpublickey != nullptr) bcryptdestroykey(importedpublickey); localfree(subjectpublickeyinfo); return exitcode; }
Comments
Post a Comment