源代码是这样的:

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改写的更多相关文章

  1. 你真的了解一段Java程序的生命史吗

    作为一名程序猿 ,我们每天都在写Code,但你真的了解它的生命周期么?今天就来简单聊下它的生命历程,说起一段Java Code,从出生到game over大体分这么几步:编译.类加载.运行.GC. 编 ...

  2. jsp页面:js方法里嵌套java代码(是操作数据库的),如果这个js 方法没被调用,当jsp页面被解析的时候,不管这个js方法有没有被调用这段java代码都会被执行?

    jsp页面:js方法里嵌套java代码(是操作数据库的),如果这个js 方法没被调用,当jsp页面被解析的时候,不管这个js方法有没有被调用这段java代码都会被执行? 因为在解析时最新解析的就是JA ...

  3. linux学习之---在linux服务器上跑一段Java代码

    经常在windows上进行开发,有时候,需要在Linux环境上跑一些程序测下代码,要怎么办才好嘞? 假设你对Java常用命令和linux常用命令已经基本熟悉,就可以直接按照以下步骤来啦,默认linux ...

  4. 你觉得我的这段Java代码还有优化的空间吗?

    上周,因为要测试一个方法的在并发场景下的结果是不是符合预期,我写了一段单元测试的代码.写完之后截了个图发了一个朋友圈,很多人表示短短的几行代码,涉及到好几个知识点. 还有人给出了一些优化的建议.那么, ...

  5. 分享一段Java搞笑的代码注释

    今天在群里看到有人分享了一段搞笑的注释代码,觉得挺好玩的,在这里收藏一下 // _ooOoo_ // o8888888o // 88" . "88 // (| -_- |) // ...

  6. 激活MyEclipse 6.5方法-通过一段Java程序生成激活码

    在MyEclipse中新建一个Java类,名为MyEclipseKeyGen,将下面的Java代码拷贝到MyEclipseKeyGen类中,先修改变量subscriber的值,然后运行程序即可获得Su ...

  7. 一段JAVA代码了解多线程,JUC、CAS原子性操作。

    @Test public void testPaceController_multiThread() throws InterruptedException { final PaceControlle ...

  8. 如何看一段JAVA代码耗了多少内存

    简单的方法,如下: Runtime r = Runtime.getRuntime();  r.gc();  long startMem = r.freememory(); // 开始时的剩余内存  你 ...

  9. 在jsp中默认写上的一段java代码表示basePath 的路径的具体的意思是什么?

    <% String path = request.getContextPath(); String basePath = request.getScheme() + "://" ...

随机推荐

  1. 解决Shockwave flash在chrome浏览器上崩溃的问题

    越来越多的人開始使用chrome浏览器,非常多用户都遇到过flash崩溃的问题,有时候重新启动chrome能够解决,有时候会导致无法用chrome打开不论什么站点上的不论什么flash.这个问题非常少 ...

  2. Qt 学习之路 :视图代理

    与 Qt model/view 架构类似,在自定义用户界面中,代理扮演着重要的角色.模型中的每一个数据项都要通过一个代理向用户展示,事实上,用户看到的可视部分就是代理. 每一个代理都可以访问一系列属性 ...

  3. MapReduce计数器

    1.MapReduce计数器是什么? 计数器是用来记录job的执行进度和状态的.它的作用可以理解为日志.我们可以在程序的某个位置插入计数器,记录数据或者进度的变化情况. 2.MapReduce计数器能 ...

  4. Android read-only file system解决方法

    adb shell su - mount -o rw,remount /system

  5. xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer directory '/Library/Deve

    以上错误是因为安装了 xcode , 但并不是系统默认的位置, 所以可以使用以下命令把 xcode 的路径修改为你安装的位置即可 sudo xcode-select --switch /Applica ...

  6. SQLCLR

    hsrzyn SQLCLR   什么是SQLCLR SQL CLR (SQL Common Language Runtime) 是自 SQL Server 2005 才出现的新功能,它将.NET Fr ...

  7. inner join

    select Person.LastName,Person.FirstName,Orders.OrderNo from Persons INNER JOIN Orders ON Person.Id_P ...

  8. LA 6856 Circle of digits 解题报告

    题目链接 先用后缀数组给串排好序.dc3 O(n) 二分答案+贪心check 答案的长度len=(n+k-1)/k 如果起点为i长为len串大于当前枚举的答案,i的长度取len-1 从起点判断k个串的 ...

  9. Visual Studio 2013环境下操作vc6/vc7/vc8等低版本平台项目【编译|生成|调试】

    现代化的开发环境,微软一直在推出更新换代,我们所处的技术环境在日新月异的变化:不过在中国多数人们一边疲惫的追赶着时代的步伐,一边坚守着自己所获悉所掌握的那些紧吧吧的知本.对技术工具的掌握并非他们所想要 ...

  10. alsa utils工具使用

    1.amixer用于控制设置 amixer [-c card] [cmd] ./amixer contents ./amixer cset ./amixer cget 2. aplay ./aplay ...