Skip to content

Instantly share code, notes, and snippets.

@siddontang
Last active December 18, 2015 13:48
Show Gist options
  • Save siddontang/5792247 to your computer and use it in GitHub Desktop.
Save siddontang/5792247 to your computer and use it in GitHub Desktop.
windows csp, rsa, certificate
#include "rsa.h"
#include <stdio.h>
#include <conio.h>
#include <windows.h>
#include <wincrypt.h>
#include "base64.h"
#pragma comment(lib, "crypt32.lib")
#define CERT_PERSONAL_STORE_NAME L"MY"
#define MY_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
void ReverseBuffer(char *buf, int len)
{
char temp;
for(int i = 0; i < len / 2; i++)
{
temp = buf[i];
buf[i] = buf[len- i - 1];
buf[len - i - 1] = temp;
}
}
int WINAPI rsa_sign(const wchar_t* subjectName, const char* srcData, int srcLen, char* destData, int* destLen)
{
HCERTSTORE hStoreHandle = NULL;
PCCERT_CONTEXT pSignerCert = NULL;
HCRYPTPROV hCryptProv = NULL;
DWORD dwKeySpec = 0;
HCRYPTHASH hHash = NULL;
BOOL bResult = FALSE;
BOOL bFreeKeyProv;
DWORD errCode = 0;
int i = 0;
// Open the certificate store.
hStoreHandle = CertOpenStore(
CERT_STORE_PROV_SYSTEM,
0,
NULL,
CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_READONLY_FLAG,
CERT_PERSONAL_STORE_NAME
);
if(!hStoreHandle)
{
//open store error
return GetLastError();
}
pSignerCert = CertFindCertificateInStore(
hStoreHandle,
MY_TYPE,
0,
CERT_FIND_SUBJECT_STR,
subjectName,
pSignerCert
);
if(!pSignerCert)
{
errCode = GetLastError();
//find singer cert error
CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG);
return errCode;
}
// Get the CSP, and check if we can sign with the private key
bResult = CryptAcquireCertificatePrivateKey(
pSignerCert,
0,
NULL,
&hCryptProv,
&dwKeySpec,
&bFreeKeyProv
);
if(!bResult)
{
errCode = GetLastError();
CertFreeCertificateContext(pSignerCert);
CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG);
return errCode;
}
// Create the hash object.
bResult = CryptCreateHash(
hCryptProv,
CALG_SHA1,
0,
0,
&hHash
);
if(!bResult)
{
errCode = GetLastError();
//create hash error
if(bFreeKeyProv)
{
CryptReleaseContext(hCryptProv, 0);
}
CertFreeCertificateContext(pSignerCert);
CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG);
return errCode;
}
bResult = CryptHashData(
hHash,
(const BYTE*)srcData,
srcLen,
0
);
if(!bResult)
{
errCode = GetLastError();
CryptDestroyHash(hHash);
if(bFreeKeyProv)
{
CryptReleaseContext(hCryptProv, 0);
}
CertFreeCertificateContext(pSignerCert);
CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG);
return errCode;
}
// Sign the hash object
bResult = CryptSignHash(
hHash,
dwKeySpec,
NULL,
0,
(BYTE*)destData,
(DWORD*)destLen
);
if(!bResult)
{
errCode = GetLastError();
CryptDestroyHash(hHash);
if(bFreeKeyProv)
{
CryptReleaseContext(hCryptProv, 0);
}
CertFreeCertificateContext(pSignerCert);
CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG);
return errCode;
}
ReverseBuffer(destData, *destLen);
CryptDestroyHash(hHash);
if(bFreeKeyProv)
{
CryptReleaseContext(hCryptProv, 0);
}
CertFreeCertificateContext(pSignerCert);
CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG);
return 0;
}
int WINAPI rsa_verify(const wchar_t* subjectName, const char* srcData, int srcLen, char* signData, int signLen)
{
HCERTSTORE hStoreHandle = NULL;
PCCERT_CONTEXT pSignerCert = NULL;
HCRYPTPROV hCryptProv = NULL;
HCRYPTHASH hHash = NULL;
BOOL bResult = FALSE;
HCRYPTKEY hPubKey = NULL;
char* signBuffer = NULL;
DWORD errCode;
hStoreHandle = CertOpenStore(
CERT_STORE_PROV_SYSTEM,
0,
NULL,
CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_READONLY_FLAG,
CERT_PERSONAL_STORE_NAME
);
if(!hStoreHandle)
{
errCode = GetLastError();
return errCode;
}
pSignerCert = CertFindCertificateInStore(
hStoreHandle,
MY_TYPE,
0,
CERT_FIND_SUBJECT_STR,
subjectName,
pSignerCert
);
if(!pSignerCert)
{
errCode = GetLastError();
CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG);
return errCode;
}
bResult = CryptAcquireContext(
&hCryptProv,
NULL,
NULL,
PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT
);
if(!bResult)
{
errCode = GetLastError();
CertFreeCertificateContext(pSignerCert);
CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG);
return errCode;
}
bResult = CryptCreateHash(
hCryptProv,
CALG_SHA1,
0,
0,
&hHash
);
if(!bResult)
{
errCode = GetLastError();
CryptReleaseContext(hCryptProv, 0);
CertFreeCertificateContext(pSignerCert);
CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG);
return errCode;
}
bResult = CryptHashData(
hHash,
(const BYTE*)srcData,
srcLen,
0
);
if(!bResult)
{
errCode = GetLastError();
CryptDestroyHash(hHash);
CryptReleaseContext(hCryptProv, 0);
CertFreeCertificateContext(pSignerCert);
CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG);
return errCode;
}
bResult = CryptImportPublicKeyInfo(
hCryptProv,
MY_TYPE,
&pSignerCert->pCertInfo->SubjectPublicKeyInfo,
&hPubKey
);
if(!bResult)
{
errCode = GetLastError();
CryptDestroyHash(hHash);
CryptReleaseContext(hCryptProv, 0);
CertFreeCertificateContext(pSignerCert);
CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG);
return errCode;
}
signBuffer = (char*)malloc(signLen);
memcpy(signBuffer, signData, signLen);
ReverseBuffer(signBuffer, signLen);
bResult = CryptVerifySignature(
hHash,
(const BYTE*)signBuffer,
signLen,
hPubKey,
NULL,
0
);
free(signBuffer);
if(!bResult)
{
errCode = GetLastError();
CryptDestroyHash(hHash);
CryptReleaseContext(hCryptProv, 0);
CertFreeCertificateContext(pSignerCert);
CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG);
return errCode;
}
CryptDestroyHash(hHash);
CryptReleaseContext(hCryptProv, 0);
CertFreeCertificateContext(pSignerCert);
CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG);
return 0;
}
int WINAPI rsa_encrypt(const wchar_t* subjectName, const char* srcData, int srcLen, char* destData, int* destLen)
{
HCERTSTORE hStoreHandle = NULL;
PCCERT_CONTEXT pSignerCert = NULL;
HCRYPTPROV hCryptProv = NULL;
HCRYPTHASH hHash = NULL;
BOOL bResult = FALSE;
HCRYPTKEY hCryptKey = NULL;
DWORD errCode;
hStoreHandle = CertOpenStore(
CERT_STORE_PROV_SYSTEM,
0,
NULL,
CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_READONLY_FLAG,
CERT_PERSONAL_STORE_NAME
);
if(!hStoreHandle)
{
errCode = GetLastError();
return errCode;
}
pSignerCert = CertFindCertificateInStore(
hStoreHandle,
MY_TYPE,
0,
CERT_FIND_SUBJECT_STR,
subjectName,
pSignerCert
);
if(!pSignerCert)
{
errCode = GetLastError();
CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG);
return errCode;
}
bResult = CryptAcquireContext(
&hCryptProv,
NULL,
NULL,
PROV_RSA_FULL,
0
);
if(!bResult)
{
errCode = GetLastError();
CertFreeCertificateContext(pSignerCert);
CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG);
return errCode;
}
bResult = CryptImportPublicKeyInfo(
hCryptProv,
MY_TYPE,
&pSignerCert->pCertInfo->SubjectPublicKeyInfo,
&hCryptKey
);
if(!bResult)
{
errCode = GetLastError();
CryptReleaseContext(hCryptProv, 0);
CertFreeCertificateContext(pSignerCert);
CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG);
return errCode;
}
memcpy(destData, srcData, srcLen);
*destLen = srcLen;
bResult = CryptEncrypt(hCryptKey, NULL, TRUE, 0, (BYTE*)destData, (DWORD*)destLen, 128);
if(!bResult)
{
errCode = GetLastError();
CryptDestroyKey(hCryptKey);
CryptReleaseContext(hCryptProv, 0);
CertFreeCertificateContext(pSignerCert);
CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG);
return errCode;
}
ReverseBuffer(destData, *destLen);
CryptDestroyKey(hCryptKey);
CryptReleaseContext(hCryptProv, 0);
CertFreeCertificateContext(pSignerCert);
CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG);
return 0;
}
int WINAPI rsa_decrypt(const wchar_t* subjectName, const char* srcData, int srcLen, char* destData, int* destLen)
{
HCERTSTORE hStoreHandle = NULL;
PCCERT_CONTEXT pSignerCert = NULL;
HCRYPTPROV hCryptProv = NULL;
HCRYPTHASH hHash = NULL;
BOOL bResult = FALSE;
HCRYPTKEY hCryptKey = NULL;
BOOL bFreeKeyProv;
DWORD dwKeySpec = 0;
DWORD errCode;
hStoreHandle = CertOpenStore(
CERT_STORE_PROV_SYSTEM,
0,
NULL,
CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_READONLY_FLAG,
CERT_PERSONAL_STORE_NAME
);
if(!hStoreHandle)
{
errCode = GetLastError();
return errCode;
}
pSignerCert = CertFindCertificateInStore(
hStoreHandle,
MY_TYPE,
0,
CERT_FIND_SUBJECT_STR,
subjectName,
pSignerCert
);
if(!pSignerCert)
{
errCode = GetLastError();
CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG);
return errCode;
}
bResult = CryptAcquireCertificatePrivateKey(
pSignerCert,
0,
NULL,
&hCryptProv,
&dwKeySpec,
&bFreeKeyProv
);
if(!bResult)
{
errCode = GetLastError();
CertFreeCertificateContext(pSignerCert);
CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG);
return errCode;
}
bResult = CryptGetUserKey(hCryptProv, AT_KEYEXCHANGE, &hCryptKey);
if(!bResult)
{
errCode = GetLastError();
if(bFreeKeyProv)
{
CryptReleaseContext(hCryptProv, 0);
}
CertFreeCertificateContext(pSignerCert);
CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG);
return errCode;
}
memcpy(destData, srcData, srcLen);
*destLen = srcLen;
ReverseBuffer(destData, *destLen);
bResult = CryptDecrypt(hCryptKey, NULL, TRUE, 0, (BYTE*)destData, (DWORD*)destLen);
if(!bResult)
{
errCode = GetLastError();
CryptDestroyKey(hCryptKey);
if(bFreeKeyProv)
{
CryptReleaseContext(hCryptProv, 0);
}
CertFreeCertificateContext(pSignerCert);
CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG);
return errCode;
}
CryptDestroyKey(hCryptKey);
if(bFreeKeyProv)
{
CryptReleaseContext(hCryptProv, 0);
}
CertFreeCertificateContext(pSignerCert);
CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG);
return 0;
}
int WINAPI rsa_b64_sign(const wchar_t* subjectName, const char* srcB64Data, char* destB64Data)
{
int srcB64Len = (int)strlen(srcB64Data);
int srcLen = base64_decoded_length(srcB64Len);
char* srcData = (char*)malloc(srcLen);
char* destData = NULL;
int destLen = 1024;
int destB64Len = 0;
int i = 0;
int hr = decode_base64((const unsigned char*)srcB64Data, srcB64Len, (unsigned char*)srcData, &srcLen);
if(hr != 0)
{
free(srcData);
return -1;
}
destData = (char*)malloc(destLen);
hr = rsa_sign(subjectName, srcData, srcLen, destData, &destLen);
if(hr == 0)
{
encode_base64((const unsigned char*)destData, destLen, (unsigned char*)destB64Data, &destB64Len);
destB64Data[destB64Len] = '\0';
}
free(destData);
free(srcData);
return hr;
}
int WINAPI rsa_b64_verify(const wchar_t* subjectName, const char* srcB64Data, const char* signB64Data)
{
int srcB64Len = (int)strlen(srcB64Data);
int srcLen = base64_decoded_length(srcB64Len);
char* srcData = NULL;
int signB64Len = (int)strlen(signB64Data);
int signLen = base64_decoded_length(signB64Len);
char* signData = NULL;
int hr = 0;
srcData = (char*)malloc(srcLen);
hr = decode_base64((const unsigned char*)srcB64Data, srcB64Len, (unsigned char*)srcData, &srcLen);
if(hr != 0)
{
free(srcData);
return -1;
}
signData = (char*)malloc(signLen);
hr = decode_base64((const unsigned char*)signB64Data, signB64Len, (unsigned char*)signData, &signLen);
if(hr != 0)
{
free(srcData);
free(signData);
return -1;
}
hr = rsa_verify(subjectName, srcData, srcLen, signData, signLen);
free(srcData);
free(signData);
return hr;
}
int WINAPI rsa_b64_encrypt(const wchar_t* subjectName, const char* srcB64Data, char* destB64Data)
{
int srcB64Len = (int)strlen(srcB64Data);
int srcLen = base64_decoded_length(srcB64Len);
char* srcData = NULL;
char* destData = NULL;
int destLen = 1024;
int destB64Len = 0;
int hr = 0;
srcData = (char*)malloc(srcLen);
hr = decode_base64((const unsigned char*)srcB64Data, srcB64Len, (unsigned char*)srcData, &srcLen);
if(hr != 0)
{
free(srcData);
return -1;
}
destData = (char*)malloc(destLen);
hr = rsa_encrypt(subjectName, srcData, srcLen, destData, &destLen);
if(hr == 0)
{
encode_base64((const unsigned char*)destData, destLen, (unsigned char*)destB64Data, &destB64Len);
destB64Data[destB64Len] = '\0';
}
free(srcData);
free(destData);
return hr;
}
int WINAPI rsa_b64_decrypt(const wchar_t* subjectName, const char* srcB64Data, char* destB64Data)
{
int srcB64Len = (int)strlen(srcB64Data);
int srcLen = base64_decoded_length(srcB64Len);
char* srcData = NULL;
char* destData = NULL;
int destLen = 1024;
int destB64Len = 0;
int hr = 0;
srcData = (char*)malloc(srcLen);
hr = decode_base64((const unsigned char*)srcB64Data, srcB64Len, (unsigned char*)srcData, &srcLen);
if(hr != 0)
{
free(srcData);
return -1;
}
destData = (char*)malloc(destLen);
hr = rsa_decrypt(subjectName, srcData, srcLen, destData, &destLen);
if(hr == 0)
{
encode_base64((const unsigned char*)destData, destLen, (unsigned char*)destB64Data, &destB64Len);
destB64Data[destB64Len] = '\0';
}
free(srcData);
free(destData);
return hr;
}
int WINAPI cert_add(const wchar_t* subjectName, const char* certData, int certLen)
{
HCERTSTORE hStoreHandle = NULL;
BOOL bResult = FALSE;
DWORD errCode;
PCCERT_CONTEXT hContext = NULL;
HCERTSTORE hMemoryStore = NULL;
CRYPT_DATA_BLOB blob;
blob.pbData = (BYTE*)certData;
blob.cbData = certLen;
hMemoryStore = PFXImportCertStore(&blob, L"", CRYPT_EXPORTABLE | CRYPT_USER_KEYSET);
if(!hMemoryStore)
{
errCode = GetLastError();
return errCode;
}
hStoreHandle = CertOpenStore(
CERT_STORE_PROV_SYSTEM,
0,
NULL,
CERT_SYSTEM_STORE_CURRENT_USER,
CERT_PERSONAL_STORE_NAME
);
if(!hStoreHandle)
{
errCode = GetLastError();
CertCloseStore(hMemoryStore, 0);
return errCode;
}
while(hContext = CertEnumCertificatesInStore(hMemoryStore, hContext))
{
bResult = CertAddCertificateContextToStore(hStoreHandle, hContext,
CERT_STORE_ADD_REPLACE_EXISTING, NULL);
if(!bResult)
{
errCode = GetLastError();
CertCloseStore(hMemoryStore, 0);
CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG);
return errCode;
}
}
CertCloseStore(hMemoryStore, 0);
CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG);
return 0;
}
int WINAPI cert_b64_add(const wchar_t* subjectName, const char* certB64Data)
{
int certB64Len = (int)strlen(certB64Data);
int certLen = base64_decoded_length(certB64Len);
char* certData = NULL;
int hr = 0;
certData = (char*)malloc(certLen);
hr = decode_base64((const unsigned char*)certB64Data, certB64Len, (unsigned char*)certData, &certLen);
if(hr != 0)
{
free(certData);
return -1;
}
hr = cert_add(subjectName, certData, certLen);
free(certData);
return hr;
}
int WINAPI cert_del(const wchar_t* subjectName)
{
HCERTSTORE hStoreHandle = NULL;
PCCERT_CONTEXT pSignerCert = NULL;
BOOL bResult = FALSE;
DWORD errCode;
hStoreHandle = CertOpenStore(
CERT_STORE_PROV_SYSTEM,
0,
NULL,
CERT_SYSTEM_STORE_CURRENT_USER,
CERT_PERSONAL_STORE_NAME
);
if(!hStoreHandle)
{
errCode = GetLastError();
return errCode;
}
while(pSignerCert = CertFindCertificateInStore(
hStoreHandle,
MY_TYPE,
0,
CERT_FIND_SUBJECT_STR,
subjectName,
pSignerCert))
{
if(!pSignerCert)
{
break;
}
bResult = CertDeleteCertificateFromStore(pSignerCert);
if(!bResult)
{
errCode = GetLastError();
CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG);
return errCode;
}
pSignerCert = NULL;
}
CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG);
return 0;
}
int WINAPI cert_exists(const wchar_t* subjectName)
{
HCERTSTORE hStoreHandle = NULL;
PCCERT_CONTEXT pSignerCert = NULL;
BOOL bResult = FALSE;
DWORD errCode;
int exists = 0;
hStoreHandle = CertOpenStore(
CERT_STORE_PROV_SYSTEM,
0,
NULL,
CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_READONLY_FLAG,
CERT_PERSONAL_STORE_NAME
);
if(!hStoreHandle)
{
errCode = GetLastError();
return errCode;
}
pSignerCert = CertFindCertificateInStore(
hStoreHandle,
MY_TYPE,
0,
CERT_FIND_SUBJECT_STR,
subjectName,
pSignerCert
);
exists = pSignerCert ? 1 : 0;
CertFreeCertificateContext(pSignerCert);
CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG);
return exists;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment