This post was updated 654 days ago and some of the ideas may be out of date.
PHP版
/**
*
* 可逆随机加密函数
* @param string $string 明文或密文
* @param bool $operation 是否加密。true表示加密,false表示解密。
* @param string $key 密钥
* @param int $outTime 密文有效期,单位为秒
* @param string $encryptType 加密方式,有md5和sha1两种。加密解密需要统一使用同一种方式才能正确还原明文。
* @return string
*/
function encryption(string $string, bool $operation = true, string $key = '', int $outTime = 0, string $encryptType = 'md5'): string
{
if ($encryptType === 'md5') {
// 使用md5方式
$longLen = 2;
$halfLen = 1;
} else {
// 使用sha1方式
$longLen = 40;
$halfLen = 20;
$encryptType = 'sha1';
}
$keyLength = 4;
$fixedKey = hash($encryptType, $key);
$hashedKey = md5(substr($fixedKey, $halfLen, $halfLen));
$runToKey = $operation ? substr(hash($encryptType, md5($key . $string)), -$keyLength) : substr($string, 0, $keyLength);
$keys = hash($encryptType, substr($runToKey, 0, $halfLen) . substr($fixedKey, 0, $halfLen) . substr($runToKey, $halfLen) . substr($fixedKey, $halfLen));
$string = $operation ? sprintf('%010d', $outTime ? $outTime + time() : 0) . substr(md5($string . $hashedKey), 0, $halfLen) . $string : base64_decode(substr($string, $keyLength));
$result = '';
$stringLength = strlen($string);
for ($i = 0; $i < $stringLength; $i++) {
$result .= chr(ord($string[$i]) ^ ord($keys[$i % $longLen]));
}
if ($operation) {
return $runToKey . str_replace('=', '', base64_encode($result));
} else {
if (((int)substr($result, 0, 10) === 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, $halfLen) === substr(md5(substr($result, $halfLen + 10) . $hashedKey), 0, $halfLen)) {
return substr($result, $halfLen + 10);
} else {
return '';
}
}
}
JavaScript版,依赖CryptoJS
库
/**
*
* 可逆随机加密函数
* @param {string} string 明文或密文
* @param {boolean} operation 是否加密。true表示加密,false表示解密。
* @param {string} key 密钥
* @param {number} outTime 密文有效期,单位为秒
* @param {string} encryptType 加密方式,有md5和sha1两种。加密解密需要统一使用同一种方式才能正确还原明文。
* @return {string}
*/
function encryption(string, operation = true, key = '', outTime = 0, encryptType = 'sha1') {
let longLen, halfLen;
if (encryptType === 'md5') {
// 使用md5方式
longLen = 2;
halfLen = 1;
} else {
// 使用sha1方式
longLen = 40;
halfLen = 20;
encryptType = 'sha1';
}
const keyLength = 4;
const fixedKey = CryptoJS[encryptType.toUpperCase()](key).toString();
const hashedKey = CryptoJS.MD5(fixedKey.substring(halfLen, halfLen + halfLen)).toString();
const runToKey = operation ? CryptoJS[encryptType.toUpperCase()](CryptoJS.MD5(key + string).toString()).toString().substr(-keyLength) : string.substring(0, keyLength);
const keys = CryptoJS[encryptType.toUpperCase()](runToKey.substring(0, halfLen) + fixedKey.substring(0, halfLen) + runToKey.substring(halfLen) + fixedKey.substring(halfLen)).toString();
string = operation ? String(outTime ? outTime + parseInt(String(Date.now() / 1000)) : 0).padStart(10, '0') + CryptoJS.MD5(string + hashedKey).toString().substr(0, halfLen) + string : atob(string.substring(keyLength));
let result = '';
const stringLength = string.length;
for (let i = 0; i < stringLength; i++) {
result += String.fromCharCode(string.charCodeAt(i) ^ keys.charCodeAt(i % longLen));
}
if (operation) {
return runToKey + btoa(result).replace(/=/g, '');
} else {
if ((parseInt(result.substr(0, 10)) === 0 || parseInt(result.substr(0, 10)) - parseInt(String(Date.now() / 1000)) > 0) && result.substr(10, halfLen) === CryptoJS.MD5(result.substr(halfLen + 10) + hashedKey).toString().substr(0, halfLen)) {
return result.substr(halfLen + 10);
} else {
return '';
}
}
}
参与讨论