#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 #include #include #include static char* type_filter( const char* name ) { char* res; asprintf( &res, "", 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 }, { "", offsetof( struct ap_activity, type ), &rdf_enum_field, &types }, { "", offsetof( struct ap_activity, actor ), &rdf_string_ref_field }, { "", offsetof( struct ap_activity, content ), &rdf_string_field }, { "", offsetof( struct ap_activity, published ), &rdf_date_field }, { "", offsetof( struct ap_activity, to ), &rdf_array_of_field, &rdf_string_ref_field }, { "", offsetof( struct ap_activity, cc ), &rdf_array_of_field, &rdf_string_ref_field }, { "", offsetof( struct ap_activity, bcc ), &rdf_array_of_field, &rdf_string_ref_field }, { "", 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 }, { "", offsetof( struct ap_signature, creator ), &rdf_string_ref_field }, { "", 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); }