Signature Verification of transaction executed on Payment Gateway in NodeJs - python

How do I implement the below python/Java/PHP code in NodeJs?
ReferenceLink
Python Code (for reference):
import hashlib
import hmac
import base64
#app.route('/notify_url/', methods=["POST"])
def notify_url_process():
postData = {
"orderId" : request.form['orderId'],
"orderAmount" : request.form['orderAmount'],
"referenceId" : request.form['referenceId'],
"txStatus" : request.form['txStatus'],
"paymentMode" : request.form['paymentMode'],
"txMsg" : request.form['txMsg'],
"txTime" : request.form['txTime'],
}
signatureData = postData["orderId"] + postData["orderAmount"] + postData["referenceId"] + postData["txStatus"] + postData["paymentMode"] + postData["txMsg"] + postData["txTime"]
message = bytes(signatureData).encode('utf-8')
#get secret key from your config
secret = bytes(secretKey).encode('utf-8')
signature = base64.b64encode(hmac.new(secret,
message,digestmod=hashlib.sha256).digest())
So far, I was able to come up with the below code. However, the generated and received signatures do not match.
var hmac = crypto.createHmac('sha256', "appSecret"); //Key hidden for posting here
hmac.update(request.body.orderId + request.body.orderAmount+request.body.referenceId+request.body.txStatus+request.body.paymentMode+request.body.txMsg+request.body.txTime);
let generatedSignature = hmac.digest('hex');
let isSignatureValid = generatedSignature == request.body.cashfreeSignature;
console.log(isSignatureValid);

Have you tried comparing the base64 encoding as opposed to the hex value?
Instead of
let generatedSignature = hmac.digest('hex');
use
let generatedSignature = hmac.digest('base64');

Related

Need help to create signature in python

I have sample code from golang,
here is some sample values to run the code:
app_secret = 777, path = /api/orders, app_key = 12345, timestamp = 1623812664
or you guys can refer this link to get more info https://developers.tiktok-shops.com/documents/document/234136#3.Signature%20Algorithm
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"sort"
)
func generateSHA256(path string, queries map[string]string, secret string) string{
keys := make([]string, len(queries))
idx := 0
for k, _ := range queries{
keys[idx] = k
idx++
}
sort.Slice(keys, func(i, j int) bool {
return keys[i] < keys[j]
})
input := path
for _, key := range keys{
input = input + key + queries[key]
}
input = secret + input + secret
h := hmac.New(sha256.New, []byte(secret))
if _, err := h.Write([]byte(input)); err != nil{
// todo: log error
return ""
}
return hex.EncodeToString(h.Sum(nil))
}
need help converting this golang sample into python sample
i have tried but keep getting signature invalid when submit
my python code
import hmac
import hashlib
def _short_sign(self, app_key, app_secret, path, timestamp):
base_string = "%sapp_key%stimestamp%s"%(path, app_key, timestamp)
sign_string = app_secret + base_string + app_secret
sign = hmac.new(app_secret.encode(), sign_string.encode(), hashlib.sha256).hexdigest()
return sign
Found the issue, i was trying to digest with out digestmod
Working Example:
sign = hmac.new(
app_secret.encode(),
sign_string.encode(),
digestmod = hashlib.sha256
).hexdigest()

I want to send my response to an API using TOTP?

I want to sent my assignment gist in the JSON Response :
{
gist :"",
email :""
}
to an API using TOTP(Time-based one-time password) method . Is there any solution available for that?
Although you have to do it by yourself but still if you invested lot's of time and didn't find solution then you can use my solution for that :
import requests
import hmac
import hashlib
import time
import sys
import struct
import json
from requests.auth import HTTPBasicAuth
root = "YOUR API RESIDES HERE"
content_type = "application/json"
userid = "YOUR USERID"
secret_suffix = "YOUR SECRET SUFFIX OR KEY"
shared_secret = userid+secret_suffix
timestep = 30
T0 = 0
def HOTP(K, C, digits=10):
"""HTOP:
K is the shared key
C is the counter value
digits control the response length
"""
K_bytes = str.encode(K)
C_bytes = struct.pack(">Q", C)
hmac_sha512 = hmac.new(key = K_bytes, msg=C_bytes, digestmod=hashlib.sha512).hexdigest()
return Truncate(hmac_sha512)[-digits:]
def Truncate(hmac_sha512):
"""truncate sha512 value"""
offset = int(hmac_sha512[-1], 16)
binary = int(hmac_sha512[(offset *2):((offset*2)+8)], 16) & 0x7FFFFFFF
return str(binary)
def TOTP(K, digits=10, timeref = 0, timestep = 30):
"""TOTP, time-based variant of HOTP
digits control the response length
the C in HOTP is replaced by ( (currentTime - timeref) / timestep )
"""
C = int ( time.time() - timeref ) // timestep
return HOTP(K, C, digits = digits)
data = {
"github_url": "YOUR GITHUB URL",
"contact_email": "YOUR EMAIL",
"solution_language": "IT IS OPTIONAL"
}
passwd = TOTP(shared_secret, 10, T0, timestep).zfill(10)
resp = requests.post(root, auth=HTTPBasicAuth(userid, passwd), data=json.dumps(data))
print(resp.json())
I hope this works !!
Happy Coding !!

