From 24850f8b96a1b10ecdb8d98b551d4c38cbd9f6e9 Mon Sep 17 00:00:00 2001 From: kdeme Date: Fri, 25 Oct 2019 14:50:14 +0200 Subject: [PATCH] Add asymmetric and symmetric key API for whisper --- wrappers/libnimbus.h | 23 +++++++-- wrappers/libnimbus.nim | 73 +++++++++++++++++++++++------ wrappers/wrapper_whisper_example.go | 4 +- 3 files changed, 79 insertions(+), 21 deletions(-) diff --git a/wrappers/libnimbus.h b/wrappers/libnimbus.h index 8a30b9840..db5fb86d9 100644 --- a/wrappers/libnimbus.h +++ b/wrappers/libnimbus.h @@ -65,20 +65,33 @@ void nimbus_join_public_chat(const char* channel, received_msg_handler msg); /* Whisper API */ +/* Helper, can be removed */ topic nimbus_string_to_topic(const char* s); -/* Generate asymmetric keypair */ + +/* Asymmetric Keys API */ + const char* nimbus_new_keypair(); -/* Generate symmetric key from password */ +const char* nimbus_add_keypair(const uint8_t* privkey); +int nimbus_delete_keypair(const char* id); +int nimbus_get_private_key(const char* id, uint8_t* privkey); + +/* Symmetric Keys API */ + +const char* nimbus_add_symkey(const uint8_t* symkey); const char* nimbus_add_symkey_from_password(const char* password); +int nimbus_delete_symkey(const char* id); +int nimbus_get_symkey(const char* id, uint8_t* symkey); + +/* Whisper message posting and receiving API */ + /* Subscribe to given filter */ -void nimbus_whisper_subscribe(filter_options* filter_options, +void nimbus_subscribe_filter(filter_options* filter_options, received_msg_handler msg); /* Post Whisper message */ -void nimbus_whisper_post(post_message* msg); +void nimbus_post(post_message* msg); #ifdef __cplusplus } #endif #endif //__LIBNIMBUS_H__ - diff --git a/wrappers/libnimbus.nim b/wrappers/libnimbus.nim index a6d560a1b..3221949e2 100644 --- a/wrappers/libnimbus.nim +++ b/wrappers/libnimbus.nim @@ -62,6 +62,11 @@ type CTopic* = object topic*: Topic +template foreignThreadGc*(body: untyped) = + setupForeignThreadGc() + `body` + tearDownForeignThreadGc() + proc `$`*(digest: SymKey): string = for c in digest: result &= hexChar(c.byte) @@ -219,35 +224,74 @@ proc nimbus_string_to_topic(s: cstring): CTopic {.exportc.} = tearDownForeignThreadGc() -proc nimbus_new_keypair(): cstring {.exportc.} = - setupForeignThreadGc() +# Asymmetric Keys API +proc nimbus_new_keypair(): cstring {.exportc,foreignThreadGc.} = + ## It is important that the caller makes a copy of the returned cstring before + ## doing any other API calls. result = generateRandomID() whisperKeys.asymKeys.add($result, newKeyPair()) - tearDownForeignThreadGc() +proc nimbus_add_keypair(key: ptr PrivateKey): + cstring {.exportc,foreignThreadGc.} = + ## It is important that the caller makes a copy of the returned cstring before + ## doing any other API calls. + result = generateRandomID() -proc nimbus_add_keypair(key: PrivateKey): cstring = discard -proc nimbus_delete_keypair(id: cstring) = discard -proc nimbus_add_symkey(key: SymKey): cstring = discard + # Creating a KeyPair here does a copy of the key and so does the add + whisperKeys.asymKeys.add($result, KeyPair(seckey: key[], + pubkey: key[].getPublicKey())) -proc nimbus_add_symkey_from_password(password: cstring): cstring {.exportc.} = - setupForeignThreadGc() +proc nimbus_delete_keypair(id: cstring): bool {.exportc,foreignThreadGc.} = + var unneeded: KeyPair + result = whisperKeys.asymKeys.take($id, unneeded) +proc nimbus_get_private_key(id: cstring, privateKey: ptr PrivateKey): + bool {.exportc,foreignThreadGc.} = + try: + privateKey[] = whisperKeys.asymkeys[$id].seckey + result = true + except KeyError: + result = false + +# Symmetric Keys API + +proc nimbus_add_symkey(key: ptr SymKey): cstring {.exportc,foreignThreadGc.} = + ## It is important that the caller makes a copy of the returned cstring before + ## doing any other API calls. + result = generateRandomID().cstring + + # Copy of key happens at add + whisperKeys.symKeys.add($result, key[]) + +proc nimbus_add_symkey_from_password(password: cstring): + cstring {.exportc,foreignThreadGc.} = + ## It is important that the caller makes a copy of the returned cstring before + ## doing any other API calls. var ctx: HMAC[sha256] var symKey: SymKey if pbkdf2(ctx, $password, "", 65356, symKey) != sizeof(SymKey): - raise newException(KeyGenerationError, "Failed generating key") + return nil # TODO: Something else than nil? And, can this practically occur? result = generateRandomID() whisperKeys.symKeys.add($result, symKey) - tearDownForeignThreadGc() +proc nimbus_delete_symkey(id: cstring): bool {.exportc,foreignThreadGc.} = + var unneeded: SymKey + result = whisperKeys.symKeys.take($id, unneeded) -proc nimbus_delete_symkey(id: cstring) = discard +proc nimbus_get_symkey(id: cstring, symKey: ptr SymKey): + bool {.exportc,foreignThreadGc.} = + try: + symKey[] = whisperKeys.symkeys[$id] + result = true + except KeyError: + result = false -proc nimbus_whisper_post(message: ptr CPostMessage) {.exportc.} = +# Whisper message posting and receiving API + +proc nimbus_post(message: ptr CPostMessage) {.exportc.} = setupForeignThreadGc() var @@ -293,7 +337,7 @@ proc nimbus_whisper_post(message: ptr CPostMessage) {.exportc.} = tearDownForeignThreadGc() -proc nimbus_whisper_subscribe(options: ptr CFilterOptions, +proc nimbus_subscribe_filter(options: ptr CFilterOptions, handler: proc (msg: ptr CReceivedMessage) {.gcsafe, cdecl.}) {.exportc.} = setupForeignThreadGc() @@ -335,4 +379,5 @@ proc nimbus_whisper_subscribe(options: ptr CFilterOptions, tearDownForeignThreadGc() -proc nimbus_whisper_unsubscribe(id: cstring) = discard +proc nimbus_unsubscribe_filter(id: cstring): bool {.exportc.} = + result = node.unsubscribeFilter($id) diff --git a/wrappers/wrapper_whisper_example.go b/wrappers/wrapper_whisper_example.go index 2d0c6bfa7..417c5fa34 100644 --- a/wrappers/wrapper_whisper_example.go +++ b/wrappers/wrapper_whisper_example.go @@ -54,7 +54,7 @@ func StatusListenAndPost(channel string) { options := C.filter_options{symKeyID: C.CString(symKeyId), minPow: 0.002, topic: C.nimbus_string_to_topic(C.CString(channel)).topic} - C.nimbus_whisper_subscribe(&options, + C.nimbus_subscribe_filter(&options, (C.received_msg_handler)(unsafe.Pointer(C.receiveHandler_cgo))) postMessage := C.post_message{symKeyID: C.CString(symKeyId), @@ -74,7 +74,7 @@ func StatusListenAndPost(channel string) { if i%1000 == 0 { fmt.Println("[nim-status] posting", message) postMessage.payload = (C.CString(message)) - C.nimbus_whisper_post(&postMessage) + C.nimbus_post(&postMessage) } } }