Can any one help to do the same code in Python
<?php
$payload = '{"amount":205.16,"currency":"AED","language":"en","merchant_code":"O8Ryrfvy8aUb","merchant_order":"931","redirect_urls":{"cancel":"http://127.0.0.1:8000/api/pointspay-cancel","fail":"http://127.0.0.1:8000/api/pointspay-failed","success":"http://127.0.0.1:8000/api/pointspay-success"},"timestamp":1604722764987,"type":"direct"}';
echo x509_fingerprint($payload, '/home/tmt/Documents/Protect4less/LoyLogic/pointspay_certificate.p12', 'Protect4Less#123', 'sha256') . "\n\n";
function x509_fingerprint($payload, $cert_path, $cert_pass, $algorithm = 'sha256')
{
$algorithm = in_array($algorithm, array(
'sha1',
'md5',
'sha256'
)) ? $algorithm : 'sha1';
// 1. Capture the private key from certificate
if (!$cert_store = file_get_contents($cert_path)) {
echo "Error: Unable to read the cert file\n";
exit;
}
if (openssl_pkcs12_read($cert_store, $cert_info, $cert_pass)) {
} else {
echo "Error: Unable to read the cert store.\n";
exit;
}
$privateKey = $cert_info['pkey'];
print_r($privateKey);
// 2. create message digest
$messageDigest = openssl_digest($payload, $algorithm, true);
// 3. Sign the message digest using private key
openssl_private_encrypt($messageDigest, $encryptedData, $privateKey);
return base64_encode($encryptedData);
}
?>
This is PHP code and I want to do the same steps in PYTHON, can any 1 help me to do so.
I tried many things in python but was not able to do so.
Following is the Python code I tried, but the final signature doesn't match with the PHP signature
from OpenSSL import crypto
import hashlib
from base64 import b64encode
str1 = b'{"amount":205.16,"currency":"AED","language":"en","merchant_code":"O8Ryrfvy8aUb","merchant_order":"931","redirect_urls":{"cancel":"http://127.0.0.1:8000/api/pointspay-cancel","fail":"http://127.0.0.1:8000/api/pointspay-failed","success":"http://127.0.0.1:8000/api/pointspay-success"},"timestamp":1604722764987,"type":"direct"}'
psw = 'Protect4Less#123'
p12 = crypto.load_pkcs12(open("/home/tmt/Documents/Protect4less/LoyLogic/pointspay_certificate.p12", 'rb').read(), psw)
pkey = p12.get_privatekey()
my_hash2 = hashlib.sha256() #Choose SHA256 and update with same bytes
my_hash2.update(str1)
hash_digest = my_hash2.hexdigest()
print("Result after digesting: " + str(my_hash2.hexdigest()))
# data = str1
my_signature = crypto.sign(pkey, str1, 'sha256')
signature_b64 = b64encode(my_signature)
print(signature_b64)
Related
Hi I have this code from this article
https://medium.com/#alexastrum/firebase-auth-for-iot-devices-286679a8b59e
I was wondering what the equivalent python code would be thanks.
String getDeviceToken()
{
String header = "";
DynamicJsonDocument json(1024);
// ATECCx08 crypto chips only support ES256:
// https://github.com/MicrochipTech/cryptoauthlib/blob/master/lib/jwt/atca_jwt.c
json["alg"] = "ES256";
json["kid"] = DEVICE_ID;
serializeJson(json, header);
String payload;
json.clear();
json["nonce"] = NONCE;
serializeJson(json, payload);
return ECCX08JWS.sign(/* slot */ 0, header, payload);
}
import jwt as jwt
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import ec
# Generates the private key
private_key = ec.generate_private_key(ec.SECP256R1(), default_backend())
# Generates the public key
public_key = private_key.public_key()
jwt.encode(
payload={"nonce": NONCE},
key=private_key,
algorithm="ES256",
headers={"alg": "ES256", "kid": DEVICE_ID},
)
I am in the process of incorporating the gate,io rest api and am currently trying to convert the signature function from python to php(laravel).
Apparently there is a bug hiding in the conversion.
Can someone take a look and tell me if this is all correct or if something is missing here?
For improvement suggestions I would be grateful
Python code:
def gen_sign(method, url, query_string=None, payload_string=None):
key = '' # api_key
secret = '' # api_secret
t = time.time()
m = hashlib.sha512()
m.update((payload_string or "").encode('utf-8'))
hashed_payload = m.hexdigest()
s = '%s\n%s\n%s\n%s\n%s' % (method, url, query_string or "", hashed_payload, t)
sign = hmac.new(secret.encode('utf-8'), s.encode('utf-8'), hashlib.sha512).hexdigest()
return {'KEY': key, 'Timestamp': str(t), 'SIGN': sign}
Source: Gate.io API Signature string generation
Php Code:
public function createSignature($method, $url, $query=null, $payload=null, $algo = 'sha256'){
$key = 'xxx';
$secret= 'xxx';
$time = microtime(true);
$hashed_payload = hash_hmac($algo,$query ?? '');
$string = "{$methode}\n{$url}\n{$query ?? ''}\n{$hashed_payload}\n{$time}"
$sign = hash_hmac($algo,$string,$secret)
return ['KEY' => $key, 'Timestamp' => "{$time}", 'SIGN' => $sign]
}
i got the answer, i hope it will helps:
public function buildSignHeaders($method, $resourcePath, $queryParams = [], $payload = null)
{
$fullPath = parse_url(config('gate-io.host'), PHP_URL_PATH) . $resourcePath;
$fmt = "%s\n%s\n%s\n%s\n%s";
$timestamp = time();
$hashedPayload = hash("sha512", ($payload !== null) ? $payload : "");
$signatureString = sprintf(
$fmt,
$method,
$fullPath,
GuzzleHttp\Psr7\build_query($queryParams, false),
$hashedPayload,
$timestamp
);
$signature = hash_hmac("sha512", $signatureString, config('gate-io.apiSecretKey'));
return [
"KEY" => config('gate-io.apiKey'),
"SIGN" => $signature,
"Timestamp" => $timestamp
];
}
i have a python application that send data to request.log using webhook.php
webhook.php working code :
<?php
$request = file_get_contents('php://input');
$req_dump = print_r( $request, true );
$fp = file_put_contents( 'request.log', $req_dump );
// Updated Answer
if($json = json_decode(file_get_contents("php://input"), true)){
$data = $json;
}
print_r($data);
?>
content in request.log is on json format.
I get results in request.log without issue, but i need to send same details to telegram, here's the not working code :
<?php
$request = file_get_contents('php://input');
$req_dump = print_r( $request, true );
$fp = file_put_contents( 'request.log', $req_dump );
// Updated Answer
if($json = json_decode(file_get_contents("php://input"), true)){
$data = $json;
}
print_r($data);
if($json = json_decode(file_get_contents("php://input"), true)){
$token = "166.....:AAFlfaCuGdkG3MD1hO.......";
$chatid = "-51....";
$message = $data;
function sendMessage($chatid, $message, $token)
{
$url = "https://api.telegram.org/bot" . $token . "/sendMessage?chat_id=" . $chatid;
$url = $url . "&text=" . urlencode($message);
$ch = curl_init();
$optArray = array(
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true
);
curl_setopt_array($ch, $optArray);
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
sendMessage($chatid, $message, $token);
}
?>
Can't figure out how to get those data sent to telegram, if it's impossible to send to request.log and to telegram in same time, is there a way to get updated content from request.log and send them to telegram.
Thank you
I need to take the RSA PSS signatures of a message generated from Python and validate in .NET. But validation in .NET fails.
I have generated the RSA key pair using the following command:
openssl req -x509 -nodes -newkey rsa:4096 -keyout /tmp/certs/private.pem -out /tmp/certs/public.pem -days 365
Python code:
from cryptography import x509
from cryptography.exceptions import InvalidSignature
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding
from nacl.encoding import HexEncoder
def sign(message: str) -> str:
with open("/tmp/certs/private.pem", "rb") as pem:
private_key = serialization.load_pem_private_key(
pem.read(),
password=None,
backend=default_backend(),
)
return HexEncoder.encode(
private_key.sign(
message.encode("utf-8"),
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()), salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256(),
)
).decode("utf-8")
def verify(message: str, signature: str) -> bool:
with open("/tmp/certs/public.pem", "rb") as pem:
cert = x509.load_pem_x509_certificate(pem.read(), default_backend())
public_key = cert.public_key()
try:
signature = HexEncoder().decode(signature)
public_key.verify(
signature,
message.encode(),
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()), salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256(),
)
return True
except InvalidSignature:
return False
def main():
message = "hello"
signature = sign(message)
print(f"Signature: {signature}")
# print(f"isValidated: {verify(message, signature)}")
if __name__ == '__main__':
main()
C# code targeting .NET 5.0:
using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
namespace HelloWorld
{
internal static class Program
{
private static string ByteArrayToString(IReadOnlyCollection<byte> ba)
{
var hex = new StringBuilder(ba.Count * 2);
foreach (var b in ba)
hex.AppendFormat("{0:x2}", b);
return hex.ToString();
}
private static byte[] StringToByteArray(string hex)
{
var numberChars = hex.Length;
var bytes = new byte[numberChars / 2];
for (var i = 0; i < numberChars; i += 2)
bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
return bytes;
}
private static string Sign(string message)
{
var rsa = RSA.Create();
rsa.ImportFromPem(File.ReadAllText("/tmp/certs/private.pem"));
var messageBytes = Encoding.UTF8.GetBytes(message);
var signature = rsa.SignData(messageBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pss);
return ByteArrayToString(signature);
}
private static bool Verify(string message, string signature)
{
var rsa = RSA.Create();
var cert = X509Certificate.CreateFromCertFile("/tmp/certs/public.pem");
var publicKey = cert.GetPublicKey();
rsa.ImportRSAPublicKey(publicKey, out _);
var messageBytes = Encoding.UTF8.GetBytes(message);
var signatureBytes = StringToByteArray(signature);
return rsa.VerifyData(messageBytes, signatureBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pss);
}
public static void Main()
{
const string message = "hello";
// var signature = Sign(message);
const string signature = <value_from_python>;
// Console.WriteLine($"Signature is: {signature}");
Console.WriteLine($"isValidated: {Verify(message, signature)}");
}
}
}
The verification fails because both codes use different salt lengths. The Python code explicitly applies the maximum salt length, the C# code defaults to the digest output length. The latter is also defined as PSS default in RFC8017, A.2.3. RSASSA-PSS.
So to fix this
either use the digest output length in the Python code, i.e. 32 (bytes for SHA256),
or in the C# code the maximum salt length: signature length - digest output length - 2 = 512 - 32 - 2 = 478 (for a 4096 bits key).
As far as I know this is not possible with .NET onboard means, but with BouncyCastle and the class Org.BouncyCastle.Crypto.Signers.PssSigner, which also provides constructors for defining the salt length. You can find an example here, last section.
I write code to verify an HMAC Auth incoming POST request with JSON to our API. The HMAC I received is OD5ZxL4tdGgWr78e9vO3cYrjuOFT8WOrTbTIuuIH1PQ=
When I try to generate it by my self using Python, it is always different.
Here is the JSON request I received:
{
"shipper_id": 4841,
"status": "Cancelled",
"shipper_ref_no": "",
"tracking_ref_no": "",
"shipper_order_ref_no": "",
"timestamp": "2018-05-23T15:13:28+0800",
"id": "61185ecf-3484-4985-b625-ffe30ba36e28",
"previous_status": "Pending Pickup",
"tracking_id": "NVSGBHINK000000001"
}
And the client secret is 817a3723917f4c7fac24b1f1b324bbab.
The HMAC secret I received is OD5ZxL4tdGgWr78e9vO3cYrjuOFT8WOrTbTIuuIH1PQ=.
Here is the code when I write it in PHP:
<?php
define('CLIENT_SECRET', 'my_shared_secret');
function verify_webhook($data, $hmac_header){
$calculated_hmac = base64_encode(hash_hmac('sha256', $data, CLIENT_SECRET, true));
return ($hmac_header == $calculated_hmac);
}
$hmac_header = $_SERVER['X-NINJAVAN-HMAC-SHA256'];
$data = file_get_contents('php://input');
$verified = verify_webhook($data, $hmac_header);
error_log('Webhook verified: '.var_export($verified, true)); //check error.log to see result
?>
But I have no idea how to do it in Python 3.
In Python 3 you basically want something like the following, taken from how you handle GitHub webhook requests.
import hashlib
import hmac
secret = 'CLIENT_SECRET'
data = rsp.content # assumes you're using requests for data/sig
signature = rsp.headers['X-Something-Signature']
signature_computed = 'sha1=' + hmac.new(
key=secret.encode('utf-8'),
msg=data.encode('utf-8'),
digestmod=hashlib.sha1
).hexdigest()
if not hmac.compare_digest(signature, signature_computed):
log("Invalid payload")
If you want to recreate the hashing code from PHP to Python do it thusly:
def create_signature(key, data):
sig_hash = hmac.new(key.encode('utf8'), data.encode('utf8'), hashlib.sha256).digest()
base64_message = base64.b64encode(sig_hash).decode()
return base64_message
This will create the signature that should match what your PHP code is creating. Just compare the signature to what is sent in the header.
from collections import OrderedDict
params = orderedDict()
params["shipper_id"] = 4841
params["status"] = "Cancelled"
params["shipper_ref_no"] = ""
params["tracking_ref_no"] = ""
params["shipper_order_ref_no"] = ""
params["timestamp"] = "2018-05-23T15:13:28+0800"
params["id"] = "61185ecf-3484-4985-b625-ffe30ba36e28"
params["previous_status"] = "Pending Pickup"
params["tracking_id"] = "NVSGBHINK000000001"
mes = json(params, separator = (";",",")).highdigest()
sighnature = hmac.new(mes, sha256)
# separators = (";",",") - i'm not shure
params['sighnature'] = sighnature
r = response.post(url,params,sighnature)
print(r.text())