在项目中需要增加一个注册的功能,想到了用rsa非对称加密的方法。对比了openssl等第三方库,最后采用了Cryptopp。
1.源文件整理
可以在http://www.cryptopp.com/获取库的源文件,解压后将文件重新归档。头文件放置到include文件夹,cpp放到src目录。同时去除所有的test相关的cpp及非cpp、h文件。拷本cryptopp目录到工程目录下
2.加入工程
在vs2010工程中增加新的filter,命名为Cryptopp,再增加子filter include和src。将include下的h文件导入到include,将src下的cpp导入到src filter。
3.编译
打开src,选中所有的cpp文件,更改属性,将预编译头改为pch.h。将工程的vc++路径更新,增加include和src。
编译工程,如果编译不过修改一下错误。
4.生成rsa公钥、私钥,经过base64编码后保存到文件
需要导入一些头文件:#include "iterhash.h" #include "files.h" #include "rsa.h" #include "randpool.h" #include "hex.h" #include "base64.h" #include "osrng.h"void CKeyController::GenerateRSAKey(unsigned int keyLength, CString decFilename, CString encFilename, CString seed) { RandomPool randPool; randPool.Put((byte *)seed.GetBuffer(seed.GetLength()), seed.GetLength()); RSAES_OAEP_SHA_Decryptor decrypt(randPool, keyLength); HexEncoder decFile(new Base64Encoder(new FileSink(decFilename.GetBuffer(decFilename.GetLength())))); decrypt.DEREncode(decFile); decFile.MessageEnd(); RSAES_OAEP_SHA_Encryptor encrypt(decrypt); HexEncoder encFile(new Base64Encoder(new FileSink(encFilename.GetBuffer(encFilename.GetLength())))); encrypt.DEREncode(encFile); encFile.MessageEnd(); return; } RandomPool & CKeyController::GlobalRNG() { static RandomPool randomPool; return randomPool; }5.通过生成的公钥文件加密字符串
CString CKeyController::RSAEncryptString( CString encFilename, CString seed, CString message ) { string encString; FileSource encFile( encFilename.GetBuffer(encFilename.GetLength()), true, new Base64Decoder(new StringSink(encString)) ); HexDecoder decoder; decoder.Put( (byte*)encString.c_str(), encString.size() ); decoder.MessageEnd(); RSAES_OAEP_SHA_Encryptor enc; enc.AccessKey().Load(decoder); RandomPool randPool; randPool.Put( (byte *)seed.GetBuffer(seed.GetLength()), seed.GetLength() ); string result; StringSource( c2s(message), true, new PK_EncryptorFilter(randPool, enc, new HexEncoder(new StringSink(result))) ); return CString(result.c_str()); }6.通过生成的私钥文件解密字符串
CString CKeyController::RSADecryptString( CString decFilename, CString ciphertext ) { string decString; FileSource decFile( decFilename.GetBuffer(decFilename.GetLength()), true, new Base64Decoder(new StringSink(decString)) ); HexDecoder decoder; decoder.Put( (byte*)decString.c_str(), decString.size() ); decoder.MessageEnd(); RSAES_OAEP_SHA_Decryptor dec; dec.AccessKey().Load(decoder); string result; StringSource( c2s(ciphertext), true, new HexDecoder(new PK_DecryptorFilter(GlobalRNG(), dec, new StringSink(result))) ); return CString(result.c_str()); }7.使用私钥签名
CString CKeyController::SignMessage( const std::string& privateKeyFileName, const std::string& message ) { std::string signedMessage = ""; string encString; FileSource privFile( privateKeyFileName.c_str(), true, new Base64Decoder(new StringSink(encString))); RSASSA_PKCS1v15_SHA_Signer priv; HexDecoder decoder; decoder.Put( (byte*)encString.c_str(), encString.size() ); decoder.MessageEnd(); priv.AccessKey().Load(decoder); AutoSeededRandomPool rng; StringSource s1(message, true, new SignerFilter(rng, priv, new HexEncoder(new StringSink(signedMessage)))); return CString(signedMessage.c_str()); }8.使用公钥验证签名
bool CKeyController::VerifySignature( const std::string& publicKeyFileName, const std::string& message, const std::string& signedMessage ) { string decString; FileSource pubFile( publicKeyFileName.c_str(), true, new Base64Decoder(new StringSink(decString)) ); RSASSA_PKCS1v15_SHA_Verifier pub; HexDecoder decoder; decoder.Put( (byte*)decString.c_str(), decString.size() ); decoder.MessageEnd(); pub.AccessKey().Load(decoder); StringSource signatureFile( signedMessage, true, new HexDecoder); if (signatureFile.MaxRetrievable() != pub.SignatureLength()) { throw std::string( "Signature Size Problem" ); } SecByteBlock signature(pub.SignatureLength()); signatureFile.Get(signature, signature.size()); VerifierFilter *verifierFilter = new VerifierFilter(pub); verifierFilter->Put(signature, pub.SignatureLength()); StringSource s(message, true, verifierFilter); return verifierFilter->GetLastResult(); }9.测试函数调用
void CKeyController::testRSA() { CString encryptKey = _T("key.pub"); CString decryptKey = _T("key.pri"); CString seed = _T("seed"); //GenerateRSAKey( 1024, decryptKey, encryptKey, seed ); CString message = _T("X3BA-9NSF-8N9Q-UWQC-U7FX-AZZF-JAJW"); CString encryptedText = RSAEncryptString( encryptKey, seed, message ); CString decryptedText = RSADecryptString( decryptKey, encryptedText ); CString signedMessage = SignMessage("key.pri", c2s(decryptedText)); bool verified = VerifySignature("key.pub", c2s(message), c2s(signedMessage)); }10.工具函数如base64转码,字符串转换
std::string CKeyController::EncodeBase64( string message ) { string encode; StringSource(message, true, new Base64Encoder(new StringSink(encode))); return encode; } std::string CKeyController::DecodeBase64( string message ) { string decode; StringSource(message, true, new Base64Decoder(new StringSink(decode))); return decode; } CString CKeyController::hashString( CString message ) { string digest; SHA256 hash; StringSource foo(c2s(message), true, new HashFilter(hash, new HexEncoder(new StringSink(digest)))); return CString(digest.c_str()); } CString CKeyController::hashFile( CString fileName ) { string digest; SHA256 hash; FileSource(fileName, true, new HashFilter(hash, new HexEncoder(new StringSink(digest)))); return CString(digest.c_str()); } std::string c2s( CString &cs ) { CT2CA pszConvertedAnsiString(cs); std::string strStd(pszConvertedAnsiString); return strStd; }来源:天宇空间