一段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() + "://" ...
随机推荐
- 解决Shockwave flash在chrome浏览器上崩溃的问题
越来越多的人開始使用chrome浏览器,非常多用户都遇到过flash崩溃的问题,有时候重新启动chrome能够解决,有时候会导致无法用chrome打开不论什么站点上的不论什么flash.这个问题非常少 ...
- Qt 学习之路 :视图代理
与 Qt model/view 架构类似,在自定义用户界面中,代理扮演着重要的角色.模型中的每一个数据项都要通过一个代理向用户展示,事实上,用户看到的可视部分就是代理. 每一个代理都可以访问一系列属性 ...
- MapReduce计数器
1.MapReduce计数器是什么? 计数器是用来记录job的执行进度和状态的.它的作用可以理解为日志.我们可以在程序的某个位置插入计数器,记录数据或者进度的变化情况. 2.MapReduce计数器能 ...
- Android read-only file system解决方法
adb shell su - mount -o rw,remount /system
- xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer directory '/Library/Deve
以上错误是因为安装了 xcode , 但并不是系统默认的位置, 所以可以使用以下命令把 xcode 的路径修改为你安装的位置即可 sudo xcode-select --switch /Applica ...
- SQLCLR
hsrzyn SQLCLR 什么是SQLCLR SQL CLR (SQL Common Language Runtime) 是自 SQL Server 2005 才出现的新功能,它将.NET Fr ...
- inner join
select Person.LastName,Person.FirstName,Orders.OrderNo from Persons INNER JOIN Orders ON Person.Id_P ...
- LA 6856 Circle of digits 解题报告
题目链接 先用后缀数组给串排好序.dc3 O(n) 二分答案+贪心check 答案的长度len=(n+k-1)/k 如果起点为i长为len串大于当前枚举的答案,i的长度取len-1 从起点判断k个串的 ...
- Visual Studio 2013环境下操作vc6/vc7/vc8等低版本平台项目【编译|生成|调试】
现代化的开发环境,微软一直在推出更新换代,我们所处的技术环境在日新月异的变化:不过在中国多数人们一边疲惫的追赶着时代的步伐,一边坚守着自己所获悉所掌握的那些紧吧吧的知本.对技术工具的掌握并非他们所想要 ...
- alsa utils工具使用
1.amixer用于控制设置 amixer [-c card] [cmd] ./amixer contents ./amixer cset ./amixer cget 2. aplay ./aplay ...