【问题标题】:Why is my decrypted data formatted like this?为什么我的解密数据格式是这样的?
【发布时间】:2014-07-23 18:58:24
【问题描述】:

我目前正在研究如何使用 Crypto++ 进行加密/解密。为了测试我的项目,我获得了以下值来帮助设置和验证我的项目是否正常工作:

original string: "100000"
encrypted value: "f3q2PYciHlwmS0S1NFpIdA=="
key and iv: empty byte array
key size: 24 bytes
iv size: 16 bytes

项目运行并解密加密值没问题,但不是返回

"100000"

返回

"1 0 0 0 0 0 "

每个空格实际上是“\0”。这是我用于解密的最小代码:

#include "modes.h"
#include "aes.h"
#include "base64.h"

using namespace CryptoPP;

void main()
{
    string strEncoded = "f3q2PYciHlwmS0S1NFpIdA==";
    string strDecrypted;
    string strDecoded;
    byte abKey[24];
    byte abIV[AES::BLOCKSIZE];

    memset(abKey, 0, sizeof(abKey));
    memset(abIV, 0, AES::BLOCKSIZE);

    AES::Decryption cAESDecryption(abKey, sizeof(abKey));
    CBC_Mode_ExternalCipher::Decryption cCBCDecryption(cAESDecryption, abIV);

    StringSource(strEncoded, true, new Base64Decoder(new StringSink(strDecoded)));

    StreamTransformationFilter cDecryptor(cCBCDecryption, new StringSink(strDecrypted));
    cDecryptor.Put(reinterpret_cast<const byte*>(strDecoded.c_str()), strDecoded.size());
    cDecryptor.MessageEnd();
}

我可以按原样使用解密值,但我需要帮助理解的是为什么解密值显示“1 0 0 0 0 0”而不是“100000”?顺便说一句,这是在 VS2005 中作为 Windows 控制台应用程序构建的,Crypto++ 作为静态库,我使用调试模式来查看值。

【问题讨论】:

  • 你输入的字符是8位还是16位?
  • @bmm6o 我不确定如何准确检查。如果您要问的话,我将字符集设置为“未设置”。
  • 您的代码示例不够完整,我无法引用任何变量,但是使用“100000”的地方,它存储在什么地方?它的 c_str() 的 type 和 sizeof 是什么?
  • @bmm6o 我无法告诉你,因为我无法直接访问未加密的值,但 jww 正确地知道它是在 C# 中创建的,因此导致加密字符串为 16 位二进制字符串。
  • 加密算法总是对原始字节进行操作,你有责任正确解释这些字节——包括在两端使用相同的字符编码。

标签: c++ encryption aes crypto++


【解决方案1】:

添加strHex 字符串,解密文本后添加以下行:

StringSource ss2(strDecrypted, true, new HexEncoder(new StringSink(strHex)));
cout << strHex << endl;

您应该会看到类似以下内容:

$ ./cryptopp-test.exe
310030003000300030003000

正如@Maarten 所说,它看起来像 UTF-16 LE 没有 BOM。我的猜测是样本是在 .Net 中创建的,他们要求您使用 C++/Crypto++ 进行解密。我猜 .Net 是因为它的 UTF-16 little endian,而 Java 默认是 UTF-16 big endian (IIRC)。

您也可以要求他们为您提供由getBytes(Encoding.UTF8) 生成的字符串。这也将回避问题。

所以strDecrypted 中的值不是 std::string。它只是一个需要转换的二进制字符串(又名Rope)。对于转为 UTF-8(或其他窄字符集),相信可以使用iconvlibiconv 内置在 GNU Linux 的 GLIBC (IIRC) 中,可以在 BSD 的 lib 目录中找到。

如果您在 Windows 上,则使用 WideCharToMultiByte 函数。

【讨论】:

  • 感谢现场答疑!加密值是在 .Net 中创建的,这意味着二进制字符串是 16 位的。当我使用 WideCharToMultiByte 将其转换为 UTF8 时,它给了我"100000찀쳌"。我现在可以处理了。
  • 您致电WideCharToMultiByte 两次。第一次是确定缓冲区的大小;第二次转换字符串。在调用之间,您分配一个缓冲区。 strDecryptedNULL 终止的,所以让 API 确定字符串的长度。里希特在他的书Programming Applications for Microsoft Windows 中谈到了这一点。
  • 我确实调用了该函数两次,第一次调用返回的大小为 16,但我一定会读那本书。
【解决方案2】:

很可能只是使用UTF-16LE or UCS-2LE 编码的文本,显然没有字节顺序标记(BOM)。因此,要显示文本,您必须先对其进行解码。

【讨论】:

  • reinterpret_cast&lt;const wchar_t*&gt; 替换reinterpret_cast&lt;const byte*&gt; 给了我转换参数错误,但是当我把reinterpret_cast&lt;const byte*&gt; 放在周围时,我仍然得到相同的结果。
  • 很抱歉,答案可能是正确的,但我的 C++ 字符串处理并非如此。转换/转换为某种 16 位小端字符编码数组 应该 可以解决问题,但如果我知道怎么做的话,我会被诅咒的。
猜你喜欢
  • 2011-08-05
  • 1970-01-01
  • 2012-06-06
  • 1970-01-01
  • 2011-03-14
  • 2018-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多