Can't signing a Message using sha512 in python at iconomi

I am trying to send an authentificated message over an API at iconomi.com.
I am used to sign message when dealing with other exchange API, but can't be authentificated with this specific one.
I read the official documentation for authentification:
You generate the ICN-SIGN header by creating a sha512 HMAC using the
base64-decoded secret key on the prehash string timestamp + method +
requestPath + body (where + represents string concatenation) and
base64-encode the output, where:
the timestamp value is the same as the ICN-TIMESTAMP header. the body
is the request body string or omitted if there is no request body
(typically for GET requests). method must always be in upper case
Example: base64_encode(HMAC_SHA512(secret_key, timestamp + upper_case(method) + requestPath + body))
I found also a java client example on the official github, please see bellow signature generation in java :
private String generateServerDigest(String method, String uri, long timestamp, String body) {
//return timestamp + request.getMethodValue() + uri + body;
String checkDigestString = timestamp + method + uri + body;// "GET+/v1/daa-list+123123123"; //timestamp in epoch milliseconds
// hash server composited digest with algorithm and apikeys secret
SecretKeySpec signingKey = new SecretKeySpec(apiSecret.getBytes(), "HmacSHA512");
Mac mac;
try {
mac = Mac.getInstance(signingKey.getAlgorithm());
mac.init(signingKey);
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
log.warn("Could not ={}", signingKey.getAlgorithm());
return null;
}
return Base64.getEncoder().encodeToString(mac.doFinal(checkDigestString.getBytes()));
}
Please note that checkDigestString code timestamp + method + uri + body and comment GET+/v1/daa-list+123123123 are already different on the official doc.
And this is my python implementation attempt :
def sign(timestamp,method,requestPath,body):
global api_secret
base64_decoded_secret_key = base64.b64decode(api_secret)
content_to_hash = (str(timestamp) + method.upper() + requestPath + body).encode('utf-8')
sign_digest = hmac.new(base64_decoded_secret_key, content_to_hash , hashlib.sha512).digest()
return base64.b64encode(sign_digest).decode('utf-8')
When I try this signature method with requestPath = "/v1/user/balance" (which required to be authentificated), it fail without error...
Does any one used with both java and python may help me to convert this signature method to python ?
This code will work for GET:
import time,requests
import hashlib,hmac,base64
api_key = "my api key"
api_secret = "my api secret"
defaut_encoding = "utf8"
uri = "https://api.iconomi.com"
requestPath = "/v1/user/balance"
api_url_target = uri+requestPath # https://api.iconomi.com/v1/user/balance
method="GET"
body=""
icn_timestamp = int(1000.*time.time())
message = (str(icn_timestamp) + method.upper() + requestPath + body).encode(defaut_encoding)
signature_digest = hmac.new(api_secret.encode(defaut_encoding), message, hashlib.sha512).digest() #here digest is byte
b64_signature_digest= base64.b64encode(signature_digest).decode(defaut_encoding)
headers_sign= {
"ICN-API-KEY":api_key,
"ICN-SIGN":b64_signature_digest,
"ICN-TIMESTAMP":str(icn_timestamp)
}
s=requests.session()
res = s.get(api_url_target,headers=headers_sign,timeout=3, verify=True).content
print (res)
Update for #Karl comment, this code will work for POST:
import time,requests
import hashlib,hmac,base64,json
api_key = "my api key"
api_secret = "my api secret"
ticker = "my ticker strategy"
defaut_encoding = "utf8"
uri = "https://api.iconomi.com"
requestPath = "/v1/strategies/"+ticker+"/structure"
api_url_target = uri+requestPath # https://api.iconomi.com/v1/strategies/{my ticker strategy}/structure
method="POST"
body="{'ticker': ticker, 'values': [{'rebalancedWeight': 1., 'targetWeight':1., 'assetTicker': 'XMR', 'assetName': 'Monero', 'assetCategory': 'Privacy'}]}"
icn_timestamp = int(1000.*time.time())
message = (str(icn_timestamp) + method.upper() + requestPath + body).encode(defaut_encoding)
signature_digest = hmac.new(api_secret.encode(defaut_encoding), message, hashlib.sha512).digest() #here digest is byte
b64_signature_digest= base64.b64encode(signature_digest).decode(defaut_encoding)
headers_sign= {
"ICN-API-KEY":api_key,
"ICN-SIGN":b64_signature_digest,
"ICN-TIMESTAMP":str(icn_timestamp)
}
s=requests.session()
res = s.post(api_url_target,headers=headers_sign,json = json.loads(body), timeout=3, verify=True).content
print (res)

Evernote - OAuth access token - Python

