csrf 0.5.0

CSRF protection primitives
Documentation
#![feature(test)]

extern crate csrf;
extern crate data_encoding;
#[cfg(test)]
extern crate test;

macro_rules! benchmark {
    ($strct: ident, $md: ident) => {
        mod $md {
            use csrf::{$strct, CsrfProtection};
            use data_encoding::BASE64;
            use test::Bencher;

            const KEY_32: [u8; 32] = *b"01234567012345670123456701234567";
            const TOKEN: &[u8; 64] =
                b"0123456701234567012345670123456701234567012345670123456701234567";

            #[bench]
            fn generate_pair(b: &mut Bencher) {
                let protect = $strct::from_key(KEY_32);
                b.iter(|| {
                    let _ = protect.generate_token_pair(Some(TOKEN), 3600);
                });
            }

            #[bench]
            fn validate_pair_success(b: &mut Bencher) {
                let protect = $strct::from_key(KEY_32);
                let mut pairs = Vec::new();

                for _ in 0..10 {
                    let (token, cookie) = protect
                        .generate_token_pair(Some(TOKEN), 3600)
                        .expect("failed to generate token");
                    let token = BASE64
                        .decode(token.b64_string().as_bytes())
                        .expect("token not base64");
                    let token = protect.parse_token(&token).expect("token not parsed");
                    let cookie = BASE64
                        .decode(cookie.b64_string().as_bytes())
                        .expect("cookie not base64");
                    let cookie = protect.parse_cookie(&cookie).expect("cookie not parsed");
                    pairs.push((token, cookie));
                }

                b.iter(|| {
                    for &(ref token, ref cookie) in pairs.iter() {
                        protect.verify_token_pair(&token, &cookie).unwrap();
                    }
                });
            }

            #[bench]
            fn parse_cookie_success(b: &mut Bencher) {
                let protect = $strct::from_key(KEY_32);
                let mut cookies = Vec::new();

                for _ in 0..10 {
                    let (_, cookie) = protect
                        .generate_token_pair(Some(TOKEN), 3600)
                        .expect("failed to generate cookie");
                    let cookie = BASE64
                        .decode(cookie.b64_string().as_bytes())
                        .expect("cookie not base64");
                    cookies.push(cookie)
                }

                b.iter(|| {
                    for cookie in cookies.iter() {
                        let _ = protect.parse_cookie(&cookie).expect("cookie not parsed");
                    }
                });
            }

            #[bench]
            fn parse_token_success(b: &mut Bencher) {
                let protect = $strct::from_key(KEY_32);
                let mut tokens = Vec::new();

                for _ in 0..10 {
                    let (token, _) = protect
                        .generate_token_pair(Some(TOKEN), 3600)
                        .expect("failed to generate token");
                    let token = BASE64
                        .decode(token.b64_string().as_bytes())
                        .expect("token not base64");
                    tokens.push(token)
                }

                b.iter(|| {
                    for token in tokens.iter() {
                        let _ = protect.parse_token(&token).expect("token not parsed");
                    }
                });
            }

            #[bench]
            fn parse_cookie_bad_sig(b: &mut Bencher) {
                let protect = $strct::from_key(KEY_32);
                let mut cookies = Vec::new();

                for _ in 0..10 {
                    let (_, cookie) = protect
                        .generate_token_pair(Some(TOKEN), 3600)
                        .expect("failed to generate cookie");
                    let mut cookie = BASE64
                        .decode(cookie.b64_string().as_bytes())
                        .expect("cookie not base64");
                    let cookie_len = cookie.len();
                    cookie[cookie_len - 1] ^= 0x01;
                    cookies.push(cookie)
                }

                b.iter(|| {
                    for cookie in cookies.iter() {
                        assert!(protect.parse_cookie(&cookie).is_err());
                    }
                });
            }

            #[bench]
            fn parse_token_bad_sig(b: &mut Bencher) {
                let protect = $strct::from_key(KEY_32);
                let mut tokens = Vec::new();

                for _ in 0..10 {
                    let (token, _) = protect
                        .generate_token_pair(Some(TOKEN), 3600)
                        .expect("failed to generate token");
                    let mut token = BASE64
                        .decode(token.b64_string().as_bytes())
                        .expect("token not base64");
                    let token_len = token.len();
                    token[token_len - 1] ^= 0x01;
                    tokens.push(token)
                }

                b.iter(|| {
                    for token in tokens.iter() {
                        assert!(protect.parse_token(&token).is_err());
                    }
                });
            }

            #[bench]
            fn parse_cookie_bad_value(b: &mut Bencher) {
                let protect = $strct::from_key(KEY_32);
                let mut cookies = Vec::new();

                for _ in 0..10 {
                    let (_, cookie) = protect
                        .generate_token_pair(Some(TOKEN), 3600)
                        .expect("failed to generate cookie");
                    let mut cookie = BASE64
                        .decode(cookie.b64_string().as_bytes())
                        .expect("cookie not base64");
                    cookie[0] ^= 0x01;
                    cookies.push(cookie)
                }

                b.iter(|| {
                    for cookie in cookies.iter() {
                        assert!(protect.parse_cookie(&cookie).is_err());
                    }
                });
            }

            #[bench]
            fn parse_token_bad_value(b: &mut Bencher) {
                let protect = $strct::from_key(KEY_32);
                let mut tokens = Vec::new();

                for _ in 0..10 {
                    let (token, _) = protect
                        .generate_token_pair(Some(TOKEN), 3600)
                        .expect("failed to generate token");
                    let mut token = BASE64
                        .decode(token.b64_string().as_bytes())
                        .expect("token not base64");
                    token[0] ^= 0x01;
                    tokens.push(token)
                }

                b.iter(|| {
                    for token in tokens.iter() {
                        assert!(protect.parse_token(&token).is_err());
                    }
                });
            }
        }
    };
}

benchmark!(AesGcmCsrfProtection, aesgcm);
benchmark!(ChaCha20Poly1305CsrfProtection, chacha20poly1305);
benchmark!(HmacCsrfProtection, hmac);