Skip to content

Commit

Permalink
update keygen and keygen's README
Browse files Browse the repository at this point in the history
  • Loading branch information
or-else committed Jan 8, 2023
1 parent 774e954 commit 107f6ef
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 13 deletions.
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ When you register a new account you are asked for an email address to send valid
* [Web](https://github.com/tinode/webapp/) (React.js)
* Scriptable [command line](tn-cli/) (Python)
* User features:
* One-on-one and group messaging. Voice messages.
* Video calls.
* One-on-one and group messaging.
* Video and voice calls. Voice messages.
* Channels with unlimited number of read-only subscribers.
* All chats are synchronized across all devices.
* Granular access control with permissions for various actions.
Expand All @@ -95,6 +95,7 @@ When you register a new account you are asked for an email address to send valid
* Most recent message preview in contact list.
* Server-generated presence notifications for people, group chats.
* Forwarding and replying to messages.
* Editing sent messages.
* Administration:
* Granular access control with permissions for various actions.
* Support for custom authentication backends.
Expand All @@ -117,10 +118,9 @@ When you register a new account you are asked for an email address to send valid

* [Federation](https://en.wikipedia.org/wiki/Federation_(information_technology)).
* Location and contacts sharing.
* Previews of attached videos, documents, links.
* Previews of attached documents, links.
* Recording video messages.
* Attaching music/audio.
* Audio-only calls.
* Attaching music/audio other than voice messages.
* Hot standby.
* Different levels of message persistence (from strict persistence to "store until delivered" to purely ephemeral messaging).
* Message encryption at rest.
Expand Down
34 changes: 32 additions & 2 deletions keygen/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,39 @@

A command-line utility to generate an API key for [Tinode server](../server/)

Parameters:
**Parameters:**

* `sequence`: Sequential number of the API key. This value can be used to reject previously issued keys.
* `isroot`: Currently unused. Intended to designate key of a system administrator.
* `validate`: Key to validate: check previously issued key for validity.
* `salt`: [HMAC](https://en.wikipedia.org/wiki/HMAC) salt, 32 random bytes base64 encoded or `auto` to automatically generate salt.
* `salt`: [HMAC](https://en.wikipedia.org/wiki/HMAC) salt, 32 random bytes base64 encoded; must be present for key validation; optional when generating the key: if missing, a cryptographically-strong salt will be automatically generated.


## Usage

The API key is used to provide some protection from automatic scraping of server API and for identification of client applications.

* `API key` is used on the client side.
* `HMAC salt` is used on the server side to verify the API key.

Run the generator:

```sh
./keygen
```

Sample output:

```text
API key v1 seq1 [ordinary]: AQAAAAABAACGOIyP2vh5avSff5oVvMpk
HMAC salt: TC0Jzr8f28kAspXrb4UYccJUJ63b7CSA16n1qMxxGpw=
```

Copy `HMAC salt` to `api_key_salt` parameter in your server [config file](https://github.com/tinode/chat/blob/master/server/tinode.conf).
Copy `API key` to the client applications:

* TinodeWeb: `API_KEY` in [config.js](https://github.com/tinode/webapp/blob/master/src/config.js)
* Tindroid: `API_KEY` in [Cache.java](https://github.com/tinode/tindroid/blob/master/app/src/main/java/co/tinode/tindroid/Cache.java)
* Tinodious: `kApiKey` in [SharedUtils.swift](https://github.com/tinode/ios/blob/master/TinodiosDB/SharedUtils.swift)

Rebuild the clients after changing the API key.
14 changes: 8 additions & 6 deletions keygen/keygen.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,22 @@ import (

// Generate API key
// Composition:
// [1:algorithm version][4:deprecated (used to be application ID)][2:key sequence][1:isRoot][16:signature] = 24 bytes
//
// [1:algorithm version][4:deprecated (used to be application ID)][2:key sequence][1:isRoot][16:signature] = 24 bytes
//
// convertible to base64 without padding.
// All integers are little-endian.
func main() {
version := flag.Int("sequence", 1, "Sequential number of the API key")
isRoot := flag.Int("isroot", 0, "Is this a root API key?")
apikey := flag.String("validate", "", "API key to validate")
hmacSalt := flag.String("salt", "auto", "HMAC salt, 32 random bytes base64 encoded or 'auto' to generate salt")
hmacSalt := flag.String("salt", "", "HMAC salt, 32 random bytes base64-encoded")

flag.Parse()

if *apikey != "" {
if *hmacSalt == "auto" {
log.Println("Error: Cannot validate the key with 'auto' HMAC salt")
if *hmacSalt == "" {
log.Println("Error: must provide HMAC salt for key validation")
os.Exit(1)
}
os.Exit(validate(*apikey, *hmacSalt))
Expand Down Expand Up @@ -56,7 +58,7 @@ func generate(sequence, isRoot int, hmacSaltB64 string) int {
var data [APIKEY_LENGTH]byte
var hmacSalt []byte

if hmacSaltB64 == "auto" {
if hmacSaltB64 == "" {
hmacSalt = make([]byte, 32)
_, err := rand.Read(hmacSalt)
if err != nil {
Expand Down Expand Up @@ -100,7 +102,7 @@ func generate(sequence, isRoot int, hmacSaltB64 string) int {
strIsRoot = "ordinary"
}

fmt.Printf("API key v%d seq%d [%s]: %s\nUsed HMAC salt: %s\n", 1, sequence, strIsRoot,
fmt.Printf("API key v%d seq%d [%s]: %s\nHMAC salt: %s\n", 1, sequence, strIsRoot,
base64.URLEncoding.EncodeToString(data[:]), hmacSaltB64)

return 0
Expand Down

0 comments on commit 107f6ef

Please sign in to comment.