// Copyright (c) 2017 Martijn Rijkeboer // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use std::fmt; use super::error::Error; use super::result::Result; /// The Argon2 variant. #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)] pub enum Variant { /// Argon2 using data-dependent memory access to thwart tradeoff attacks. /// Recommended for cryptocurrencies and backend servers. Argon2d = 0, /// Argon2 using data-independent memory access to thwart side-channel /// attacks. Recommended for password hashing and password-based key /// derivation. Argon2i = 1, /// Argon2 using hybrid construction. Argon2id = 2, } impl Variant { /// Gets the lowercase string slice representation of the variant. pub fn as_lowercase_str(&self) -> &'static str { match *self { Variant::Argon2d => "argon2d", Variant::Argon2i => "argon2i", Variant::Argon2id => "argon2id", } } /// Gets the u32 representation of the variant. pub fn as_u32(&self) -> u32 { *self as u32 } /// Gets the u64 representation of the variant. pub fn as_u64(&self) -> u64 { *self as u64 } /// Gets the uppercase string slice representation of the variant. pub fn as_uppercase_str(&self) -> &'static str { match *self { Variant::Argon2d => "Argon2d", Variant::Argon2i => "Argon2i", Variant::Argon2id => "Argon2id", } } /// Attempts to create a variant from a string slice. pub fn from_str(str: &str) -> Result { match str { "Argon2d" => Ok(Variant::Argon2d), "Argon2i" => Ok(Variant::Argon2i), "Argon2id" => Ok(Variant::Argon2id), "argon2d" => Ok(Variant::Argon2d), "argon2i" => Ok(Variant::Argon2i), "argon2id" => Ok(Variant::Argon2id), _ => Err(Error::DecodingFail), } } /// Attempts to create a variant from an u32. pub fn from_u32(val: u32) -> Result { match val { 0 => Ok(Variant::Argon2d), 1 => Ok(Variant::Argon2i), 2 => Ok(Variant::Argon2id), _ => Err(Error::IncorrectType), } } } impl Default for Variant { fn default() -> Variant { Variant::Argon2i } } impl fmt::Display for Variant { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.as_lowercase_str()) } } #[cfg(test)] mod tests { use error::Error; use super::*; #[test] fn as_lowercase_str_returns_correct_str() { assert_eq!(Variant::Argon2d.as_lowercase_str(), "argon2d"); assert_eq!(Variant::Argon2i.as_lowercase_str(), "argon2i"); assert_eq!(Variant::Argon2id.as_lowercase_str(), "argon2id"); } #[test] fn as_u32_returns_correct_u32() { assert_eq!(Variant::Argon2d.as_u32(), 0); assert_eq!(Variant::Argon2i.as_u32(), 1); assert_eq!(Variant::Argon2id.as_u32(), 2); } #[test] fn as_u64_returns_correct_u64() { assert_eq!(Variant::Argon2d.as_u64(), 0); assert_eq!(Variant::Argon2i.as_u64(), 1); assert_eq!(Variant::Argon2id.as_u64(), 2); } #[test] fn as_uppercase_str_returns_correct_str() { assert_eq!(Variant::Argon2d.as_uppercase_str(), "Argon2d"); assert_eq!(Variant::Argon2i.as_uppercase_str(), "Argon2i"); assert_eq!(Variant::Argon2id.as_uppercase_str(), "Argon2id"); } #[test] fn default_returns_correct_variant() { assert_eq!(Variant::default(), Variant::Argon2i); } #[test] fn display_returns_correct_string() { assert_eq!(format!("{}", Variant::Argon2d), "argon2d"); assert_eq!(format!("{}", Variant::Argon2i), "argon2i"); assert_eq!(format!("{}", Variant::Argon2id), "argon2id"); } #[test] fn from_str_returns_correct_result() { assert_eq!(Variant::from_str("Argon2d"), Ok(Variant::Argon2d)); assert_eq!(Variant::from_str("Argon2i"), Ok(Variant::Argon2i)); assert_eq!(Variant::from_str("Argon2id"), Ok(Variant::Argon2id)); assert_eq!(Variant::from_str("argon2d"), Ok(Variant::Argon2d)); assert_eq!(Variant::from_str("argon2i"), Ok(Variant::Argon2i)); assert_eq!(Variant::from_str("argon2id"), Ok(Variant::Argon2id)); assert_eq!(Variant::from_str("foobar"), Err(Error::DecodingFail)); } #[test] fn from_u32_returns_correct_result() { assert_eq!(Variant::from_u32(0), Ok(Variant::Argon2d)); assert_eq!(Variant::from_u32(1), Ok(Variant::Argon2i)); assert_eq!(Variant::from_u32(2), Ok(Variant::Argon2id)); assert_eq!(Variant::from_u32(3), Err(Error::IncorrectType)); } }