Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / security / cryptography

cngsha3: A Cryptography Next Generation Implementation of Newer Algorithms

4.68/5 (7 votes)
14 Aug 2023CPOL2 min read 16.2K  
Use SHA-3 and the CRYSTALS Kyber, Dilithium and Sphincs in Win32 projects
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:

C++
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

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)