I am going through Evernote OAuth documentation. Was not able to get the temp token. It was resolved after receiving help here. Now, struck at the last step of this flow while receiving Access token. Could you someone let me know what could be the potential issue here?
Its following the similar below to the first one to retrieve the access token. Not sure if there is anything I miss.
import time
import base64
import random
import uuid
import urllib
import collections
import urllib.parse
import hmac
import hashlib
import binascii
import requests
def escape(s):
return urllib.parse.quote(s, safe='~')
def get_nonce():
return uuid.uuid4().hex
def stringify_parameters(parameters):
output = ''
ordered_parameters = {}
ordered_parameters =collections.OrderedDict(sorted(parameters.items()))
counter = 1
for k, v in ordered_parameters.items():
output += escape(str(k)) + '=' + escape(str(v))
if counter < len(ordered_parameters):
output += '&'
counter += 1
return output
oauth_parameters={
'oauth_timestamp': str(int(time.time())),
'oauth_signature_method': "HMAC-SHA1",
'oauth_version': "1.0",
'oauth_nonce': get_nonce(),
'oauth_consumer_key': 'xxxxx',
'oauth_callback':'http://localhost'
}
string_parameters=stringify_parameters(oauth_parameters)
secret='3************f'
### below portion of the code will return temp_token
key = (escape(secret)+'&').encode()
message = ('GET&' + escape('https://sandbox.evernote.com/oauth') + '&' + escape(string_parameters)).encode()
signature = hmac.new(key, message, hashlib.sha1).digest()
oauth_parameters['oauth_signature'] = base64.b64encode(signature).decode()
print(stringify_parameters(oauth_parameters))
res = requests.get('https://sandbox.evernote.com/oauth?' + stringify_parameters(oauth_parameters))
print(res.text)
####
##login to the url below based on the temp_token from above
##https://sandbox.evernote.com/OAuth.action?oauth_token=xxxxx.1652F9812D6.687474703A2F2F6C6F63616C686F7374.3A695C3760E6EFB92B3AB6033222E9D7
## after successful authorization from user, page is redirected along with 'oauth_verifier' value
##http://localhost/?oauth_token=xxxxx.1652F9812D6.687474703A2F2F6C6F63616C686F7374.3A695C3760E6EFB92B3AB6033222E9D7&oauth_verifier=1808C99D6868D17A89871E9290B334D6&sandbox_lnb=false
###error part - below doesn't work while retrieving the access token.
oauth_parameters={
'oauth_consumer_key': 'xxxxx',
'oauth_token': 'xxxxx.1652F9812D6.687474703A2F2F6C6F63616C686F7374.3A695C3760E6EFB92B3AB6033222E9D7',
'oauth_verifier':'1808C99D6868D17A89871E9290B334D6',
'oauth_nonce': get_nonce(),
'oauth_signature_method':'HMAC-SHA1',
'oauth_timestamp': str(int(time.time())),
'oauth_version': '1.0'
}
string_parameters=stringify_parameters(oauth_parameters)
key = (escape(secret)+'&').encode()
message = ('GET&' + escape('https://sandbox.evernote.com/oauth') + '&' + escape(string_parameters)).encode()
signature = hmac.new(key, message, hashlib.sha1).digest()
oauth_parameters['oauth_signature'] =
base64.b64encode(signature).decode()
res = requests.get('https://sandbox.evernote.com/oauth?' +
stringify_parameters(oauth_parameters))
print(res.text)
The only thing I can think of without knowing what the error message is (if there is any), is whether the oauth_verifier is copied over correctly. Everything else looks like it should work fine.

Python secret key encoding from API

I've been trying to use the Poloniex APIg. I get a key and secret from my account, exactly like this. Then, following the examples, I should use one of the following forms:
import poloniex
polo = poloniex.Poloniex('yourApiKeyHere','yourSecretKeyHere123')
# or
polo.APIKey = 'yourApiKeyHere'
polo.Secret = 'yourSecretKeyHere123'
By using either one of them, I get this error:
TypeError: key: expected bytes or bytearray, but got 'str'
I've tried:
polo.Secret = b'yourSecretKeyHere123'
And get:
TypeError: Unicode-objects must be encoded before hashing
So I tried:
polo.Secret = 'yourSecretKeyHere123'.encode('utf-8')
I'm a bit out of my depth here with the encoding and would also expect the API just take my secret key as a string. What am I missing?
This code will works (assuming both your Secret & APIKey exists and also that API are not IP or withdraw-only restricted):
import urllib
import urllib2
import json
import time
import hmac,hashlib
req={}
APIKey = "<my_API_key>"
Secret = "<my_secret>"
command="returnBalances"
req['command'] = command
req['nonce'] = int(time.time()*1000)
post_data = urllib.urlencode(req)
sign = hmac.new(Secret, post_data, hashlib.sha512).hexdigest()
#print sign
headers = {
'Sign': sign,
'Key': APIKey
}
ret = urllib2.urlopen(urllib2.Request('https://poloniex.com/tradingApi', post_data, headers))
jsonRet = json.loads(ret.read())
print jsonRet

Categories