In this article, you will see how to use the CNG API with the newer functions in an abstract way.
Introduction
While SHA-3 has long been released, Windows CNG API doesn't yet support it. Here's a DLL that you can install into your system so SHA-3 family is fully supported by any application that uses CNG, including CMS.
In addition, the new CRYSTAL algorithms that are supposedly resistant to quantum-computer break attempts have been released. Here they are:
- CRYSTALS-Kyber, a Public/Private key encryption/decryption algorithm. Implementation here. 512,768,1024 bit implementations.
- CRYSTALS-Dilithium, a Public/Private sign/verify algorithm. Implementation here. In three versions (2,3 and 5).
- CRYSTALS-Sphincs, a Public/Private sign/verify algorithm. Implementation here.
Background
Microsoft has released a CNG SDK here. This SDK allows a developer to create user-mode DLL extensions for the CNG, including custom hash providers.
Registration of this DLL includes calling functions from this SDK and putting the DLL into the system32 directory (else it won't work). The DLL provides placeholders for the functions that are routed to from the user calls of BCryptCreateHash()
, BCryptHashData()
, etc.
I used librhash for the SHA-3 implementation.
Building the Library
- Install the CNG SDK as mentioned above.
- Open the solution with Visual Studio.
- In both DLL and test project properties, set the C++
include
path to the above CNG SDK (mine is set at c:\Windows Kits\10\Cryptographic Provider Development Kit\include) - Build the project.
You are ready!
Installing the Library
The library includes a DllRegisterServer/DllUnregisterServer
set so you can use regsvr32
on it. It registers the following names:
inline const wchar_t* ProviderB = L"Michael Chourdakis CNG Implementations";
#define SHA3_224_ALGORITHM L"SHA3-224"
#define SHA3_256_ALGORITHM L"SHA3-256"
#define SHA3_384_ALGORITHM L"SHA3-384"
#define SHA3_512_ALGORITHM L"SHA3-512"
#define KYBER_512_ALGORITHM L"KYBER-512"
#define KYBER_768_ALGORITHM L"KYBER-768"
#define KYBER_1024_ALGORITHM L"KYBER-1024"
#define DILITHIUM_2_ALGORITHM L"DILITHIUM-2"
#define DILITHIUM_3_ALGORITHM L"DILITHIUM-3"
#define DILITHIUM_5_ALGORITHM L"DILITHIUM-5"
#define SPHINCS_ALGORITHM L"SPHINCS"
Using the Library
As in any other CNG hash function:
- Open the provider with
BCryptOpenAlgorithmProvider
with one of the above algorithms. - Create the hash with
BCryptCreateHash
. - Hash the data repeatedly with
BCryptHashData
. - Get the hash length with
BCryptGetProperty
. It will respectively return 24, 32, 48 or 64. - Get the hash by calling
BCryptFinishHash
. - You may reuse the handle with
BCryptHashData
.
To use the Public/Private encrypt/decrypt, you call BCryptEncrypt
and BCryptDecrypt
. Note that Kyber algorithms need 32-bytes of data to be encrypted/decrypted, so I use the hash.
To use the Public/Private sign/verify, you call BCryptSignHash
and BCryptVerifyHash
.
Test.cpp contains a simple demo of this.
History
- 14th August, 2023: Added new algorithms
- 11th January, 2023: First release