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.

223 lines
5.4 KiB
C

#define _GNU_SOURCE
#include "rsa_signature_2017.h"
#include "ap/object.h"
#include "rdf/serial.h"
#include "rdf/memory_store.h"
#include "rdf/normalize.h"
#include "sha256/sha256.h"
#include "collections/collection.h"
// TODO: figure out how to remove this dependency
#include "model/crypto/keys.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,
};
extern struct rdf_serialize_field ap_object_rdf[];
static struct rdf_serialize_field activity_ref_types[] = {
{
.predicate = { (char*)apaot_ref, "" },
.offset = offsetof( struct ap_object, object.ref ),
.type = &rdf_string_field
},
{
.predicate = { (char*)apaot_activity, "", },
.offset = offsetof( struct ap_object, object.ptr ),
.type = &rdf_object_field,
.subtype = &ap_object_rdf
},
{ .predicate = {0} },
};
#define OBJ_TYPE struct ap_object
struct rdf_serialize_field ap_object_rdf[] = {
{
.predicate = {
"", ""
},
.offset = offsetof( OBJ_TYPE, id ),
.type = &rdf_id_field
},
{
.predicate = { "<http://www.w3.org/1999/02/22-rdf-syntax-ns#", "type>" },
.offset = offsetof( OBJ_TYPE, type ),
.type = &rdf_enum_field,
.subtype = &types
},
{
.predicate = { "<https://www.w3.org/ns/activitystreams#", "actor>" },
.offset = offsetof( OBJ_TYPE, actor ),
.type = &rdf_string_ref_field
},
{
.predicate = { "<https://www.w3.org/ns/activitystreams#", "content>" },
.offset = offsetof( OBJ_TYPE, content ),
.type = &rdf_string_field
},
{
.predicate = { "<https://www.w3.org/ns/activitystreams#", "published>" },
.offset = offsetof( OBJ_TYPE, published ),
.type = &rdf_date_field
},
{
.predicate = { "<https://www.w3.org/ns/activitystreams#", "to>" },
.offset = offsetof( OBJ_TYPE, to ),
.type = &rdf_array_of_field,
.subtype = &rdf_string_ref_field
},
{
.predicate = { "<https://www.w3.org/ns/activitystreams#", "cc>" },
.offset = offsetof( OBJ_TYPE, cc ),
.type = &rdf_array_of_field,
.subtype = &rdf_string_ref_field
},
{
.predicate = { "<https://www.w3.org/ns/activitystreams#", "bcc>" },
.offset = offsetof( OBJ_TYPE, bcc ),
.type = &rdf_array_of_field,
.subtype = &rdf_string_ref_field
},
{
.predicate = { "<https://www.w3.org/ns/activitystreams#", "object>" },
.offset = offsetof( OBJ_TYPE, object.tag ),
.type = &rdf_tagged_union_field,
.subtype = activity_ref_types
},
{
.predicate = { NULL, NULL },
.offset = sizeof(struct ap_object)
},
};
#undef OBJ_TYPE
struct rdf_serialize_field ap_signature_rdf[] = {
{
.predicate = {"", "" },
.offset = 0,
.type = &rdf_id_blank
},
{
.predicate = { "<http://purl.org/dc/terms/", "creator>" },
.offset = offsetof( struct ap_signature, creator ),
.type = &rdf_string_ref_field
},
{
.predicate = { "<http://purl.org/dc/terms/", "created>" },
.offset = offsetof( struct ap_signature, created ),
.type = &rdf_date_field
},
{
.predicate = { NULL, 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_object* act, FILE* out )
{
write_normalized_rdf( ap_object_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, unsigned 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_object* act, struct crypto_keys* keys )
{
//printf( "ap_activity_create_rsa_signature_2017\n" );
// Setup signature
asprintf( &act->signature.creator, "%s#main-key", act->actor );
act->signature.created = time(NULL);
unsigned char raw_hash[64];
if( !calculate_hash_for_object( ap_object_rdf, act, &raw_hash[0] ) ) { return NULL; }
if( !calculate_hash_for_object( ap_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);
}