前言
secret_id: 密钥的Id
secret_key: 密钥的Key
SHA1: 签名方式
hash_hmac: php hash函数
hash_hmac_file:生成密钥
1.生成secret_key
hash_hmac_file('SHA1','signature.txt','secret');
2.生成签名
base64_encode(hash_hmac('SHA1', $init, $secret_key, true).$init);
3.签名比对
base64_decode($initSign);
base64_encode(hash_hmac('SHA1', $init, $secret_key, true).$init);
4.网站验证(sha1.html)
访问 sha1.html
5.代码
5.1 HashHmacSha1.php
code;
}
/** 获取处理message
* @return string
*/
public function getMessage()
{
return $this->message;
}
/** 产生随机字符串,不长于32位
* @param int $length
* @return string
*/
public function getNonceStr($length = 32)
{
$chars = "abcdefghijklmnopqrstuvwxyz0123456789!@#%^&*;:-=_+,.";
$str ="";
for ( $i = 0; $i < $length; $i++ ) {
$str .= substr($chars, mt_rand(0, strlen($chars)-1), 1);
}
return $str;
}
/** 生成sha1的secret
* @other 绑定生成的 内容,secret_key,secret_id
* @return string
*/
public function signSha1Create()
{
$nonce = $this->getNonceStr();
$rand = rand();
$time = time();
$content = "The signature : nonce={$nonce}; rand={$rand}; time={$time}, by sok yo!";
//生成签名内容
file_put_contents('signature.txt', $content);
$signature = hash_hmac_file('SHA1','signature.txt','secret');
unlink('signature.txt');
return $signature;
}
/** sha1数据加密
* @param $secret_id
* @param $secret_key
* @return string
*/
public function signSha1Encrypt($secret_id,$secret_key)
{
$time = time();
// 业务逻辑,向参数列表填入参数(可抽离)
$arg_list = array(
"secretId" => $secret_id,
"currentTimeStamp" => $time,
"expireTime" => $time+86400,
"random" =>rand(),
);
$init = http_build_query($arg_list);
// 计算签名
// raw_output = false ; 53e55273e57c3cf6b7c16e5840479566be3aa0d2,16进制小写字符串格式(40个字符)
// raw_output = true ; �� Ej���۔����̠��,原始二进制数据(20个字符)
// base64_encode 设计此种编码是为了使二进制数据可以通过非纯 8-bit 的传输层传输(防止特殊字符在传输过程中被转义)。
// base64_encode 数据要比原始数据多占用 33% 左右的空间。
$signature = base64_encode(hash_hmac('SHA1', $init, $secret_key, true).$init);
// JS CryptoJS
return $signature ;
}
/** sha1数据解密
* @param $initSign
* @param $secretId
* @param $secretKey
* @return bool
*/
public function signSha1Decrypt($initSign,$secretId,$secretKey)
{
//先做 base64 解码,拿到数据
$sign = base64_decode($initSign);
//前 5 个单元是 sha1 ,这里的代码单元默认为:编码+16进制(0041),5个单元 = 5 * 4(字节) = 20(字节)
$signStr = substr($sign,20);
//数组形式
parse_str($signStr,$signArr);
//逻辑判断(可抽离)
$mustKey = ['secretId','currentTimeStamp','expireTime','random'];
foreach ($mustKey as $k) {
if(!isset($signArr[$k])) {
$this->code = 400;
$this->message = 'miss '.$k;
return false;
}
}
//secretId
if((string)$signArr['secretId'] !== (string)$secretId) {
$this->code = 400;
$this->message = 'error secretId';
return false;
}
//时间
if($signArr['currentTimeStamp'] > $signArr['expireTime']) {
$this->code = 400;
$this->message = 'error currentTimeStamp';
return false;
}
//过期
if($signArr['expireTime'] < time()) {
$this->code = 400;
$this->message = 'expireTime expired';
return false;
}
// 计算签名
$signature = base64_encode(hash_hmac('SHA1', $signStr, $secretKey, true).$signStr);
if($signature === $initSign) {
$this->code = 200;
$this->message = 'success';
return true;
}else{
$this->code = 400;
$this->message = 'error signature';
return false;
}
}
}
5.2 sha1.html
hash_hmac sha1 签名校验工具
6.测试
//测试
$model = new HashHmacSha1();
//随机的 secret_id
$secretId = 'abc1234Def453';
//生成 secret_key
$secretKey = $model->signSha1Create();
//'fe08bd195744e08e289174167b1d53cd638e6f7b';
//生成签名
$sign = $model->signSha1Encrypt($secretId,$secretKey);
//'ZQlqVb8DKt14kDD6TCxWQMQARVxzZWNyZXRJZD1hYmMxMjM0RGVmNDUzJmN1cnJlbnRUaW1lU3RhbXA9MTU2Njg4NzA2MyZleHBpcmVUaW1lPTE1NjY5NzM0NjMmcmFuZG9tPTk4MTEzNjMwNA==';
//比对
$res = $model->signSha1Decrypt($sign,$secretId,$secretKey);
var_dump($res);
7.sha1.html 运行参照
感谢阅读!