[英]How to encrypt/decrypt an integer in PHP
有沒有辦法對整數(或字符串)進行 2 路加密/解密請注意,我不是在尋找編碼
我需要這樣的東西
加密 (100) --> 24694
加密 (101) --> 9564jh4 或 45216 或 gvhjdfT 或其他任何...
解密 (24694) --> 100
我不需要編碼,因為它是雙射的
base64_encode(100) --> MTAw
base64_encode(101) --> MTAx
我希望我能在這里找到一種加密/解密純數字的方法(計算機喜歡數字,它更快)
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);
}
64位支持。 負數支持。 和一點安全鹽。
@Petr Cibulka
class NumHash {
private static $SALT = 0xd0c0adbf;
public static function encrypt($n) {
return (PHP_INT_SIZE == 4 ? self::encrypt32($n) : self::encrypt64($n)) ^ self::$SALT;
}
public static function decrypt($n) {
$n ^= self::$SALT;
return PHP_INT_SIZE == 4 ? self::decrypt32($n) : self::decrypt64($n);
}
public static function encrypt32($n) {
return ((0x000000FF & $n) << 24) + (((0xFFFFFF00 & $n) >> 8) & 0x00FFFFFF);
}
public static function decrypt32($n) {
return ((0x00FFFFFF & $n) << 8) + (((0xFF000000 & $n) >> 24) & 0x000000FF);
}
public static function encrypt64($n) {
/*
echo PHP_EOL . $n . PHP_EOL;
printf("n :%20X\n", $n);
printf("<< :%20X\n", (0x000000000000FFFF & $n) << 48);
printf(">> :%20X\n", (0xFFFFFFFFFFFF0000 & $n) >> 16);
printf(">>& :%20X\n", ((0xFFFFFFFFFFFF0000 & $n) >> 16) & 0x0000FFFFFFFFFFFF);
printf("= :%20X\n", ((0x000000000000FFFF & $n) << 48) + (((0xFFFFFFFFFFFF0000 & $n) >> 16) & 0x0000FFFFFFFFFFFF));
/* */
return ((0x000000000000FFFF & $n) << 48) + (((0xFFFFFFFFFFFF0000 & $n) >> 16) & 0x0000FFFFFFFFFFFF);
}
public static function decrypt64($n) {
/*
echo PHP_EOL;
printf("n :%20X\n", $n);
printf("<< :%20X\n", (0x0000FFFFFFFFFFFF & $n) << 16);
printf(">> :%20X\n", (0xFFFF000000000000 & $n) >> 48);
printf(">>& :%20X\n", ((0xFFFF000000000000 & $n) >> 48) & 0x000000000000FFFF);
printf("= :%20X\n", ((0x0000FFFFFFFFFFFF & $n) << 16) + (((0xFFFF000000000000 & $n) >> 48) & 0x000000000000FFFF));
/* */
return ((0x0000FFFFFFFFFFFF & $n) << 16) + (((0xFFFF000000000000 & $n) >> 48) & 0x000000000000FFFF);
}
}
var_dump(NumHash::encrypt(42));
var_dump(NumHash::encrypt(NumHash::encrypt(42)));
var_dump(NumHash::decrypt(NumHash::encrypt(42)));
echo PHP_EOL;
// stability test
var_dump(NumHash::decrypt(NumHash::encrypt(0)));
var_dump(NumHash::decrypt(NumHash::encrypt(-1)));
var_dump(NumHash::decrypt(NumHash::encrypt(210021200651)));
var_dump(NumHash::decrypt(NumHash::encrypt(210042420501)));
這是一步一步(刪除評論):
210042420501
n : 30E780FD15
<< : FD15000000000000
>> : 30E780
>>& : 30E780
= : FD1500000030E780
n : FD1500000030E780
<< : 30E7800000
>> : FFFFFFFFFFFFFD15
>>& : FD15
= : 30E780FD15
int(210042420501)
您可以簡單地使用 3DES CBC 模式加密來執行操作。 如果您只想接受您生成的值,您可以在密文中添加一個 HMAC。 如果 HMAC 不夠用,您可以依賴此特定方案的數字格式。 如果您希望用戶不能相互復制值,您可以使用隨機 IV。
所以基本上你通過用零值左填充將數字存儲為 8 字節或 8 ASCII 字符串。 然后對單個塊執行加密。 這允許您擁有 2^64 或 10^8 個數字。 您可以對結果進行 base 64 加密,將+
和/
字符替換為 URL 安全的-
和_
字符。
請注意,這種加密/解密當然是雙射的(或置換,因為它通常在加密中被稱為)。 不過沒關系,因為輸出足夠大,攻擊者很難猜測一個值。
這可能比您正在尋找的要多,但我認為構建一個答案會很有趣。 這是一個簡單的格式保留加密,它采用任何 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
一個簡單的函數,它破壞整數保持較小的數字很小(如果你需要保持幅度):
function switchquartets($n){
return ((0x0000000F & $n) << 4) + ((0x000000F0& $n)>>4)
+ ((0x00000F00 & $n) << 4) + ((0x0000F000& $n)>>4)
+ ((0x000F0000 & $n) << 4) + ((0x00F00000& $n)>>4)
+ ((0x0F000000 & $n) << 4) + ((0xF0000000& $n)>>4);
}
方法“雙方”:
function dsCrypt($input,$decrypt=false) {
$o = $s1 = $s2 = array(); // Arrays for: Output, Square1, Square2
// формируем базовый массив с набором символов
$basea = array('?','(','@',';','$','#',"]","&",'*'); // base symbol set
$basea = array_merge($basea, range('a','z'), range('A','Z'), range(0,9) );
$basea = array_merge($basea, array('!',')','_','+','|','%','/','[','.',' ') );
$dimension=9; // of squares
for($i=0;$i<$dimension;$i++) { // create Squares
for($j=0;$j<$dimension;$j++) {
$s1[$i][$j] = $basea[$i*$dimension+$j];
$s2[$i][$j] = str_rot13($basea[($dimension*$dimension-1) - ($i*$dimension+$j)]);
}
}
unset($basea);
$m = floor(strlen($input)/2)*2; // !strlen%2
$symbl = $m==strlen($input) ? '':$input[strlen($input)-1]; // last symbol (unpaired)
$al = array();
// crypt/uncrypt pairs of symbols
for ($ii=0; $ii<$m; $ii+=2) {
$symb1 = $symbn1 = strval($input[$ii]);
$symb2 = $symbn2 = strval($input[$ii+1]);
$a1 = $a2 = array();
for($i=0;$i<$dimension;$i++) { // search symbols in Squares
for($j=0;$j<$dimension;$j++) {
if ($decrypt) {
if ($symb1===strval($s2[$i][$j]) ) $a1=array($i,$j);
if ($symb2===strval($s1[$i][$j]) ) $a2=array($i,$j);
if (!empty($symbl) && $symbl===strval($s2[$i][$j])) $al=array($i,$j);
}
else {
if ($symb1===strval($s1[$i][$j]) ) $a1=array($i,$j);
if ($symb2===strval($s2[$i][$j]) ) $a2=array($i,$j);
if (!empty($symbl) && $symbl===strval($s1[$i][$j])) $al=array($i,$j);
}
}
}
if (sizeof($a1) && sizeof($a2)) {
$symbn1 = $decrypt ? $s1[$a1[0]][$a2[1]] : $s2[$a1[0]][$a2[1]];
$symbn2 = $decrypt ? $s2[$a2[0]][$a1[1]] : $s1[$a2[0]][$a1[1]];
}
$o[] = $symbn1.$symbn2;
}
if (!empty($symbl) && sizeof($al)) // last symbol
$o[] = $decrypt ? $s1[$al[1]][$al[0]] : $s2[$al[1]][$al[0]];
return implode('',$o);
}
echo dsCrypt('586851105743');
echo '<br />'.dsCrypt('tdtevmdrsdoc', 1);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.