google / libsxg

Signed HTTP Exchange library
Apache License 2.0
54 stars 22 forks source link

Signed HTTP Exchange library

Build Status

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

Build \& Install

Simple cmake project.

$ mkdir build
$ cd build
$ cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=path/to/usr -DCMAKE_INSTALL_LIBDIR=lib -DCMAKE_INSTALL_BINDIR=bin
$ 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