#parser #cookies #security #encryption #signing #secure #signed

simple-cookie

Functions for creating and parsing signed & encrypted cookies

3 releases (1 stable)

1.0.0 Mar 16, 2024
0.1.1 Jan 26, 2023
0.1.0 Jan 26, 2023

#526 in Cryptography

Download history 29/week @ 2024-06-24 15/week @ 2024-07-08 8/week @ 2024-07-15 60/week @ 2024-07-22 99/week @ 2024-07-29 100/week @ 2024-08-05 38/week @ 2024-08-19 28/week @ 2024-08-26 31/week @ 2024-09-02 122/week @ 2024-09-09 418/week @ 2024-09-16 845/week @ 2024-09-23 385/week @ 2024-09-30

1,770 downloads per month

MIT license

17KB
155 lines

Functions for creating and parsing signed & encrypted cookies.

The cookie crate is the de facto secure cookie library in Rust. It is Way Too Complicated (TM) for what I need. (And, in my opinion, for what most people need.) This is the 80% solution for 20% of the effort.

This library has only two goals:

  • A simple, easily auditable implementation of signing, encrypting, decrypting & verifying cookies.
  • Clear comments pointing out security issues and describing how to avoid them.

The goals of this library are not:

  • Automatically detecting when a new Set-Cookie header is required.
  • Tracking changes to cookies.
  • Validating cookie name compliance with RFC6265. (Just don't use any weird cookie names.)
  • Any kind of cookie "jar" functionality.
  • Literally anything else.

Examples

Basic use:

use simple_cookie::{generate_signing_key, encode_cookie, decode_cookie};

let signing_key = generate_signing_key();
let encoded = encode_cookie(&signing_key, "account_id", &[56]);
let decoded = decode_cookie(&signing_key, "account_id", encoded);

assert_eq!(decoded, Some(vec![56]));

You probably want an actual Set-Cookie header. You can build one pretty easily:

use simple_cookie::{generate_signing_key, encode_cookie};

let signing_key = generate_signing_key();
let encoded = encode_cookie(&signing_key, "account_id", &[56]);
let header = format!("Set-Cookie: session={}; Max-Age=604800; Secure; HttpOnly; SameSite=Strict", encoded);

Then, to decrypt a header:

use simple_cookie::{parse_cookie_header_value, decode_cookie};

// You can create your own key or load it from somewhere.
// Don't use all zeros like this though. See the documentation for SigningKey for more info.
let signing_key = [0; 32];

// This is a standard HTTP Cookie header, pretty much exactly what the browser sends to your server.
let header = b"Cookie: session=gNm1wQ6lTTgAxLxfD2ntNS2nIBVcnjSmI+7FdFk; another-cookie=another-value";

// parse_cookie_header_value doesn't expect the header name.
// You don't normally need this step since HTTP libraries typically automatically parse
// the header name & value into separate parts of a tuple or struct or something.
let header = &header[8..];

// parse_cookie_header_value returns an iterator, so you can use it in a for loop or something.
// I'll just find the cookie we're interested in here.
let (name, encoded_value) = parse_cookie_header_value(header).find(|(name, _value)| *name == "session").unwrap();
let value = decode_cookie(&signing_key, name, encoded_value);

assert!(value.is_some())

Dependencies

~1.5MB
~26K SLoC