What to put in query string in post request? -NiceHash API - python

I am working on a python program that turns on/off my mining rig with Nicehash API. I did everything that I need to but I am stuck with what to put in query string.
In header of post request must be X-auth which which is built from API Key and HMAC signature. On NiceHash website it says that HMAC signature must be build like this:
Input structure is the following:
-API Key
-X-Time request header value
-X-Nonce request header value
-Empty field
-X-Organization-Id request header value
-Empty field
-Request method (example: GET, POST, DELETE, PUT)
-Request path (example: /main/api/v2/hashpower/orderBook)
-Request query string (example: algorithm=X16R&page=0&size=100, The query string should be the same as
passed to the server - without the leading question mark)
Input is a byte array composed of ordered fields using zero byte (0x00) as a separator. There is no
separator before the first field or after the last field. Some fields are always empty in which case the
separators immediately follow one another. For request body you should use the raw bytes as they are sent
to the server. For JSON messages the character encoding should always be UTF-8.
So input should look like this (already hashed in UTF-8) and then be hashed again (in order from first to last:
API KEY,TIME,NONCE,ORGANISATION ID,REQUEST METHOD,REQUEST PATH,REQUEST QUERY STRING) :
4ebd366d-76f4-4400-a3b6-e51515d054d6 ⊠ 1543597115712 ⊠ 9675d0f8-1325-484b-9594-c9d6d3268890 ⊠ ⊠ da41b3bc-3d0b-4226-b7ea-aee73f94a518 ⊠ ⊠ GET ⊠ /main/api/v2/hashpower/orderBook ⊠ algorithm=X16R&page=0&size=100
(this sign: ⊠ is zero byte: 0x00)
My code:
import hashlib
import uuid
import requests
import json
import hmac
url = "https://api2.nicehash.com/main/api/v2/mining/rigs/status2"
path = "/main/api/v2/mining/rigs/status2"
ms = str(json.loads(requests.get('https://api2.nicehash.com/api/v2/time').text)['serverTime'])
req_id = str(uuid.uuid4())
nonce = str(uuid.uuid4())
org_id = organizationId
sec_key = secretKey
apiKey = apiKey
method = "POST"
query = ?
input = bytearray(f"{apiKey}\00{ms}\00{nonce}\00\00{org_id}\00\00{method}\00{path}\00{query}", "utf-8")
secret=hmac.new(bytearray(sec_key, "utf-8"), input, hashlib.sha256).hexdigest()
auth = apiKey + ":" + secret
#HEADER
header = {
"X-Time":ms,
"X-Nonce":nonce,
"X-Organization-Id":org_id,
"X-Auth":auth,
"X-Request-Id":req_id}
#BODY
body = {
"rigId": "SOMETHING",
"action": "STOP"
}
r=requests.post(url=url, headers=header, params=body)
print(r)
print(r.json())
But on website the example demostrates if you want to get a hashpower order book and I understand query string there. But I dont know what to put in query string in my case.
For now this is the main problem for me so the rest of the code is not finished yet.

try this:
query="action=STOP&rigId=yourigid" #stops certain rig
I tried to use https://www.nicehash.com/docs/rest and https://www.nicehash.com/docs/
picture of what worked for me

Related

Python API request POST does not pass parameters that contain "="

I've been trying out an API call that contains content with the character "=". When I check the API content inside the C# API, the parameter with the "=" character is missing.
Theres also an issue with the "+" character, which simply disappears and gets replaced with " ". I've tried different encodings but the issue persists.
Do you have any idea where the issue might be?
import requests
import json
qry = "select SUM(this + that) as a from asd WHERE a = 10"
URL = "http://127.0.0.1:42100"
PARAMS = {'request_type':'translate_model',
'content_string': qry}
r = requests.post(url = URL, params = PARAMS)
In the example above the content_string parameter is not present in the C# API parameters.

Validating webhook with sha256 hmac using PHP and Python

