Как преобразовать SecByteBlock в строку?
У меня возникла проблема при попытке конвертировать SecByteBlock
нанизывать. Вот мой случай:
Я хочу зашифровать данные доступа пользователей, используя AES со статическим ключом и динамическим iv. Мой код примерно такой:
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;
Код выше должен:
Загрузить ключ из файла;
Создать iv;
Шифровать (AES) данные доступа пользователей;
Объединить iv с зашифрованным доступом к данным пользователя, чтобы создать "токен";
Запуск теста несколько раз, иногда (от 1 до 10 раз) std::string(iv.begin(), iv.end())
не работает правильно. Кажется, что в iv есть "разрыв строки", который делает преобразование неудачным.
Я много чего пробовал, но ничего не работает, и у меня нет опыта работы с C++.
Я надеюсь, что кто-то может мне помочь.
2 ответа
Я думаю, что Эрик ответил на ваш основной вопрос о том, как преобразовать 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 нулями, но вы должны быть знакомы с источниками, потому что он не документирован по Doxygen от 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
в репо на HKDF class
, Это автономный заголовок, поэтому он будет "просто работать".
Типичный прогон программы со случайными значениями для iv
а также userAccess
является:
$ ./cryptopp-test.exe
061CF705259058C4E01A2BF22830FC3F2A7E97F12FE605B38405B1E1B19A9E0F
Другой способ приблизиться к этому мог бы быть объединением, основанным на SecByteBlock
"s 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
, Он использует веб-безопасный алфавит.
У меня возникла проблема при попытке преобразовать 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;
Другая проблема, которая может возникнуть string
в SecByteBlock
, Вы должны сделать это:
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());