计算 RSA 并以十六进制格式保存到文件

Calculate RSA and save to file in HEX

本文关键字:格式 存到文件 十六进制 RSA 计算      更新时间:2023-10-16

>我正在尝试使用 rsa 加密缓冲区,然后将十六进制格式的数据保存到文件中。我正在使用加密++ 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;
}

现在我坚持将加密数据写入可读十六进制文件,例如:

AB123CDE456

使用像 std::hex 这样的流运算符似乎不起作用。你能给我任何建议如何做到这一点吗?

不工作:

unsigned char *buf[] = "123456789";
file << std::hex << RSA_Encrypt(buf, 9);

仅打印一些不可读的二进制数据;

好的,对于任何感兴趣的人...我在这里找到了一个通用的十六进制格式化程序: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);
}

现在我在文件中得到十六进制字符。

十六进制输出函数可能如下所示:

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"
    "x00x01x02x03x04x05x06x07x08x09x0ax0bx0cx0dx0ex0f"
    "x10x11x12x13x14x15x16x17x18x19x1ax1bx1cx1dx1ex1f"
    "x20x21x22x23x24x25x26x27x28x29x2ax2bx2cx2dx2ex2f"
    "x30x31x32x33x34x35x36x37x38x39x3ax3bx3cx3dx3ex3f";
  // test writeHex()
  writeHex(std::cout, data, sizeof data);
  std::cout << std::endl;
  // done
  return 0;
}

在Windows 10(64位(上使用VS2013编译和测试:

5468697320697320736F6D65207465737420646174613A0A000102030078303405060708090A0B0C0D0E0F101112130078313415161718191A1B1C1D1E1F202122230078323425262728292A2B2C2D2E2F303132330078333435363738393A3B3C3D3E3F00

我的测试data[]开始时的人类可读文本可以使用 ASCII 表进行检查。我只是搜索了"000102",之前看到了"0A"(n(。输出末尾的"00"表示字符串 0 终止符(sizeof也考虑了这一点(。

现在我坚持将加密数据写入可读文件 十六进制,如:

AB123CDE456

添加HexEncoder并在管道中使用FileSink

StringSource ss(plain, true, new PK_EncryptorFilter(rng, enc, new HexEncoder(new FileSink("file.enc"))));  
通过

上述更改,数据在通过管道时进行十六进制编码。

稍后,当您准备好读取数据时,您可以使用FileSource并在管道中添加HexDecoder。Ad 解码器是在解密器之前添加的,而不是像加密时那样在之后添加。

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)));    
    ...
}

您可以改用buflen

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的类型定义。