Created
October 17, 2019 06:09
-
-
Save dangdungcntt/63c7a3560af5cfc1b9bd076f7a65d508 to your computer and use it in GitHub Desktop.
Simple data protect in php. Javascript version here: https://github.com/dangdungcntt/data-protect
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class DataProtect | |
{ | |
protected static function substrAndToInt($string, $index = 0, $length = 3) | |
{ | |
return hexdec(self::unmix(substr($string, $index, $length))); | |
} | |
protected static function pad($string, $length = 6, $char = '0') | |
{ | |
return (strlen($string) < $length ? str_repeat($char, $length - strlen($string)) . $string : $string); | |
} | |
protected static function mix($string) | |
{ | |
$firstSeg = floor(strlen($string) / 2); | |
return self::pad(rand(1, 99) . '', 2) | |
. substr($string, 0, $firstSeg) | |
. self::pad(rand(1, 99) . '', 2) | |
. substr($string, $firstSeg, strlen($string) - $firstSeg) | |
. self::pad(rand(1, 99) . '', 2); | |
} | |
protected static function unmix($string) | |
{ | |
$originalLength = strlen($string) - 6; | |
$firstSeg = floor($originalLength / 2); | |
return substr($string, 2, $firstSeg) . substr($string, $firstSeg + 4, $originalLength - $firstSeg); | |
} | |
/** | |
* @param $input | |
* @param $secret | |
* @param int $seg | |
* @return string | |
* @throws \Exception | |
*/ | |
public static function encrypt($input, $secret, $seg = 3) | |
{ | |
if (!in_array($seg, range(2, 15))) { | |
throw new \Exception('Invalid seg. seg must between 2-15'); | |
} | |
if (!$input) { | |
throw new \Exception('Invalid input. Input must not empty'); | |
} | |
if (!$secret) { | |
throw new \Exception('Invalid secret. Secret must not empty'); | |
} | |
$decSeg = hexdec(str_repeat('f', $seg)); | |
$time = round($decSeg * rand(0, 1000) / 1000); | |
$key = 10; | |
foreach (str_split($secret) as $cur) { | |
$key = ($key * 10 % $decSeg) + (ord($cur) % $decSeg); | |
$key %= $decSeg; | |
} | |
$base = $key ^ $time; | |
$time16 = dechex($time); | |
$output = self::mix(self::pad($time16, $seg)); | |
foreach (str_split(trim($input)) as $c) { | |
$output .= '' . self::mix(self::pad(dechex(ord($c) ^ $base), $seg)); | |
} | |
return $output; | |
} | |
/** | |
* @param $encrypted | |
* @param $secret | |
* @param int $seg | |
* @return string | |
* @throws \Exception | |
*/ | |
public static function decrypt($encrypted, $secret, $seg = 3) | |
{ | |
if (!in_array($seg, range(2, 15))) { | |
throw new \Exception('Invalid seg. seg must between 2-15'); | |
} | |
if (!$encrypted) { | |
throw new \Exception('Invalid encrypted. Encrypted must not empty'); | |
} | |
if (!$secret) { | |
throw new \Exception('Invalid secret. Secret must not empty'); | |
} | |
$decSeg = hexdec(str_repeat('f', $seg)); | |
$seg += 6; | |
$key = 10; | |
foreach (str_split($secret) as $cur) { | |
$key = ($key * 10 % $decSeg) + (ord($cur) % $decSeg); | |
$key %= $decSeg; | |
} | |
$time = self::substrAndToInt($encrypted, 0, $seg); | |
$base = $key ^ $time; | |
$result = ''; | |
$encryptedLength = strlen($encrypted); | |
for ($i = $seg; $i < $encryptedLength; $i += $seg) { | |
$result .= chr(self::substrAndToInt($encrypted, $i, $seg) ^ $base); | |
} | |
return $result; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment