Как мне хешировать целое число в очень маленькую строку? - PullRequest
3 голосов
/ 21 апреля 2011

Мне нужна функция, которая, учитывая целое число соли и целое значение, будет возвращать небольшую строку хеша.Вызов функции с 1 и 56 может вернуть «1AF3».Вызов с 2 и 56 может вернуть «C2FA».

Справочная информация: у меня есть веб-приложение (написанное на C #, если это имеет значение), в котором значения Id сотрудников хранятся в виде целых чисел.Пользователи должны иметь возможность видеть непротиворечивое представление этого идентификатора, но ни один пользователь не должен видеть фактический идентификатор или такое же представление этого идентификатора, которое видит другой пользователь.

Например, предположим, что есть сотрудникс идентификатором 56.

Когда пользователь 1 входит в систему, где бы он ни увидел этого сотрудника, он видит «1AF3» или что-то в этом роде.Он может видеть этого сотрудника на разных страницах приложения, и его идентификатор всегда должен быть 1AF3, поэтому он знает, что это один и тот же парень.

Когда пользователь 2 входит в систему, если он встретит того же сотрудника, он всегда будет видеть"C2FA" или что-то в этом роде.То же самое касается пользователя 2: где бы он ни находился в системе, он увидел бы, что один сотрудник представлен этой же строкой.

Если пользователь 2 заглянет через плечо пользователя 1, а пользователь 1 вошел в систему, пользователь 2не должен быть в состоянии распознать кого-либо из своих сотрудников на экране пользователя 1. Это хэш должен быть необратимым.

Имеет ли это смысл?

Еще одно дополнительное требование заключается в том, что пользователи будут обсуждатьЭти сотрудники в электронной почте, на телефоне и в факсе должны иметь минимальный размер хеша и не содержать буквенно-цифровых символов.Идеальным было бы 10 символов или меньше.

Может быть, есть способ «свернуть» результат SHA-256 в меньшее количество символов, поскольку можно использовать весь алфавит?Понятия не имею.

Обновление: еще один обзор Спасибо всем за то, что дали этот шанс, но похоже, что я плохо объясняю это или что-то в этом роде.

Давайте представим, что вы и я оба пользователи этой системы.Ты Фред, а я Крис.Ваш UserId равен 2, а мой UserId равен 1. Давайте также предположим, что в системе 5 сотрудников.Сотрудники не являются пользователями.Вы можете думать о них как о продуктах или о чем угодно.Я просто говорю о 5 общих сущностях, с которыми вы, Фред и я, Крис, имеете дело с каждым.

Фред, каждый раз, когда вы входите в систему, вы должны иметь возможность однозначно идентифицировать каждого сотрудника.Каждый раз, когда я, Крис, захожу в систему, мне также нужно работать с сотрудниками, и мне тоже нужно будет идентифицировать их уникальным образом.Но если я когда-нибудь посмотрю через ваше плечо, пока вы управляете сотрудниками, я не смогу выяснить, какими из них вы управляете.

Итак, в то время как в базе данных идентификаторы сотрудников равны 1, 2, 3, 4 и 5. Вы и я не видим их в нашем интерфейсе.Я могу видеть A, B, C, D и E, а вы можете видеть F, G, H, I и J. Так что, хотя E и J представляют одного и того же сотрудника, я не могу смотреть на ваш экран, пока вывы работаете с вашим сотрудником "J" и знаете, что вы работаете с сотрудником 5, потому что для меня этот сотрудник называется сотрудником "E" для меня.

Итак, каждый Фред и Крис могут работать с одним и тем женабор сотрудников, но если бы они увидели работу друг друга или обсуждение в электронном письме, они не смогли бы узнать, о каких сотрудниках говорил другой парень.

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

Поскольку Фреду и Крису каждый из них должен обсудить сотрудников по электронной почте и телефону со своими клиентами и клиентамиЯ хотел бы, чтобы идентификаторы, которые они используют в этих обсуждениях, были настолько простыми, насколько мы можем их получить.

Ответы [ 6 ]

3 голосов
/ 22 апреля 2011

Концептуально, вот что вы хотите:

У вас есть набор идентификаторов сотрудников, которые вы можете представить как элемент в данном пространстве S . У вас также есть несколько пользователей, и вы хотите, чтобы каждый пользователь видел перестановку пространства S , которая является специфической для пользователя и такой, что детали этой перестановки не могут быть угаданы любым другим пользователем.

Это требует симметричного шифрования. А именно, каждый идентификатор сотрудника является числовым значением (например, 32-разрядным целым числом), и пользователь «A» видит сотрудника x как E k (x) , там k - это секретный ключ, который специфичен для «A» и о котором «B» не может догадаться. Итак, вам нужно две вещи:

  • блочный шифр, который может работать с короткими значениями (например, 32-битными словами);
  • метод, который превращает идентификатор пользователя в пользовательский ключ.

Для блочного шифра проблема заключается в том, что короткие блоки представляют собой проблему безопасности для нормального использования блочного шифра (то есть для шифрования длинных сообщений). Поэтому во всех опубликованных безопасных блочных шифрах используются большие блоки (64 бита и более). 64 бита могут быть представлены более чем 11 символами с использованием прописных и строчных букв и цифр (62 11 несколько больше, чем 2 64 ). Если вам этого достаточно, используйте 3DES . Если вы хотите что-то меньшее, вам придется создать свой собственный шифр, который не рекомендуется вообще . Возможно, вы захотите попробовать KeeLoq: см. этот документ для указателей (KeeLoq криптографически «сломан», но не слишком сильно, учитывая ваш контекст). Существует универсальный метод для строительных блочных шифров с произвольными размерами блоков при заданном потоковом шифре с возможностью поиска, но это в основном теоретический подход (реализация требует разбираться с высокоточными значениями с плавающей запятой, что может быть сделано, но очень медленно).

Для пользовательского ключа: вы хотите что-то, что может вычислять веб-приложение, но не пользователи. Это означает, что веб-приложение знает секретный ключ K ; затем пользовательский ключ шифрования может быть результатом HMAC (с хорошей хэш-функцией, такой как SHA-256), примененной к идентификатору пользователя, и использованием ключа K . Затем вы усекаете вывод HMAC до длины, необходимой для пользовательского ключа (например, для 3DES требуется 24-байтовый ключ).

C # имеет реализации TripleDES и HMAC / SHA-256 (в System.Security.Cryptography пространстве имен).

(Не существует общепринятого стандарта безопасности для блочного шифра с 32-разрядными блоками. Это все еще открытая область исследований.)

1 голос
/ 21 апреля 2011

При таком подходе могут возникнуть проблемы, но вы можете сделать это следующим образом:

  • Создать массив, содержащий все ваши символы (скажем, массив из 25 элементов)
  • Хешировать вашу строкуиспользуя любую хеш-функцию
  • Выберите число октетов из полученного хеша (4 октета, если вы хотите 4 символа в нашей результирующей строке) из предопределенных позиций
  • Для каждого октета вычислите index = octet % array_size.Индекс дает позицию для каждого из ваших символов

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

0 голосов
/ 22 апреля 2011

Используя 4 символа, вы получите в сумме: 36 ^ 4 = 1679616. Вы можете изменить все возможности сотрудников вместе.Если вы вычислите de квадратный корень, вы получите 1296.

Затем вы можете сгенерировать упорядоченную таблицу со всеми возможностями в первом столбце, а затем случайным образом распределить идентификаторы от 1 до 1296 в столбцы одера.Вы получите что-то вроде этого:

key    a    b
AAAA  386   67
AAAB   86  945
...

С этим решением у вас будет справочная таблица, масштабируемая до 1296 сотрудников.Однако, если вы подумаете о добавлении дополнительного символа к своему ключу, вы получите гораздо больше возможностей (36 ^ 5) ^ 0.5 = 7776.

С этим решением угадывание ключа даст вам один шанс на 1296 или 7776 длясм. информацию о сотруднике.

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

0 голосов
/ 22 апреля 2011

Просто идея подхода, основанного на добавленной вами дополнительной информации. Безопасность этой идеи - очень очень легкая, и я бы не рекомендовал ее, если вы думаете, что люди попытаются ее взломать, но ее стоит бросить в горшок.

Вы можете создать личный хеш, сдвинув бит идентификатора сотрудника на основе вашего собственного идентификатора сотрудника. Затем, добавив любой дополнительный код обфускации, который вам нужен к полученному числу, например, преобразовав его в шестнадцатеричный код. Э.Г.

string hashedEmployeeId = (employeeIdToHash << myEmployeeId).ToString("X");

Это будет генерировать хэшированные идентификаторы сотрудников на основе вашего собственного идентификатора, но вы можете столкнуться с проблемами, когда идентификаторы сотрудников станут большими (особенно ваши собственные!)

Просто повторюсь, что это само по себе не очень безопасно, но может помочь вам на вашем пути.

0 голосов
/ 21 апреля 2011

Вот мои мысли, доходящие до сути (я полагаю, что если вы обговорили свой вопрос, я обговорю мой ответ. Полагаю, вы найдете это полезным):

  • Все приветствуют Томаса, потому что он четко установил свое господство.
  • 0-9, A-F - представление данных. Вы можете сделать это A-Z, 0-9, исключить некоторые необычные буквы и представлять шесть бит на символ.
  • Можно сказать, что все хэши имеют коллизии. Если вы приблизитесь к насыщению, у вас получится два человека с одинаковым хешем. Хэши тоже односторонние. Вам понадобится отображение, которое позволяет разворот. Если у вас есть обратное отображение, почему бы не заполнить его случайными строками, которые не сталкиваются?
  • Вы запутываете ограниченный набор данных. С большой и секретной солью вы можете предотвратить разворот. Тем не менее, вы меняете один идентификатор на другой. Идентификатор все еще уникален и постоянен, поэтому мне интересно, как это повышает безопасность.
    • У меня есть клиенты, и если бы я увидел что-то подобное, я бы положил деньги, чтобы идентификатор сотрудника был SSN. Надеюсь, ты этого не делаешь.

Идентификатор сотрудника и альтернативный идентификатор сотрудника - это то, что вы предлагаете. Так как они должны быть обратимыми для вас, но не для публики, вы должны хранить это в двустороннем соединении и хранить это в секрете. Поскольку существует риск столкновения с хешем, и вам все равно нужно иметь обратную карту, альтернативный идентификатор также может быть случайной строкой. В любом случае идентификатор должен быть произвольным, и мне бы очень хотелось узнать о предполагаемом преимуществе безопасности вашего подхода с двумя идентификаторами для одного сотрудника; это заставляет меня думать о невыполнимой миссии и списке NOC.

0 голосов
/ 21 апреля 2011

Существует много способов «анонимизации» информации. Было бы полезно, если бы вы могли быть более конкретными относительно контекста и того, какие «активы» вы действительно пытаетесь защитить здесь, от кого. Смотрите наш FAQ.

Например, может ли один пользователь знать номер другого пользователя? Вероятно, они могли бы быстро это выяснить, если обнаружат с помощью других средств соответствие между 1AF3 и C2FA.

Но специально для вашего более узкого вопроса хороший хеш уже будет хорошо перемешан, поэтому я думаю, что вы могли бы просто укоротить, например, значение хеш-функции SHA-256. Но Томас, вероятно, будет знать окончательный ответ там.

...