php hmac,PHP签名验证之hash_hmac sha1
前言
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
class HashHmacSha1
{
/** code
* @var int
*/
protected $code = 200;
/** message
* @var string
*/
protected $message = 'success';
/** 获取处理code
* @return int
*/
public function getCode()
{
return $this->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 签名校验工具
.form-value{
width:74% !important;
}
.form-name{
width:25% !important;
}
.form-block{
width: 100% !important;
}
.text-danger{
color:red;
}
.form-inline{
margin-bottom: 10px;
}
.control-label{
text-align: left !important;
padding:0 0 0 15px;
}
.non-required-form .control-label{
font-weight: normal;
}
.non-required-form{
display: none;
}
hash_hmac sha1 签名校验工具
签名结果串(必填)*
解析签名
中间结果(Query String)
Secret ID
当前时间戳
签名失效时间戳
随机数
Secret Key(必填)*
校验
签名校验结果
var signature,secret_key;
$("#decodeSig").click(function(){
signature = $("input[name=signature]").val();
if(!signature) {
alert('签名结果串 不能为空');
} else {
var signature = $("input[name=signature]").val();
decodeSignature(signature);
}
});
$("#checkSecretkey").click(function(){
signature = $("input[name=signature]").val();
secret_key = $("input[name=secretKey]").val();
var checkResult;
if(!secret_key) {
$("input[name=decodeResult]").val('Secret Key 不能为空');
} else {
checkResult = check(signature, secret_key);
if(checkResult){
if(checkResult == 'expired') {
$("input[name=decodeResult]").val('签名已过期');
} else if(checkResult == 'notInt') {
$("input[name=decodeResult]").val('时间戳和随机数必须为纯数字');
} else if (checkResult == 'wrongExpireTime') {
$("input[name=decodeResult]").val('expireTime 不可小于 currentTimeStamp');
} else {
$("input[name=decodeResult]").val('签名校验通过');
}
}else {
$("input[name=decodeResult]").val('签名校验失败');
}
}
});
var decodeSignature = function(signature){
// var sha = CryptoJS.HmacSHA1(argStr, secret_key);
// sha.concat(CryptoJS.enc.Utf8.parse(argStr))
// var signature = CryptoJS.enc.Base64.stringify(sha);
$(".non-required-form").hide();
$(".required-form .form-value").val("");
$("input[name=queryString]").val("");
var queryString = getOriginalStr(signature);
//将解析的结果填入input
$("input[name=queryString]").val(queryString);
var arr = queryString.split("&");
arr.map(function(item){
var name = item.split("=")[0].replace(/\./,"_");
var value = decodeURIComponent(item.split("=")[1]);
if(!name || !value) {
alert('签名结果串格式不合法,请检查输入的签名结果串');
return;
}
var input = $("input[name='"+escape(name)+"']");
if(input.length>=1){
$(input).val(value);
$(input).closest(".non-required-form").show();
if (name === 'currentTimeStamp') {
$('.currentTimeStampHuman').text(new Date(value * 1000))
}
if (name === 'expireTime') {
$('.expireTimeHuman').text(new Date(value * 1000))
}
}else{
var customInput = '
+ ''
+ '
+ ''
+ ''
+ '
';
$(".required-form:last").after(customInput);
$(".required-form:last").next().find('.form-name').val(name);
$(".required-form:last").next().find('.form-value').val(value);
}
})
}
function getOriginalStr(signature) {
var buffer = CryptoJS.enc.Base64.parse(signature);
var argBuffer = CryptoJS.lib.WordArray.create(buffer.words.slice(5), buffer.sigBytes-20);
return argBuffer.toString(CryptoJS.enc.Utf8);
}
function check(signature, secret_key) {
// 先做 base64 解码,拿到整个数据的 buffer
var buffer = CryptoJS.enc.Base64.parse(signature);
// 前 5 个单元是 sha1
var shaBuffer = CryptoJS.lib.WordArray.create(buffer.words.slice(0, 5), 20);
// 后 5 个单元是 querystring,并且是 UTF8 编码的
var argBuffer = CryptoJS.lib.WordArray.create(buffer.words.slice(5), buffer.sigBytes-20);
// 把 querystring 从 UTF8 编码的 buffer 转成 string
var argStr = argBuffer.toString(CryptoJS.enc.Utf8);
// 再次用 sk + querystring 计算出 sha
var sha = CryptoJS.HmacSHA1(argStr, secret_key);
// 对比两个 sha 是不是一样的
if(!$("input[name=expireTime]").val()) {
decodeSignature(signature);
}
if(+$("input[name=currentTimeStamp]").val() > +$("input[name=expireTime]").val()) {
return 'wrongExpireTime';
}
// 校验时间是否过期
if(+$("input[name=expireTime]").val() < Math.floor((+new Date())/1000)) {
return 'expired';
}
if(isNaN($("input[name=random]").val()) || isNaN($("input[name=currentTimeStamp]").val()) || isNaN($("input[name=expireTime]").val())) {
return 'notInt';
}
return sha.toString(CryptoJS.enc.Base64) === shaBuffer.toString(CryptoJS.enc.Base64);
}
var _mtac = {};
(function() {
var mta = document.createElement("script");
mta.src = "https://pingjs.qq.com/h5/stats.js?v2.0.2";
mta.setAttribute("name", "MTAH5");
mta.setAttribute("sid", "500428027");
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(mta, s);
})();
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 运行参照
感谢阅读!
php hmac,PHP签名验证之hash_hmac sha1相关推荐
- HASH和HMAC(3):SHA-1算法原理
协议标准:https://csrc.nist.gov/CSRC/media/Publications/fips/180/2/archive/2002-08-01/documents/fips180-2 ...
- PHP hash_hmac与python hmac sha1匹配
因为不同语言,对应加密的规则有些许不同.然后这个问题在度娘上也搜不到一个正确的答案,特此记录一下. 1.首先双方基本算法需要一致,这里都以sha1为基本规则 2.python部分,如果是使用diges ...
- golang hmac的sha1加密例子
想要用go写btcchina平台的接口,api加密形式在php中是hash_hmac('sha1',$string,$key); go中的一样有hmac包,下面是代码 package mainimpo ...
- MD5 SHA1 HMAC HMAC_SHA1区别
MD5是一种不可逆的加密算法,目前是最牢靠的加密算法之一,尚没有能够逆运算的程序被开发出来,它对应任何字符串都可以加密成一段唯一的固定长度的代码. SHA1是由NISTNSA设计为同DSA一起使用的, ...
- python学习笔记(二十七) -- 常用内建模块(二) Base64、MD5、SHA1、hmac
目录 base64 hashlib MD5 SHA1 hmac base64 原理 base64就是对二进制数据进行编码,比如我有6字节的二进制数据,然后每3个字节分为一组,也就是一组有3*8 = 2 ...
- C#实现php的hash_hmac函数
from:http://blog.csdn.net/ciaos/article/details/12618487 PHP代码示例如下 <?php $res1 = hash_hmac(" ...
- python hmac
1.首先双方基本算法需要一致,这里都以sha1为基本规则 2.python部分,如果是使用digest()输出,php部分则一定要使用原始二进制数据输出. python: hmac.new('test ...
- php中使用hash_hmac函数实现HMAC-SHA1签名算法的来龙去脉
前言 最近工作中频繁和其他部门甚至公司进行接口上的对接,不免接触到林林总总的签名验权算法.其中属HMAC-SHA1签名算法最多,刚开始接触的时候我也觉得有一点懵,慢慢搞清楚了原理,所以在这里跟大家如何 ...
- php 中文key_API常用签名验证方法(PHP实现)
php中文网最新课程 每日17点准时技术干货分享 本文为php中文网认证作者:"安安杰尼"投稿,欢迎加入php中文网有偿投稿计划! 使用场景 现在越来越多的项目使用的前后端分离的模 ...
最新文章
- python可视化来分析全国疫情
- [Linux内核]软中断与硬中断
- 【Spark Summit East 2017】BigDL:Spark上的分布式深度学习库
- Py之urllib2:Python库之urllib、urllib2、urllib3系列简介、安装、使用方法之详细攻略
- python训练营微信公众号真实性_用python进行微信公众号开发(仅测试学习)
- C语言学习之输入一行字符,分别统计出其中英文字母、空格、数字和其他字符的个数。
- 【C++grammar】访问控制与抽象类与纯虚函数
- 【转】基于XML-RPC的BloggerAPI学习
- 兼容iOS 10 资料整理笔记
- java扫描一个端口状态_java扫描端口,如何判断端口是用来做什么的(提供什么服务的)?...
- linux下使用命令行分区、格式化文件系统、更新卷标名称
- 九度OJ 1037:Powerful Calculator(强大的计算器) (大整数运算)
- 客户端动态化系列之——URLRoute
- 上传文件_Spring Boot文件上传
- Windows系统怎么将dmg文件转换为iso格式
- 在vc++如何响应键盘和鼠标事件-visual c++
- Hbase的table存储详解
- 深度沉浸能力的锻炼方法
- 在Godot中制作杀戮尖塔的箭头
- android多任务列表高斯模糊
热门文章
- flink的神奇分流器-sideoutput
- 『津津乐道播客』#139. 日本异闻录·三句日语,就在涩谷推倒了她们
- UnicodeDecodeError: 'utf-8' codec can't decode byte 0xf3 in position 4645: invalid continuation byte
- 星型结构和雪花型结构
- SVN安装 443 端口被占用
- 人脸识别经典论文Arcface解读
- 线性代数之 投影矩阵
- 删除Github中项目步骤
- QPixmap,QImage load图片失败问题
- 从苹果logo到冤案的发生 谈人类注意力饱和现象