Python FIX API - no response at Logon - python

I've been trying to set up a connection to the FIX API for the GDAX crpyto exchange, but I can't seem to logon properly. I'm using the code below to generate the message:
import time
import simplefix
import socket
import base64
import hmac
import hashlib
from datetime import datetime
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("127.0.0.1", 4197))
API_KEY = "KEY_GOES_HERE"
PASSPHRASE = "PASSPHRASE_GOES_HERE"
API_SECRET = "SECRET_GOES_HERE"
seq_num = "1"
sendingTime = str(datetime.utcnow()).replace("-","").replace(" ", "-")[:-3]
rawSig = "\x01".join([sendingTime, "A", seq_num, API_KEY, "Coinbase", PASSPHRASE]).encode("utf-8")
hmac_key = base64.b64decode(API_SECRET)
signature = hmac.new(hmac_key, rawSig, hashlib.sha256)
sign_b64 = base64.b64encode(signature.digest()).decode()
msg = simplefix.FixMessage()
msg.append_pair(8, "FIX.4.2")
msg.append_pair(35, "A")
msg.append_pair(49, API_KEY)
msg.append_pair(52, sendingTime)
msg.append_pair(56, "Coinbase")
msg.append_pair(98, "0")
msg.append_pair(108, "30")
msg.append_pair(554, PASSPHRASE)
msg.append_pair(96, sign_b64)
msg.append_pair(8013, "Y")
print(msg.encode())
s.sendall(msg.encode("ascii"))
print(s.recv(4096))
And I'm getting 0 bytes of response from the server. As far as I can tell, the stunnel is working properly (connects and validates certificates successfully, but disconnects after sending my logon message).
Have just tried with a newly generated API key, passphrase and secret but to no avail.
For reference, I was working from the question asked here: How to send FIX logon message with Python to GDAX but I'm not allowed to comment there.
If anyone has any ideas, would be appreciated. Below is an example of the fix message generated, passwords removed in post:
8=FIX.4.2\x019=161\x0135=A\x0149=[KEY_REMOVED]\x0152=20180113-18:24:07.889\x0156=Coinbase\x0198=0\x01108=30\x01554=[PASSPHRASE_REMOVED]\x0196=jueSJHoSNQM2BOCN3KM0mgB2/9tXpICbg4amqDKc2wY=\x018013=Y\x0110=053\x01

Related

InfluxDB : cant connect with the client because of my token and os.getenv

I am just starting with InfluxDB.
On the UI there is a section for Python to start with the database with an example: initialize the client, write data, make a request and close the client. In order to authenticate the request you have to generate a token on the UI which allows to secure the request. But when I run the example code I get the error "can only concatenate str (not "NoneType") to str" from line 12 of my code.
The code :
from datetime import datetime
import os
from influxdb_client import InfluxDBClient, Point, WritePrecision
from influxdb_client.client.write_api import SYNCHRONOUS
# You can generate an API token from the "API Tokens Tab" in the UI
token = os.getenv("INFLUX_TOKEN")
org = "XXXXXXX"
bucket = "XXXXXXX Bucket"
with InfluxDBClient(url="https://europe-west1-1.gcp.cloud2.influxdata.com", token=token, org=org) as client:
write_api = client.write_api(write_options=SYNCHRONOUS)
point = Point("mem") \
.tag("host", "host1") \
.field("used_percent", 23.43234543) \
.time(datetime.utcnow(), WritePrecision.NS)
write_api.write(bucket, org, point)
query = """from(bucket: "XXXXXXX Bucket") |> range(start: -1h)"""
tables = client.query_api().query(query, org=org)
for table in tables:
for record in table.records:
print(record)
client.close()
I understand that the problem come from the os.getenv("INFLUX_TOKEN") because it's supposed to return a string but actually return NoneType object, but I dont know why it doesn't work. With the token I got 2 things : the name of the token and its code which I obtain when when it's created.
I've tried :
os.getenv("the name of the token")
os.getenv("the code of the token")
same of 2 above but with ' instead of "
All the time the same error, so please if someone can help me!
You actually have a problem with your environment variable if
os.getenv("INFLUX_TOKEN") returns None it means that INFLUX_TOKEN variable is not set.
You can manually set it in your shell, after you generate the token by typing in your ssh shell
export INFLUX_TOKEN="your-influx-token"
You can find more about the environment variables here

How to create a SECRET_HASH for AWS Cognito using boto3?

I want to create/calculate a SECRET_HASH for AWS Cognito using boto3 and python. This will be incorporated in to my fork of warrant.
I configured my cognito app client to use an app client secret. However, this broke the following code.
def renew_access_token(self):
"""
Sets a new access token on the User using the refresh token.
NOTE:
Does not work if "App client secret" is enabled. 'SECRET_HASH' is needed in AuthParameters.
'SECRET_HASH' requires HMAC calculations.
Does not work if "Device Tracking" is turned on.
https://stackoverflow.com/a/40875783/1783439
'DEVICE_KEY' is needed in AuthParameters. See AuthParameters section.
https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html
"""
refresh_response = self.client.initiate_auth(
ClientId=self.client_id,
AuthFlow='REFRESH_TOKEN',
AuthParameters={
'REFRESH_TOKEN': self.refresh_token
# 'SECRET_HASH': How to generate this?
},
)
self._set_attributes(
refresh_response,
{
'access_token': refresh_response['AuthenticationResult']['AccessToken'],
'id_token': refresh_response['AuthenticationResult']['IdToken'],
'token_type': refresh_response['AuthenticationResult']['TokenType']
}
)
When I run this I receive the following exception:
botocore.errorfactory.NotAuthorizedException:
An error occurred (NotAuthorizedException) when calling the InitiateAuth operation:
Unable to verify secret hash for client <client id echoed here>.
This answer informed me that a SECRET_HASH is required to use the cognito client secret.
The aws API reference docs AuthParameters section states the following:
For REFRESH_TOKEN_AUTH/REFRESH_TOKEN: USERNAME (required), SECRET_HASH
(required if the app client is configured with a client secret),
REFRESH_TOKEN (required), DEVICE_KEY
The boto3 docs state that a SECRET_HASH is
A keyed-hash message authentication code (HMAC) calculated using the
secret key of a user pool client and username plus the client ID in
the message.
The docs explain what is needed, but not how to achieve this.
The below get_secret_hash method is a solution that I wrote in Python for a Cognito User Pool implementation, with example usage:
import boto3
import botocore
import hmac
import hashlib
import base64
class Cognito:
client_id = app.config.get('AWS_CLIENT_ID')
user_pool_id = app.config.get('AWS_USER_POOL_ID')
identity_pool_id = app.config.get('AWS_IDENTITY_POOL_ID')
client_secret = app.config.get('AWS_APP_CLIENT_SECRET')
# Public Keys used to verify tokens returned by Cognito:
# http://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html#amazon-cognito-identity-user-pools-using-id-and-access-tokens-in-web-api
id_token_public_key = app.config.get('JWT_ID_TOKEN_PUB_KEY')
access_token_public_key = app.config.get('JWT_ACCESS_TOKEN_PUB_KEY')
def __get_client(self):
return boto3.client('cognito-idp')
def get_secret_hash(self, username):
# A keyed-hash message authentication code (HMAC) calculated using
# the secret key of a user pool client and username plus the client
# ID in the message.
message = username + self.client_id
dig = hmac.new(self.client_secret, msg=message.encode('UTF-8'),
digestmod=hashlib.sha256).digest()
return base64.b64encode(dig).decode()
# REQUIRES that `ADMIN_NO_SRP_AUTH` be enabled on Client App for User Pool
def login_user(self, username_or_alias, password):
try:
return self.__get_client().admin_initiate_auth(
UserPoolId=self.user_pool_id,
ClientId=self.client_id,
AuthFlow='ADMIN_NO_SRP_AUTH',
AuthParameters={
'USERNAME': username_or_alias,
'PASSWORD': password,
'SECRET_HASH': self.get_secret_hash(username_or_alias)
}
)
except botocore.exceptions.ClientError as e:
return e.response
I also got a TypeError when I tried the above solution. Here is the solution that worked for me:
import hmac
import hashlib
import base64
# Function used to calculate SecretHash value for a given client
def calculateSecretHash(client_id, client_secret, username):
key = bytes(client_secret, 'utf-8')
message = bytes(f'{username}{client_id}', 'utf-8')
return base64.b64encode(hmac.new(key, message, digestmod=hashlib.sha256).digest()).decode()
# Usage example
calculateSecretHash(client_id, client_secret, username)

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.

