Created
August 14, 2012 20:21
-
-
Save jiaaro/3352528 to your computer and use it in GitHub Desktop.
Rootbuzz Request signing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
function apisig($salt, $dataDict) { | |
# sort the data by key | |
ksort($dataDict); | |
# url encode the data | |
$dataStr = http_build_query($dataDict); | |
# %20 is more robust than + for spaces | |
$dataStr = str_replace("+", "%20", $dataStr); | |
# make the hash and return the hex version of the output | |
return sha1($salt . $dataStr); | |
} | |
function signRequest($salt, $requestData) { | |
if (array_key_exists('s', $requestData)) { | |
unset($requestData['s']); | |
} | |
$requestData['s'] = apisig($salt, $requestData); | |
return $requestData; | |
} | |
function isValid($salt, $signedRequest) { | |
$signedRequestClone = $signedRequest; | |
$signature = $signedRequestClone["s"]; | |
unset($signedRequestClone["s"]); | |
return ($signature == apisig($salt, $signedRequestClone)); | |
} | |
?> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from urllib import urlencode | |
from hashlib import sha1 | |
def apisig(salt, data_dict): | |
# put sort the data by key, and store it in an ordered dict | |
data = sorted(data_dict.items()) | |
data_str = urlencode(data) | |
# %20 is more robust than + for spaces | |
data_str = data_str.replace("+", "%20") | |
# make the hash and return the hex version of the output | |
return sha1(salt + data_str).hexdigest() | |
def sign_request(salt, request_data): | |
if "s" in request_data: | |
request_data.pop("s") | |
request_data["s"] = apisig(salt, request_data) | |
return request_data | |
def is_valid(salt, signed_request): | |
signed_request = signed_request.copy() | |
signature = signed_request.pop("s") | |
return signature == apisig(salt, signed_request) | |
############################### | |
########## Tests ########## | |
############################### | |
# example salt | |
salt = "51f7b5601fcbae7d44692e690cce4d9ef8b87a48" | |
# simulate logged in user | |
data1 = { | |
"user_id": 2348768723, | |
"email": "hi-mom+nospam@gmail.com" | |
} | |
assert apisig(salt, data1) == "be457f788510725104923f300a7bf20a75977aa2" | |
assert sign_request(salt, data1) == { | |
"user_id": 2348768723, | |
"email": "hi-mom+nospam@gmail.com", | |
"s": "be457f788510725104923f300a7bf20a75977aa2" | |
} | |
# simulate anonymous user | |
data2 = { | |
"user_id": None | |
} | |
assert apisig(salt, data2) == "4a66714331fe8e82de4c106911b2db8bf84a13d3" | |
assert sign_request(salt, data2) == { | |
"user_id": None, | |
"s": "4a66714331fe8e82de4c106911b2db8bf84a13d3" | |
} | |
# checking a request signature | |
signed1 = { | |
'email': 'hi-mom+nospam@gmail.com', | |
's': 'be457f788510725104923f300a7bf20a75977aa2', | |
'user_id': 2348768723 | |
} | |
signed2 = { | |
's': '4a66714331fe8e82de4c106911b2db8bf84a13d3', | |
'user_id': None | |
} | |
assert is_valid(salt, signed1) | |
assert is_valid(salt, signed2) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# requires addressable (i.e. gem install addressable) | |
require 'digest/sha1' | |
require "addressable/uri" | |
def apisig(salt, data_dict) | |
uri = Addressable::URI.new | |
uri.query_values = data_dict.sort_by {|k, v| k}.map {|k,v| v.nil? ? [k,"None"] : [k,v] } | |
Digest::SHA1.hexdigest salt + uri.query | |
end | |
def sign_request(salt, request_data) | |
if request_data.has_key? "s" | |
request_data.delete "s" | |
end | |
request_data["s"] = apisig salt, request_data | |
return request_data | |
end | |
def is_valid(salt, signed_request) | |
signature = signed_request["s"] | |
request = signed_request.clone | |
request.delete "s" | |
return signature == apisig(salt, request) | |
end | |
############################### | |
########## Tests ########## | |
############################### | |
# helper fn from http://www.dzone.com/snippets/basic-ruby-assert-function | |
def assert(conditional) | |
raise "Assertion failed !" unless conditional | |
end | |
# example salt | |
salt = "51f7b5601fcbae7d44692e690cce4d9ef8b87a48" | |
# simulate logged in user | |
data1 = { | |
"user_id" => 2348768723, | |
"email" => "hi-mom+nospam@gmail.com" | |
} | |
assert apisig(salt, data1) == "be457f788510725104923f300a7bf20a75977aa2" | |
assert sign_request(salt, data1) == { | |
"user_id" => 2348768723, | |
"email" => "hi-mom+nospam@gmail.com", | |
"s" => "be457f788510725104923f300a7bf20a75977aa2" | |
} | |
# simulate anonymous user | |
data2 = { | |
"user_id" => nil | |
} | |
assert apisig(salt, data2) == "4a66714331fe8e82de4c106911b2db8bf84a13d3" | |
assert sign_request(salt, data2) == { | |
"user_id" => nil, | |
"s" => "4a66714331fe8e82de4c106911b2db8bf84a13d3" | |
} | |
# checking a request signature | |
signed1 = { | |
'email' => 'hi-mom+nospam@gmail.com', | |
's' => 'be457f788510725104923f300a7bf20a75977aa2', | |
'user_id' => 2348768723 | |
} | |
signed2 = { | |
's' => '4a66714331fe8e82de4c106911b2db8bf84a13d3', | |
'user_id' => nil | |
} | |
assert is_valid(salt, signed1) | |
assert is_valid(salt, signed2) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment