keychat on Nostr: In Keychat, there are two ways to add friends: via QR code (scanning or copy-pasting) ...
In Keychat, there are two ways to add friends: via QR code (scanning or copy-pasting) or through Npub. We recommend using the QR code, with Npub as a secondary option.
Let's first review how Signal app handles adding friends.
In Signal, the phone number serves as the user's ID. When Alice adds Bob as a Signal friend, she enters Bob's phone number, and Signal’s server returns Bob's three public keys: IK(B), SPK(B), and OPK(B). Locally, Alice has two private keys: IK(A) and EK(A). Using the five keys (Bob's public keys and Alice’s private keys), Alice performs four DH (Diffie-Hellman) calculations to derive a shared key (SK). This SK is then used in the double ratchet algorithm, allowing Alice to generate an encryption key, k1. Alice encrypts her first message to Bob using k1, and her message header includes her public keys, IK(A) and EK(A), in plaintext.
IK(A): Alice's identity key
EK(A): Alice's ephemeral key
IK(B): Bob's identity key
SPK(B): Bob's signed prekey
OPK(B): Bob's one-time prekey
Bob similarly uses the five keys (his private keys and Alice’s public keys) to perform four DH calculations, resulting in the same SK. He then uses the double ratchet algorithm to generate the same k1, which decrypts Alice’s message. Bob’s keys (IK(B), SPK(B), OPK(B)) are stored on Signal’s server, with OPK being a one-time-use key controlled by the server.
DH1 = DH(IK(A), SPK(B)) DH2 = DH(EK(A), IK(B)) DH3 = DH(EK(A), SPK(B)) DH4 = DH(EK(A), OPK(B)) SK = KDF(DH1 || DH2 || DH3 || DH4)
The key difference between Keychat and Signal is that in Keychat, Bob’s keys (IK(B), SPK(B), OPK(B)) are only stored locally on the client and not uploaded to a relay.
When Alice adds Bob as a Keychat friend, Bob shows her a QR code (face-to-face or via email). This QR code contains Bob’s Nostr public key, IK(B), SPK(B), and OPK(B). The Nostr public key is Keychat’s equivalent of Signal’s phone number as an ID.
The QR code also includes a one-time-use receiving address, so Alice’s message is sent to this address, not directly to Bob’s Nostr public key.
(Why not store Bob’s keys on the relay, like in Signal? This could lead to metadata privacy issues, and relays currently cannot ensure that OPK is used only once. We are keeping an eye on this approach.)
Alice can now use the five keys (her IK(A) and EK(A) with Bob’s IK(B), SPK(B), OPK(B)) to proceed with encryption, just like in Signal.
However, if Alice and Bob are in the same group and Alice only knows Bob’s Npub, how can Alice add Bob as a friend? Alice sends a friend request to Bob using a method similar to NIP4, including her IK(A), SPK(A), and OPK(A). Once Bob accepts, they can exchange messages using the Signal encryption method.
If you can use the QR code to add friends, avoid using the Npub method.
Let's first review how Signal app handles adding friends.
In Signal, the phone number serves as the user's ID. When Alice adds Bob as a Signal friend, she enters Bob's phone number, and Signal’s server returns Bob's three public keys: IK(B), SPK(B), and OPK(B). Locally, Alice has two private keys: IK(A) and EK(A). Using the five keys (Bob's public keys and Alice’s private keys), Alice performs four DH (Diffie-Hellman) calculations to derive a shared key (SK). This SK is then used in the double ratchet algorithm, allowing Alice to generate an encryption key, k1. Alice encrypts her first message to Bob using k1, and her message header includes her public keys, IK(A) and EK(A), in plaintext.
IK(A): Alice's identity key
EK(A): Alice's ephemeral key
IK(B): Bob's identity key
SPK(B): Bob's signed prekey
OPK(B): Bob's one-time prekey
Bob similarly uses the five keys (his private keys and Alice’s public keys) to perform four DH calculations, resulting in the same SK. He then uses the double ratchet algorithm to generate the same k1, which decrypts Alice’s message. Bob’s keys (IK(B), SPK(B), OPK(B)) are stored on Signal’s server, with OPK being a one-time-use key controlled by the server.
DH1 = DH(IK(A), SPK(B)) DH2 = DH(EK(A), IK(B)) DH3 = DH(EK(A), SPK(B)) DH4 = DH(EK(A), OPK(B)) SK = KDF(DH1 || DH2 || DH3 || DH4)
The key difference between Keychat and Signal is that in Keychat, Bob’s keys (IK(B), SPK(B), OPK(B)) are only stored locally on the client and not uploaded to a relay.
When Alice adds Bob as a Keychat friend, Bob shows her a QR code (face-to-face or via email). This QR code contains Bob’s Nostr public key, IK(B), SPK(B), and OPK(B). The Nostr public key is Keychat’s equivalent of Signal’s phone number as an ID.
The QR code also includes a one-time-use receiving address, so Alice’s message is sent to this address, not directly to Bob’s Nostr public key.
(Why not store Bob’s keys on the relay, like in Signal? This could lead to metadata privacy issues, and relays currently cannot ensure that OPK is used only once. We are keeping an eye on this approach.)
Alice can now use the five keys (her IK(A) and EK(A) with Bob’s IK(B), SPK(B), OPK(B)) to proceed with encryption, just like in Signal.
However, if Alice and Bob are in the same group and Alice only knows Bob’s Npub, how can Alice add Bob as a friend? Alice sends a friend request to Bob using a method similar to NIP4, including her IK(A), SPK(A), and OPK(A). Once Bob accepts, they can exchange messages using the Signal encryption method.
If you can use the QR code to add friends, avoid using the Npub method.