Need PHP converted to Python3
New here? Learn about Bountify and follow @bountify to get notified of new bounties! x

Hi, I need the following PHP converted to Python3. Having some trouble authenticating / hashing the private key & public key. Thanks!

class ICObenchAPI {

private $privateKey = 'private-key';
private $publicKey  = 'public-key';
private $apiUrl     = 'https://icobench.com/api/v1/';
public  $result;

public function getICOs($type = 'all', $data = ''){ 
    return $this->send('icos/' . $type, $data); 
}   
public function getICO($icoId, $data = ''){ 
    return $this->send('ico/' . $icoId, $data); 
}       
public function getOther($type){ 
    return $this->send('other/' . $type, ''); 
}
public function getPeople($type = 'registered', $data = ''){ 
    return $this->send('people/' . $type, $data); 
}   

private function send($action, $data){

    $dataJson = json_encode($data);                 
    $sig = base64_encode(hash_hmac('sha384', $dataJson, $this->privateKey, true));  

    $ch = curl_init($this->apiUrl . $action);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); 
    curl_setopt($ch, CURLOPT_POSTFIELDS, $dataJson);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        'Content-Type: application/json',
        'Content-Length: ' . strlen($dataJson),
        'X-ICObench-Key: ' . $this->publicKey,
        'X-ICObench-Sig: ' . $sig)
    );

    $reply = curl_exec($ch);
    $ff = $reply;
    $reply = json_decode($reply,true);

    if(isset($reply['error'])){
        $this->result = $reply['error'];
        return false;
    }else if(isset($reply['message'])){
        $this->result = $reply['message'];
        return true;
    }else if(isset($reply)){
        $this->result = json_encode($reply);
        return true;
    }else{
        $this->result = htmlspecialchars($ff);
        return false;
    }
}

public function result(){
    return $this->result;
}

}

Crowdsource coding tasks.

1 Solution

Winning solution

import base64
import cgi
import hashlib
import hmac
import json
import urllib.request
import urllib.parse


class ICObenchAPI(object):
    def __init__(self):
        self.__private_key = b"private-key"
        self.__public_key  = b"public-key"
        self.__api_url     = "https://icobench.com/api/v1/%s"
        self.__result      = ""

    def getICOs(self, type_="all", data=""):
        return self.send("icos/%s" % type_, data)

    def getICO(self, icoId, data=""):
        return self.send("ico/%s" % icoId, data)

    def getOther(self, type_):
        return self.send("other/%s" % type_, "")

    def getPeople(self, type_ = "registered", data=""):
        return self.send("people/%s" % type_, data)

    def send(self, action, data):
        dataJson = json.dumps(data).encode("utf-8")

        hmac_ = hmac.new(self.__private_key, dataJson, hashlib.sha384)
        sig = base64.b64encode(hmac_.digest())

        req = urllib.request.Request(
            self.__api_url % action,
            dataJson,
            {
                "Content-Type": "application/json",
                "Content-Length": len(dataJson),
                "X-ICObench-Key": self.__public_key,
                "X-ICObench-Sig": sig
            }
        )

        with urllib.request.urlopen(req) as response:
            reply = json.loads(response.read())

            if reply.get("error"):
                self.__result = reply["error"]
                return False
            elif reply.get("message"):
                self.__result = reply["message"]
                return True
            elif reply:
                self.__result = json.dumps(reply)
                return True
            else:
                self.__result = cgi.escape(b"\xFF")
                return False

        self.__result = "Could not send request"
        return False

    @property
    def result(self):
        return self.__result


if __name__ == '__main__':
    api = ICObenchAPI()
    api.getICOs()

    print(api.result)

Edit 1: Renamed the result variable to result_ to avoid collision with the function.

Edit 2: Wrapped everything into a class, added a main as an example and fixed the signature bug.

Looks like a solid solution, but getting an "Invalid Content Verification Signature" response. Here are the instructions provided for the API Authentication: "To use the ICObench Data API you need to have both "Private Key" and "Public Key". - Public Key is used to identify the API user and is sent via request header as "X-ICObench-Key". - Private Key is used to sign every request together with JSON. Both are hashed by HMAC SHA384, converted to base64 and sent via request header as "X-ICObench-Sig". Please make sure to send data using POST method and from the IP that you have whitelisted in your API settings." (I whitelisted the IP)
rand0m9 15 days ago
I found the problem. I didn't see that raw_output was set to true in the call to hash_hmac, and I was sending hex characters instead of raw bytes. The Python script is now acting exactly the same as the PHP version, and it should work perfectly.
CyteBode 15 days ago
Works perfectly. Thank you so much.
rand0m9 14 days ago