/********************************************************************
	Created:	7:4:2003   10:07
	Filename: 	rsa.cpp
	Author:		Yubo
	Copyright:	
				Copyright(C) 1998-2004, Feitian Technologies Co., Ltd.
				All rights reserved.

  Purpose:	Test RSA key: public key encrypt and 
				private key decrypt!
*********************************************************************/


#include "stdafx.h"
#include "RSA.h"


#define DATALEN 100
#define MS_CSP  "Microsoft Strong Cryptographic Provider"
#define SAFESIGN "SafeSign CSP Version 1.0"

CRSA::CRSA()
{

}

CRSA::~CRSA()
{

}

int CRSA::TestRSA(int iCSP)
{
	HCRYPTPROV hCryptProv = NULL;
	printf("\n\nNOTICE:Get the handle from UsbToken...\n");
	printf("CryptAcquireContext\n");

	char cKeyContainer[32]= {0};
		srand( (unsigned)time(NULL));
		unsigned long ulName = rand() * rand();
		ltoa(ulName, cKeyContainer, 16);
		LPCSTR CSPName; 
		if(iCSP == 1)
			CSPName = EPS1K_CSP_NAME;
		if(iCSP == 2)
			CSPName = EPS2K_CSP_NAME;
		if(iCSP == 2)
			CSPName = EPS2KPBOC_CSP_NAME;
		printf("\nTest CSP name: %s\n", CSPName);
	if(!CryptAcquireContext(&hCryptProv,CONTAINER,CSPName,PROV_RSA_FULL,0))
	{
		if(!CryptAcquireContext(&hCryptProv, CONTAINER, CSPName, PROV_RSA_FULL, CRYPT_NEWKEYSET))
		{
			printf("X X X X X CryptAcquireContext() failed: ERR CODE=0x%0x\n", GetLastError());
			return CSP_FUNC_FAILED;
		}
		else
		{
			printf("...OK!\n");
		}
	}
	HCRYPTKEY hKey;
	printf("Generate RSA key pair\n");
	if(!CryptGenKey(hCryptProv, AT_KEYEXCHANGE, 0, &hKey))
	{
		printf("X X X CryptGenKey failed!ERR CODE=0x%0x\n", GetLastError());
		printf("CryptReleaseContext:");
		if(!CryptReleaseContext(hCryptProv, 0))
			printf("Err:CryptReleaseContext()!failed!ERR CODE=0x%0x\n",GetLastError());
		else
			printf("...OK!\n");
		return CSP_FUNC_FAILED;
	}
	else
	{
		printf("...OK!\n");
	}
	
	unsigned char pData[DATALEN] = {0};
	unsigned long ulDataLen = sizeof(pData);
	CK_ULONG ulEncryptedLen=ulDataLen;
	unsigned char* pOut;
	for(int i=0;i<DATALEN;i++)
	{
		pData[i] = i%255; 
	}

	printf("RSA Public key encryption:\n");
	if(!CryptEncrypt(hKey, 0, TRUE, 0, NULL, &ulEncryptedLen, ulDataLen))
	{
		printf("X X X CryptEncrypt failed!ERR CODE=0x%0x\n", GetLastError());
		printf("CryptReleaseContext:");
		if(!CryptReleaseContext(hCryptProv, 0))
			printf("Err:CryptReleaseContext()!failed!ERR CODE=0x%0x\n",GetLastError());
		else
			printf("...OK!\n");
		return CSP_FUNC_FAILED;
	}

	pOut = new unsigned char [ulEncryptedLen];
	
	memset(pOut, 0, ulEncryptedLen);
	memcpy(pOut, pData, ulDataLen);
	CK_ULONG ulTemp =ulDataLen;
	ulDataLen=ulEncryptedLen;
	ulEncryptedLen=ulTemp;

	if(!CryptEncrypt(hKey, 0, TRUE, 0, pOut, &ulEncryptedLen, ulDataLen))
	{
		delete [] pOut;pOut = NULL;
		printf("X X X CryptEncrypt failed!ERR CODE=0x%0x\n", GetLastError());
		printf("CryptReleaseContext:");
		if(!CryptReleaseContext(hCryptProv, 0))
			printf("Err:CryptReleaseContext()!failed!ERR CODE=0x%0x\n",GetLastError());
		else
		{
			printf("...OK!\n");
		}
		return CSP_FUNC_FAILED;
	}
	else
	{
		for(CK_ULONG i=0;i<ulEncryptedLen;i++)
			printf("%d=%d, ", i, pOut[i]);
		printf("...OK!\n");
	}

	printf("RSA private key decryption:\n");

	if(!CryptDecrypt(hKey, 0, TRUE, 0, pOut, &ulEncryptedLen))
	{
		printf("X X X X X CryptDecrypt() failed: ERR CODE=0x%0x\n", GetLastError());
		printf("CryptReleaseContext:");
		if(!CryptReleaseContext(hCryptProv, 0))
			printf("Err:CryptReleaseContext()!failed!ERR CODE=0x%0x\n",GetLastError());
		else
			printf("...OK!\n");

		delete [] pOut; pOut = 0;
		return CSP_FUNC_FAILED;
	}
	else
	{
		for(CK_ULONG i= 0;i<ulEncryptedLen;i++)
		{
			if(pOut[i] != i%255)
				printf("\n%d=error!", i);
			else
				printf("%d=%d, ", i, pOut[i]);
		}
		printf("...OK!\n");
	}

	if(0 != memcmp(pData, pOut, ulEncryptedLen))
	{
		delete [] pOut;pOut = NULL;
		printf("\n....RSA key Encryption and Decryption Failed!....\n");
	}
	printf("CryptReleaseContext:");
	if(!CryptReleaseContext(hCryptProv, 0))
		printf("Err:CryptReleaseContext()!failed!ERR CODE=0x%0x\n",GetLastError());
	else
		printf("...OK!\n");
	
	return CSP_OK;
}
