我正在尝试使用rsa加密缓冲区,然后将数据以十六进制格式保存到文件中。我正在使用Crypto ++ 5.6.5。
加载密钥(工作):
try
{
// Read RSA public
FileSource fs1("public.pem", true);
PEM_Load(fs1, pubKey);
// Read RSA encrypted private
FileSource fs2("private.pem", true);
PEM_Load(fs2, privKey, "1234", 4);
}
catch(const Exception& ex)
{
cout << "ERROR: RSA:" << ex.what() << endl;
SystemLog_Print("RSA: Couldn't load keys");
}
加密(好吗?):
std::string RSA_Encrypt(unsigned char *buf, uint8_t len)
{
AutoSeededRandomPool rng;
std::string plain;
std::string cipher, recovered;
for(int i = 0; i < len; ++i) {
plain.push_back(buf[i]);
}
// Encryption
RSAES_OAEP_SHA_Encryptor e(pubKey);
StringSource ss1(plain, true, new PK_EncryptorFilter(rng, e, new StringSink(cipher)));
// Test Decryption
RSAES_OAEP_SHA_Decryptor d(privKey);
StringSource ss2(cipher, true, new PK_DecryptorFilter(rng, d, new StringSink(recovered)));
if(memcmp(plain.data(), recovered.data(), plain.size()) != 0) {
cout << "RSA Mismatch" << endl;
}
return cipher;
}
现在我坚持将加密数据写入可读HEX中的文件,如:
AB123CDE456
使用像std :: hex这样的流运算符似乎不起作用。 你能给我任何建议怎么做吗?
不工作:
unsigned char *buf[] = "123456789";
file << std::hex << RSA_Encrypt(buf, 9);
仅打印一些不可读的二进制数据;
答案 0 :(得分:1)
好的,对任何有兴趣的人...... 我在这里找到了一个通用的十六进制格式化程序:Integer to hex string in C++
我稍微修改了它:
template< typename T >
std::string int2hex(T i)
{
std::stringstream stream;
stream << std::setfill ('0') << std::setw(sizeof(T)*2)
<< std::hex << (int32_t)i;
return stream.str();
}
现在我打电话给我这样的惯例:
buf = RSA_Encrypt(data, 32);
// Write hash to sig file
for(unsigned int i = 0 ; i < buf.size() ; ++i) {
uint8_t val = buf[i];
file << int2hex(val);
}
现在我的文件中有HEX字符。
答案 1 :(得分:0)
十六进制输出函数可能如下所示:
void writeHex(std::ostream &out, const char *data, size_t len)
{
char digits[] = "0123456789ABCDEF";
for (size_t i = 0; i < len; ++i) {
unsigned byte = (unsigned)data[i];
out << digits[byte >> 4] << digits[byte & 0xf];
}
}
用一个小样本来测试它:
#include <iostream>
void writeHex(std::ostream &out, const char *data, size_t len)
{
char digits[] = "0123456789ABCDEF";
for (size_t i = 0; i < len; ++i) {
unsigned byte = (unsigned)data[i];
out << digits[byte >> 4] << digits[byte & 0xf];
}
}
int main()
{
// sample data
char data[] =
"This is some test data:\n"
"\x00\x01\x02\x03\0x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
"\x10\x11\x12\x13\0x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
"\x20\x21\x22\x23\0x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
"\x30\x31\x32\x33\0x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f";
// test writeHex()
writeHex(std::cout, data, sizeof data);
std::cout << std::endl;
// done
return 0;
}
在Windows 10(64位)上使用VS2013进行编译和测试:
5468697320697320736F6D65207465737420646174613A0A000102030078303405060708090A0B0C0D0E0F101112130078313415161718191A1B1C1D1E1F202122230078323425262728292A2B2C2D2E2F303132330078333435363738393A3B3C3D3E3F00
可以使用ASCII表检查我的测试data[]
开头的人类可读文本。我只是搜索&#34; 000102&#34;并看到&#34; 0A&#34; (之前为\n
)。 &#34; 00&#34;在输出的末尾是字符串0-terminator(也被sizeof
认为)。
答案 2 :(得分:0)
现在我坚持将加密数据写入可读的文件中 HEX喜欢:
AB123CDE456
添加HexEncoder
并在管道中使用FileSink
:
StringSource ss(plain, true, new PK_EncryptorFilter(rng, enc, new HexEncoder(new FileSink("file.enc"))));
通过上述更改,数据在通过管道时会进行十六进制编码。
稍后,当您准备好阅读数据时,可以使用FileSource
并在管道中添加HexDecoder
。广告解码器在解密器之前添加,而不是在加密之后添加。
FileSource fs("file.enc", true, new HexDecoder, new PK_DecryptorFilter(rng, dec, new StringSink(recovered))));
你应该避免这种情况,因为不是一个恒定的时间比较:
if(memcmp(plain.data(), recovered.data(), plain.size()) != 0) {
cout << "RSA Mismatch" << endl;
}
改为使用VerifyBufsEqual
:
bool equal = VerifyBufsEqual(plain.data(), recovered.data(), plain.size());
VerifyBufsEqual
需要相同大小的缓冲区,所以可能是这样的:
bool equal = (plain.size() == recovered.size());
size_t size = STDMIN(plain.size(), recovered.size());
equal = VerifyBufsEqual(plain.data(), recovered.data(), size) && equal;
这可能会有所帮助......
而不是使用中间std::string
:
std::string RSA_Encrypt(unsigned char *buf, uint8_t len)
{
...
for(int i = 0; i < len; ++i) {
plain.push_back(buf[i]);
}
...
StringSource ss(plain, true, new PK_EncryptorFilter(rng, enc, new StringSink(cipher)));
...
}
您可以改为使用buf
和len
:
std::string RSA_Encrypt(unsigned char *buf, uint8_t len)
{
...
ArraySource as(buf, len, true, new PK_EncryptorFilter(rng, enc, new StringSink(cipher)));
...
}
使用构造函数重载,ArraySource
实际上是StringSource
的typedef。