#include "crypto.h" // Submodules #include "http/server/header.h" #include "util/format.h" // Model #include "model/inbox_envelope.h" #include "model/crypto/keys.h" #include "model/crypto/http_sign.h" // Standard Library #include #include #include static bool test_signatures() { struct crypto_keys* keys = crypto_keys_new(); if( !crypto_keys_load_public( keys, "assets/test.public.pem" ) ) { printf( "[FAIL] unable to load assets/test.public.pem\n" ); return false; } if( !crypto_keys_load_private( keys, "assets/test.private.pem" ) ) { printf( "[FAIL] unable to load assets/test.private.pem\n" ); return false; } char* data = "This is a test of the emergency broadcast system."; char* sign = crypto_keys_sign( keys, data, strlen(data) ); if( !sign ) { printf( "[FAIL] unable to sign data\n" ); return false; } free(sign); crypto_keys_free(keys); return true; } static bool test_http_signature() { // https://datatracker.ietf.org/doc/html/draft-cavage-http-signatures-08#C.3 All Headers Test struct http_header headers[] = { { .key = "Host", .value = "example.com" }, { .key = "Date", .value = "Thu, 05 Jan 2014 21:31:40 GMT" }, { .key = "Content-Type", .value = "application/json" }, { .key = "Digest", .value = "SHA-256=X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=" }, { .key = "Content-Length", .value = "18" }, { .key = "Signature", .value = "keyId=\"Test\",algorithm=\"rsa-sha256\"," "headers=\"(request-target) host date content-type digest content-length\"," "signature=\"Ef7MlxLXoBovhil3AlyjtBwAL9g4TN3tibLj7uuNB3CROat/9Kae" "Q4hW2NiJ+pZ6HQEOx9vYZAyi+7cmIkmJszJCut5kQLAwuX+Ms/mUFvpKlSo9StS" "2bMXDBNjOh4Auj774GFj4gwjS+3NhFeoqyr/MuN6HsEnkvn6zdgfE2i0=\"" }, }; struct ap_envelope env = { .when = "1388957500000000000", .headers = { .items = headers, .count = sizeof(headers) / sizeof(headers[0]), }, .validated = false, .body = "{\"hello\": \"world\"}", }; return http_signature_validate( &env, "post /foo?param=value&pet=dog", "Test" ); } static bool test_http_signature_2() { struct crypto_keys* keys = NULL; struct http_signature hs; bool result = false; memset(&hs,0,sizeof(hs)); keys = crypto_keys_new(); crypto_keys_load_private( keys, "assets/test.private.pem" ); if( !http_signature_make( "https://example.com/inbox", keys, &hs, "{\"hello\": \"world\"}" ) ) { goto failed; } char signature_header[512]; snprintf( signature_header, sizeof(signature_header), "keyId=\"Test\",headers=\"(request-target) host date content-length digest\",signature=\"%s\"", hs.signature ); printf( "Signature: %s\n", signature_header ); struct http_header headers[] = { { .key = "Host", .value = "example.com" }, { .key = "Date", .value = hs.date }, { .key = "Content-Type", .value = "application/json" }, { .key = "Digest", .value = hs.digest } , //"SHA-256=X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=" }, { .key = "Content-Length", .value = aformat( "%d", hs.content_length ) }, // "18" }, { .key = "Signature", .value = signature_header }, }; struct ap_envelope env = { .when = "1388957500000000000", .headers = { .items = headers, .count = sizeof(headers) / sizeof(headers[0]), }, .validated = false, .body = "{\"hello\": \"world\"}", }; result = http_signature_validate( &env, "post /inbox", "Test" ); cleanup: http_signature_free(&hs); crypto_keys_free(keys); return result; failed: result = false; goto cleanup; } bool test_crypto() { if( !test_signatures() ) { printf( "[FAIL] test_signatures()\n" ); return false; } if( !test_http_signature() ) { printf( "[FAIL] test_http_signature()\n" ); return false; } if( !test_http_signature_2() ) { printf( "[FAIL] test_http_signature_2()\n" ); return false; } return true; }