229 views
# Salty IM Specification v1 | Version | Last Modified | | -------- | ------------- | | v1.1 | 2022-03-18 | ## Introduction Salty IM is an open specification for a new Saltpack based e2e encrypted messaging protocol and platform for secure communications with a focus on privacy, security and being self-hosted. You want to send a friend, colleague or loved one a message, what do you do? You could send them en email, but email is inherently insecure and not very private (your mail provider could read your emails for example), you could use any number of "free" services such as Meta's Messenger or Apple's iMessenges, but can they really be trusted? What if they decide to change their terms of services? You could also use [Delta.Chat](https://delta.chat), but is has several key weaknesses that lend itself to being only having opportunist encryption. You could even consider [Signal](https://signal.org), which arguably is the best choice these days except for it's one drawback, it is a centralized service, admittedly run by a not-for-profit, but centralized nonetheless. There are literally dozens and dozens of messaging system. So what do you do? What if instead you could simply: - Lookup a User's "Endpoint" - Encrypt a Message to that User's "Key" - Post the encrypted Message to the User's "Endpoint" Done. So Salty IM is a specification for the simplest possible IndieWeb-style and Twtxt inspired private messaging system. It uses standard Web technologies, meaning HTTP. It uses modern cryptography such as Saltpack and isn't trying to be an all singing dancing blockchain, crypto-currency, federation complicated pile of over-engineered thing. Salty is simple. Here's how... ## Protocol Alice: - `Alice:` Creates a Ed25519 Private / Public key pair - `Alice:` Publishes her Public Key to her Domain at a Well-Known URI - `Alice:` Looks up Bob's Public Key and Endpoint via Bob's Well-Known URI at Bob's Domain - `Alice:` Constructs a Message and Encrypts and Signs it to Bob's Public Key - `Alice:` Posts the Encrypted Message to Bob's Endpoint Bob: - `Bob:` Creates a Ed25519 Private / Public key pair - `Bob:` Publishes his Public Key to her Domain at a Well-Known URI - `Bob:` Looks up Alice's Public Key and Endpoint via Alice's Well-Known URI at Alice's Domain - `Bob:` Constructs a Message and Encrypts and Signs it to Alice's Public Key - `Bob:` Posts the Encrypted Message to Alice's Endpoint Alice and Bob can continue these exchanges from the last two steps repeatedly to engage in secure and private communications. ## Keys **Note:** > Salty IM uses Ed25519 Keys for encryption, decryption and signing. > All Cryptography is deferred to the [Saltpack](https://saltpack.org) via the [keys.pub](https://keys.pub) Go libraries. A User creates an Ed25519 Private / Public key pair on first setup and stores the Private Key securely in Secure Storage. This Secure Storage is normally expected to be a System Keychain such as Keychain on macOS, Windows Credentials on Windows, and Secret Service on Linux / BSD. Alternatively but not recommended the Private Key may be stored in the User's Home Directory, in a Browser's Local Storage (at the User's own risk) or other Device-specific Secure or appropriate Storage. - The Private Key is never stored anywhere else, nor published to any server. - The Public Key is published alongside the User's Well-Known Configuration file. ## Discovery A User must publish their Public Key along with an Endpoint for which to receive messages on. This is published on a Well-Known URI that has the path: `/.well-known/salty/<user>.json` where: - `<user>` Is the User's desired Username or Nickname (typically `$USER` on a UNIX system) - The resource must be served at the root of a domain or sub-domain **NOTE:** > The User is a a pseudonym and has no bearing on a User's "identity" other than how they are discovered via the Discovery URI and presented in Clients. There is no personal identifiable information (PII) about a User. The resource must be served on at least a TLSv1.2 capable web server or better and TLSv1.3 is encouraged where possible. The contents of a User's Well-Known Configuration file contains the following JSON document: ```#!json { "endpoint": "https://domain.tld/path", "key": "xxx", } ``` For example `prologic@mills.io` has the following Well-Known Configuration available at https://mills.io/.well-known/salty/prologic.json and contains the following JSON document: ```#!sh { "endpoint": "https://msgbus.mills.io/prologic", "key": "kex1ekt5cru4vs42wnaxppkjn5pexmt2w6uxx9z2mz0fqeuc80e0g9gsggs8ah" } ``` ## Messages Messages are defined by the following simple TAB-delimited (`\t`) format ending with a NEWLINE (`\n`). ``` # <event>: [<args>] 2022-03-18T00:23:13Z (alice@domain.tld) Hey bob 👋 ``` Messages can also embed Markdown to enhance the User Experience (UX) and provide User's a way to share multimedia with each other as well as basic formatting. The format is each message contains: - An RFC3339 time-stamp to the second - The Identity of the sender - The contents of the actual message The Identity of the sender is simply the Sender's `user@domain.tld` used as part of the Discovery process and bares no meaning to the User's actual identity or in any way carries any personal identifiable information about the user (other than they are `nick` at `domain.tld`). In addition a Message may contain one or more Commented lines that are ignored by a Client for display purposes but are used for Additional features such as "Read receipts". ### Events A Message may contain one or more Comment lines containing Events that affect the behavior of Clients. Comment lines must be ignored by Clients for display purposes. The support Events are currently: - `read` -- To spport "Read receipts" - Syntax: `# read: <hash>` ## Encryption [Saltpack](https://saltpack.org) is used to encrypt the Message (once properly formatted) and the message is Signed and Encrypted (Sigcrypt) to all the intended recipients. ## Delivery Once a Message has been Signed and Encrypted to all intended recipients, those recipients are looked up using the Discovery process to determine each recipient's Endpoint(s) of where to deliver the message to. At this point the exact serialization of the Signed and Encrypted Message is not important, however is is recommended to use the Saltpack Armour encoding. The Serialized Message is delivered to each recipient's Endpoint via a simple `POST` request. Example: ```#!sh curl --data-binary "@./message.enc" https://domain.tld/user ``` The Endpoint must respond with a `202 Accepted` on success or a `400 Bad Reqeust` on any error. The Endpoint must be served on at least a TLSv1.2 capable web server or better and TLSv1.3 is encouraged where possible. How a User deals with the delivered Message(s) is Client dependent. It is expected that a Client will connect to a User's Endpoint, either request the contents of their messages or subscribe for real-time consumption. A Client should Decrypt the Messages, Verify their Signature before displaying their contents. A Client shall verify the Sender once the message has been decrypted and before display it, by making a request for the Sender's Well-Known URI to ensure the received message's signature matches the Sender's key. ## Changes - v1.1 (2022-03-18): - Drop `topic` from Discovery Config - Clarify Message Format - Add support for Events