Skip to content
/ clust Public

Nostr CLI client built with Rust (not ready yet!)

License

Notifications You must be signed in to change notification settings

vinliao/clust

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Nostr CLI client built with Rust

Encrypted chat inside Nostr leaks metadata of who talks to who. This small CLI app implements a "public inbox," which obfuscates that metadata. It's private chat, but more private.

The basic idea is this:

  1. Alice announces her pubkey to Bob
  2. Both have each other's pubkey, both can derive shared key from it
  3. They both post message to "public inbox" with sha256(shared_key) on its tag
  4. With the shared key, only both can create the private event, only both can decrypt
  5. Nobody knows who is messaging who since there's no pubkey on the event
  6. If an attacker tampers with the event, either the event's signature becomes invalid or the content can't be decrypted by Alice or Bob (which they can ignore)

Let me illustrate with an analogy: Public inbox is to PO box what public key is to home address. Instead of sending mails to each other's home address, Alice and Bob send mails to a PO box. In the PO box, only they know how to find each other's mails, only they can write to each other through that PO box.

Example private message event:

{
  "content": "B+teWrgJ4ljieX3Fbr8H3NWA7KbIl4ImRLSqDhbRgavMKGqtmCfsMdwRIp0FjYWEn9B0Kiv4TfhUls0zEkq/9N7EmDlgcX+iinna/brdXc9qy2O5PqO/kap2skbKLZ5gCHOw3oSdP5DyNuSRpxuUOFMuI9xMUxL/zipsVJQDlhbCg2qLzw5Yq2mK0RJSXnDe515lKS6Eb9XlBCa6nYWxq1QzhuvRxDgN5o1ZuIirJDsylMzcDt5/niFW9daav4/WjY1XbbjeUc2XbSFB10J5FpMoz+TgG/NVxNKpmm4VSHBhs+v/A+jF/j/HJQlsbHrsavy2aRKHkRFVYqL7Phyd4O3hKRFcZrS4tnh2nesXif5QoZgxIEqD8eCDQOorO6UUXo8SHOFKdlSXfuYCgFecIVeM+QKTaST4eizJJbx0X8+qnYuuYxAqQt0+0MUMDGPbErlCw1nDhprLY3C3th6y5dDWfGs/cGuhDZBJWpbWvXs69xury9qGfo0p9GDDwprtb363d6/cTxHgMSaji5p7hfXTHzdiyuqfH90TuW8TIuQyfpV7F/BCoUq45wdv9nqpzlV+x/HLXIlOCGu23cNriJcIDFf7SfNk8WmiQpa69nCTYvManculqE2+eIn4k/jj1lWEA7YdSWjVAqJtmhBgnQ==?iv=SbNrOyZOtL7ymyvUxK9xWw==",
  "created_at": 1644948134,
  "id": "3bee25d04aeb632c4babe4a978b838a08882c42874df64858cfd66b41284a87c",
  "kind": 4,
  "pubkey": "9073f08fa71396e45d89adf34024e5c1dccaa369bab3c0d285994fdb8e150e07",
  "sig": "185702115bdf3e5b79219e440ff56efe53924d95ab27325b2fe835c98512dcccecc733d34c807869efb19afd6a9519f42234afe798a61f0e2492669753c20cce",
  "tags": [
    [
      "shared",
      "781caa9f1d2ab6052a3b84d8b3e80cee9ac22cf41e016cc8f13a18cc5064ca4b"
    ]
  ]
}

Notice the pubkey value? That's the public inbox. Public inbox is an agreed-upon keypair to sign things with. Yes, you read it right, it's a keypair, which means anyone has access to the public inbox's private key. Don't worry, the messages are still safe; public inbox is just a central point for inbox to land on, so everyone can post and search on the same place - messages are still secured and encrypted by the shared key only both recipient and sender have.

Here's my dummy pubkey: 5a5373396fe3fb30213adcc189a79d3c6d6c03b6a3e8320e6178a025e52e31c2. Wanna chat?

How to use

This is very unstable and experimental. It's best to not use your "real identity."

  1. Clone repository
  2. cargo run init to initialize config file
  3. cargo run add-contact vincent 5a5373396fe3fb30213adcc189a79d3c6d6c03b6a3e8320e6178a025e52e31c2
  4. cargo run chat vincent

You can try requesting ["REQ", "foobar", {"#p", your_pubkey}] or ["REQ", "foobar", {"#p", 5a5373396fe3fb30213adcc189a79d3c6d6c03b6a3e8320e6178a025e52e31c2}] to relays. You won't see much.

There's a GitHub issue to discuss this "public inbox" idea: https://github.com/fiatjaf/nostr/issues/69.

APIs:

  • clust chat <name>
  • clust inbox

Low-level APIs:

  • clust init
  • clust generate-keypair
  • clust set-private <key>
  • clust get-pubkey
  • clust publish-raw <event>
  • clust get-event <id>
  • clust add-contact <name> <pubkey>
  • clust delete-contact <name>
  • clust change-contact-pubkey <name> <pubkey>
  • clust change-contact-name <pubkey> <name>

Backend to-do:

  • replace schnorr_fun with secp256k1
  • use config file to store keys and subscriptions
  • use serde and struct instead of throwing json around
  • store config file in ~/.config/clust/config.json
  • pick relay from config file
  • only use strings to pretty-print, deal directly with bytes and structs
  • write tests (duh)

About

Nostr CLI client built with Rust (not ready yet!)

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages