1 // Copyright (c) 2017 Martijn Rijkeboer <mrr@sru-systems.com>
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 
9 use crate::error::Error;
10 use crate::result::Result;
11 use std::fmt;
12 
13 /// The Argon2 variant.
14 #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)]
15 pub 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 
29 impl Variant {
30     /// Gets the lowercase string slice representation of the variant.
as_lowercase_str(&self) -> &'static str31     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.
as_u32(&self) -> u3240     pub fn as_u32(&self) -> u32 {
41         *self as u32
42     }
43 
44     /// Gets the u64 representation of the variant.
as_u64(&self) -> u6445     pub fn as_u64(&self) -> u64 {
46         *self as u64
47     }
48 
49     /// Gets the uppercase string slice representation of the variant.
as_uppercase_str(&self) -> &'static str50     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.
from_str(str: &str) -> Result<Variant>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.
from_u32(val: u32) -> Result<Variant>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 
82 impl Default for Variant {
default() -> Variant83     fn default() -> Variant {
84         Variant::Argon2i
85     }
86 }
87 
88 impl fmt::Display for Variant {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result89     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
90         write!(f, "{}", self.as_lowercase_str())
91     }
92 }
93 
94 #[cfg(test)]
95 mod tests {
96 
97     use crate::error::Error;
98     use crate::variant::Variant;
99 
100     #[test]
as_lowercase_str_returns_correct_str()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]
as_u32_returns_correct_u32()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]
as_u64_returns_correct_u64()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]
as_uppercase_str_returns_correct_str()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]
default_returns_correct_variant()129     fn default_returns_correct_variant() {
130         assert_eq!(Variant::default(), Variant::Argon2i);
131     }
132 
133     #[test]
display_returns_correct_string()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]
from_str_returns_correct_result()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]
from_u32_returns_correct_result()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 }
159