Exchange Authentication: API Keys, HMAC, JWT and Token Lifetimes
TECH INSIGHT / EXPLAINED
API key, HMAC and JWT are not three mutually exclusive security levels. A request may identify a key in a header and authenticate a signature at the same time; a JWT can itself use HMAC.
Local execution of the actual project
These captures show the existing project UI or functions executed locally with non-private sample inputs. Each caption states the scope of the execution.
Separate identity, permission and integrity
An API key is an identifier or credential under the provider’s rules. The permitted operations come from its scopes and endpoint contract, not from whether the value sits in a header. Public quotes may need no key, while private balances can require signed authentication. HTTPS supplies transport confidentiality and integrity; application signatures bind the provider-defined signing material and do not replace HTTPS.
HMAC: preserve the exact signing material
For Binance Spot HMAC keys, sign the documented parameter string with HMAC-SHA256 and send the corresponding signature plus API-key header. The example constructs a new field list instead of mutating its caller. It illustrates query-only signing with dummy values; production adapters must also follow the current encoding and parameter rules.
import hashlib, hmac
from urllib.parse import urlencode, unquote
def hmac_query(pairs, secret, timestamp_ms):
fields = list(pairs) # do not mutate caller input
if any(k in {"signature", "timestamp"} for k, _ in fields):
raise ValueError("signature and timestamp are managed here")
if type(timestamp_ms) is not int:
raise ValueError("explicit integer milliseconds required")
fields.append(("timestamp", str(timestamp_ms)))
query = urlencode(fields)
signature = hmac.new(secret.encode(), query.encode(), hashlib.sha256).hexdigest()
return query + "&signature=" + signature
# Upbit's documented, unencoded query-hash material for array parameters.
query = unquote(urlencode([("uuids[]", "demo-a"), ("uuids[]", "demo-b")], doseq=True))
assert query == "uuids[]=demo-a&uuids[]=demo-b"
query_hash = hashlib.sha512(query.encode()).hexdigest()
# No network request and no real credential in this example.Timing is not a universal five-second rule
Binance documents timestamp validation with a receive window and a separate future-time check. A timestamp window restricts replay age; it does not itself provide exactly-once order execution. Synchronize the host clock, measure drift, and follow the endpoint’s units and limits. Binance also supports RSA and Ed25519 key types, so HMAC is not its only option.
JWT: an encoded container with a signature
A signed compact JWT signs the encoded protected header and payload joined by a dot, not the raw JSON payload alone. Its claims are generally readable; signing is not encryption. Use a maintained library with the documented algorithm.
Upbit recommends HS512 and requires a fresh nonce; parameterized requests bind a SHA512 query hash. Its documented Python construction unquotes urlencode(..., doseq=True), retaining the required parameter order and array form. That canonical material is not necessarily identical to the percent-encoded bytes of the transmitted URL. See the linked Upbit example for the complete token boundary.
Current Bithumb documentation describes JWT with HS256, nonce and millisecond timestamp. A legacy delimiter-based HMAC recipe must not be presented as the current universal Bithumb scheme.
Tokens and debugging still need a contract
KIS first issues an access token; subsequent requests need endpoint-specific headers and expiry handling. Cache against documented expiry metadata rather than calendar date, and separate real and simulated environments. REST access tokens and real-time approval keys have different roles.
For a failure, record a safe error code, API version, key alias, clock drift and canonicalization test result. Compare dummy signing fixtures offline; never print live secrets, token prefixes or signed account/order parameters. Scope keys narrowly, keep them out of source history, and revoke exposed credentials before cleaning their copies.
Sources and further reading
Binance authentication · Upbit authentication · Bithumb JWT · JWS signing input · KIS official samples · Upbit Python boundary
Content and examples reviewed: 2026-09-29
댓글
댓글 쓰기