mirror of
https://github.com/curl/curl.git
synced 2026-08-04 04:49:58 +03:00
curl: make --httpsig-key take a key OR a file name for key
Verified by test 5022 Closes #22392
This commit is contained in:
parent
a55731050e
commit
9bcc64c39b
20 changed files with 98 additions and 31 deletions
|
|
@ -3,8 +3,8 @@ c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
|||
SPDX-License-Identifier: curl
|
||||
Long: httpsig-key
|
||||
Protocols: HTTP
|
||||
Arg: <file>
|
||||
Help: Key file for HTTP Message Signatures
|
||||
Arg: <key/file>
|
||||
Help: Key for HTTP Message Signatures
|
||||
Category: auth http
|
||||
Added: 8.22.0
|
||||
Multi: single
|
||||
|
|
@ -13,16 +13,19 @@ See-also:
|
|||
- httpsig-algo
|
||||
- httpsig-keyid
|
||||
Example:
|
||||
- --httpsig-algo ed25519 --httpsig-key key.hex --httpsig-keyid "my-key" $URL
|
||||
- --httpsig-algo ed25519 --httpsig-key @key.hex --httpsig-keyid "my-key" $URL
|
||||
- --httpsig-key 123a56fb72197633bc --httpsig-keyid "my-key" $URL
|
||||
---
|
||||
|
||||
# `--httpsig-key`
|
||||
|
||||
Path to the key file used for RFC 9421 HTTP Message Signatures.
|
||||
The key to use for RFC 9421 HTTP Message Signatures. Provide it as-is, or as
|
||||
`@filename`. If the argument starts with an `@`, the rest is treated as a file
|
||||
name for the key.
|
||||
|
||||
The file must contain a hex-encoded key on its first line. For **ed25519**,
|
||||
this is the 32-byte private seed (64 hex characters). For **hmac-sha256**,
|
||||
this is the shared secret. PEM files are not supported.
|
||||
The key is formatted as a series of hexadecimal digits in a single line. For
|
||||
**ed25519**, this is the 32-byte private seed (64 hex characters). For
|
||||
**hmac-sha256**, this is the shared secret. PEM files are not supported.
|
||||
|
||||
## Generating Ed25519 keys
|
||||
|
||||
|
|
@ -32,4 +35,4 @@ With OpenSSL 3:
|
|||
openssl pkey -in k.pem -outform RAW -out k.raw
|
||||
xxd -p -c 64 k.raw | tr -d '\n' > k.hex
|
||||
|
||||
Use `k.hex` with `--httpsig-key`.
|
||||
Use `@k.hex` with `--httpsig-key`.
|
||||
|
|
|
|||
|
|
@ -599,8 +599,9 @@ static CURLcode httpsig_setopts(struct OperationConfig *config, CURL *curl)
|
|||
my_setopt_long(curl, CURLOPT_HTTPSIG_ALGORITHM, httpsig_alg);
|
||||
MY_SETOPT_STR(curl, CURLOPT_HTTPSIG_HEADERS, config->httpsig_headers);
|
||||
MY_SETOPT_STR(curl, CURLOPT_HTTPSIG_KEYID, config->httpsig_keyid);
|
||||
{
|
||||
FILE *keyf = curlx_fopen(config->httpsig_key, FOPEN_READTEXT);
|
||||
|
||||
if(config->httpsig_key[0] == '@') {
|
||||
FILE *keyf = curlx_fopen(&config->httpsig_key[1], FOPEN_READTEXT);
|
||||
if(keyf) {
|
||||
char *hexdata = NULL;
|
||||
ParameterError pe = file2string(&hexdata, keyf);
|
||||
|
|
@ -612,12 +613,13 @@ static CURLcode httpsig_setopts(struct OperationConfig *config, CURL *curl)
|
|||
}
|
||||
if(pe == PARAM_READ_ERROR) {
|
||||
curlx_safefree(hexdata);
|
||||
errorf("httpsig: cannot read key file '%s'", config->httpsig_key);
|
||||
errorf("httpsig: cannot read key file '%s'",
|
||||
&config->httpsig_key[1]);
|
||||
return CURLE_READ_ERROR;
|
||||
}
|
||||
if(!hexdata || !*hexdata) {
|
||||
curlx_safefree(hexdata);
|
||||
errorf("httpsig: key file '%s' is empty", config->httpsig_key);
|
||||
errorf("httpsig: key file '%s' is empty", &config->httpsig_key[1]);
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
}
|
||||
/* can't use the MY_SETOPT_STR() macro here since it returns on error
|
||||
|
|
@ -628,10 +630,17 @@ static CURLcode httpsig_setopts(struct OperationConfig *config, CURL *curl)
|
|||
return result;
|
||||
}
|
||||
else {
|
||||
errorf("httpsig: cannot open key file '%s'", config->httpsig_key);
|
||||
errorf("httpsig: cannot open key file '%s'", &config->httpsig_key[1]);
|
||||
return CURLE_READ_ERROR;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(!config->httpsig_key[0]) {
|
||||
errorf("httpsig: key is empty");
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
}
|
||||
MY_SETOPT_STR(curl, CURLOPT_HTTPSIG_KEY, config->httpsig_key);
|
||||
}
|
||||
}
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -314,8 +314,8 @@ const struct helptxt helptext[] = {
|
|||
CURLHELP_AUTH | CURLHELP_HTTP },
|
||||
#endif
|
||||
#ifndef CURL_DISABLE_HTTPSIG
|
||||
{ " --httpsig-key <file>",
|
||||
"Key file for HTTP Message Signatures",
|
||||
{ " --httpsig-key <key/file>",
|
||||
"Key for HTTP Message Signatures",
|
||||
CURLHELP_AUTH | CURLHELP_HTTP },
|
||||
#endif
|
||||
#ifndef CURL_DISABLE_HTTPSIG
|
||||
|
|
|
|||
|
|
@ -294,7 +294,7 @@ test4000 test4001 \
|
|||
\
|
||||
test5000 test5001 test5002 test5003 test5004 test5005 test5006 test5007 \
|
||||
test5008 test5009 test5010 test5011 test5012 test5013 test5014 test5015 \
|
||||
test5016 test5017 test5018 test5019 test5020 test5021
|
||||
test5016 test5017 test5018 test5019 test5020 test5021 test5022
|
||||
|
||||
EXTRA_DIST = $(TESTCASES) DISABLED data-xml1 \
|
||||
data1461.txt data1463.txt \
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ httpsig
|
|||
HTTP RFC 9421 Message Signatures: CLI GET with query
|
||||
</name>
|
||||
<command>
|
||||
"http://example.com:8000/%TESTNUMBER/resource?action=read" --httpsig-algo "ed25519" --httpsig-key %SRCDIR/data/data-httpsig-ed25519.key --httpsig-keyid "my-key-1" --connect-to example.com:8000:%HOSTIP:%HTTPPORT
|
||||
"http://example.com:8000/%TESTNUMBER/resource?action=read" --httpsig-algo "ed25519" --httpsig-key @%SRCDIR/data/data-httpsig-ed25519.key --httpsig-keyid "my-key-1" --connect-to example.com:8000:%HOSTIP:%HTTPPORT
|
||||
</command>
|
||||
</client>
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ httpsig
|
|||
HTTP RFC 9421 Message Signatures: CLI GET with HMAC-SHA256
|
||||
</name>
|
||||
<command>
|
||||
"http://example.com:7000/%TESTNUMBER/resource" --httpsig-algo "hmac-sha256" --httpsig-key %SRCDIR/data/data-httpsig-hmac-sha256.key --httpsig-keyid "shared-key-1" --connect-to example.com:7000:%HOSTIP:%HTTPPORT
|
||||
"http://example.com:7000/%TESTNUMBER/resource" --httpsig-algo "hmac-sha256" --httpsig-key @%SRCDIR/data/data-httpsig-hmac-sha256.key --httpsig-keyid "shared-key-1" --connect-to example.com:7000:%HOSTIP:%HTTPPORT
|
||||
</command>
|
||||
</client>
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ httpsig
|
|||
HTTP RFC 9421 Message Signatures: custom --httpsig-headers
|
||||
</name>
|
||||
<command>
|
||||
"http://example.com:6000/%TESTNUMBER/resource" --httpsig-algo "ed25519" --httpsig-key %SRCDIR/data/data-httpsig-ed25519.key --httpsig-keyid "test-key-ed25519" --httpsig-headers "method authority" --connect-to example.com:6000:%HOSTIP:%HTTPPORT
|
||||
"http://example.com:6000/%TESTNUMBER/resource" --httpsig-algo "ed25519" --httpsig-key @%SRCDIR/data/data-httpsig-ed25519.key --httpsig-keyid "test-key-ed25519" --httpsig-headers "method authority" --connect-to example.com:6000:%HOSTIP:%HTTPPORT
|
||||
</command>
|
||||
</client>
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ httpsig
|
|||
HTTP RFC 9421 Message Signatures: sign with a regular HTTP header
|
||||
</name>
|
||||
<command>
|
||||
"http://example.com:5000/%TESTNUMBER/resource" --httpsig-algo "ed25519" --httpsig-key %SRCDIR/data/data-httpsig-ed25519.key --httpsig-keyid "test-key-ed25519" --httpsig-headers "method authority content-type:" -H "Content-Type: application/json" --connect-to example.com:5000:%HOSTIP:%HTTPPORT
|
||||
"http://example.com:5000/%TESTNUMBER/resource" --httpsig-algo "ed25519" --httpsig-key @%SRCDIR/data/data-httpsig-ed25519.key --httpsig-keyid "test-key-ed25519" --httpsig-headers "method authority content-type:" -H "Content-Type: application/json" --connect-to example.com:5000:%HOSTIP:%HTTPPORT
|
||||
</command>
|
||||
</client>
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ httpsig
|
|||
HTTP RFC 9421 Message Signatures: component name lowercasing
|
||||
</name>
|
||||
<command>
|
||||
"http://example.com:5100/%TESTNUMBER/resource" --httpsig-algo "ed25519" --httpsig-key %SRCDIR/data/data-httpsig-ed25519.key --httpsig-keyid "test-key-ed25519" --httpsig-headers "method Content-Type:" -H "Content-Type: text/plain" --connect-to example.com:5100:%HOSTIP:%HTTPPORT
|
||||
"http://example.com:5100/%TESTNUMBER/resource" --httpsig-algo "ed25519" --httpsig-key @%SRCDIR/data/data-httpsig-ed25519.key --httpsig-keyid "test-key-ed25519" --httpsig-headers "method Content-Type:" -H "Content-Type: text/plain" --connect-to example.com:5100:%HOSTIP:%HTTPPORT
|
||||
</command>
|
||||
</client>
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ httpsig
|
|||
HTTP RFC 9421 Message Signatures: POST method
|
||||
</name>
|
||||
<command>
|
||||
"http://example.com:5200/%TESTNUMBER/resource" --httpsig-algo "ed25519" --httpsig-key %SRCDIR/data/data-httpsig-ed25519.key --httpsig-keyid "test-key-ed25519" -d "postbody" --connect-to example.com:5200:%HOSTIP:%HTTPPORT
|
||||
"http://example.com:5200/%TESTNUMBER/resource" --httpsig-algo "ed25519" --httpsig-key @%SRCDIR/data/data-httpsig-ed25519.key --httpsig-keyid "test-key-ed25519" -d "postbody" --connect-to example.com:5200:%HOSTIP:%HTTPPORT
|
||||
</command>
|
||||
</client>
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ httpsig
|
|||
HTTP RFC 9421 Message Signatures: error - non-existent key file
|
||||
</name>
|
||||
<command>
|
||||
"http://example.com/%TESTNUMBER/resource" --httpsig-algo "ed25519" --httpsig-key /nonexistent/key.hex --httpsig-keyid "my-key" --connect-to example.com::%HOSTIP:%HTTPPORT
|
||||
"http://example.com/%TESTNUMBER/resource" --httpsig-algo "ed25519" --httpsig-key @/nonexistent/key.hex --httpsig-keyid "my-key" --connect-to example.com::%HOSTIP:%HTTPPORT
|
||||
</command>
|
||||
</client>
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ httpsig
|
|||
HTTP RFC 9421 Message Signatures: query string with special characters
|
||||
</name>
|
||||
<command>
|
||||
"http://example.com:5300/%TESTNUMBER/resource?name=me%AMPnoval%AMPaim=b%25ad" --httpsig-algo "ed25519" --httpsig-key %SRCDIR/data/data-httpsig-ed25519.key --httpsig-keyid "test-key-ed25519" --connect-to example.com:5300:%HOSTIP:%HTTPPORT
|
||||
"http://example.com:5300/%TESTNUMBER/resource?name=me%AMPnoval%AMPaim=b%25ad" --httpsig-algo "ed25519" --httpsig-key @%SRCDIR/data/data-httpsig-ed25519.key --httpsig-keyid "test-key-ed25519" --connect-to example.com:5300:%HOSTIP:%HTTPPORT
|
||||
</command>
|
||||
</client>
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ httpsig
|
|||
HTTP RFC 9421 Message Signatures: default port omitted from @authority
|
||||
</name>
|
||||
<command>
|
||||
"http://example.com/%TESTNUMBER/resource" --httpsig-algo "ed25519" --httpsig-key %SRCDIR/data/data-httpsig-ed25519.key --httpsig-keyid "test-key-ed25519" --connect-to example.com::%HOSTIP:%HTTPPORT
|
||||
"http://example.com/%TESTNUMBER/resource" --httpsig-algo "ed25519" --httpsig-key @%SRCDIR/data/data-httpsig-ed25519.key --httpsig-keyid "test-key-ed25519" --connect-to example.com::%HOSTIP:%HTTPPORT
|
||||
</command>
|
||||
</client>
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ httpsig
|
|||
HTTP RFC 9421 Message Signatures: non-default port in @authority
|
||||
</name>
|
||||
<command>
|
||||
"http://example.com:9000/%TESTNUMBER/resource" --httpsig-algo "ed25519" --httpsig-key %SRCDIR/data/data-httpsig-ed25519.key --httpsig-keyid "test-key-ed25519" --connect-to example.com:9000:%HOSTIP:%HTTPPORT
|
||||
"http://example.com:9000/%TESTNUMBER/resource" --httpsig-algo "ed25519" --httpsig-key @%SRCDIR/data/data-httpsig-ed25519.key --httpsig-keyid "test-key-ed25519" --connect-to example.com:9000:%HOSTIP:%HTTPPORT
|
||||
</command>
|
||||
</client>
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ httpsig
|
|||
HTTP RFC 9421 Message Signatures: @query explicitly requested, no query in URL
|
||||
</name>
|
||||
<command>
|
||||
"http://example.com:5400/%TESTNUMBER/resource" --httpsig-algo "ed25519" --httpsig-key %SRCDIR/data/data-httpsig-ed25519.key --httpsig-keyid "test-key-ed25519" --httpsig-headers "method authority query" --connect-to example.com:5400:%HOSTIP:%HTTPPORT
|
||||
"http://example.com:5400/%TESTNUMBER/resource" --httpsig-algo "ed25519" --httpsig-key @%SRCDIR/data/data-httpsig-ed25519.key --httpsig-keyid "test-key-ed25519" --httpsig-headers "method authority query" --connect-to example.com:5400:%HOSTIP:%HTTPPORT
|
||||
</command>
|
||||
</client>
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ httpsig
|
|||
HTTP RFC 9421 Message Signatures: POST with HMAC-SHA256
|
||||
</name>
|
||||
<command>
|
||||
"http://example.com:5500/%TESTNUMBER/resource" --httpsig-algo "hmac-sha256" --httpsig-key %SRCDIR/data/data-httpsig-hmac-sha256.key --httpsig-keyid "shared-key-1" -d "postbody" --connect-to example.com:5500:%HOSTIP:%HTTPPORT
|
||||
"http://example.com:5500/%TESTNUMBER/resource" --httpsig-algo "hmac-sha256" --httpsig-key @%SRCDIR/data/data-httpsig-hmac-sha256.key --httpsig-keyid "shared-key-1" -d "postbody" --connect-to example.com:5500:%HOSTIP:%HTTPPORT
|
||||
</command>
|
||||
</client>
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ httpsig
|
|||
HTTP RFC 9421 Message Signatures: HMAC-SHA256 with custom headers
|
||||
</name>
|
||||
<command>
|
||||
"http://example.com:5600/%TESTNUMBER/resource" --httpsig-algo "hmac-sha256" --httpsig-key %SRCDIR/data/data-httpsig-hmac-sha256.key --httpsig-keyid "shared-key-1" --httpsig-headers "method authority content-type:" -H "Content-Type: application/json" --connect-to example.com:5600:%HOSTIP:%HTTPPORT
|
||||
"http://example.com:5600/%TESTNUMBER/resource" --httpsig-algo "hmac-sha256" --httpsig-key @%SRCDIR/data/data-httpsig-hmac-sha256.key --httpsig-keyid "shared-key-1" --httpsig-headers "method authority content-type:" -H "Content-Type: application/json" --connect-to example.com:5600:%HOSTIP:%HTTPPORT
|
||||
</command>
|
||||
</client>
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ putdata
|
|||
HTTP RFC 9421 Message Signatures: PUT upload
|
||||
</name>
|
||||
<command>
|
||||
"http://example.com:5800/%TESTNUMBER/resource" --httpsig-algo "ed25519" --httpsig-key %SRCDIR/data/data-httpsig-ed25519.key --httpsig-keyid "test-key-ed25519" -T log/upload5018 --connect-to example.com:5800:%HOSTIP:%HTTPPORT
|
||||
"http://example.com:5800/%TESTNUMBER/resource" --httpsig-algo "ed25519" --httpsig-key @%SRCDIR/data/data-httpsig-ed25519.key --httpsig-keyid "test-key-ed25519" -T log/upload5018 --connect-to example.com:5800:%HOSTIP:%HTTPPORT
|
||||
</command>
|
||||
</client>
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ httpsig
|
|||
HTTP RFC 9421 Message Signatures: default algorithm (ed25519) when --httpsig-algo omitted
|
||||
</name>
|
||||
<command>
|
||||
"http://example.com:6100/%TESTNUMBER/resource" --httpsig-key %SRCDIR/data/data-httpsig-ed25519.key --httpsig-keyid "test-key-ed25519" --connect-to example.com:6100:%HOSTIP:%HTTPPORT
|
||||
"http://example.com:6100/%TESTNUMBER/resource" --httpsig-key @%SRCDIR/data/data-httpsig-ed25519.key --httpsig-keyid "test-key-ed25519" --connect-to example.com:6100:%HOSTIP:%HTTPPORT
|
||||
</command>
|
||||
</client>
|
||||
|
||||
|
|
|
|||
55
tests/data/test5022
Normal file
55
tests/data/test5022
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
<?xml version="1.0" encoding="US-ASCII"?>
|
||||
<testcase>
|
||||
<info>
|
||||
<keywords>
|
||||
HTTP
|
||||
httpsig
|
||||
RFC9421
|
||||
</keywords>
|
||||
</info>
|
||||
|
||||
# Server-side
|
||||
<reply>
|
||||
<data crlf="headers">
|
||||
HTTP/1.1 200 OK
|
||||
Date: Tue, 09 Nov 2010 14:49:00 GMT
|
||||
Server: test-server/fake
|
||||
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
|
||||
Content-Length: 6
|
||||
Connection: close
|
||||
Content-Type: text/html
|
||||
|
||||
-foo-
|
||||
</data>
|
||||
</reply>
|
||||
|
||||
# Client-side
|
||||
<client>
|
||||
<server>
|
||||
http
|
||||
</server>
|
||||
<features>
|
||||
Debug
|
||||
httpsig
|
||||
</features>
|
||||
<name>
|
||||
HTTP RFC 9421 Message Signatures: pass key directly
|
||||
</name>
|
||||
<command>
|
||||
"http://example.com:8000/5001/resource?action=read" --httpsig-algo "ed25519" --variable key@%SRCDIR/data/data-httpsig-ed25519.key --expand-httpsig-key '{{key:trim}}' --httpsig-keyid "my-key-1" --connect-to example.com:8000:%HOSTIP:%HTTPPORT
|
||||
</command>
|
||||
</client>
|
||||
|
||||
# Verify data after the test has been "shot"
|
||||
<verify>
|
||||
<protocol crlf="headers">
|
||||
GET /5001/resource?action=read HTTP/1.1
|
||||
Host: example.com:8000
|
||||
Signature-Input: sig1=("@method" "@authority" "@path" "@query");created=0;keyid="my-key-1";alg="ed25519"
|
||||
Signature: sig1=:RQniOeqmwdRzGvoDIMJ8XJha75evJWgqo5/66EeuJeEGczZtnP2U/F52Lzd/y7Vd1DCb8oUcCKHrKi2VJI7lBA==:
|
||||
User-Agent: curl/%VERSION
|
||||
Accept: */*
|
||||
|
||||
</protocol>
|
||||
</verify>
|
||||
</testcase>
|
||||
Loading…
Add table
Add a link
Reference in a new issue