Crypto移植筆記
2018.06.12 許靜
1. 環境: vs2017, crypto7.0
2. 修改代碼,使編譯通過。測試crylib項目。
無法打開源文件stdio.h, stddef.h,stdlib.h等文件, 在包含目錄中添加:
C:\Program Files(x86)\Windows Kits\10\Include\10.0.16299.0\ucrt
注意10.0.16299.0版本是否存在本機目錄下。
“找不到Windows SDK版本8.1. 請安裝所需的版本的Windows SDK或者在項目屬性頁中或通過右鍵單擊解決方案並選擇“重定解決方案目標”來更改SDK版本”。更改一下,不出現錯誤。
3. 添加cryptlib.lib和所有.h文件。
4. 屬性->c/c++->代碼生成->運行庫 多線程調試。
出錯。
#error指令:Please use the /MD switch for _AFXDLL builds.
原因:將MFC設置成在共享dll中使用MFC.
解決方案:屬性->常規->MFC的使用->在靜態庫中使用MFC.
5. 源文件
- #ifndef __RSA_MAIN_H__
- #define __RSA_MAIN_H__
- #include <iostream>
- #include <string>
- #define _GEN_RSA 1
- #if !_GEN_RSA
- #define _SPE_RSA 1
- #endif
- class RSA_C {
- public:
- RSA_C(void);
- ~RSA_C(void);
- std::string PubEn(const char* message);
- std::string PriDe(const char* chiphtertext);
- void GenerateRSAKey(unsigned int keyLength, const char *privFilename, const char *pubFilename, const char *seed);
- private:
- unsigned int keyLen;
- char *privFilename;
- char *pubFilename;
- char *seed;
- /*
- #if _SPE_RSA
- RSA::PrivateKey k1;
- RSA::PublicKey k2;
- AutoSeededRandomPool rnd;
- #endif
- */
- };
- extern RSA_C g_RSA_App;
- #endif
- #include "RSA_main.h"
- #include "rsa.h"
- #include "randpool.h"
- #include "hex.h"
- #include "files.h"
- #include "cryptlib.h"
- #include "queue.h"
- #include "filters.h"
- #include "osrng.h"
- #include <stdexcept>
- using std::runtime_error;
- using namespace CryptoPP;
- #pragma comment(lib, "cryptlib.lib")
- RSA_C g_RSA_App;
- #if _GEN_RSA
- static std::string RSADecryptString(const char *privFilename, const char *ciphertext);
- static std::string RSAEncryptString(const char *pubFilename, const char *seed, const char *message);
- static RandomPool& GlobalRNG(void);
- void Encode(const std::string& filename, const BufferedTransformation& bt);
- #endif
- #if _SPE_RSA
- void Encode(const std::string& filename, const BufferedTransformation& bt);
- void Decode(const std::string& filename, BufferedTransformation& bt);
- #endif
- #if _SPE_RSA
- RSA::PrivateKey k1;
- RSA::PublicKey k2;
- AutoSeededRandomPool rnd;
- #endif
- RSA_C::RSA_C(void)
- {
- privFilename = new char[1024];
- pubFilename = new char[1024];
- seed = new char[1024];
- }
- RSA_C::~RSA_C()
- {
- delete privFilename;
- delete pubFilename;
- delete seed;
- }
- std::string RSA_C::PubEn(const char* message)
- {
- std::string enText = "";
- #if _GEN_RSA
- std::cout << "origin text:" << message << '\n';
- enText = RSAEncryptString(pubFilename, seed, message);
- std::cout << "Encrypted Text:" << enText << '\n';
- #endif
- #if _SPE_RSA
- RSAES_OAEP_SHA_Encryptor e(k2);
- StringSource(message, true, new PK_EncryptorFilter(rnd,e, new StringSink(enText)));
- #endif
- return enText;
- }
- std::string RSA_C::PriDe(const char* chiphtertext)
- {
- std::string deText = "";
- #if _GEN_RSA
- std::cout << "Encryped text:" << chiphtertext << '\n';
- deText = RSADecryptString(privFilename, chiphtertext);
- std::cout << "Decrypted Text:" << deText << '\n';
- #endif
- #if _SPE_RSA
- RSAES_OAEP_SHA_Decryptor d(k1);
- StringSource(chiphtertext, true, new PK_DecryptorFilter(rnd, d, new StringSink(deText)));
- #endif
- return deText;
- }
- #if _GEN_RSA
- static RandomPool& GlobalRNG(void)
- {
- static RandomPool randomPool;
- return randomPool;
- }
- #endif
- #if _SPE_RSA
- void EncodePrivateKey(const std::string& filename, const RSA::PrivateKey& key)
- {
- // http://www.cryptopp.com/docs/ref/class_byte_queue.html
- ByteQueue queue;
- key.DEREncodePrivateKey(queue);
- Encode(filename, queue);
- }
- void EncodePublicKey(const std::string& filename, const RSA::PublicKey& key)
- {
- // http://www.cryptopp.com/docs/ref/class_byte_queue.html
- ByteQueue queue;
- key.DEREncodePublicKey(queue);
- Encode(filename, queue);
- }
- void Encode(const std::string& filename, const BufferedTransformation& bt)
- {
- // http://www.cryptopp.com/docs/ref/class_file_sink.html
- FileSink file(filename.c_str());
- bt.CopyTo(file);
- file.MessageEnd();
- }
- void DecodePrivatekey(const std::string& filename, RSA::PrivateKey& key)
- {
- ByteQueue queue;
- Decode(filename, queue);
- key.BERDecodePrivateKey(queue, false, queue.MaxRetrievable());
- }
- void DecodePublickey(const std::string& filename, RSA::PublicKey& key)
- {
- ByteQueue queue;
- Decode(filename, queue);
- key.BERDecodePublicKey(queue, false, queue.MaxRetrievable());
- }
- void Decode(const std::string& filename, BufferedTransformation& bt)
- {
- FileSource file(filename.c_str(), true);
- file.TransferTo(bt);
- bt.MessageEnd();
- }
- #endif
- void RSA_C::GenerateRSAKey(unsigned int ikeyLength, const char *iprivFilename, const char *ipubFilename, const char *iseed)
- {
- #if _GEN_RSA
- keyLen = ikeyLength;
- strcpy(privFilename, iprivFilename);
- strcpy(pubFilename, ipubFilename);
- strcpy(seed, iseed);
- // DEREncode() changed to Save() at Issue 569.
- RandomPool randPool;
- randPool.IncorporateEntropy((byte *)iseed, strlen(seed));
- RSAES_OAEP_SHA_Decryptor priv(randPool, ikeyLength);
- HexEncoder privFile(new FileSink(iprivFilename));
- priv.AccessMaterial().Save(privFile);
- privFile.MessageEnd();
- RSAES_OAEP_SHA_Encryptor pub(priv);
- HexEncoder pubFile(new FileSink(ipubFilename));
- pub.AccessMaterial().Save(pubFile);
- pubFile.MessageEnd();
- #endif
- #if _SPE_RSA
- AutoSeededRandomPool rnd;
- RSA::PrivateKey rsaPrivate;
- rsaPrivate.GenerateRandomWithKeySize(rnd, 2048);
- RSA::PublicKey rsaPublic(rsaPrivate);
- // generate
- EncodePrivateKey("C:\\rsa05\\rsa-private.key", rsaPrivate); //將密鑰放在C:\\rsa05目錄下
- EncodePublicKey("C:\\rsa05\\rsa-public.key", rsaPublic); //必須預先在C盤建立rsa05文件夾,否則出錯
- std::cout << "Successfully generated and saved RSA keys" << '\n';
- //load
- DecodePrivatekey("C:\\rsa05\\rsa-private.key", k1);
- DecodePublickey("C:\\rsa05\\rsa-public.key", k2);
- //check
- if (!k1.Validate(rnd, 3))
- throw runtime_error("Rsa private key validation failed");
- if (!k2.Validate(rnd, 3))
- throw runtime_error("Rsa public key validation failed");
- /*
- if (rsaPrivate.GetModulus() != k1.GetModulus() || rsaPrivate.GetPublicExponent() != k1.GetPublicExponent() || rsaPrivate.GetPrivateExponent() != k1.GetPrivateExponent)
- {
- throw runtime_error("private key data did not round trip");
- }
- if (rsaPublic.GetModulus() != k2.GetModulus() || rsaPublic.GetPublicExponent != k2.GetPublicExponent())
- {
- throw runtime_error("public key data did not round trip");
- }
- //successfully!
- */
- #endif
- }
- #if _GEN_RSA
- static std::string RSAEncryptString(const char *pubFilename, const char *seed, const char *message)
- {
- FileSource pubFile(pubFilename, true, new HexDecoder);
- RSAES_OAEP_SHA_Encryptor pub(pubFile);
- RandomPool randPool;
- randPool.IncorporateEntropy((byte *)seed, strlen(seed));
- std::string result;
- StringSource(message, true, new PK_EncryptorFilter(randPool, pub, new HexEncoder(new StringSink(result))));
- return result;
- }
- #endif
- #if _GEN_RSA
- static std::string RSADecryptString(const char *privFilename, const char *ciphertext)
- {
- FileSource privFile(privFilename, true, new HexDecoder);
- RSAES_OAEP_SHA_Decryptor priv(privFile);
- std::string result;
- StringSource(ciphertext, true, new HexDecoder(new PK_DecryptorFilter(GlobalRNG(), priv, new StringSink(result))));
- return result;
- }
- #endif
外加一個lib庫。
/**********************************************************************************************************************/
生成cryptest工程
官方文檔
在工程目錄下添加CryptoPP文件夾,將編譯好的lib,以及頭文件放入(頭文件放在include文件夾下)
流程
同時,也可以根據項目不同,生成不同的key。將項目名稱作爲seed替換。