Signed HTTP Exchange library
Introduction
Signed HTTP Exchange (SXG) is file format which contains an HTTP exchange (request and response) signed by a publisher's origin. https://tools.ietf.org/html/draft-yasskin-http-origin-signed-responses-06
If the publisher creates an SXG file with a valid signature, it will be treated like a valid HTTP response regardless of the distribution channel.
This library is a minimal toolkit for handling SXG files.
Requirements
- tested on OpenSSL 1.1.1c.
Build & Install
Simple cmake project.
$ mkdir build
$ cd build
$ cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=path/to/usr
$ make sxg
$ sudo make install
Documentation
See docs.
Quickstart
#include <assert.h>
#include <libsxg.h>
#include <openssl/crypto.h>
#include <openssl/pem.h>
#include <stdbool.h>
#include <stdio.h>
#include <time.h>
int main() {
// Load keys.
char passwd[] = "";
FILE* keyfile = fopen("ecdsa.privkey", "r");
assert(keyfile != NULL);
EVP_PKEY* priv_key = PEM_read_PrivateKey(keyfile, NULL, NULL, NULL);
fclose(keyfile);
FILE* certfile = fopen("ecdsa.cert", "r");
assert(certfile != NULL);
X509* cert = PEM_read_X509(certfile, 0, 0, passwd);
fclose(certfile);
// Initialize signers.
time_t now = time(NULL);
sxg_signer_list_t signers = sxg_empty_signer_list();
if (!sxg_add_ecdsa_signer(
"my_signer", now, now + 60 * 60 * 24,
"https://original.example.com/resource.validity.msg",
priv_key, cert, "https://yourcdn.example.test/cert.cbor",
&signers)) {
printf("Failed to append signer.\n");
return 1;
}
// Prepare contents.
sxg_raw_response_t content = sxg_empty_raw_response();
if (!sxg_header_append_string("content-type", "text/html; charset=utf-8",
&content.header)) {
printf("Failed to append content-type header.\n");
return 1;
}
if (!sxg_write_string("<!DOCTYPE html><html><body>Hello Sxg!</body></html>\n",
&content.payload)) {
printf("Failed to set payload.\n");
return 1;
}
// Encode contents.
sxg_encoded_response_t encoded = sxg_empty_encoded_response();
if (!sxg_encode_response(4096, &content, &encoded)) {
printf("Failed to encode content.\n");
return 1;
}
// Generate SXG.
sxg_buffer_t result = sxg_empty_buffer();
if (!sxg_generate("https://original.example.com/index.html", &signers,
&encoded, &result)) {
printf("Failed to generate SXG.\n");
return 1;
}
// Save SXG as a file.
FILE* fp = fopen("hello.sxg", "w");
assert(fp != NULL);
size_t wrote = fwrite(result.data, result.size, 1, fp);
assert(wrote == 1);
fclose(fp);
// Release resouces.
EVP_PKEY_free(priv_key);
X509_free(cert);
sxg_signer_list_release(&signers);
sxg_raw_response_release(&content);
sxg_encoded_response_release(&encoded);
sxg_buffer_release(&result);
return 0;
}
You can compile via:
$ gcc sxgsample.c -lsxg -lcrypto