есть ли способ сделать двухстороннее шифрование / дешифрование для целого числа (или строки). Обратите внимание, что я не ищу кодировку
мне нужно что-то вроде этого
шифрование (100) -> 24694
шифрование (101) -> 9564jh4 или 45216 или gvhjdfT или что-то еще …
дешифрование (24694) -> 100
Мне не нужна кодировка, потому что она биективна
base64_encode (100) -> MTAw
base64_encode (101) -> MTAx
Надеюсь, что я найду способ шифрования / дешифрования ЧИСТЫХ НОМЕРОВ (числа любви к компьютеру, это быстрее)
Вы пробовали смотреть в ROT-13 ?
Более серьезный ответ: из этого ответа SO вы можете использовать:
function numhash($n) { return (((0x0000FFFF & $n) << 16) + ((0xFFFF0000 & $n) >> 16)); } numhash(42); // 2752512 numhash(numhash(42)); // 42
function decrypt($string, $key) { $result = ''; $string = base64_decode($string); for($i=0; $i<strlen($string); $i++) { $char = substr($string, $i, 1); $keychar = substr($key, ($i % strlen($key))-1, 1); $char = chr(ord($char)-ord($keychar)); $result.=$char; } return $result; } function encrypt($string, $key) { $result = ''; for($i=0; $i<strlen($string); $i++) { $char = substr($string, $i, 1); $keychar = substr($key, ($i % strlen($key))-1, 1); $char = chr(ord($char)+ord($keychar)); $result.=$char; } return base64_encode($result); }
Вы можете просто использовать шифрование режима 3DES CBC для выполнения операции. Если вы хотите только принимать значения, которые вы сгенерировали, вы можете добавить HMAC к зашифрованному тексту. Если HMAC недостаточно, вы можете рассчитывать на формат номеров для этой конкретной схемы . Если вы хотите, чтобы пользователи не могли копировать значения друг другу, вы можете использовать случайный IV.
Таким образом, в основном вы храните номер в виде 8-байтной или 8-символьной строки ASCII с помощью левого заполнения с нулевыми значениями. Затем вы выполняете шифрование одного блока. Это позволяет вам иметь 2 ^ 64 или 10 ^ 8 номеров. Вы можете зашифровать исходный код 64, заменив символы +
и /
символы URL-safe -
и _
.
Обратите внимание, что это шифрование / дешифрование, конечно, является биективным (или перестановкой, как это обычно называют крипто). Это нормально, хотя, поскольку выход достаточно велик, чтобы злоумышленник мог угадать значение.
Это может быть больше, чем вы ищете, но я подумал, что было бы интересно построить ответ. Вот простое шифрование, сохраняющее формат, которое принимает любое 16-битное число (то есть от 0 до 65535) и шифрует его еще на 16-разрядное число и обратно, на основе 128-битного симметричного ключа. Вы можете построить что-то вроде этого.
Он детерминирован, поскольку любой вход всегда шифрует один и тот же вывод с одним и тем же ключом, но для любого числа n невозможно предсказать вывод для n + 1.
# Written in Ruby -- implement in PHP left as an exercise for the reader require 'openssl' def encrypt_block(b, k) cipher = OpenSSL::Cipher::Cipher.new 'AES-128-ECB' cipher.encrypt cipher.key = k cipher.update(b) + cipher.final end def round_key(i, k) encrypt_block(i.to_s, k) end def prf(c, k) encrypt_block(c.chr, k)[0].ord end def encrypt(m, key) left = (m >> 8) & 0xff right = m & 0xff (1..7).each do |i| copy = right right = left ^ prf(right, round_key(i, key)) left = copy end (left << 8) + right end def decrypt(m, key) left = (m >> 8) & 0xff right = m & 0xff (1..7).each do |i| copy = left left = right ^ prf(left, round_key(8 - i, key)) right = copy end (left << 8) + right end key = "0123456789abcdef" # This shows no fails and no collisions x = Hash.new (0..65535).each do |n| c = encrypt(n, key) p = decrypt(c, key) puts "FAIL" if n != p puts "COLLISION" if x.has_key? c x[c] = n end # Here are some samples (0..10).each do |n| c = encrypt(n, key) p = decrypt(c, key) puts "#{n} --> #{c}" end (0..10).each do n = rand(65536) c = encrypt(n, key) p = decrypt(c, key) puts "#{n} --> #{c}" end
Некоторые примеры:
0 --> 39031 1 --> 38273 2 --> 54182 3 --> 59129 4 --> 18743 5 --> 7628 6 --> 8978 7 --> 15474 8 --> 49783 9 --> 24614 10 --> 58570 1343 --> 19234 19812 --> 18968 6711 --> 31505 42243 --> 29837 62617 --> 52334 27174 --> 56551 3624 --> 31768 38685 --> 40918 27826 --> 42109 62589 --> 25562 20377 --> 2670