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 5 months 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 5 months ago
Works perfectly. Thank you so much.
rand0m9 5 months ago