Хеширование строковых значений приводит к различным выводам на Linux против Windows в C ++ - PullRequest
4 голосов
/ 20 февраля 2020

Я пытаюсь получить sh одинарных std::string и std::vector<std::string> значений. Я следую за примерами из cppreference и boost . Когда код скомпилирован и запущен на Windows против Linux, я получаю другие результаты.

Файл заголовка для MyHasher.h выглядит следующим образом.

class MyHasher {
 private:
  MyHasher() = delete;
 public:
  static std::size_t hash(std::vector<std::string> ids);
  static std::size_t hash(std::string s);
  static void hashCombine(std::size_t &seed, std::size_t value);
};

CPP file MyHasher.cpp выглядит следующим образом.

std::size_t MyHasher::hash(std::vector<std::string> ids) {
  std::size_t seed = 0;
  for (auto id : ids) {
    std::size_t h = std::hash<std::string>{}(id);
    hashCombine(seed, h);
  }
  return seed;
}
std::size_t MyHasher::hash(std::string s) {
  std::size_t seed = 0;
  std::size_t h = std::hash<std::string>{}(s);
  hashCombine(seed, h);
  return seed;
}
void MyHasher::hashCombine(std::size_t &seed, std::size_t value) {
  seed ^= value + 0x9e3779b9 + (seed<<6) + (seed>>2);
}

Пример программы затем выполняется следующим образом.

int main() {
  std::cout << std::to_string(MyHasher::hash("0")) << " | 0" << std::endl;
  std::cout << std::to_string(MyHasher::hash(std::vector<std::string>{"0"})) << " | 0" << std::endl;
  std::cout << std::to_string(MyHasher::hash(std::vector<std::string>{"0", "1"})) << " | 0 1" << std::endl;
  return 0;
}

On Linux (g ++ 7.4.0), вывод

2297668036269395695 | 0
2297668036269395695 | 0
10545066640295778616 | 0 1

Вкл. Windows (Visual Studio Community 2019, MSV C -14.0), вывод выглядит следующим образом.

12638135526163551848 | 0
12638135526163551848 | 0
1964774108746342951 | 0 1

Есть идеи по этому несоответствию?

Что я действительно хочу, так это способ всегда генерировать уникальный вывод ha sh, который зависит от ввода, но кроссплатформенный и фиксированной ширины. Ширина не важна, скажем так, но при условии, что она одинакова, независимо от входных данных.

1 Ответ

5 голосов
/ 20 февраля 2020

В до c. std :: ha sh, явно упоминается, что:

Фактические функции ha sh зависят от реализации

Функции Ha sh требуются только для получения одного и того же результата для одного и того же ввода при одном выполнении программы;

Я немного не уверен о функции ha sh, которая всегда возвращает идентичные хэши для одинакового ввода. Я немного погуглил, но не смог найти то, что осмелился бы представить.

Предполагая, что библиотека std MS VC ++ и g ++ может быть разных реализаций, нельзя ожидать, что будут созданы идентичные хеши для идентичного ввода.

Внимательно читая вторую часть цитаты, вы даже не можете ожидать, что одна и та же программа приведет к одинаковым хэшам для одинакового ввода в разных процессах (например, при запуске, выходе и повторном запуске).


Cryptographi c ha sh функции может быть решением:

  • это определено c, что означает, что одно и то же сообщение всегда приводит к то же самое ха sh
  • быстро вычислить значение га sh для любого данного сообщения
  • невозможно создать сообщение, которое приводит к данному значению га sh
  • невозможно найти два разных сообщения с одинаковым значением ha sh. Небольшое изменение в сообщении должно изменить значение ha sh настолько сильно, что новое значение ha sh выглядит некоррелированным со старым значением ha sh ( лавинный эффект )

Контрольные суммы относятся к ha sh функции. Для контрольной суммы должно потребоваться одинаковое количество выводов для идентичного ввода (чтобы быть надежным).

Таким образом, реализация контрольной суммы, основанная на функции ha sh, должна также соответствовать требованию OP.

Принятый ответ на SSE: Какой алгоритм хеширования я должен использовать для проверки контрольной суммы файла? рекомендует SHA256 или SHA512 .

Это запомнилось мне Я недавно слышал, что git использует вариант SHA-1 , но git может также использовать SHA256 , что мне кажется как вариант использования с чем (я предположим) OP может иметь.

...