一段JAVA签名算法的PHP改写
源代码是这样的:
public class AuthorizationSignature {
public static String createSignature(String verb, String contentMD5, String contentType, String date,
String canonicalizedSALHeaders, String canonicalizedResource) {
String signatureStr = verb + "\\n" + contentMD5 + "\\n" + contentType + "\\n" + date + "\\n"
+ canonicalizedSALHeaders + canonicalizedResource;
signatureStr = java.net.URLDecoder.decode(signatureStr);
HmacSHA1Signature hss = new HmacSHA1Signature();
String toSignature = hss.computeSignature(AuthConfiguration.getInstance().getAuthConfigurationDTO()
.getSecretKey(), signatureStr);
String authorization = AuthConfiguration.getInstance().getAuthConfigurationDTO().getEnterpriseHeader()
+ AuthConfiguration.getInstance().getAuthConfigurationDTO().getAccessKey() + ":" + toSignature;
return authorization;
}
}
public class HmacSHA1Signature extends ServiceSignature {
private static final Logger LOG = LoggerFactory.getLogger(HmacSHA1Signature.class);
private static final String DEFAULT_CHARSET = "UTF-8";
private static final String ALGORITHM = "HmacSHA1";
@Override
public String getAlgorithm() {
return ALGORITHM;
}
@Override
public String computeSignature(String key, String data) {
byte[] signData = null;
try {
signData = signature(key.getBytes(DEFAULT_CHARSET), data.getBytes(DEFAULT_CHARSET));
} catch (UnsupportedEncodingException ex) {
LOG.debug(ex.getMessage());
}
return BinaryUtil.toBase64String(signData);
}
private byte[] signature(byte[] key, byte[] data) {
try {
Mac mac = Mac.getInstance(ALGORITHM);
mac.init(new SecretKeySpec(key, ALGORITHM));
return mac.doFinal(data);
} catch (NoSuchAlgorithmException e1) {
// throw new RuntimeException("Unsupported algorithm: HmacSHA1");
LOG.error("Unsupported algorithm: HmacSHA1", e1);
return null;
} catch (InvalidKeyException e) {
// throw new RuntimeException();
LOG.debug(e.getMessage());
return null;
}
}
}
public class BinaryUtil {
private static final Logger LOG = LoggerFactory.getLogger(BinaryUtil.class);
public static String toBase64String(byte[] binaryData) {
String toBase64Result = null;
try {
toBase64Result = new String(Base64.encodeBase64(binaryData), ContentUtil.BYTE_CODE);
} catch (UnsupportedEncodingException e) {
LOG.debug(e.getMessage());
}
return toBase64Result;
}
public static byte[] fromBase64String(String base64String) {
byte[] fromBase64Result = null;
try {
fromBase64Result = Base64.decodeBase64(base64String.getBytes(ContentUtil.BYTE_CODE));
} catch (UnsupportedEncodingException e) {
LOG.debug(e.getMessage());
}
return fromBase64Result;
}
}
需要改写为PHP代码, 一步步分析, 首先是核心的MAC_SHA1签名算法
Mac mac = Mac.getInstance(ALGORITHM);
mac.init(new SecretKeySpec(key, ALGORITHM));
return mac.doFinal(data);
等效的PHP代码是调用内建函数hash_hmac, JAVA代码是针对字节数组签名返回字节数组, 所以这里对返回值需要处理一下, 处理成字节数组
<?php
require_once DIR_SAL . 'util/BytesUtil.php';
require_once DIR_SAL . 'util/Base64Util.php';
class HmacSHA1Signature { public function computeSignature($key, $data) {
$hash = $this->hmac ( $data, $key );
$hash = str_split ( $hash );
foreach ( $hash as $index => $value ) {
$asc = ord ( $value );
if ($asc > 128) {
$hash [$index] = ord ( $value ) - 128 * 2;
} else {
$hash [$index] = ord ( $value );
}
}
$bytes = Base64Util::encodeBase64($hash);
return BytesUtil::toStr($bytes);
} private function hmac($data, $key, $hashFunc = 'sha1', $rawOutput = true) {
if (! in_array ( $hashFunc, hash_algos () )) {
$hashFunc = 'sha1';
}
return hash_hmac ( $hashFunc, $data, $key, $rawOutput );
}
}
JAVA代码中还将结果的字节数组进行base64转换
public static String toBase64String(byte[] binaryData) {
String toBase64Result = null;
try {
toBase64Result = new String(Base64.encodeBase64(binaryData), ContentUtil.BYTE_CODE);
} catch (UnsupportedEncodingException e) {
LOG.debug(e.getMessage());
}
return toBase64Result;
}
这个转码方式符合base64的定义, 即将3个8位表示数据的方式转变为4个6位标识数据, 即3*8=4*6, 这样会多出若干字节值, 具体算法实现通过bing搜到的2篇文章中的JAVA代码综合起来实现 (直接使用base64对字符串编码的结果和预期不符):
<?php
class Base64Util { public static function encodeBase64($data) {
$encodes = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
require_once DIR_VENTOR . 'sal/util/BytesUtil.php';
$encodes = BytesUtil::getBytes_10 ( $encodes );
$dataLength = intval ( count ( $data ) );
$modulus = intval ( $dataLength % 3 );
//计算结果应有位数
if ($modulus == 0) {
//byte位数能被3整除
$sbLength = intval ( (4 * $dataLength) / 3 );
} else {
$sbLength = intval ( 4 * (intval ( ($dataLength / 3) ) + 1) );
}
$sb = array ();
$pos = 0;
$val = 0;
foreach ( $data as $i => $byte ) {
$val = ($val << 8) | ($data [$i] & 0xFF);
$pos += 8;
while ( $pos > 5 ) {
$index = $val >> ($pos -= 6);
$sb [] = $encodes [$index];
$val &= ((1 << $pos) - 1);
}
}
if ($pos > 0) {
$index = $val << (6 - $pos);
$sb [] = $encodes [$index];
}
//位数不够的用=字符(ascII值为61)填充
$real = count ( $sb );
if ($real < $sbLength) {
for($i = 0; $i < $sbLength - $real; $i ++) {
$sb [] = 61;
}
}
return $sb;
}
}
一段JAVA签名算法的PHP改写的更多相关文章
- 你真的了解一段Java程序的生命史吗
作为一名程序猿 ,我们每天都在写Code,但你真的了解它的生命周期么?今天就来简单聊下它的生命历程,说起一段Java Code,从出生到game over大体分这么几步:编译.类加载.运行.GC. 编 ...
- jsp页面:js方法里嵌套java代码(是操作数据库的),如果这个js 方法没被调用,当jsp页面被解析的时候,不管这个js方法有没有被调用这段java代码都会被执行?
jsp页面:js方法里嵌套java代码(是操作数据库的),如果这个js 方法没被调用,当jsp页面被解析的时候,不管这个js方法有没有被调用这段java代码都会被执行? 因为在解析时最新解析的就是JA ...
- linux学习之---在linux服务器上跑一段Java代码
经常在windows上进行开发,有时候,需要在Linux环境上跑一些程序测下代码,要怎么办才好嘞? 假设你对Java常用命令和linux常用命令已经基本熟悉,就可以直接按照以下步骤来啦,默认linux ...
- 你觉得我的这段Java代码还有优化的空间吗?
上周,因为要测试一个方法的在并发场景下的结果是不是符合预期,我写了一段单元测试的代码.写完之后截了个图发了一个朋友圈,很多人表示短短的几行代码,涉及到好几个知识点. 还有人给出了一些优化的建议.那么, ...
- 分享一段Java搞笑的代码注释
今天在群里看到有人分享了一段搞笑的注释代码,觉得挺好玩的,在这里收藏一下 // _ooOoo_ // o8888888o // 88" . "88 // (| -_- |) // ...
- 激活MyEclipse 6.5方法-通过一段Java程序生成激活码
在MyEclipse中新建一个Java类,名为MyEclipseKeyGen,将下面的Java代码拷贝到MyEclipseKeyGen类中,先修改变量subscriber的值,然后运行程序即可获得Su ...
- 一段JAVA代码了解多线程,JUC、CAS原子性操作。
@Test public void testPaceController_multiThread() throws InterruptedException { final PaceControlle ...
- 如何看一段JAVA代码耗了多少内存
简单的方法,如下: Runtime r = Runtime.getRuntime(); r.gc(); long startMem = r.freememory(); // 开始时的剩余内存 你 ...
- 在jsp中默认写上的一段java代码表示basePath 的路径的具体的意思是什么?
<% String path = request.getContextPath(); String basePath = request.getScheme() + "://" ...
随机推荐
- PHP面向对象之旅:抽象类继承抽象类(转)
可以理解为对抽象类的扩展 抽象类继承另外一个抽象类时,不用重写其中的抽象方法.抽象类中,不能重写抽象父类的抽象方法.这样的用法,可以理解为对抽象类的扩展. 下面的例子,演示了一个抽象类继承自另外一个抽 ...
- 关于css中伪类及伪元素的总结
css中的伪类和伪元素总是混淆,今天参考了很多资料,也查看了部分文档,现将伪类及伪元素总结如下: 一.由来: 伪类和伪元素的引入都是因为在文档树里有些信息无法被充分描述,比如CSS没有"段落 ...
- iOS UIKit:Auto Layout
@import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css); @import url(/ ...
- c#正则表达式采集数据
protected void Page_Load(object sender, EventArgs e){ StringBuilder MyStringBuilder = new StringBuil ...
- Tomcat-java.lang.IllegalArgumentException: Document base F:apps does not exist or is not a readable
启动Tomcat的时候,报错:java.lang.IllegalArgumentException: Document base F:apps does not exist or is not a r ...
- HTTP could not register URL http://+:8000/.... Your process does not have access rights to this namespace
windows 7, Visual Studio 2013 在托管 Windows 服务中承载 WCF 服务时报错: HTTP could not register URL http://+:8000 ...
- c# 左连接写法
var itemandformulas = from i in AttendanceItemList join f in AttendanceFormulaList on i.AttendanceCo ...
- IOS开发效率之为Xcode添加常用的代码片段
IOS开发效率之为Xcode添加常用的代码片段 原文地址:http://blog.csdn.net/pingchangtan367/article/details/30041285 tableview ...
- sql server主动推送客户端更新数据
小谈需求: 最近工作上接到一个需求,做一个web展示数据的报表,最好能实时更新,不限制所用技术. 第一个问题:web服务器推送给浏览器新数据,一开始我想到的最快的最简单的方法就是 在web页面上js轮 ...
- 【HDU4348】【主席树】To the moon
Problem Description BackgroundTo The Moon is a independent game released in November 2011, it is a r ...