Oracle中使用hash_hmac() 函数报错问题/以及Oracle遇到Oauth1.0授权和oauth_signature生成规则
最近在Oracle上发现使用hash_hmac()报找不到此函数。为此特意查到oracle的文档。详细请看官网回答:https://cx.rightnow.com/app/answers/detail/a_id/9825/~/cannot-use-the-hash_hmac-function-in-php
原因是:此扩展在 Oracle B2C 服务中未启用,无法启用。就很无语。但是它家自己推出个 Crypto API 也是加密的一个类
下面是 sha256 简单是例子:
oracle云api直通车:https://documentation.custhelp.com/euf/assets/devdocs/cloud21a/Connect_PHP/Default.htm 里面 有详细的 Crypto API 介绍
<?php /**************Agent Authentication**************/ require_once(get_cfg_var("doc_root") . "/ConnectPHP/Connect_init.php" ); initConnectAPI("admin", "adminpwd"); /******Use the “Crypto” versioned namespace*********/ use RightNow\Connect\Crypto\v1_4 as Crypto; //这里引入 try{ $md = new Crypto\MessageDigest(); $md->Algorithm->ID = 3; //SHA256 $md->Text = "This is a message to be digested using SHA256"; echo "Data : " .$md->Text . "<br>"; $md->hash(); $hashed_text = $md->HashText; echo "Output : " .bin2Hex($hashed_text)."<br>"; } catch (Exception $err ){ echo $err->getMessage(); } ?>
坑①:默认情况下,Crypto API 的 SHA-256 API 没有实现密钥。为了获得与 PHP 的 HASH_HMAC 相同的功能,但是官网给出了解决办法。
可以使用以下代码在 PHP 中复制此功能: /* The sample code in this document or accessed through this document is not certified or supported by Oracle. It is intended for educational or testing purposes only. Use of this sample code implies acceptance of the License Agreement at https://www.oracle.com/downloads/licenses/standard-license.html . */ function standard_crypt($msg){ try{ $md = new Crypto\MessageDigest(); $md->Algorithm->ID = 3; // SHA-256 $md->Text = $msg; $md->hash(); $hashed_text = $md->HashText; return ($hashed_text); } catch (Exception $err ){ echo $err->getMessage(); } } // Create Signature Hash function custom_hmac($algo, $data, $key) { $size = 64; $pack = chr(0x00); if (strlen($key) > $size) { $key = $algo($key);
ps:注意千年大坑来了,卡了我两天的地方就在这里,官网文档如下: //} else { // $key = $key . str_repeat(chr(0x00), $size - strlen($key)); //}
其实这里不需要eles
$key = $key . str_repeat(chr(0x00), $size - strlen($key)); 坑全被我踩完了
// Outter and Inner pad $opad = str_repeat(chr(0x5C), $size); $ipad = str_repeat(chr(0x36), $size); $k_ipad = $ipad ^ $key; $k_opad = $opad ^ $key; return $algo($k_opad.$algo($k_ipad.$data)); } $data = "foo"; $secret = "bar"; $bin_hash = custom_hmac('standard_crypt', $data, $secret, false); echo "HASH: ".bin2hex($bin_hash); //最后从二进制转换成十六进制,但是一般需要的是 base64_encode(),把bin2hex替换就好。
但是我自己也找到了实现秘钥加密的方法,更为简单 (个人推荐这种)并且本人测试过和 php原函数 hash_hmac() 加密效果一样!
function oauth_hmacsha1($key, $data) { return base64_encode(hmacsha1($key, $data)); } function hmacsha1($key,$data) { $blocksize=64; $hashfunc='sha1'; if (strlen($key)>$blocksize) $key=pack('H*', $hashfunc($key)); $key=str_pad($key,$blocksize,chr(0x00)); $ipad=str_repeat(chr(0x36),$blocksize); $opad=str_repeat(chr(0x5c),$blocksize); $hmac = pack( 'H*',$hashfunc( ($key^$opad).pack( 'H*',$hashfunc( ($key^$ipad).$data ) ) ) ); return $hmac; }
或者
function getSignature($key,$str)
{
$signature = "";
if (function_exists('hash_hmac')) {
$signature = base64_encode(hash_hmac("sha1", $str, $key, true));
} else {
$blocksize = 64;
$hashfunc = 'sha1';
if (strlen($key) > $blocksize) {
$key = pack('H*', $hashfunc($key));
}
$key = str_pad($key, $blocksize, chr(0x00));
$ipad = str_repeat(chr(0x36), $blocksize);
$opad = str_repeat(chr(0x5c), $blocksize);
$hmac = pack(
'H*', $hashfunc(
($key ^ $opad).pack(
'H*', $hashfunc(
($key ^ $ipad).$str
)
)
)
);
$signature = base64_encode($hmac);
}
return $signature;
}
坑②:那就是oauth1.0的 oauth_signature 的生成规则 (这里用的sha1加密)其它也类似
重点1:源串由3部分内容用“&”拼接起来
HTTP请求方式(对应 GET | POST ) & urlencode(uri) & urlencode(a=x&b=y&...)
示例代码:
ps:重点中的重点来了!!!!
post:GET | POST 一定要大写;
uri也就是例中 $cur: url也就是你的发送请求的 例如:https://5035664-sb2.restlets.api.netsuite.com/app/site/hosting/restlet.nl?script=456&deploy=1。
如果请求后面 ?号是携带参数的 script=456&deploy=1像这样的,千万记得 $cur 的值不需要加上参数 https://5035664-sb2.restlets.api.netsuite.com/app/site/hosting/restlet.nl 这样就行。
script=456&deploy=1 需要放到下面 $paramstring 进行拼接。
$paramstring :就是 oauth_version=1.0&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1299143758&oauth_nonce=1606024431&oauth_consumer_key=200001。
ps:$paramstring 拼接的话是一定要按照字典排序从低到高的(切记 !)没有额外参数的话就不用 加上,以 oauth_consumer_key 开头那样!
$paramstring = "deploy=1&oauth_consumer_key=" . $oauth_consumer_key . "&oauth_nonce=" . $oauth_nonce . "&oauth_signature_method=HMAC-SHA1" . "&oauth_timestamp=" . $oauth_timestamp . "&oauth_token=" . $oauth_token ."&oauth_version=1.0&script=456";
//密钥
$secret = urlencode($oauth_consumer_secret) ."&".urlencode($oauth_token_secret);
$oauth_signature =urlencode(base64_encode(hmacsha1($secret,$paramstring ))); //带入上面自定义加密函数,最后千万记得用urlencode 转义,不然概率报无效登入,切记!!!
以上就是生成 $oauth_signature 的注意事项了!
最后,其实在这个问题上我卡了好好几天,菜的抠脚,而且能找的文章少之又少。所以才写了这么一篇博客来希望后面的人能快速找到问题!如果对你有帮助的话,记得点个赞再走^_^!!!