PHP带时效性的字符串加解密函数实现
在Web开发中,常需对敏感信息进行临时加密,如SSO Token或动态密码。本方案提供了一款PHP函数,能在指定秒数内完成字符串的加密与还原。若超出有效期,解密将直接返回空值。核心逻辑结合了密钥派生、伪随机混淆及时间戳哈希校验,兼顾了安全性与易用性。
加密原理解析
该函数并非仅依赖简单的Base64编码,而是构建了一套完整的加解密流程,主要包含以下关键点:
- 密钥处理:主密钥经过MD5摘要后拆分为
$keya和$keyb,分别用于初始向量构造和内容校验,降低主密钥泄露风险。 - 随机前缀:每次加密时加入由当前微时间生成的
$ckey_length位随机字符串,使得即使原文和密钥完全相同,密文也会变化,增加暴力破解难度。 - 时间戳绑定:加密时将Unix时间戳(补全至10位)置于密文头部。解密时先比对当前时间与头部时间戳,若超过设定
$expiry,则拒绝还原。 - 完整性校验:正文前插入16位的MD5哈希值(由原文+副密钥生成)。解密成功与否不仅取决于能否正确逆向算法,还取决于哈希校验是否匹配,防止密文被篡改。
参数与使用方法
函数签名如下,支持两种操作模式:
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 3600)
参数说明:
$string:待处理的原始字符串或已编码的密文。$operation:操作类型。ENCODE为加密,DECODE为解密(默认)。$key:加解密密钥。建议设置为固定常量或从配置中心读取。$expiry:有效期(秒)。设为0表示永久有效,大于0则表示相对当前时间的存活时长。
第1步:生成带时效的加密串
在用户登录或需要颁发临时凭证时调用加密函数,限制其有效期。
// 加密内容 'abc',使用密钥 'my_secret_key',有效期 3600 秒 (1小时)
$encrypted = authcode('abc', 'ENCODE', 'my_secret_key', 3600);
echo "加密结果: " . $encrypted;
此时获取的$encrypted即为密文,可安全传输给前端或存储在Cookie中。
第2步:在有效期内还原明文
在处理请求时,使用相同的密钥尝试解密。
// 传入密文,操作设为 DECODE
$decrypted = authcode($encrypted, 'DECODE', 'my_secret_key');
if ($decrypted === 'abc') {
echo "解密成功:" . $decrypted;
} else {
echo "解密失败或已过期";
}
只要在当前时间戳之后的3600秒内执行此步骤,即可准确还原出'abc'。
第3步:验证超时失效机制
模拟过期场景,延时后再次请求解密,观察返回结果。
// 假设等待超过 3600 秒...
// 再次解密
$expired_result = authcode($encrypted, 'DECODE', 'my_secret_key');
if ($expired_result === '') {
echo "令牌已过期,拒绝访问";
}
由于内部逻辑检测到了头部时间戳与当前时间差值超出了$expiry的限制,函数会直接返回空字符串'',从而达到自动过期的目的。
完整代码实现
以下为完整的authcode函数定义,可直接嵌入项目中使用。该逻辑参考了经典社区框架的实现方式,具有较高的稳定性。
/**
* @param string $string 原文或者密文
* @param string $operation 操作(ENCODE | DECODE), 默认为 DECODE
* @param string $key 密钥
* @param int $expiry 密文有效期, 加密时候有效, 单位 秒,0 为永久有效
* @return string 处理后的 原文或者 经过 base64_encode 处理后的密文
*/
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 3600) {
$ckey_length = 4; // 随机密钥长度
// 密钥派生:区分主密钥副密钥
$key = md5($key ? $key : 'DEFAULT_KEY_VALUE'); // 此处替换为你的实际KEY获取逻辑
$keya = md5(substr($key, 0, 16));
$keyb = md5(substr($key, 16, 16));
// 初始化控制数组:解密取前缀,加密取随机微时间后缀
$keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
$cryptkey = $keya.md5($keya.$keyc);
$key_length = strlen($cryptkey);
// 组装待加密字符串:[10位时间戳] + [16位校验哈希] + [原文]
// 解密时则去掉前缀ckey_length,进行base64解码
$string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
$string_length = strlen($string);
// RC4-like 流密码核心循环
$result = '';
$box = range(0, 255);
$rndkey = array();
for($i = 0; $i <= 255; $i++) {
$rndkey[$i] = ord($cryptkey[$i % $key_length]);
}
for($j = $i = 0; $i < 256; $i++) {
$j = ($j + $box[$i] + $rndkey[$i]) % 256;
$tmp = $box[$i];
$box[$i] = $box[$j];
$box[$j] = $tmp;
}
for($a = $j = $i = 0; $i < $string_length; $i++) {
$a = ($a + 1) % 256;
$j = ($j + $box[$a]) % 256;
$tmp = $box[$a];
$box[$a] = $box[$j];
$box[$j] = $tmp;
$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
}
if($operation == 'DECODE') {
// 验证:1. 时间戳合法 (且未过期)
// 2. 内容哈希合法 (防止中间人篡改)
if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
return substr($result, 26);
} else {
return '';
}
} else {
return $keyc.str_replace('=', '', base64_encode($result));
}
}
注意事项
- 环境一致性:加解密双方(如服务端A发送,服务端B接收)必须保持
$key一致,否则无法还原。 - 性能考量:该算法在PHP环境中运行效率较高,但若处理极大体积文本,建议分块处理或改用AES等更高级别加密标准。
- 密钥管理:
$key参数务必硬编码或在环境变量中严格保护,切勿在日志或前端暴露。
以上就是带时间限制的PHP字符串加密函数的详细内容,更多关于PHP安全开发的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













