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