Как преобразовать 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;

Код выше должен:

  1. Загрузить ключ из файла;

  2. Создать iv;

  3. Шифровать (AES) данные доступа пользователей;

  4. Объединить 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());
Другие вопросы по тегам