I need little help to figure out issue with php hash_hmac
. I am converting a existing python
script into php
that call an api for process data. Python script is working fine.
There is few similar question out there, one of them is HMAC value not consistent in Python and PHP but it dosen't help me. I have tried many way but all time i am getting error your signature doesn't match
Here is my php
code
$session_id = xxxxxxxxxxxxxxxxxxxxx;
$accessKey = xxxxxxxxxxxxxxxxxxxxxx;
$url = '/APIENDPOINT?action=mobileAccess&autoJoin=true';
$timestamp = date('r');
$body = '{"expireTime": "20160322T2359", "doorOperations": [{"operation": "guest", "doors": ["103"]}], "endPointID": "enpointID", "format": "rfid48"}';
$params["action"] = "mobileAccess";
$params["override"] = "true";
$canonicalized_query = array();
foreach ($params as $param => $value) {
$param = str_replace("%7E", "~", rawurlencode($param));
$value = str_replace("%7E", "~", rawurlencode($value));
$canonicalized_query[] = $param . "=" . $value;
}
ksort($canonicalized_query);
$canonicalized_query = implode("&", $canonicalized_query);
$string_to_sign = "POST
";
$string_to_sign .= base64_encode(md5($body, true))."
";
$string_to_sign .="application/json;charset=utf-8
";
$string_to_sign .= $timestamp."
";
$string_to_sign .= 'APIEDNPOINT?'.$canonicalized_query;
echo strlen($string_to_sign);
$header=array(
'Date: '.$timestamp,
'Content-Type: application/json;charset=utf-8',
'Content-MD5: '.base64_encode(md5($body, true)),
'Authorization: Basic '.$session_id.':'.base64_encode(hash_hmac('sha1', iconv(mb_detect_encoding($string_to_sign, mb_detect_order(), true), "UTF-8", $string_to_sign), iconv(mb_detect_encoding($accessKey, mb_detect_order(), true), "UTF-8", $accessKey), true))
Here is working python
code
url=self._basepath+url
headers={}
if body:
# Encode request body as JSON
body=json.dumps(body)
headers['Content-Type']='application/json;charset=utf-8'
# Compute MD5 digest
h=hashlib.new('md5')
h.update(body)
headers['Content-MD5']=base64.b64encode(h.digest())
# Format the date correctly, after applying the client/server skew
headers['Date']=email.Utils.formatdate(time()+self._time_skew)
if sign and 'id' in self._session:
# Canonicalize the URL
(canonicalized_resource,q,query_string)=url.partition('?')
canonicalized_resource+=q+'&'.join(sorted(query_string.split('&')))
# Build the string to be signed
string_to_sign=method+"
"
if 'Content-MD5' in headers:
string_to_sign+=headers['Content-MD5']
string_to_sign+="
"
if 'Content-Type' in headers:
string_to_sign+=headers['Content-Type']
string_to_sign+="
"+headers['Date']+"
"+canonicalized_resource
# Create the signature
h=hmac.new(self._session['accessKey'].encode('utf-8'),\
string_to_sign.encode('utf-8'),hashlib.sha1)
headers['Authorization']='Basic %s:%s'\
%(self._session['id'],base64.b64encode(h.digest()))
call for endpoint
in python
ws.send_request("POST","APIENDPOINT",\
{"doorOperations": [{"doors": ["101"],"operation": "guest"}],"expireTime": "20150522T2359","format": "rfid48","endPointID":"endpointid"})
I have checked body content md5 & string_to_sign
output is same for both script.