0

I need to create a signature from a private key and a message in Python using HMAC SHA256.

The OpenSSL command, ran in the command window, is the following:

echo -n "recvWindow=0&symbol=BTC-USDT&timestamp=1696751141337" | openssl dgst -sha256 -hmac "mheO6dR8ovSsxZQCOYEFCtelpuxcWGTfHw7te326y6jOwq5WpvFQ9JNljoTwBXZGv5It07m9RXSPpDQEK2w" -hex
SHA2-256(stdin)= 04003ddfe0e52231a2bdfe94e8d3f5a369522b82f28b7d5511414b4d7f87d698

The Python code used to recreate the same behavior is the following:

def calcu(key, data):
    hmac_digest = hmac.new(key.encode("UTF-8"),
                           data.encode("UTF-8"),
                           hashlib.sha256).hexdigest()
    return hmac_digest

key = "mheO6dR8ovSsxZQCOYEFCtelpuxcWGTfHw7te326y6jOwq5WpvFQ9JNljoTwBXZGv5It07m9RXSPpDQEK2w"
data = "recvWindow=0&symbol=BTC-USDT&timestamp=1696751141337"

sign = calcu(key, data)

print(sign.upper())

yielding: F8D883609DFD31C824FEB4DE865B071008DEDB1D461451FA70847875C8E7A7A2

What tells me that there is some basic mistake that I am making is that if I use a simple string, like 333 for key and data, the results keep differing from the OpenSSL and Python implementation:

Example:

OpenSSL CMD

echo -n "333" | openssl dgst -sha256 -hmac "333" -hex
SHA2-256(stdin)= 32fc726256e8a10d99fbef0d7b27fa51e932ea6cd76530fcfb4641057a813bd8

Python

def calcu(key, data):
    hmac_digest = hmac.new(key.encode("UTF-8"),
                           data.encode("UTF-8"),
                           hashlib.sha256).hexdigest()
    return hmac_digest

key = "333"
data = "333"

sign = calcu(key, data)

print(sign.upper())

0006A5A7658EBA166B26B598748E821E943B769C97A6F366C723712E6CD92DEB I also tried with b"" and r"" strings, no success with that neither.

What am I overlooking? I tried different encoding like UTF-8, 16, 32, ascii, and so on but none made this work

edit1: I am running Windows 10, OpenSSL 3.2.1 30 Jan 2024 (Library: OpenSSL 3.2.1 30 Jan 2024), Python 3.10, pyopenssl 24.0.0.

The problem was that Windows was not taking the -n as a parameter, but as part of the input. So, as Topaco and Tim Peters said, using /p= {...} solved it for me.

6
  • Check your outputs against the examples here: en.wikipedia.org/wiki/HMAC#Examples Your Python code reproduces the SHA-258 sample output. Don't know about your dgst output. Commented Feb 23, 2024 at 5:07
  • 1
    When I run ` echo -n "recvWindow=0&symbol=BTC-USDT&timestamp=1696751141337" | openssl dgst -sha256 -hmac "mheO6dR8ovSsxZQCOYEFCtelpuxcWGTfHw7te326y6jOwq5WpvFQ9JNljoTwBXZGv5It07m9RXSPpDQEK2w" -hex ` I get ``f8d883609dfd31c824feb4de865b071008dedb1d461451fa70847875c8e7a7a2`, which is exactly the same thing that Python returns. You're sure you copied the strings perfectly? Commented Feb 23, 2024 at 5:53
  • 1
    Likewise, when I type your echo -n "333" .... command, I get a completely different output. Exactly what the Python outputs. Is there something strange about your openssl?? Commented Feb 23, 2024 at 5:58
  • 2
    Probably depends on the OS and/or OpenSSL version, which is why both should be posted. I can reproduce the result of the OP on Windows (10) when the OpenSSL statement is entered in the console. Everything following the first blank after the echo until immediately before the pipe is interpreted as input and a linebreak is added at the end. This can be verified if in the Python program data = "-n \"333\" \r\n" is used and the same output is generated, see jdoodle.com/ia/WSQ (and jdoodle.com/ia/WSR for the longer input). Commented Feb 23, 2024 at 10:21
  • 2
    On Windows, the line break can be suppressed as described in this SO post, e.g. echo|set /p="333"|openssl dgst -sha256 -hmac "333" -hex works for me, i.e. returns 0006a5a7658eba166b26b598748e821e943b769c97a6f366c723712e6cd92deb. Commented Feb 23, 2024 at 12:54

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.