源代码是这样的:

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. 晨曦之光 linux Crontab 使用(转)

    cron用法说明 cron的用法老是记不住,索性写下来备忘.下文内容大部分是根据<Cron Help Guide>翻译而来,有些部分是自己加上的. 全文如下: cron来源于希腊单词chr ...

  2. mysql查看端口

    在你的my.ini(Windows)或my.cfg(Linux) 中就有啊. 或者如果已经连入MySQL可以直接 SQL code ? 1 2 3 4 5 6 7 8 9 mysql> show ...

  3. [转] JavaScript 和事件

    与浏览器进行交互的时候浏览器就会触发各种事件.比如当我们打开某一个网页的时候,浏览器加载完成了这个网页,就会触发一个 load 事件:当我们点击页面中的某一个“地方”,浏览器就会在那个“地方”触发一个 ...

  4. tcmalloc资料

    1. 确定dylib在max os是可以成功的. http://lists.apple.com/archives/perfoptimization-dev/2008/Dec/msg00002.html ...

  5. win7、xp下Meclipse SVN用户名修改

    Meclipse SVN用户名修改,在网上查找后发现如下方法: 1.查看你的Eclipse中使用的是什么SVNInterface windows>preference>Team>SV ...

  6. hadoop-0.20-集群搭建___实体机通过SSH访问基于VM安装的Linux

    不得不说LZ在最开始搭建hadoop的时候,由于VM中的网段配置和本地IP地址没有配置好, 所以一直都在使用 VM的共享文件夹的功能, 以至于集群搭建好之后,只有namenode主机可以实现共享的功能 ...

  7. MySQL性能状态查看方式

    1. QPS(每秒Query量) QPS = Questions(or Queries) / seconds mysql > show global status like 'Question% ...

  8. CentOS 6.5下搭建NFS文件服务器

    环境介绍:服务器: 192.168.0.1客户机: 192.168.0.2安装软件包:服务器和客户机都要安装nfs 和 rpcbind 软件包:yum -y install nfs-utils rpc ...

  9. oracle数据库读取操作系统的物理文件-转载,待完善

    --源地址不详 --创建目录SQL> create directory dir_xls as '/home/oracle'; Directory created. --给用户授权SQL> ...

  10. Junit4_单元测试

    不多说,直接练习学习. 1.将Junit4单元测试包引入项目:项目右键——“属性”,选择“Java Build Path”,然后到右上选择“Libraries”标签,之后在最右边点击“Add Libr ...