diff --git a/src/chat/client.nim b/src/chat/client.nim index 02e2c73..06f2c3f 100644 --- a/src/chat/client.nim +++ b/src/chat/client.nim @@ -50,7 +50,7 @@ type KeyEntry* = object type Client* = ref object ident: Identity ds*: WakuClient - keyStore: Table[string, KeyEntry] # Keyed by HexEncoded Public Key + keyStore: Table[RemoteKeyIdentifier, seq[KeyEntry]] conversations: Table[string, Conversation] # Keyed by conversation ID inboundQueue: QueueRef isRunning: bool @@ -77,7 +77,7 @@ proc newClient*(cfg: WakuConfig, ident: Identity): Client {.raises: [IOError, var q = QueueRef(queue: newAsyncQueue[ChatPayload](10)) var c = Client(ident: ident, ds: waku, - keyStore: initTable[string, KeyEntry](), + keyStore: initTable[RemoteKeyIdentifier, seq[KeyEntry]](), conversations: initTable[string, Conversation](), inboundQueue: q, isRunning: false, @@ -150,18 +150,23 @@ proc notifyDeliveryAck(client: Client, convo: Conversation, # Functional ################################################# +proc cacheInviteKey(self: var Client, key: PrivateKey) = + + let rki_ephemeral = generateRemoteKeyIdentifier(key.getPublicKey()) + + self.keyStore[rki_ephemeral] = @[KeyEntry( + keyType: "ephemeral", + privateKey: key, + timestamp: getCurrentTimestamp() + )] + proc createIntroBundle*(self: var Client): IntroBundle = ## Generates an IntroBundle for the client, which includes ## the required information to send a message. # Create Ephemeral keypair, save it in the key store let ephemeralKey = generateKey() - - self.keyStore[ephemeralKey.getPublicKey().bytes().bytesToHex()] = KeyEntry( - keyType: "ephemeral", - privateKey: ephemeralKey, - timestamp: getCurrentTimestamp() - ) + self.cacheInviteKey(ephemeralKey) result = IntroBundle( ident: @(self.ident.getPubkey().bytes()), diff --git a/src/chat/conversations/private_v1.nim b/src/chat/conversations/private_v1.nim index 9e8b264..b52c478 100644 --- a/src/chat/conversations/private_v1.nim +++ b/src/chat/conversations/private_v1.nim @@ -1,5 +1,3 @@ - -import blake2 import chronicles import chronos import sds @@ -75,7 +73,7 @@ proc getConvoIdRaw(participants: seq[PublicKey], addrs.sort() addrs.add(discriminator) let raw = addrs.join("|") - return utils.hash_func(raw) + return utils.hash_func_str(16, raw) proc getConvoId*(self: PrivateV1): string = return getConvoIdRaw(@[self.owner.getPubkey(), self.participant], self.discriminator) @@ -83,7 +81,7 @@ proc getConvoId*(self: PrivateV1): string = proc calcMsgId(self: PrivateV1, msgBytes: seq[byte]): string = let s = fmt"{self.getConvoId()}|{msgBytes}" - result = getBlake2b(s, 16, "") + result = utils.hash_func_str(16, s) proc encrypt*(convo: PrivateV1, plaintext: var seq[byte]): EncryptedPayload = diff --git a/src/chat/crypto.nim b/src/chat/crypto.nim index 1aa4cc5..2e819d7 100644 --- a/src/chat/crypto.nim +++ b/src/chat/crypto.nim @@ -1,11 +1,13 @@ -import proto_types - -import strformat import crypto/ecdh -import std/[sysrand] import results +import sequtils +import std/[endians,sysrand] +import strformat +import types import utils +import proto_types + export PublicKey, PrivateKey, bytes, createRandomKey, loadPrivateKeyFromBytes, loadPublicKeyFromBytes, getPublicKey, Dh, Result, get_addr, `$` @@ -33,3 +35,10 @@ proc toHex*(key: PublicKey): string = proc `$`*(key: PublicKey): string = let byteStr = toHex(key) fmt"{byteStr[0..3]}..{byteStr[^4 .. ^1]}" + +proc generateRemoteKeyIdentifier*(publicKey: PublicKey): RemoteKeyIdentifier = + let bytes = cast[seq[byte]]("WAP") & publicKey.bytes().toSeq() + let hash = utils.hash_func_bytes(4,bytes) + + var result: uint32 + littleEndian32(addr result, unsafeAddr hash[0]) \ No newline at end of file diff --git a/src/chat/crypto/ecdh.nim b/src/chat/crypto/ecdh.nim index 8237fbe..0e4f00d 100644 --- a/src/chat/crypto/ecdh.nim +++ b/src/chat/crypto/ecdh.nim @@ -15,7 +15,7 @@ proc bytes*(key: PublicKey): array[Curve25519KeySize, byte] = proc get_addr*(pubkey: PublicKey): string = # TODO: Needs Spec - result = hash_func(pubkey.bytes().bytesToHex()) + result = hash_func_str(6,pubkey.bytes().bytesToHex()) proc bytes*(key: PrivateKey): Curve25519Key = diff --git a/src/chat/inbox.nim b/src/chat/inbox.nim index 7af319a..3f4e8d1 100644 --- a/src/chat/inbox.nim +++ b/src/chat/inbox.nim @@ -86,14 +86,14 @@ proc sendFrame(ds: WakuClient, remote: PublicKey, frame: InboxV1Frame ): Future[ proc newPrivateInvite(initator_static: PublicKey, initator_ephemeral: PublicKey, recipient_static: PublicKey, - recipient_ephemeral: uint32, + recipient_ephemeral: PublicKey, payload: EncryptedPayload) : InboxV1Frame = let invite = InvitePrivateV1( initiator: @(initator_static.bytes()), initiatorEphemeral: @(initator_ephemeral.bytes()), participant: @(recipient_static.bytes()), - participantEphemeralId: 0, + participantEphemeralId: cast[int32](generateRemoteKeyIdentifier(recipient_ephemeral)), discriminator: "", initial_message: payload ) @@ -115,7 +115,7 @@ proc inviteToPrivateConversation*(self: Inbox, ds: Wakuclient, remote_static: Pu result = convo # # Build Invite - let frame = newPrivateInvite(self.identity.getPubkey(), local_ephemeral.getPublicKey(), remote_static, 0, encPayload) + let frame = newPrivateInvite(self.identity.getPubkey(), local_ephemeral.getPublicKey(), remote_static, remote_ephemeral, encPayload) # Send await sendFrame(ds, remote_static, frame) diff --git a/src/chat/types.nim b/src/chat/types.nim index d5989fd..493a36d 100644 --- a/src/chat/types.nim +++ b/src/chat/types.nim @@ -1,2 +1,4 @@ type MessageId* = string type Content* = seq[byte] + +type RemoteKeyIdentifier* = uint32 diff --git a/src/chat/utils.nim b/src/chat/utils.nim index d6b3a26..e02a2b1 100644 --- a/src/chat/utils.nim +++ b/src/chat/utils.nim @@ -7,9 +7,16 @@ proc getCurrentTimestamp*(): Timestamp = result = waku_core.getNanosecondTime(getTime().toUnix()) -proc hash_func*(s: string | seq[byte]): string = - # This should be Blake2s but it does not exist so substituting with Blake2b - result = getBlake2b(s, 4, "") +proc hash_func_bytes*(n: static range[1..64], s: string | seq[byte]): seq[uint8] = + + let key = "" + var b: Blake2b + blake2b_init(b, n, cstring(key), len(key)) + blake2b_update(b, s, len(s)) + result = blake2b_final(b) + +proc hash_func_str*(n: static range[1..64], s: string | seq[byte]): string = + result = $hash_func_bytes(n,s) proc bytesToHex*[T](bytes: openarray[T], lowercase: bool = false): string = ## Convert bytes to hex string with case option