#algorithm #encryption #encryption-symmetric
Вопрос:
Мне нужны две функции:
enc("FE45LOABCD") -> "ABCDEFGHIJ"
dec("ABCDEFGHIJ") -> "FE45LOABCD"
Входные данные длиной 10 символов всегда имеют длину 10 символов, и вывод enc также должен быть уникальной строкой длиной 10 символов.
Входная строка должна отличаться от выходной строки. Выходная строка должна выглядеть совершенно иначе, чем входная строка.
Разрешенные буквы, которые находятся в выводе и вводе A
, — Z
и 0
— 9
Глупый подход был бы:
function enc(plaintext) {
switch plaintext:
case "AAAAAAAAA2":
return "WGTHJURTZB";
case "AAAAAAAAA3":
return "TWRJK4QLJH";
case "AAAAAAAAA4":
return "WE7GHPLOYX";
//and so on. In total 36^10 possibilities, that is obiously to much
}
Язык программирования-Javascript, и я использую NodeJS.
Есть ли способ решить эту проблему?
Комментарии:
1. Какова ваша цель? Вы когда-нибудь рассматривали шифрование с сохранением формата ?
2. Какие требования вы хотите получить для этого результата? Например: если мы просто выведем исходную десятисимвольную строку, это будет соответствовать вашему текущему набору требований.
3. Эй, входная строка должна отличаться от выходной строки. Выходная строка должна выглядеть совершенно иначе, чем входная строка.
4. Эй, @RBarryYoung, я обновил информацию в своем вопросе.
Ответ №1:
Вам просто нужен симметричный шифр-любой симметричный шифр может быть адаптирован, хотя вы хотите убедиться, что он поддерживает нужный вам ограниченный алфавит. Хорошим выбором был бы шифр вигенера. Что-то вроде [код C]:
bool vigenere(char *data, bool decode, const char *alphabet, const char *key) {
size_t alpha_size = strlen(alphabet);
size_t key_size = strlen(key);
unsigned char code[key_size];
for (size_t i = 0; i < key_size; i ) {
if (const char *p = strchr(alphabet, key[i])) {
code[i] = p - alphabet;
if (decode)
code[i] = (alpha_size - code[i]) % alpha_size;
} else {
fprintf(stderr, "key character %c not in the alphabetn", key[i]);
return false; } }
for (size_t i = 0; data[i]; i) {
if (const char *p = strchr(alphabet, data[i]))
data[i] = alphabet[(p - alphabet code[i % key_size]) % alpha_size]; }
return true;
}
Вы бы использовали это в "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
качестве своего алфавита (просто фиксированная строка со всеми разрешенными символами и БЕЗ повторов), и любая строка из этих символов в качестве ключа (она не должна быть длиной 10 символов, но с 10 это было бы довольно хорошо для ваших требований).
Ответ №2:
Хороший способ сделать это-использовать сеть Feistel:
Сначала разделите строку на две половины и преобразуйте их в числа a
и b
, где каждое число находится в [0,36 5].
Пусть ПРЕДЕЛ = 36 5, а затем:
repeat 3 times:
a = (a hash(b)%LIMIT ) % LIMIT
b = (b hash(a)%LIMIT ) % LIMIT
hash()
может быть любая хэш-функция. Когда это будет сделано, вы преобразуете a
и b
возвращаете строки и соединяете их.
Чтобы вернуть исходную строку, вам нужно отменить этот цикл. Это легко, потому что каждую из выполняемых им операций легко инвертировать:
repeat 3 times:
b = (b LIMIT - hash(a)%LIMIT ) % LIMIT
a = (a LIMIT - hash(b)%LIMIT ) % LIMIT
Обратите внимание, что LIMIT
деталь находится там, потому что нам нужно предоставить положительное значение %
оператору.