argon2/
variant.rs

1// Copyright (c) 2017 Martijn Rijkeboer <[email protected]>
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9use crate::error::Error;
10use crate::result::Result;
11use std::fmt;
12
13/// The Argon2 variant.
14#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)]
15pub enum Variant {
16    /// Argon2 using data-dependent memory access to thwart tradeoff attacks.
17    /// Recommended for cryptocurrencies and backend servers.
18    Argon2d = 0,
19
20    /// Argon2 using data-independent memory access to thwart side-channel
21    /// attacks. Recommended for password hashing and password-based key
22    /// derivation.
23    Argon2i = 1,
24
25    /// Argon2 using hybrid construction.
26    Argon2id = 2,
27}
28
29impl Variant {
30    /// Gets the lowercase string slice representation of the variant.
31    pub fn as_lowercase_str(&self) -> &'static str {
32        match *self {
33            Variant::Argon2d => "argon2d",
34            Variant::Argon2i => "argon2i",
35            Variant::Argon2id => "argon2id",
36        }
37    }
38
39    /// Gets the u32 representation of the variant.
40    pub fn as_u32(&self) -> u32 {
41        *self as u32
42    }
43
44    /// Gets the u64 representation of the variant.
45    pub fn as_u64(&self) -> u64 {
46        *self as u64
47    }
48
49    /// Gets the uppercase string slice representation of the variant.
50    pub fn as_uppercase_str(&self) -> &'static str {
51        match *self {
52            Variant::Argon2d => "Argon2d",
53            Variant::Argon2i => "Argon2i",
54            Variant::Argon2id => "Argon2id",
55        }
56    }
57
58    /// Attempts to create a variant from a string slice.
59    pub fn from_str(str: &str) -> Result<Variant> {
60        match str {
61            "Argon2d" => Ok(Variant::Argon2d),
62            "Argon2i" => Ok(Variant::Argon2i),
63            "Argon2id" => Ok(Variant::Argon2id),
64            "argon2d" => Ok(Variant::Argon2d),
65            "argon2i" => Ok(Variant::Argon2i),
66            "argon2id" => Ok(Variant::Argon2id),
67            _ => Err(Error::DecodingFail),
68        }
69    }
70
71    /// Attempts to create a variant from an u32.
72    pub fn from_u32(val: u32) -> Result<Variant> {
73        match val {
74            0 => Ok(Variant::Argon2d),
75            1 => Ok(Variant::Argon2i),
76            2 => Ok(Variant::Argon2id),
77            _ => Err(Error::IncorrectType),
78        }
79    }
80}
81
82impl Default for Variant {
83    fn default() -> Variant {
84        Variant::Argon2i
85    }
86}
87
88impl fmt::Display for Variant {
89    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
90        write!(f, "{}", self.as_lowercase_str())
91    }
92}
93
94#[cfg(test)]
95mod tests {
96
97    use crate::error::Error;
98    use crate::variant::Variant;
99
100    #[test]
101    fn as_lowercase_str_returns_correct_str() {
102        assert_eq!(Variant::Argon2d.as_lowercase_str(), "argon2d");
103        assert_eq!(Variant::Argon2i.as_lowercase_str(), "argon2i");
104        assert_eq!(Variant::Argon2id.as_lowercase_str(), "argon2id");
105    }
106
107    #[test]
108    fn as_u32_returns_correct_u32() {
109        assert_eq!(Variant::Argon2d.as_u32(), 0);
110        assert_eq!(Variant::Argon2i.as_u32(), 1);
111        assert_eq!(Variant::Argon2id.as_u32(), 2);
112    }
113
114    #[test]
115    fn as_u64_returns_correct_u64() {
116        assert_eq!(Variant::Argon2d.as_u64(), 0);
117        assert_eq!(Variant::Argon2i.as_u64(), 1);
118        assert_eq!(Variant::Argon2id.as_u64(), 2);
119    }
120
121    #[test]
122    fn as_uppercase_str_returns_correct_str() {
123        assert_eq!(Variant::Argon2d.as_uppercase_str(), "Argon2d");
124        assert_eq!(Variant::Argon2i.as_uppercase_str(), "Argon2i");
125        assert_eq!(Variant::Argon2id.as_uppercase_str(), "Argon2id");
126    }
127
128    #[test]
129    fn default_returns_correct_variant() {
130        assert_eq!(Variant::default(), Variant::Argon2i);
131    }
132
133    #[test]
134    fn display_returns_correct_string() {
135        assert_eq!(format!("{}", Variant::Argon2d), "argon2d");
136        assert_eq!(format!("{}", Variant::Argon2i), "argon2i");
137        assert_eq!(format!("{}", Variant::Argon2id), "argon2id");
138    }
139
140    #[test]
141    fn from_str_returns_correct_result() {
142        assert_eq!(Variant::from_str("Argon2d"), Ok(Variant::Argon2d));
143        assert_eq!(Variant::from_str("Argon2i"), Ok(Variant::Argon2i));
144        assert_eq!(Variant::from_str("Argon2id"), Ok(Variant::Argon2id));
145        assert_eq!(Variant::from_str("argon2d"), Ok(Variant::Argon2d));
146        assert_eq!(Variant::from_str("argon2i"), Ok(Variant::Argon2i));
147        assert_eq!(Variant::from_str("argon2id"), Ok(Variant::Argon2id));
148        assert_eq!(Variant::from_str("foobar"), Err(Error::DecodingFail));
149    }
150
151    #[test]
152    fn from_u32_returns_correct_result() {
153        assert_eq!(Variant::from_u32(0), Ok(Variant::Argon2d));
154        assert_eq!(Variant::from_u32(1), Ok(Variant::Argon2i));
155        assert_eq!(Variant::from_u32(2), Ok(Variant::Argon2id));
156        assert_eq!(Variant::from_u32(3), Err(Error::IncorrectType));
157    }
158}