В одном из проектов, клиент поставил задачу хранить номера кредитных карточек и код 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
Вызовем функцию 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 приведена для примера.
Сразу подумал о 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 приведена для примера.