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
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);
|
|
}
|
|
|