Skip to content

Fast, tiny and secured token for session cookie and Authorization HTTP header

License

Notifications You must be signed in to change notification settings

teal-finance/incorruptible

Repository files navigation

🍸 Incorruptible       GoDoc Go Report Card

The Incorruptible project provides a safer, shorter and faster Bearer Token for session cookie and Authorization HTTP header. See the limitations.

Incorruptible is also a 🍸 drink that the Garçon de café likes to serve to clients. See the origin of the name.

logo

🎯 Target

  • Safer: State-of-the-art cipher configuration, including expiration time and client IP, shuffled BasE91 alphabet, random padding and salt.

  • Shorter: BasE91 encoded (shorter than Base64), optimized data encoding (no string keys) and adaptive compression. The smallest token is 27 bytes long at default settings.

  • Faster: AES-128 (no RSA), hardwired encryption (AMD/Intel processors) and CPU-friendly serializer.

👶 Motivation

At Teal.Finance, our cookies were based on JWT and gorilla/session. The JWT is well standardized. We use the usual way: JSON, Base64, RSA, HMAC-SHA256… This is not very fast and generates large tokens: the long JSON string is converted into Base64 text, to which the signature stuff is appended.

With the purpose of the session cookie purpose, we are free to innovate. We love challenges. As a hobby we tried to replace gorilla/session. The result is Incorruptible. 🎉

To make the implementation successful, we updated our security knowledge to the latest research. We also benchmarked Base64/Ascii85/BasE91/Base92 encoders. We think we did a good job, with a good tradeoff between security, performance and low bandwidth.

🤫 Usage

Now we use less JWT and more Incorruptible tokens in production:

  • JWT as authentication provided by the Quid server (trusted third party).
  • Incorruptible as a session token (session cookie).

JWT

The JWT is well suited when multiple servers manage the authentication: It avoids sharing the private key. We use the good old RSA with a 32-bytes key (256 bits). The Auth server is the only one that owns the private key. Thus, the backend manages the user login, since the signature provided by the authentication server is sufficient. So our backend can be moderately secure (no user data). Only the authentication server requires high security (for example, we uninstall the SSH daemon on the machine).

Incorruptible

We use Incorruptible when the backend manages alone its relationship with the frontend alone. The secret is known only to the backend (it does not need to be shared).

🔐 Encryption

The current trend towards symmetric encryption prefers ChaCha20 / Poly1305 (server-side). In addition to its cryptographic qualities, ChaCha20 is easy to configure and requires few CPU/memory resources (chosen by Wireguard).

On the other hand, AES is faster on AMD/Intel processors (optimized instructions). In addition, the Go crypto allows easy and secure AES configuration.

Therefore, Incorruptible supports both ciphers:

  • ChaCha20-Poly1305
  • AES-128 (256 bits is not relevant for fast short cookie)

We place more emphasis on mastering the encryption configuration than on performance. See also https://go.dev/blog/tls-cipher-suites.

The encryption depends only on standard Go library. The package "math/rand" is used when a strong random number generator is not required ("math/rand" is 40 times faster than "crypto/rand"). The user may call rand.Seed() to randomize the "math/rand" generator.

Read more about our security design.

Please share your thoughts on security or other topics.

🍪 Encoding format

Serialization has been designed for the Incorruptible needs. The format consists of:

  • Magic Code (1 byte)
  • Random salt (1 byte)
  • Header bits (1 byte)
  • Expiration time (from 0 to 4 bytes)
  • Client IP (0, 4 or 16 bytes)
  • Conveyed values, up to 31 values (from 0 to 7900 bytes)
  • Optional random padding (padding length is also random)

See also https://pkg.go.dev/github.com/teal-finance/incorruptible/format.

The precision of the expiration time is defined at build time with constants in the source code. The default encoding size is 24 bits, giving a range of 10 years with an accuracy of 20 seconds. The configuration constants allow to easily decrease/increase of the storage from 1 to 4 bytes, reducing/improving the timing precision.

Random padding can also be appended. This feature is currently disabled, but can be enabled in the source code.

If the token is too long, its payload is compressed with Snappy S2.

Then, the entire data bytes are encrypted with AES-GCM 128 bits. This encryption adds 28 bytes: 12 bytes for the nonce, and 16 bytes for the GCM tag including the authentication. We may split the nonce and trim the GCM tag in a future release… Please share your thoughts.

Finally, the cipher-text is encoded with BasE91, which produces cookie-friendly tokens at the cost of increasing the size by 19% (³⁄₁₆). In comparison, Base64 and Ascii85 increase the size by 33% and 25%, respectively.

In the end, the minimum required 3 bytes (Magic+Salt+Header) becomes a 42-bytes long Incorruptible token (BasE91).

🚫 Limitations

Incorruptible works perfectly with a single server. Secrets can be stored in a data vault, or randomly generated at startup time.

However, with multiple servers (load-balancer, authentication server) the encryption key must be shared.

In this last case, JWT/CWT are preferable, since sharing secrets is a weak link in the security chain.

See also Quid, a JWT authentication server with public-key verified signatures.

🍸 Name

The name Incorruptible comes from the incorruptible drink, a mocktail with lemonade, grapefruit, and orange juice.

The Incorruptible project was originally implemented as part of the Teal.Finance/Garcon server. In French, "Garcon" (garçon) is a 💁‍♂️ waiter, who serves drinks to clients. 😉

We wanted a name for a drink without alcohol, that uses a single word, and could be understood in different languages. So Incorruptible was our best choice at that time.

✨ Contributions welcome

This new project needs your help to get better. Please suggest your improvements or even further refactoring.

We welcome contributions in many forms, and there is always plenty to do!

🗣️ Feedback

If you have some suggestions or need a new feature, please open an issue or contact us at Teal.Finance@pm.me / @TealFinance.

Feel free to pull a request too. Your contributions are welcome. 😉

🗽 Copyright and license

Copyright (c) 2022 Teal.Finance/incorruptible contributors

Teal.Finance/incorruptible is free software, and may be redistributed and/or modified under the terms of the MIT License. SPDX-License-Identifier: MIT

Teal.Finance/incorruptible is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

See the LICENSE file (alongside the source files) or https://opensource.org/licenses/MIT.