如何将SecByteBlock转换为字符串?

时间:2015-08-10 21:31:16

标签: c++ security aes crypto++

我在尝试将SecByteBlock转换为字符串时遇到问题。 这是我的情况:

我想使用带静态密钥和动态iv的AES加密用户访问数据。 我的代码是这样的:

AesKeyIvFactory aesKeyIvFactory;
SecByteBlock key = aesKeyIvFactory.loadKey();
SecByteBlock iv = aesKeyIvFactory.createIv();

encryptionService->encode(&userAccess, key, iv);
std::string token = std::string(iv.begin(), iv.end()) + userAccess;

上面的代码应该是:

  1. 从文件加载密钥;

  2. 创建iv;

  3. 加密(AES)用户访问数据;

  4. 将iv与加密的用户数据访问连接起来以创建“令牌”;

  5. 多次运行测试,有时(1到10次)std::string(iv.begin(), iv.end())无法正常运行。似乎静脉注射中存在“换行”,导致转换失败。

    我尝试了很多东西,但没有任何作用,我没有使用c ++的经验。

    我希望有人可以帮助我。

2 个答案:

答案 0 :(得分:3)

  

我在尝试将SecByteBlock转换为字符串

时遇到问题

如果问题是从SecByteBlock及其byte数组转换为std::string及其char数组,那么您应该:

SecByteBlock iv;
...

// C-style cast
std::string token = std::string((const char*)iv.data(), iv.size()) + userAccess;

或者,

SecByteBlock iv;
...

// C++-style cast
std::string token = std::string(reinterpret_cast<const char*>(iv.data()), iv.size()) + userAccess;

您也可以放弃作业,只需初始化并稍后添加:

SecByteBlock iv;
...

std::string token(reinterpret_cast<const char*>(iv.data()), iv.size());
...

std::string userAccess;
...

token += userAccess;

您可能遇到的另一个问题是stringSecByteBlock。你应该这样做:

std::string str;
...

// C-style cast
SecByteBlock sbb((const byte*)str.data(), str.size());

或者:

std::string str;
...

// C++-style cast
SecByteBlock sbb(reinterpret_cast<const byte*>(str.data()), str.size());

答案 1 :(得分:2)

我认为Eric回答了关于如何将SecByteBlock转换为std::string的主要问题(包括char*byte*之间的明确转换)。但是,您可以在这里解决std::string token = std::string(iv.begin(), iv.end()) + userAccess;问题。

string token;

SecByteBlock iv(16), userAccess(16);
OS_GenerateRandomBlock(false, iv, iv.size());
OS_GenerateRandomBlock(false, userAccess, userAccess.size());

SecByteBlock nil;
nil.CleanNew(HMAC<SHA256>::DEFAULT_KEYLENGTH);

HMAC<SHA256> hmac;
hmac.SetKey(nil.data(), nil.size());

HashFilter filter(hmac, new HexEncoder(new StringSink(token)));
filter.Put(iv.data(), iv.size());
filter.Put(userAccess.data(), userAccess.size());
filter.MessageEnd();

cout << token << endl;

SecByteBlock nil创建一个没有内存或大小的对象。 nil.CleanNew(HMAC<SHA256>::DEFAULT_KEYLENGTH)大小并将SecByteBlock初始化为0.否则,您有一个未初始化的内存块。

可以用0-inialized数组声明它并调整它的大小,但你必须熟悉这些来源,因为它没有Docry-Docimented,因为Crypto ++ 5.6.2。这种方式是使用NULL指针,但非0大小。这是它的样子,但它非常不直观:

SecByteBlock nil(NULL, HMAC<SHA256>::DEFAULT_KEYLENGTH);

这个技巧依赖于这个SecBlock<T>构造函数:

00250    SecBlock(const T *t, size_type len)
00251        : m_size(len)
00252    {
00253        m_ptr = m_alloc.allocate(len, NULL);
00254        if (t == NULL)
00255            memset_z(m_ptr, 0, len*sizeof(T));
00256        else
00257            memcpy(m_ptr, t, len*sizeof(T));
00258    }

如果可能,您应使用HKDF代替带有HMAC<SHA>向量的nil来从安全参数中提取熵。您可以在HKDF class的回购中找到HKDF。它是一个独立的标题,所以它只会工作&#34;。

使用ivuserAccess的随机值的典型程序运行是:

$ ./cryptopp-test.exe
061CF705259058C4E01A2BF22830FC3F2A7E97F12FE605B38405B1E1B19A9E0F

另一种接近它的方法可能是基于SecByteBlock operator +=的连接。结果是二进制字符串,而不是人类可读的ASCII字符串。

SecByteBlock result;

result += iv;
result += SecByteBlock(userAccess.data(), userAccess.size());

string token(result.data(), result.size());

如果您需要一个人类可读的字符串,请通过HexEncoder

运行它
HexEncoder hex(new StringSink(token));
hex.Put(result.data(), result.size());
hex.MessageEnd();

但是它没有从参数中提取熵,所以我个人更喜欢它。

当您从SecByteBlock移动到std::string时,您实际上会失去安全分配器。这意味着在将数据导出到string对象后,副本中的数据不会被归零。

HexEncoder是一个便利项,它允许您转储二进制字符串。

另一个有用的可能是Base64URLEncoder。它使用网络安全字母表。