Sending and Receiving files in XMPP bot with Python

I'm using the following bot (based on xmppy):
import xmpp, os
user = 'uname'
password = 'pass'
server="talk.google.com"
def message_handler(connect_object, message_node):
messageFromCounterPart = message_node.getBody()
connect_object.send( xmpp.Message( message_node.getFrom() ,message_node.getBody()))
jid = xmpp.JID(user)
connection = xmpp.Client(jid.getDomain())
connection.connect(server = (server, 5223))
result = connection.auth(jid.getNode(), password, "LFY-client")
connection.RegisterHandler('message', message_handler)
connection.sendInitPresence()
while connection.Process(1):
pass
How to cause it to receive and send files? Is there special name for stanzas in this case? (like in connection.RegisterHandler('message', message_handler))
Thanks.

SMTP through Exchange using Integrated Windows Authentication (NTLM) using Python

I want to use the credentials of the logged-in Windows user to authenticate an SMTP connection to an Exchange server using NTLM.
I'm aware of the python-ntlm module and the two patches that enable NTLM authentication for SMTP, however I want to use the current user's security token and not have to supply a username and password.
Very similar problem to Windows Authentication with Python and urllib2.
Although the solution below only uses the Python Win32 extensions (the sspi example code included with the Python Win32 extensions was very helpful), the python-ntlm IMAP & SMTP patches mentioned in the question also served as useful guides.
from smtplib import SMTPException, SMTPAuthenticationError
import string
import base64
import sspi
# NTLM Guide -- http://curl.haxx.se/rfc/ntlm.html
SMTP_EHLO_OKAY = 250
SMTP_AUTH_CHALLENGE = 334
SMTP_AUTH_OKAY = 235
def asbase64(msg):
# encoding the message then convert to string
return base64.b64encode(msg).decode("utf-8")
def connect_to_exchange_as_current_user(smtp):
"""Example:
>>> import smtplib
>>> smtp = smtplib.SMTP("my.smtp.server")
>>> connect_to_exchange_as_current_user(smtp)
"""
# Send the SMTP EHLO command
code, response = smtp.ehlo()
if code != SMTP_EHLO_OKAY:
raise SMTPException("Server did not respond as expected to EHLO command")
sspiclient = sspi.ClientAuth('NTLM')
# Generate the NTLM Type 1 message
sec_buffer=None
err, sec_buffer = sspiclient.authorize(sec_buffer)
ntlm_message = asbase64(sec_buffer[0].Buffer)
# Send the NTLM Type 1 message -- Authentication Request
code, response = smtp.docmd("AUTH", "NTLM " + ntlm_message)
# Verify the NTLM Type 2 response -- Challenge Message
if code != SMTP_AUTH_CHALLENGE:
raise SMTPException("Server did not respond as expected to NTLM negotiate message")
# Generate the NTLM Type 3 message
err, sec_buffer = sspiclient.authorize(base64.decodebytes(response))
ntlm_message = asbase64(sec_buffer[0].Buffer)
# Send the NTLM Type 3 message -- Response Message
code, response = smtp.docmd(ntlm_message)
if code != SMTP_AUTH_OKAY:
raise SMTPAuthenticationError(code, response)
Great answer but as an update for python 3
def asbase64(msg):
# encoding the message then convert to string
return base64.b64encode(msg).decode("utf-8")
Python 2.7.x will fail on sending the NTLM Type 3 message due to the blank cmd specified:
code, response = smtp.docmd("", ntlm_message)
This ends up sending the correct response back to the server, however it pre-pends a space due to the nature of docmd() calling putcmd().
smtplib.py:
def putcmd(self, cmd, args=""):
"""Send a command to the server."""
if args == "":
str = '%s%s' % (cmd, CRLF)
else:
str = '%s %s%s' % (cmd, args, CRLF)
self.send(str)
# ...
def docmd(self, cmd, args=""):
"""Send a command, and return its response code."""
self.putcmd(cmd, args)
return self.getreply()
which as a result takes the path of the else condition, thereby sending str(' ' + ntlm_message + CRLF) which results in (501, 'Syntax error in parameters or arguments').
As such the fix is simply to send the NTLM message as the cmd.
code, response = smtp.docmd(ntlm_message)
A fix to the above answer was submitted, though who knows when it will be reviewed/accepted.

Categories

Resources