You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

154 lines
4.7 KiB
C

#define _GNU_SOURCE
#include "rsa_signature_2017.h"
#include "../object.h"
// TODO: figure out how to remove this dependency
#include "model/crypto/keys.h"
#include "rdf/serial.h"
#include "rdf/memory_store.h"
#include "rdf/normalize.h"
#include "sha256/sha256.h"
#include "collections/collection.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
static char* type_filter( const char* name )
{
char* res;
asprintf( &res, "<https://www.w3.org/ns/activitystreams#%s>", name );
return res;
}
struct rdf_enum types = {
.items = (struct rdf_enum_item*)ap_object_type_enum,
.filter = type_filter,
};
struct rdf_serialize_field ap_activity_rdf[];
static struct rdf_serialize_field activity_ref_types[] = {
{ (char*)apaot_ref, offsetof( struct ap_activity, object.ref ), &rdf_string_field },
{ (char*)apaot_activity, offsetof( struct ap_activity, object.ptr ), &rdf_object_field, &ap_activity_rdf },
{ NULL },
};
struct rdf_serialize_field ap_activity_rdf[] = {
{ "", offsetof( struct ap_activity, id ), &rdf_id_field },
{ "<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>", offsetof( struct ap_activity, type ), &rdf_enum_field, &types },
{ "<https://www.w3.org/ns/activitystreams#actor>", offsetof( struct ap_activity, actor ), &rdf_string_ref_field },
{ "<https://www.w3.org/ns/activitystreams#content>", offsetof( struct ap_activity, content ), &rdf_string_field },
{ "<https://www.w3.org/ns/activitystreams#published>", offsetof( struct ap_activity, published ), &rdf_date_field },
{ "<https://www.w3.org/ns/activitystreams#to>", offsetof( struct ap_activity, to ), &rdf_array_of_field, &rdf_string_ref_field },
{ "<https://www.w3.org/ns/activitystreams#cc>", offsetof( struct ap_activity, cc ), &rdf_array_of_field, &rdf_string_ref_field },
{ "<https://www.w3.org/ns/activitystreams#bcc>", offsetof( struct ap_activity, bcc ), &rdf_array_of_field, &rdf_string_ref_field },
{ "<https://www.w3.org/ns/activitystreams#object>", offsetof( struct ap_activity, object.tag ), &rdf_tagged_union_field, activity_ref_types },
{ NULL, sizeof(struct ap_activity) },
};
struct rdf_serialize_field ap_activity_signature_rdf[] = {
{ "", 0, &rdf_id_blank },
{ "<http://purl.org/dc/terms/creator>", offsetof( struct ap_signature, creator ), &rdf_string_ref_field },
{ "<http://purl.org/dc/terms/created>", offsetof( struct ap_signature, created ), &rdf_date_field },
{ NULL },
};
static void write_normalized_rdf( struct rdf_serialize_field* layout, void* object, FILE* f )
{
// Serialize activity to RDF
struct rdf_serializer rs;
memset(&rs,0,sizeof(rs));
rs.subject = strdup("");
rs.graph = strdup(".");
struct rdf_memory_store* ms = rdf_memory_store_new();
rdf_memory_store_init_serializer( ms, &rs );
rdf_serialize_object( &rs, layout, object );
// Normalize
struct collection i;
rdf_memory_store_as_collection( ms, &i );
rdf_normalize(i);
rdf_memory_store_dump( ms, f );
rdf_memory_store_free(ms);
free((char*)rs.subject);
free((char*)rs.graph);
}
void ap_activity_write_normalized_rdf( struct ap_activity* act, FILE* out )
{
write_normalized_rdf( ap_activity_rdf, act, out );
}
static char* serialize_normalized_object( struct rdf_serialize_field* layout, void* object, size_t* result_size )
{
char* outbuf = NULL;
FILE* f = open_memstream( &outbuf, result_size );
if( !f ) {
printf( "Error opening memstream\n" );
return NULL;
}
write_normalized_rdf( layout, object, f );
fclose(f);
return outbuf;
}
static bool calculate_hash_for_object( struct rdf_serialize_field* layout, void* object, char* hash )
{
size_t size = 0;
// Serialize to normalized RDF
char* buffer = serialize_normalized_object( layout, object, &size );
if( !buffer ) {
return false;
}
// Hash with SHA-256
sha256_easy_hash( buffer, size, &hash[0] );
// Debug
printf( "RDF: \n" );
fwrite( buffer, size, 1, stdout );
printf( "\nHash: " );
for( int i = 0; i < 32; ++i ) {
printf( "%02X", (int)((unsigned char*)hash)[i] );
}
printf( "\n" );
free(buffer);
return true;
}
bool ap_activity_create_rsa_signature_2017( struct ap_activity* act, struct crypto_keys* keys )
{
char* signature_buf = NULL;
printf( "ap_activity_create_rsa_signature_2017\n" );
// Setup signature
asprintf( &act->signature.creator, "%s#main-key", act->actor );
act->signature.created = time(NULL);
char raw_hash[64];
if( !calculate_hash_for_object( ap_activity_rdf, act, &raw_hash[0] ) ) { return NULL; }
if( !calculate_hash_for_object( ap_activity_signature_rdf, &act->signature, &raw_hash[32] ) ) { return NULL; }
char* sign = crypto_keys_sign( keys, raw_hash, 64 );
act->signature.value = sign;
act->signature.type = apst_rsa_signature_2017;
printf( "act->signature = %s\n", sign );
return (act->has_signature = !!act->signature.value);
}