Skip to content

Commit

Permalink
v3: Enforce key length for EncryptCookie middleware default functions (
Browse files Browse the repository at this point in the history
…#3056)

* Support for key length, Add benchmarks for EncryptCookie middleware

* Format tests

* Add tests for panics and key check in Encryptor and Decryptor functions

* Add tests for base64 decoding errors

* Update docs/middleware/encryptcookie.md

Co-authored-by: Jason McNeil <[email protected]>

* Update middleware/encryptcookie/utils.go

Co-authored-by: Jason McNeil <[email protected]>

* Add suggestions from code review

---------

Co-authored-by: Jason McNeil <[email protected]>
  • Loading branch information
gaby and sixcolors authored Jul 5, 2024
1 parent 55138fa commit d17eb99
Show file tree
Hide file tree
Showing 6 changed files with 555 additions and 24 deletions.
5 changes: 1 addition & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,6 @@ jobs:
slug: gofiber/fiber

repeated:
strategy:
matrix:
go-version: [stable]
runs-on: ubuntu-latest
steps:
- name: Fetch Repository
Expand All @@ -55,7 +52,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go-version }}
go-version: stable

- name: Test
run: go run gotest.tools/gotestsum@latest -f testname -- ./... -race -count=15 -shuffle=on
31 changes: 26 additions & 5 deletions docs/middleware/encryptcookie.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ This middleware encrypts cookie values and not the cookie names.
// Intitializes the middleware
func New(config ...Config) fiber.Handler

// Returns a random 32 character long string
func GenerateKey() string
// GenerateKey returns a random string of 16, 24, or 32 bytes.
// The length of the key determines the AES encryption algorithm used:
// 16 bytes for AES-128, 24 bytes for AES-192, and 32 bytes for AES-256-GCM.
func GenerateKey(length int) string
```

## Examples
Expand Down Expand Up @@ -55,9 +57,8 @@ app.Post("/", func(c fiber.Ctx) error {
```

:::note
`Key` must be a 32 character string. It's used to encrypt the values, so make sure it is random and keep it secret.
You can run `openssl rand -base64 32` or call `encryptcookie.GenerateKey()` to create a random key for you.
Make sure not to set `Key` to `encryptcookie.GenerateKey()` because that will create a new key every run.
The `Key` parameter requires an encoded string of 16, 24, or 32 bytes for encryption, corresponding to AES-128, AES-192, and AES-256-GCM standards, respectively. Ensure the key is randomly generated and securely stored.
To generate a 32 char key, use `openssl rand -base64 32` or `encryptcookie.GenerateKey(32)`. Avoid dynamically generating a new `Key` with `encryptcookie.GenerateKey(32)` at each application startup to prevent rendering previously encrypted data inaccessible.
:::

## Config
Expand All @@ -83,6 +84,7 @@ var ConfigDefault = Config{
```

## Usage With Other Middlewares That Reads Or Modify Cookies

Place the `encryptcookie` middleware before any other middleware that reads or modifies cookies. For example, if you are using the CSRF middleware, ensure that the `encryptcookie` middleware is placed before it. Failure to do so may prevent the CSRF middleware from reading the encrypted cookie.

You may also choose to exclude certain cookies from encryption. For instance, if you are using the `CSRF` middleware with a frontend framework like Angular, and the framework reads the token from a cookie, you should exclude that cookie from encryption. This can be achieved by adding the cookie name to the Except array in the configuration:
Expand All @@ -99,3 +101,22 @@ app.Use(csrf.New(csrf.Config{
CookieHTTPOnly: false,
}))
```

## Encryption Algorithms

The default Encryptor and Decryptor functions use `AES-256-GCM` for encryption and decryption. If you need to use `AES-128` or `AES-192` instead, you can do so by changing the length of the key when calling `encryptcookie.GenerateKey(length)` or by providing a key of one of the following lengths:
- AES-128 requires a 16-byte key.
- AES-192 requires a 24-byte key.
- AES-256 requires a 32-byte key.

For example, to generate a key for AES-128:

```go
key := encryptcookie.GenerateKey(16)
```

And for AES-192:

```go
key := encryptcookie.GenerateKey(24)
```
4 changes: 4 additions & 0 deletions docs/whats_new.md
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,10 @@ We've updated several fields from a single string (containing comma-separated va

We've added support for `zstd` compression on top of `gzip`, `deflate`, and `brotli`.

### EncryptCookie

Added support for specifying Key length when using `encryptcookie.GenerateKey(length)`. This allows the user to generate keys compatible with `AES-128`, `AES-192`, and `AES-256` (Default).

### Session

:::caution
Expand Down
10 changes: 5 additions & 5 deletions middleware/encryptcookie/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,19 @@ type Config struct {

// Base64 encoded unique key to encode & decode cookies.
//
// Required. Key length should be 32 characters.
// You may use `encryptcookie.GenerateKey()` to generate a new key.
// Required. Key length should be 16, 24, or 32 bytes when decoded
// if using the default EncryptCookie and DecryptCookie functions.
// You may use `encryptcookie.GenerateKey(length)` to generate a new key.
Key string

// Custom function to encrypt cookies.
//
// Optional. Default: EncryptCookie
// Optional. Default: EncryptCookie (using AES-GCM)
Encryptor func(decryptedString, key string) (string, error)

// Custom function to decrypt cookies.
//
// Optional. Default: DecryptCookie
// Optional. Default: DecryptCookie (using AES-GCM)
Decryptor func(encryptedString, key string) (string, error)
}

Expand All @@ -52,7 +53,6 @@ func configDefault(config ...Config) Config {
cfg = config[0]

// Set default values

if cfg.Next == nil {
cfg.Next = ConfigDefault.Next
}
Expand Down
Loading

0 comments on commit d17eb99

Please sign in to comment.