#include "stdafx.h"
#include "CryptoTool.h"

using namespace CryptoPP;
CCryptoTool::CCryptoTool()
{
}


CCryptoTool::~CCryptoTool()
{

}


NonblockingRng CCryptoTool::m_rng;
//RSA加密解密
string CCryptoTool::EncodeBase64(string message)
{
	string encode;
	StringSource(message, true, new Base64Encoder(new StringSink(encode)));
	return encode;
}

string CCryptoTool::DecodeBase64(string message)
{
	string decode;
	StringSource(message, true, new Base64Decoder(new StringSink(decode)));
	return decode;
}

RandomNumberGenerator  CCryptoTool::GlobalRNG()
{
	static RandomPool randPool;
	return randPool;
}

void CCryptoTool::GenerateRSAKey(unsigned int keyLength, const char *privFilename, const char *pubFilename, const char *seed)
{
	// DEREncode() changed to Save() at Issue 569.
	RandomPool randPool;
	randPool.IncorporateEntropy((unsigned char *)seed, strlen(seed));

	RSAES_PKCS1v15_Decryptor priv(randPool, keyLength);
	Base64Encoder privFile(new FileSink(privFilename));
	priv.AccessMaterial().Save(privFile);
	privFile.MessageEnd();

	RSAES_PKCS1v15_Encryptor pub(priv);
	Base64Encoder pubFile(new FileSink(pubFilename));
	pub.AccessMaterial().Save(pubFile);
	pubFile.MessageEnd();
}
string CCryptoTool::RSAEncryptString(const char *pubFilename, const char *message)
{
	FileSource pubFile(pubFilename, true, new Base64Decoder);
	RSAES_PKCS1v15_Encryptor pub(pubFile);

	string strSeed = "seed";
	RandomPool randPool;
	randPool.IncorporateEntropy((unsigned char *)strSeed.c_str(), strSeed.length());

	std::string result;
	StringSource(message, true, new PK_EncryptorFilter(randPool, pub, new Base64Encoder(new StringSink(result))));
	return result;
}
string CCryptoTool::RSAEncryptStringHex(const char *pubFilename, const  string& message)
{

	FileSource pubFile(pubFilename, true, new Base64Decoder);
	RSAES_PKCS1v15_Encryptor pub(pubFile);

	string strSeed = "seed";
	RandomPool randPool;
	randPool.IncorporateEntropy((unsigned char *)strSeed.c_str(), strSeed.length());
	int nLen = message.length();
	std::string result;
	int fixedLen =pub.FixedMaxPlaintextLength();
	for (int i = 0; i < nLen; i += fixedLen)
	{
		size_t len = fixedLen < (nLen - i) ? fixedLen : (nLen - i);
		string sPlain = message.substr(i, len);
		string sOut;
		StringSource(sPlain, true, new PK_EncryptorFilter(randPool, pub, new StringSink(sOut)));
		result += sOut;
	}
	return result;
}

string CCryptoTool::RSADecryptString(const char *privFilename, const char *ciphertext)
{
	FileSource privFile(privFilename, true, new Base64Decoder);
	RSAES_PKCS1v15_Decryptor priv(privFile);
	std::string result;
	string strSeed = "seed";
	RandomPool randPool;
	randPool.IncorporateEntropy((unsigned char *)strSeed.c_str(), 0);
	try
	{
		StringSource(ciphertext, true, new Base64Decoder(new PK_DecryptorFilter(randPool, priv, new StringSink(result))));
	}
	catch (const std::exception& e)
	{
		cout << "私匙错误:" << e.what() << endl;
	}

	return result;
}
string CCryptoTool::RSADecryptStringHex(const char *privFilename, const  char* ciphertext, int nLen)
{
	FileSource privFile(privFilename, true, new Base64Decoder);
	RSAES_PKCS1v15_Decryptor priv(privFile);

	string strSeed = "seed";
	RandomPool randPool;
	randPool.IncorporateEntropy((unsigned char *)strSeed.c_str(), 0);
	//int nLen = ciphertext.length();
	std::string result;
	int fixedLen = priv.FixedCiphertextLength();
	for (int i = 0; i < nLen; i += fixedLen)
	{
		size_t len = fixedLen < (nLen - i) ? fixedLen : (nLen - i);
		//string sPlain = ciphertext.substr(i, len);
		string sOut;
		try
		{
			StringSource((byte *)(ciphertext + i), len, true, new PK_DecryptorFilter(randPool, priv, new StringSink(sOut)));
		}
		catch (const std::exception& e)
		{
			cout << "私匙错误:" << e.what() << endl;
		}
		result += sOut;
	}

	return result;
}

void CCryptoTool::RSASignFile(const char *privFilename, const char *messageFilename, const char *signatureFilename)
{
	FileSource privFile(privFilename, true, new HexDecoder);
	RSASS<PKCS1v15, SHA1>::Signer priv(privFile);
	FileSource f(messageFilename, true, new SignerFilter(GlobalRNG(), priv, new HexEncoder(new FileSink(signatureFilename))));
}
string CCryptoTool::sha1(string text)
{
	std::string hash;
	CryptoPP::SHA1 sha1;
	CryptoPP::HashFilter hashfilter(sha1);
	hashfilter.Attach(new CryptoPP::HexEncoder(new CryptoPP::StringSink(hash), false));
	hashfilter.Put(reinterpret_cast<const unsigned char*>(text.c_str()), text.length());
	hashfilter.MessageEnd();
	return hash;
}
string CCryptoTool::RSASignString(const char *privFilename, string message)
{
	std::string result;
	CryptoPP::FileSource privFile(privFilename, true, new CryptoPP::Base64Decoder);
	CryptoPP::RSASSA_PKCS1v15_SHA_Signer signer(privFile);
	size_t length = signer.MaxSignatureLength();
	CryptoPP::SecByteBlock signature(length);
	string strSeed = "seed";
	CryptoPP::RandomPool randPool;
	randPool.IncorporateEntropy((unsigned char *)strSeed.c_str(), 0);
	size_t szlength = signer.SignMessage(randPool, (const byte*)message.c_str(), message.length(), signature);
	signature.resize(szlength);
	result = string((const char *)signature.data(), signature.size());
	return result;
}
bool CCryptoTool::RSASignVerifyString(const char *pubFilename, string message,string sSignString)
{
	CryptoPP::FileSource pubFile(pubFilename, true, new CryptoPP::Base64Decoder);
	CryptoPP::RSASSA_PKCS1v15_SHA_Verifier verifier(pubFile);

	// Verify
	bool bRet = verifier.VerifyMessage((const byte*)message.c_str(),
		message.length(), (byte*)sSignString.c_str(), sSignString.size());
	return bRet;
}
bool CCryptoTool::RSAVerifyFile(const char *pubFilename, const char *messageFilename, const char *signatureFilename)
{
	FileSource pubFile(pubFilename, true, new HexDecoder);
	RSASS<PKCS1v15, SHA1>::Verifier pub(pubFile);

	FileSource signatureFile(signatureFilename, true, new HexDecoder);
	if (signatureFile.MaxRetrievable() != pub.SignatureLength())
		return false;
	SecByteBlock signature(pub.SignatureLength());
	signatureFile.Get(signature, signature.size());

	SignatureVerificationFilter *verifierFilter = new SignatureVerificationFilter(pub);
	verifierFilter->Put(signature, pub.SignatureLength());
	FileSource f(messageFilename, true, verifierFilter);

	return verifierFilter->GetLastResult();
}
///////////////////////////AES加密解密
string CCryptoTool::encryptAES(const string& str_in, const string& key)
{
	string str_out;
	ECB_Mode<AES>::Encryption encryption((unsigned char*)key.c_str(), key.length());
	StringSource encryptor(str_in, true,new StreamTransformationFilter(encryption,new StringSink(str_out)));
	return str_out;
}
string CCryptoTool::decryptAES(const char* str_in, int iLen, const string& key)//ecb模式 没有iv
{
	string str_out;
	ECB_Mode<AES>::Decryption decryption((unsigned char*)key.c_str(), key.length());
	StringSource decryptor((byte*)str_in, iLen, true,new StreamTransformationFilter(decryption,new StringSink(str_out)));
	return str_out;
}