I am working with webhooks from Bold Commerce, which are validated using a hash of the timestamp and the body of the webhook, with a secret key as the signing key. The headers from the webhook looks like this :
X-Bold-Signature: 06cc9aab9fd856bdc326f21d54a23e62441adb5966182e784db47ab4f2568231
timestamp: 1556410547
Content-Type: application/json
charset: utf-8
According to their documentation, the hash is built like so (in PHP):
$now = time(); // current unix timestamp
$json = json_encode($payload, JSON_FORCE_OBJECT);
$signature = hash_hmac('sha256', $now.'.'.$json, $signingKey);
I am trying to recreate the same hash using python, and I am always getting the wrong value for the hash. I've tried several combinations, with and without base64 encoding. In python3, a bytes object is expected for the hmac, so I need to encode everything before I can compare it. At this point my code looks like so :
json_loaded = json.loads(request.body)
json_dumped = json.dumps(json_loaded)
# if I dont load and then dump the json, the message has escaped \n characters in it
message = timestamp + '.' + json_dumped
# => 1556410547.{"event_type" : "order.created", "date": "2020-06-08".....}
hash = hmac.new(secret.encode(), message.encode(), hashlib.sha256)
hex_digest = hash.hexdigest()
# => 3e4520c869552a282ed29b6523eecbd591fc19d1a3f9e4933e03ae8ce3f77bd4
# hmac_to_verify = 06cc9aab9fd856bdc326f21d54a23e62441adb5966182e784db47ab4f2568231
return hmac.compare_digest(hex_digest, hmac_to_verify)
Im not sure what I am doing wrong. For the other webhooks I am validating, I used base64 encoding, but it seems like here, that hasnt been used on the PHP side. I am not so familiar with PHP so maybe there is something I've missed in how they built the orginal hash. There could be complications coming from the fact that I have to convert back and forth between byte arrays and strings, maybe I am using the wrong encoding for that ? Please someone help, I feel like I've tried every combination and am at a loss.
EDIT : Tried this solution by leaving the body without encoding it in json and it still fails :
print(type(timestamp)
# => <class 'str'>
print(type(body))
# => <class 'bytes'>
# cant concatenate bytes to string...
message = timestamp.encode('utf-8') + b'.' + body
# => b'1556410547.{\n "event_type": "order.created",\n "event_time": "2020-06-08 11:16:04",\n ...
hash = hmac.new(secret.encode(), message, hashlib.sha256)
hex_digest = hash.hexdigest()
# ...etc
EDIT EDIT :
Actually it is working in production ! Thanks to the solution described above (concatenating everything as bytes). My Postman request with the faked webhook was still failing, but that's probably because of how I copied and pasted the webhook data from my heroku logs :) .

How do I send a query parameter which have '+' in the string in the value

I have a webapp on django. My url is http://localhost?state=mCLap0iv7XYFOZBG/WKv/EZBAC6butVk2tuJC44o8q/6U6PdDbPhxPQl4cTxAmvU06/s1HpkpJWqwqK8fbWECoydMYQjOBqyOzhStK24pVhM3OUejfPLR4JVIwVO9VEAtL0DjToYArBcC8mG/3bm0LYmLUbwcrulTBsLtd+eSkY=&code=aa28b2256deeaf311fa4b4311807f4a
I am getting this string by doing
bin_data = RSAKey.encrypt(string)
encoded_data = base64.urlsafe_b64encode(bin_data)
On backend when I check the get parameter I get mCLap0iv7XYFOZBG/WKv/EZBAC6butVk2tuJC44o8q/6U6PdDbPhxPQl4cTxAmvU06/s1HpkpJWqwqK8fbWECoydMYQjOBqyOzhStK24pVhM3OUejfPLR4JVIwVO9VEAtL0DjToYArBcC8mG/3bm0LYmLUbwcrulTBsLtd eSkY= .
Here"+" is getting replaced by " ". The string is encrypted by RSA in python.
Basically I want to do a base64.urlsafe_b64decode(encoded_string) on the string.
Screenshot from chrome inspector networks tab :

Steam WebAPI AuthenticateUser

How to auth user via https://api.steampowered.com/ISteamUserAuth/AuthenticateUser/v0001 api method?
For example, I will get steam public key data from https://steamcommunity.com/login/getrsakey/, do some encryption and then send this data to specified api url as POST.
But server returns '403 Forbidden' everytime.
My code example:
from Crypto.Cipher import AES
from Crypto.Cipher.PKCS1_v1_5 import PKCS115_Cipher
from Crypto.PublicKey import RSA
from Crypto.Random import get_random_bytes
import hashlib
import json
import requests
steamid = '<MY_STEAMID64>'
steampass = '<MY_STEAM_PASSWORD>'
loginkey = hashlib.md5(bytes(steampass, 'utf-8')).hexdigest()
blob32 = get_random_bytes(32)
getrsa_url = 'https://steamcommunity.com/login/getrsakey/'
getrsa_data = {'username': '<MY_STEAM_USERNAME>'}
getrsa_resp = requests.get(getrsa_url, params=getrsa_data)
response = json.loads(getrsa_resp.text)
if response.get('success'):
steam_publickey_mod = response.get('publickey_mod')
steam_publickey_mod = int(steam_publickey_mod, 16)
steam_publickey_exp = response.get('publickey_exp')
steam_publickey_exp = int(steam_publickey_exp, 16)
steam_rsa_key = RSA.construct((steam_publickey_mod, steam_publickey_exp))
steam_rsa = PKCS115_Cipher(steam_rsa_key)
if steam_rsa_key.can_encrypt():
sessionkey = steam_rsa.encrypt(blob32)
if type(sessionkey) is tuple:
sessionkey = sessionkey[0]
steam_aes = AES.new(blob32)
encrypted_loginkey = steam_aes.encrypt(loginkey)
if all([steamid, sessionkey, encrypted_loginkey]):
authenticate_user_url = (
'https://api.steampowered.com/ISteamUserAuth/AuthenticateUser/v0001')
authenticate_user_json = {
'steamid': steamid,
'sessionkey': sessionkey,
'encrypted_loginkey': encrypted_loginkey,
}
if __name__ == '__main__':
import ipdb
ipdb.set_trace()
authenticate_user_resp = requests.post(url=authenticate_user_url,
data=authenticate_user_json)
authenticate_user_resp.ok returns False
authenticate_user_resp.status_code returns 403
authenticate_user_resp.reason returns Forbidden
Sorry for my bad English, please
AuthenticateUser doesn't do what you think it does. It's used by the Steam client to get web session logon cookies for the user who is currently logged into the client. The loginkey that AuthenticateUser asks for comes from the CM (the server which the client connects to).
If you want to log a user into the websites, you need to use the HTTP endpoints to do so. Once you have the RSA key and have encrypted your password with that key, you can authenticate by POSTing to https://steamcommunity.com/login/dologin/ with these urlencoded parameters in the body:
captcha_text - Empty string or the text of a CAPTCHA you've been prompted with
captchagid - The GID of the CAPTCHA you've been prompted with, or -1 if you haven't been
emailauth - The Steam Guard code sent to your email address, or empty string if not applicable
emailsteamid - Empty string
loginfriendlyname - Empty string
password - Your password, encrypted with the RSA public key, and the resulting ciphertext in base64
remember_login - true if you want to remember your login or false if not (the strings true and false)
rsatimestamp - The timestamp that you got with the RSA key
twofactorcode - The TOTP code you got from your mobile app, or empty string if not applicable
username - Your account name
As far as I am concerned, you are not allowed to do this operation, hence the "403 forbidden" So, you simply are not "authorized" to perform this with the credentials you have.
https://en.wikipedia.org/wiki/HTTP_403
A 403 response generally indicates one of two conditions:
Authentication was provided, but the authenticated user is not
permitted to perform the requested operation. The operation is
forbidden to all users. For example, requests for a directory listing
return code 403 when directory listing has been disabled.

Different return when using base64.encodestring with database and session variable

I'm trying to do API-request and I need API-key to different view. I'm trying to use session variable, but the key seems to be in some other format than trying to use variable from Sqlite database. API requests work with the key from database, but not with session variable
How I get API-key from database and from session:
key_session = request.session['key']
key_db = APIkey.objects.values_list('key', flat=True).get(pk=2)
Both of these return same values, when I print them. Key example:
3h3asdh-asdasd:oisf87sdf87a5df76asdf83jhjhasgd8
I'm using base64.encodestring function when trying to do authentication to API-service with my key:
query = request.GET.get('query')
url = urllib2.Request('https://api.someapiwebsite.com',
None, headers={'Content-Type':'application/json'})
base64string = base64.encodestring('%s' % (key_session)).replace('\n', '')
If I print base64string with session variable (key_session), I get:
MmoihjsdasdoihhaG5tbjpuq9876eq9asd98a7Nmd3dWYzN2JmbWZ2aW1nMGVw==
If I print base64string with session variable (key_db), only difference is the two last characters == is now 'IC', and I think that's why the authentication to API service is failing:
MmoihjsdasdoihhaG5tbjpuq9876eq9asd98a7Nmd3dWYzN2JmbWZ2aW1nMGVwIC
What is making this difference in the base64 encoded string?
Edit:
I can see difference when using print repr():
print repr(key_db)
3h3asdh-asdasd:oisf87sdf87a5df76asdf83jhjhasgd8
print repr(key_session)
3h3asdh-asdasd:oisf87sdf87a5df76asdf83jhjhasgd8\x02\x02
One of the strings probably contains some trailing characters that print isn't showing. If you use repr then you should be able to see what the difference is.
print(repr(key_session))
print(repr(key_db))
You can then strip any characters as necessary before encoding the string, for example:
key_session = key_session.rstrip('\x02')

Categories

Resources