HMAC is a mechanism that allows a server to verify that a request came from you and was not altered along the way. It is a fundamental aspect of security when working with private API endpoints.
What is HMAC and why is it needed?
Imagine you are sending a messenger with an order. To make sure the recipient knows the order came from you and has not been swapped, you stamp it with your unique wax seal. HMAC (Hash-based Message Authentication Code) is exactly that kind of digital "seal".
It solves two problems:
- Authentication: It proves the request came from the owner of the API key (only you have the secret key — the "seal").
- Integrity: It guarantees that the request data (for example, the order amount) was not modified by an attacker during transmission.
Unlike simple hashing, HMAC uses a secret key known only to you and the server, which makes forging the signature practically impossible.
Step-by-step signature creation algorithm
The process of creating a signature for APIs that use HMAC-SHA256 (as on AsterDEX, Binance and many others) is nearly identical everywhere:
- Assembling the string to sign (query string): You combine all of your request parameters into a single string. The order of parameters matters. For example:
symbol=BTCUSDT&side=BUY&type=LIMIT&quantity=1&price=30000×tamp=1672531200000. - Hashing: You take this string and hash it using the HMAC-SHA256 algorithm, with your Secret Key serving as the hashing key.
- Encoding: The hashing result (binary data) is converted into a hexadecimal string (hex). This is your
signature. - Sending the request: You append the resulting signature as another parameter to your request (
&signature=...) and send it to the server, remembering to include your API Key in theX-MBX-APIKEYheader.
Python example
Python is perfect for this task thanks to its built-in hashlib and hmac libraries.
import hmac
import hashlib
import time
# Your keys (NEVER store them in plain text inside your code!)
apiKey = "your_api_key"
secretKey = "your_secret_key"
# 1. Request parameters
params = {
'symbol': 'BTCUSDT',
'side': 'BUY',
'type': 'LIMIT',
'timeInForce': 'GTC',
'quantity': 0.001,
'price': 30000,
'timestamp': int(time.time() * 1000)
}
# Assembling the string to sign
query_string = '&'.join([f"{key}={value}" for key, value in params.items()])
# 2. Creating the signature
signature = hmac.new(
secretKey.encode('utf-8'),
query_string.encode('utf-8'),
hashlib.sha256
).hexdigest()
print(f"Query String: {query_string}")
print(f"Signature: {signature}")
# 3. Final request URL
# final_url = f"https://api.binance.com/api/v3/order?{query_string}&signature={signature}"
# headers = {'X-MBX-APIKEY': apiKey}
# ... the request is then sent using requests ...
JavaScript example (Node.js)
In Node.js, the built-in crypto module is used for this.
const crypto = require('crypto');
// Your keys
const apiKey = 'your_api_key';
const secretKey = 'your_secret_key';
// 1. Request parameters
const params = {
symbol: 'BTCUSDT',
side: 'BUY',
type: 'LIMIT',
timeInForce: 'GTC',
quantity: 0.001,
price: 30000,
timestamp: Date.now()
};
const queryString = Object.entries(params).map(([key, val]) => `${key}=${val}`).join('&');
// 2. Creating the signature
const signature = crypto
.createHmac('sha256', secretKey)
.update(queryString)
.digest('hex');
console.log(`Query String: ${queryString}`);
console.log(`Signature: ${signature}`);
// 3. Final request URL
// const finalUrl = `https://api.binance.com/api/v3/order?${queryString}&signature=${signature}`;
// const headers = { 'X-MBX-APIKEY': apiKey };
// ... the request is then sent using axios/fetch ...
Conclusion
HMAC authentication is a straightforward yet critically important protection mechanism. Once you understand it, you can securely work with the API of any major exchange. The main thing is to always keep your Secret Key strictly confidential and never transmit it over insecure channels.