двусторонний ключ шифрования / алгоритм хэширования - PullRequest
11 голосов
/ 26 августа 2009

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

encrypt(w,x,y) = z

decrypt(z) = w, x, y

Where w = integer 
      x = string (username)
      y = unix timestamp 

и z = - это 8-значное число (возможно, включая буквы, спецификации еще нет.)

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

EDIT

Спасибо за ответы, многому научились. Таким образом, чтобы уточнить, единственное жесткое требование - 8 символов, а также возможность связывать W <-> Z. Имя пользователя (Y) и метка времени (Z) будут считаться глазурью на торте.

Я бы хотел сделать это математически, а не выполнять поиск по какой-либо базе данных, если это возможно.

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

Ответы [ 7 ]

17 голосов
/ 26 августа 2009

Шифрование и хеширование

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

Для шифрования необходим материал ключа. Существует много алгоритмов шифрования, но они делятся на две основные группы: симметричные и асимметричные.

Применение

Приложение здесь не ясно. Но если вы «зашифровываете» некоторую информацию и отправляете ее куда-то, а затем возвращаете ее и что-то делаете с ней, то стоит использовать симметричное шифрование. Например, скажем, вы хотите закодировать имя пользователя, IP-адрес и некоторый идентификатор из вашего приложения в параметре, который вы включаете в ссылку в каком-то HTML. Когда пользователь щелкает ссылку, этот параметр передается обратно в ваше приложение, и вы декодируете его, чтобы восстановить исходную информацию. Это отлично подходит для симметричного шифрования, поскольку отправитель и получатель - одна и та же сторона, а обмен ключами запрещен.

Фон

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

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

Большое преимущество симметричного шифрования в том, что оно быстрое. Все хорошо разработанные протоколы используют симметричный алгоритм для шифрования больших объемов данных. Недостатком является то, что может быть трудно безопасно обменяться ключами - что если вы не можете «встретиться» (виртуально или физически) в безопасном месте, чтобы договориться о пароле?

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

11 голосов
/ 26 августа 2009

Вам просто нужно зашифровать сериализацию (w, x, y) с помощью закрытого ключа. Используйте тот же закрытый ключ, чтобы расшифровать его.

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

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

РЕДАКТИРОВАТЬ: Поскольку размер z является жестким ограничением, вам необходимо ограничить ввод до 8 байтов и выбрать метод шифрования, который использует размер блока 64 бит (или меньше). Blowfish и Triple DES используют 64-битные блоки, но помните, что эти алгоритмы не получили такую ​​же проверку, как AES .

Если вы хотите что-то действительно простое и совершенно небезопасное, просто введите xor свой секретный ключ.

3 голосов
/ 26 августа 2009

Вы, вероятно, не можете.

Скажем, w - 32 бита, x поддерживает не менее 8 символов ASCII без учета регистра, поэтому не менее 37 бит, а y - 32 бита (возвращает вас к 2038 году, а 31 бит даже не дает вам сейчас ).

Итак, это всего не менее 101 бита данных. Вы пытаетесь сохранить его в 8-значном числе. С математической точки зрения невозможно создать обратимую функцию из большего набора в меньший, поэтому вам потребуется хранить более 12,5 битов на «цифру».

Конечно, если вы наберете более 8 символов или если у вас 16-битный юникод, то у вас, по крайней мере, есть шанс.

1 голос
/ 26 августа 2009

Давайте формализуем вашу проблему, чтобы лучше ее изучить.

Пусть k - это ключ из набора K возможных ключей, а (w, x, y) - информация из набора I, которую нам необходимо зашифровать. Давайте определим набор «зашифрованных сообщений» как A 8 , где A - алфавит, из которого мы извлекаем символы в наше зашифрованное сообщение (A = {0, 1, ..., 9, a , b, ..., z, ...}, в зависимости от ваших характеристик, как вы сказали).

Мы определяем две функции:

crypt: I * K --> A^8.
decrypt A^8 * K --> I

Проблема здесь в том, что размер набора зашифрованных сообщений A ^ 8 может быть меньше, чем набор фрагментов информации (w, x, y). Если это так, просто невозможно достичь того, что вы ищете, если мы не попробуем что-то другое ...

Предположим, что только ВЫ (или ваш сервер, или ваше приложение на вашем сервере) должны иметь возможность вычислять (w, x, y) из z. То есть вы можете отправить z кому-то, и вам все равно, что они не смогут его расшифровать.

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

Id: char[8]
CryptedInformation: byte[]

Затем вы сохраните z в столбце Id, а зашифрованную информацию в соответствующем столбце.

Когда вам нужно расшифровать информацию, кто-то даст вам z, индекс зашифрованной информации, а затем вы можете приступить к расшифровке.

Однако, если это работает для вас, вам может даже не понадобиться шифровать информацию, у вас может быть таблица:

Id: char[8]
Integer: int
Username: char[]
Timestamp: DateTime

И использовать тот же метод, ничего не расшифровывая.

Это может быть применено, например, к «системе проверки электронной почты» в процессе подписки. Ссылка, которую вы отправите пользователю по почте, будет содержать z.

Надеюсь, это поможет.

1 голос
/ 26 августа 2009

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

Целое число составляет 4 байта. Давайте предположим, что ваше имя пользователя ограничено 8 символами, и эти символы являются байтами. Тогда отметка времени составляет как минимум еще 4 байта. Это 16 байтов прямо здесь. В шестнадцатеричном формате это займет 32 цифры. Base36 или что-то будет меньше, но это не будет где-то около 8.

1 голос
/ 26 августа 2009

Хеши по определению являются только односторонними, после хеширования очень трудно вернуть исходное значение снова.

Для 2-х стороннего шифрования я бы посмотрел на TripleDES, в который .net встроил TripleDESCryptoServiceProvider .

Довольно прямолинейная статья о реализации.

EDIT

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

0 голосов
/ 26 августа 2009

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

Если вы действительно хотите сделать то, что вы описали, вам нужно просто объединить строку и метку времени (заполните лишние пробелы подчеркиванием или чем-то еще). Возьмите эту результирующую строку, преобразуйте ее в ASCII или UTF-8 или что-то еще, и найдите ее значение по модулю наибольшего простого числа меньше 10 ^ 8.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...