Skip to content

Instantly share code, notes, and snippets.

Created February 24, 2018 20:41
Show Gist options
  • Save anonymous/8a3338614e5218a8832a0ef840d56330 to your computer and use it in GitHub Desktop.
Save anonymous/8a3338614e5218a8832a0ef840d56330 to your computer and use it in GitHub Desktop.
#define _CRT_SECURE_NO_WARNINGS
#include "stdafx.h"
#include <stdio.h>
#include <windows.h>
#include <wincrypt.h>
#include <iostream>
#include <fstream>
#pragma comment(lib,"Crypt32.lib")
using namespace std;
#define MY_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
// credentials
#define CERT_STORE_NAME L"VeeSecurity"
#define SIGNER_NAME L"tehcpu"
HCRYPTPROV hProv = 0; // crypt provider
HCERTSTORE hStore = 0; // cert store
PCCERT_CONTEXT certificate = 0; // cert
HCRYPTKEY privateKey = 0;
HCRYPTKEY publicKey = 0;
HCRYPTHASH hashHandle = 0; // hash handle
bool providerConnect(); // Connecting to the provider
bool getHash(FILE * file); //Getting the hash of file
DWORD fileSize(FILE * file); // Get size of file
bool getCertContext(); // get context of cert
bool getPublicKey(); //dont understand?
bool getPrivateKey(); //dont understand?
bool getSignature(BYTE *& outSignature, DWORD * signLen); // get digest of hash
bool testSignature(BYTE* sign_hash, DWORD signLen); // match decrypt signature (in sign_hash) and hash (init in HCRYPTHASH hashHandle)
//P.S. FUNCTIONS WORKS WITH GLOBAL VARAIBLES, SO INPUT ARG DONT NEED
int main()
{
FILE* in = fopen("C:\\lab1\\source.txt", "rb");
FILE* signature = fopen("C:\\lab1\\signature.txt", "wb");
DWORD digestLen;
BYTE* outSignature;
if (!providerConnect()) { // get provider
getchar();
return -1;
}
if (!getCertContext()) { // get cert context
getchar();
return -1;
}
if (!getPublicKey()) { //get pubKey
getchar();
return -1;
}
if (!getPrivateKey()) { //get privKey
getchar();
return -1;
}
if (!getHash(in)) { //get hash of original file
getchar();
return -1;
}
if (!getSignature(outSignature, &digestLen)) { //get digest
getchar();
return -1;
}
if (fwrite(outSignature, sizeof(BYTE), digestLen, signature) < 1){ // try write digest to the file
puts("[ERROR]: cant write signature to file! \n");
getchar();
return -1;
} else {
puts("[OK]: signature was writen into the file! \n");
}
if (testSignature(outSignature, digestLen)) {
getchar();
return -1;
}
getchar();
}
bool providerConnect(){ // Connecting to the provider
if (CryptAcquireContext(
&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0))
{
printf("[OK]: a cryptographic context with the key container has been acquired.\n\n");
return true;
}
else
{
if (GetLastError() == NTE_BAD_KEYSET) // check existence of container with such name ..
{
if (CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0)) // create new one (if not exist)
{
printf("[NOTICE]: a new key container has been created (you may need to restart the application).\n");
return true;
}
else
{
printf("[ERROR]: could not create a new key container.\n");
return false;
}
}
else
{
printf("[ERROR]: a cryptographic service handle could not be acquired.\n");
return false;
}
}
}
bool getHash(FILE * file){ //Getting the hash of file
DWORD dwLen;
DWORD fSize = fileSize(file);
if (!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hashHandle))
{
puts("[ERROR]: Error with CryptCreateHash");
return false;
}
BYTE* read = new BYTE[fSize + 8];
dwLen = fread(read, sizeof(BYTE), fSize, file);
if (dwLen < 1)
{
puts("[ERROR]: Error reading file\n");
return false;
}
if (!CryptHashData(hashHandle, read, dwLen, 0))
{
puts("[ERROR]: Error with CryptHashData");
return false;
}
cout <<"[OK]: Hash data loaded" << std::endl;
DWORD count = 0;
if (!CryptGetHashParam(hashHandle, HP_HASHVAL, NULL, &count, 0))
{
puts("[ERROR]: CryptGetHashParam");
return false;
}
//char* hash_value = static_cast<char*>(malloc(count + 1));
BYTE* hash_value = new BYTE[count + 1];
ZeroMemory(hash_value, count + 1);
if (!CryptGetHashParam(hashHandle, HP_HASHVAL, hash_value, &count, 0))
{
puts("[ERROR]: CryptGetHashParam");
return false;
}
cout << "[OK]: Hash value is received" << endl;
return true;
}
DWORD fileSize(FILE * file){
fseek(file, 0, SEEK_END); // to END
DWORD lSize = ftell(file);
rewind(file); // to BEGIN
return lSize;
}
bool getCertContext(){
if (!(hStore = CertOpenStore(
CERT_STORE_PROV_SYSTEM,
0,
NULL,
CERT_SYSTEM_STORE_CURRENT_USER,
CERT_STORE_NAME)))
{
printf("[ERROR]: can't open the store with such name.\n");
return false;
}
// get certificate's pointer
if (certificate = CertFindCertificateInStore(
hStore,
MY_TYPE,
0,
CERT_FIND_SUBJECT_STR,
SIGNER_NAME,
NULL))
{
printf("[OK]: certificate find success.\n");
return true;
}
else
{
printf("[ERROR]: certificate find failure.\n");
return false;
}
}
bool getPublicKey(){
if (CryptImportPublicKeyInfo(
hProv,
MY_TYPE,
&(certificate->pCertInfo->SubjectPublicKeyInfo),
&publicKey))
{
printf("[OK]: public key was successfully imported.\n");
return true;
}
else
{
printf("[ERROR]: public key import failure.\n");
return false;
}
}
bool getPrivateKey(){
DWORD keySpec = 0;
if (!CryptAcquireCertificatePrivateKey(certificate, 0, 0, &hProv, &keySpec, 0))
{
printf("[ERROR]: error getting private context\n");
return false;
}
// get private key from private context
if (!CryptGetUserKey(hProv, keySpec, &privateKey))
{
printf("[ERROR]: error getting private key\n");
return false;
}
printf("[OK]: private key was successfully imported.\n");
return true;
}
bool getSignature(BYTE *& outSignature, DWORD * signLen){ // get digest of hash
DWORD count = 0;
if (!CryptSignHash(hashHandle, 1, NULL, 0, NULL, &count))
{
printf("[ERROR]: error CryptSignHash\n");
return false;
}
BYTE* sign_hash = new BYTE[count + 1];
ZeroMemory(sign_hash, count + 1);
if (!CryptSignHashW(hashHandle, 1, NULL, 0, sign_hash,
&count))
{
printf("[ERROR]: error CryptSignHash\n");
return false;
}
cout << "[OK]: Signature created" << std::endl;
outSignature = sign_hash;
*signLen = count + 1;
return true;
}
bool testSignature(BYTE* sign_hash, DWORD signLen) {
DWORD count = signLen - 1; //because getSignature return count+1
if (!CryptGetUserKey(hProv, 1, &publicKey))
{
puts("[ERROR]: CryptGetUserKey");
return false;
}
puts("[OK]: Public key is received \n");
BOOL result = CryptVerifySignatureW(hashHandle, sign_hash, count, publicKey, NULL, 0);
puts("[OK]: Check is completed \n");
if (result)
puts("[OK]: Verified!\n");
else
puts("[OK]: TOTAL FAIL!!! \n");
CryptReleaseContext(hProv, 0);
return true;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment