CURLOPT_HTTPSIG_KEY(3)
π CURLOPT_HTTPSIG_KEY(3) β like, the libcurl manual, but make it make sense
okay bestie so real quick: this page lives in the Library Functions Manual and it's here to explain CURLOPT_HTTPSIG_KEY. yes, the name is a mouthful. no, we're not skipping it. π«Ά
β¨ NAME β¨
CURLOPT_HTTPSIG_KEY β the hex-encoded key for HTTP Message Signatures. that's it, that's the whole vibe. π
πΈ SYNOPSIS πΈ
#include <curl/curl.h>
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HTTPSIG_KEY, char *key);
π¦ DESCRIPTION π¦
π§ͺ vibe check: this feature is experimental and may change before anyone decides it's actually stable. the docs literally advise against using it in production, so likeβ¦ don't. fr fr.
So what you do is you pass a null-terminated string containing the hex-encoded private key or shared secret that you're using for RFC 9421 HTTP Message Signatures.
The deets by algorithm, because they're different, iykyk:
- ed25519 π β this is the 32-byte private seed, which is
64hex characters. - hmac-sha256 π β this is the shared secret, as hex. the decoded length is half the number of hex digits, up to
CURL_MAX_INPUT_LENGTH / 2bytes. that's the same upper bound every other libcurl string option gets, no special treatment.
PEM and other encodings are not supported. you pass the raw key material as hex. that's the whole assignment. π
π₯ Generating Ed25519 keys
With OpenSSL 3:
openssl genpkey -algorithm ED25519 -out k.pem
openssl pkey -in k.pem -text -noout | \
grep -A3 ^priv: | \
tr -cd '[:xdigit:]' > k.hex
and then k.hex is literally one line of 64 hexadecimal digits. slay. β¨
Good news though β the application does not have to keep the string around after setting this option. so you can free your little buffer and not think about it again. π§
Also: using this option multiple times makes the last set string override the previous ones. classic. and set it to NULL to disable its use again. π
π DEFAULT π
NULL
like, nothing. no key, no drama.
π PROTOCOLS π
This functionality affects http only. that's it. just http.
β EXAMPLE β
int main(void)
{
CURL *curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/api");
curl_easy_setopt(curl, CURLOPT_HTTPSIG_ALGORITHM, CURLHTTPSIG_ED25519);
curl_easy_setopt(curl, CURLOPT_HTTPSIG_KEY,
"9f8362f87a484a954e6e740c5b4c0e84"
"229139a20aa8ab56ff66586f6a7d29c5");
curl_easy_setopt(curl, CURLOPT_HTTPSIG_KEYID, "my-key-id");
curl_easy_perform(curl);
}
}
look at that. key set, algorithm set, key id set, request sent. main character energy. π₯
π AVAILABILITY π
Added in curl 8.22.0. if your curl is older than that, this option simply does not exist yet, so don't come for me. π
π RETURN VALUE π
curl_easy_setopt(3) returns a CURLcode that tells you success or error.
CURLE_OK (0) means everything was OK. non-zero means an error happened β see libcurl-errors(3) for the full list. πΈ
π«Ά SEE ALSO π«Ά
k bye ily, go sign some messages responsibly π¦
this page came to you from libcurl, dated 2026-10-25, in the CURLOPT_HTTPSIG_KEY(3) era of the Library Functions Manual. mwah π
π¦ where this page comes from
- alpine 3.23: curl-doc 8.23.0-r0 Β· curl
- alpine 3.24: curl-doc 8.23.0-r0 Β· curl
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms