Skip to content

Instantly share code, notes, and snippets.

@tuxuser
Last active February 1, 2019 01:46
Show Gist options
  • Save tuxuser/d2bb11378b2b27a5a95d148ca48f3c8a to your computer and use it in GitHub Desktop.
Save tuxuser/d2bb11378b2b27a5a95d148ca48f3c8a to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <windows.h>
#include <bcrypt.h>
#define NT_SUCCESS(x) (x == 0)
#define STATUS_SUCCESS ((NTSTATUS)0)
#define STATUS_ERROR ((NTSTATUS)1)
NTSTATUS SaveFile(PUCHAR dataBlob, ULONG dataSz, LPCWSTR filePath)
{
BOOL bErrorFlag = FALSE;
DWORD dwBytesWritten = 0;
HANDLE hFile = NULL;
hFile = CreateFileW(filePath,
GENERIC_WRITE,
0,
NULL, // default security
CREATE_NEW, // create new file only
FILE_ATTRIBUTE_NORMAL, // normal file
NULL); // no attr. template
if (hFile == INVALID_HANDLE_VALUE)
{
printf(":: ERROR :: UNABLE TO OPEN FiLE \"%ls\" FOR WRITE\n", filePath);
return STATUS_ERROR;
}
printf(":: WRiTiNG %u BYTES TO %ls\n", dataSz, filePath);
bErrorFlag = WriteFile(
hFile, // open file handle
dataBlob, // start of data to write
dataSz, // number of bytes to write
&dwBytesWritten, // number of bytes that were written
NULL); // no overlapped structure
if (FALSE == bErrorFlag)
{
printf(":: ERROR :: ERROR WRiTiNG FiLE \"%ls\"\n", filePath);
return STATUS_ERROR;
}
else if (dwBytesWritten != dataSz)
{
// This is an error because a synchronous write that results in
// success (WriteFile returns TRUE) should write all data as
// requested. This would not necessarily be the case for
// asynchronous writes.
printf(":: ERROR :: dwBytesWritten != dwBytesToWrite \"%ls\"\n", filePath);
return STATUS_ERROR;
}
printf(":: WROTE %u BYTES SUCCESSFULLY\n", dataSz);
CloseHandle(hFile);
return STATUS_SUCCESS;
}
NTSTATUS ExportRsaKey(BCRYPT_KEY_HANDLE hKey, LPCWSTR pszBlobType)
{
NTSTATUS ret = 0;
ULONG resultLength = 0;
ULONG requiredSize = 0;
ULONG writtenSize = 0;
DWORD keyStrength = 0;
ret = BCryptGetProperty(hKey, BCRYPT_KEY_STRENGTH, (PBYTE)&keyStrength, sizeof(keyStrength), &resultLength, 0);
if (!NT_SUCCESS(ret))
{
printf(":: ERROR :: FAiLED TO GET KEYSTRENGTH :: CODE :: %u\n", GetLastError());
return ret;
}
ret = BCryptExportKey(hKey, NULL, pszBlobType, NULL, 0, &requiredSize, 0);
if (!NT_SUCCESS(ret))
{
printf(":: ERROR :: FAiLED TO GET KEYSiZE :: CODE :: %u\n", GetLastError());
return ret;
}
PUCHAR pKeyBlob = (PUCHAR)malloc(requiredSize);
ret = BCryptExportKey(hKey, NULL, pszBlobType, pKeyBlob, requiredSize, &writtenSize, 0);
if (!NT_SUCCESS(ret))
{
printf(":: ERROR :: FAiLED TO EXPORT KEY :: CODE :: %u\n", GetLastError());
free(pKeyBlob);
return ret;
}
LPWSTR filePath = (LPWSTR)malloc(255);
wsprintfW(filePath, L"RSA_%u_%ls.bin", keyStrength, pszBlobType);
ret = SaveFile(pKeyBlob, writtenSize, filePath);
free(pKeyBlob);
if (!NT_SUCCESS(ret))
{
printf(":: ERROR :: FAiLED TO SAVE KEY :: CODE :: %u\n", GetLastError());
return ret;
}
return STATUS_SUCCESS;
}
NTSTATUS ExportRsaKeys(BCRYPT_KEY_HANDLE hKey)
{
NTSTATUS ret = STATUS_SUCCESS;
ret = ExportRsaKey(hKey, BCRYPT_RSAPUBLIC_BLOB);
if (!NT_SUCCESS(ret)) return ret;
ExportRsaKey(hKey, BCRYPT_RSAPRIVATE_BLOB);
if (!NT_SUCCESS(ret)) return ret;
ExportRsaKey(hKey, BCRYPT_RSAFULLPRIVATE_BLOB);
if (!NT_SUCCESS(ret)) return ret;
ExportRsaKey(hKey, LEGACY_RSAPRIVATE_BLOB);
if (!NT_SUCCESS(ret)) return ret;
ExportRsaKey(hKey, LEGACY_RSAPUBLIC_BLOB);
if (!NT_SUCCESS(ret)) return ret;
return STATUS_SUCCESS;
}
NTSTATUS ExportRsaKeyInfo(BCRYPT_KEY_HANDLE hKey)
{
return STATUS_SUCCESS;
}
NTSTATUS GenerateRsaKey(int bitLength)
{
NTSTATUS ret = 0;
BCRYPT_ALG_HANDLE hProvider = NULL;
BCRYPT_KEY_HANDLE hKey = NULL;
printf(":: OPENiNG ALGORiTHM PROViDER\n");
ret = BCryptOpenAlgorithmProvider(&hProvider, BCRYPT_RSA_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0);
if (!NT_SUCCESS(ret))
{
printf(":: ERROR :: FAiLED TO OPEN RSA PROViDER :: Code: %u\n", GetLastError());
return ret;
}
printf(":: GENERATiNG KEYPAiR\n");
ret = BCryptGenerateKeyPair(hProvider, &hKey, bitLength, 0);
if (!NT_SUCCESS(ret))
{
printf(":: ERROR :: FAiLED TO GENERATE KEYPAiR :: Code: %u\n", GetLastError());
return ret;
}
/*
ret = BCryptSetProperty(hKey, BCRYPT_PADDING_SCHEMES, BCRYPT_SUPPORTED_PAD_PSS, 1, 0);
if (!NT_SUCCESS(ret))
{
printf(":: ERROR :: FAiLED TO SET PADDiNG SCHEME :: CODE: %u\n", GetLastError());
return ret;
}
*/
printf(":: FiNALiZING KEYPAiR\n");
ret = BCryptFinalizeKeyPair(hKey, 0);
if (!NT_SUCCESS(ret))
{
printf(":: ERROR :: FAiLED to FiNALiZE KEYPAiR :: Code: %u\n", GetLastError());
return ret;
}
ret = ExportRsaKeys(hKey);
if (!NT_SUCCESS(ret))
{
printf(":: ERROR :: FAiLED to EXPORT RSA KEYS :: Code: %u\n", GetLastError());
return ret;
}
ret = ExportRsaKeyInfo(hKey);
if (!NT_SUCCESS(ret))
{
printf(":: ERROR :: FAiLED to EXPORT RSA KEY INFO :: Code: %u\n", GetLastError());
return ret;
}
printf(":: CLEANUP");
ret = BCryptDestroyKey(hKey);
if (!NT_SUCCESS(ret))
{
printf(":: ERROR :: CLEANUP FAiLED :: DESTROYiNG KEY :: Code: %u\n", GetLastError());
return ret;
}
ret = BCryptCloseAlgorithmProvider(hProvider, 0);
if (!NT_SUCCESS(ret))
{
printf(":: ERROR :: CLEANUP FAiLED :: DESTROYiNG PROViDER :: Code: %u\n", GetLastError());
return ret;
}
return STATUS_SUCCESS;
}
int main()
{
GenerateRsaKey(512);
GenerateRsaKey(1024);
GenerateRsaKey(2048);
GenerateRsaKey(3072);
GenerateRsaKey(4096);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment