一段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() + "://" ...
随机推荐
- Json字符串与字典互转
#pragma mark 转换json字符串 +(NSString *)toJSON:(id)aParam { NSData *jsonData=[NSJSONSerialization data ...
- Java多线程——其他工具类CyclicBarrier、CountDownLatch和Exchange
CyclicBarrier 适用于:创建一组任务,它们并行地执行任务,然后在进行下一个步骤之前等待,直至所有任务完成.它使得所有的并行任务都将在栅栏处列队,因此可以一致地向前移动. 表示大家彼此等待, ...
- 如何通过WiFi来进行Android的真机模拟
我们知道,在使用模拟机模拟的时候会出现较多的问题,所以如果有一部Android手机的话进行真机模拟是极好的. 准备工作: 第一种方法:使用数据线,具体操作百度.略(非WIFI操作的真机模拟) 第二方法 ...
- 进程识别号(PID)的理解
PID(Process Identification)操作系统里指进程识别号,也就是进程标识符.操作系统里每打开一个程序都会创建一个进程ID,即PID. PID(进程控制符)英文全称为Process ...
- CSS居中的方法总结
[水平居中] 行内:text-align:center; 定宽块状:1.left:0 right:0然后用margin: auto外边距填充,水平方向不会发生外边距叠加; 2.绝对定位(父元素定位不 ...
- Flyweight 模式
如果一个应用程序使用了太多的对象, 就会造成很大的存储开销. 特别是对于大量轻量级 (细粒度)的对象,比如在文档编辑器的设计过程中,我们如果为每个字母创建一个对象的话,系统可能会因为大量的对象而造成存 ...
- hdu_5276
//不管怎么样还是希望天天做笔记把,真是太懒了#include<iostream> #include<cstdio> #include<vector> #inclu ...
- c++primerplus(第六版)编程题——第3章(数据类型)
声明:作者为了调试方便,每一章的程序写在一个工程文件中,每一道编程练习题新建一个独立文件,在主函数中调用,我建议同我一样的初学者可以采用这种方式,调试起来会比较方便. 工程命名和文件命名可以命名成易识 ...
- list-style-type -- 定义列表样式
取值:disc | circle | square | decimal | decimal-leading-zero | lower-roman | upper-roman | lower-greek ...
- Swift中的dispatch_once 单例模式
以下有三种方法实现单例模式,支持懒初始化和线程安全 全局变量 结构 dispatch_once 全局变量: 这里使用了全局变量而非类变量,是因为不支持类变量 private let _Singleto ...