Created
February 24, 2018 20:41
-
-
Save anonymous/8a3338614e5218a8832a0ef840d56330 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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