Как стать автором
Обновить

Простой алгоритм шифрования данных

В одном из проектов, клиент поставил задачу хранить номера кредитных карточек и код cvv в базе данных. Сказано сделано. Но хранить в открытом виде данные в базе — смерти подобно. Нужно было быть уверенным, что если сопрут базу, то толку от нее никакого не будет.

Сразу подумал о md5. Но использовать хеш md5 можно в одну сторону. Родные функции шифрования mysql тоже не хотелось, а хотелось написать что нить свое, простое.

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

Но простая математика не пойдет, довольно просто разгадать. И вот здесь мне вспомнился ролик на ютубе о числах Фибоначчи.

Если взять, для каждого кодируемого числа, число Фибоначчи и произвести над ними математическое уравнение, то в результате мы получим некое число, которое можно назад декриптовать, используя ранее придуманный результат.

И опять, в любых числах мы увидим закономерность. К примеру, надо закриптовать число 4 из строки «12345». Для четверки из чисел Фибоначчи подойдет 1 2 3 5 8.

(4 + 5) + (4*5) = 29

Думаю, увидеть закономерность не составит большого труда. Как же выкрутится, самый просто способ, это сдвинуть последовательность чисел Фибоначчи на определенный шаг. Допустим, пользователь в системе имеет какой-то идентификатор, к примеру 26. Вот с этого числа и рассчитаем новую последовательность — 26 52 78 130 208.

Новый результат:

(4 + 130) + (4*130) = 654

Теперь для каждого пользователя будет своя последовательность, что сделать почти невозможным угадать логику.

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

Немного кода на PHP

function enc($num, $guid) {
    $old = 0;
    $fib_old = 0;
    $fib = $guid;
    ///
    $data = array();
    ///
    $i = 0;
    $len = strlen($num);
    while ($i < $len) {
        ///
        $fib_old = $fib;
        $fib = $fib + $old;
        ///
        $chr = (int)substr($num, $i, 1);
        $data[] = ($chr + $fib) + ($fib * $chr);
        ///
        $old = $fib_old;
        ///
        $i++;
    }
    return implode("|", $data);
}
 
function dec($enc, $guid) {
    $data = explode("|", $enc);
    ///
    $cnt = count($data);
    ///
    $old = 0;
    $fib_old = 0;
    $fib = $guid;
    ///
    $numbs = array();
    ///
    $i = 0;
    while ($i < $cnt) {
        ///
        $fib_old = $fib;
        $fib = $fib + $old;
        ///
        $s = (int)$data[$i];
        $numbs[] = ($s - $fib)/(1 + $fib);
        ///
        $old = $fib_old;
        ///
        $i++;
    }
    ///
    return implode("", $numbs);
}


Вызовем функцию enc(«1234512345», 26)
Результат: 53|158|315|654|1253|677|1640|3539|7154|13889

В обратную сторону dec(«53|158|315|654|1253|677|1640|3539|7154|13889», 26)
Результат: «1234512345»

Единственный минус, это пришлось использовать символ разделителя, иначе не получится число для расшифровки.

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

PS В реальном коде я применил более сложную математическую формулу, а формула (x + y) + (x*y) = z приведена для примера.
Теги:
Хабы:
Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.