password_security.rs 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. use crate::config::Config;
  2. use sodiumoxide::base64;
  3. use std::sync::{Arc, RwLock};
  4. lazy_static::lazy_static! {
  5. pub static ref TEMPORARY_PASSWORD:Arc<RwLock<String>> = Arc::new(RwLock::new(Config::get_auto_password(temporary_password_length())));
  6. }
  7. #[derive(Debug, Clone, Copy, PartialEq, Eq)]
  8. enum VerificationMethod {
  9. OnlyUseTemporaryPassword,
  10. OnlyUsePermanentPassword,
  11. UseBothPasswords,
  12. }
  13. #[derive(Debug, Clone, Copy, PartialEq, Eq)]
  14. pub enum ApproveMode {
  15. Both,
  16. Password,
  17. Click,
  18. }
  19. // Should only be called in server
  20. pub fn update_temporary_password() {
  21. *TEMPORARY_PASSWORD.write().unwrap() = Config::get_auto_password(temporary_password_length());
  22. }
  23. // Should only be called in server
  24. pub fn temporary_password() -> String {
  25. TEMPORARY_PASSWORD.read().unwrap().clone()
  26. }
  27. fn verification_method() -> VerificationMethod {
  28. let method = Config::get_option("verification-method");
  29. if method == "use-temporary-password" {
  30. VerificationMethod::OnlyUseTemporaryPassword
  31. } else if method == "use-permanent-password" {
  32. VerificationMethod::OnlyUsePermanentPassword
  33. } else {
  34. VerificationMethod::UseBothPasswords // default
  35. }
  36. }
  37. pub fn temporary_password_length() -> usize {
  38. let length = Config::get_option("temporary-password-length");
  39. if length == "8" {
  40. 8
  41. } else if length == "10" {
  42. 10
  43. } else {
  44. 6 // default
  45. }
  46. }
  47. pub fn temporary_enabled() -> bool {
  48. verification_method() != VerificationMethod::OnlyUsePermanentPassword
  49. }
  50. pub fn permanent_enabled() -> bool {
  51. verification_method() != VerificationMethod::OnlyUseTemporaryPassword
  52. }
  53. pub fn has_valid_password() -> bool {
  54. temporary_enabled() && !temporary_password().is_empty()
  55. || permanent_enabled() && !Config::get_permanent_password().is_empty()
  56. }
  57. pub fn approve_mode() -> ApproveMode {
  58. let mode = Config::get_option("approve-mode");
  59. if mode == "password" {
  60. ApproveMode::Password
  61. } else if mode == "click" {
  62. ApproveMode::Click
  63. } else {
  64. ApproveMode::Both
  65. }
  66. }
  67. pub fn hide_cm() -> bool {
  68. approve_mode() == ApproveMode::Password
  69. && verification_method() == VerificationMethod::OnlyUsePermanentPassword
  70. && !Config::get_option("allow-hide-cm").is_empty()
  71. }
  72. const VERSION_LEN: usize = 2;
  73. pub fn encrypt_str_or_original(s: &str, version: &str) -> String {
  74. if decrypt_str_or_original(s, version).1 {
  75. log::error!("Duplicate encryption!");
  76. return s.to_owned();
  77. }
  78. if version == "00" {
  79. if let Ok(s) = encrypt(s.as_bytes()) {
  80. return version.to_owned() + &s;
  81. }
  82. }
  83. s.to_owned()
  84. }
  85. // String: password
  86. // bool: whether decryption is successful
  87. // bool: whether should store to re-encrypt when load
  88. pub fn decrypt_str_or_original(s: &str, current_version: &str) -> (String, bool, bool) {
  89. if s.len() > VERSION_LEN {
  90. let version = &s[..VERSION_LEN];
  91. if version == "00" {
  92. if let Ok(v) = decrypt(s[VERSION_LEN..].as_bytes()) {
  93. return (
  94. String::from_utf8_lossy(&v).to_string(),
  95. true,
  96. version != current_version,
  97. );
  98. }
  99. }
  100. }
  101. (s.to_owned(), false, !s.is_empty())
  102. }
  103. pub fn encrypt_vec_or_original(v: &[u8], version: &str) -> Vec<u8> {
  104. if decrypt_vec_or_original(v, version).1 {
  105. log::error!("Duplicate encryption!");
  106. return v.to_owned();
  107. }
  108. if version == "00" {
  109. if let Ok(s) = encrypt(v) {
  110. let mut version = version.to_owned().into_bytes();
  111. version.append(&mut s.into_bytes());
  112. return version;
  113. }
  114. }
  115. v.to_owned()
  116. }
  117. // Vec<u8>: password
  118. // bool: whether decryption is successful
  119. // bool: whether should store to re-encrypt when load
  120. pub fn decrypt_vec_or_original(v: &[u8], current_version: &str) -> (Vec<u8>, bool, bool) {
  121. if v.len() > VERSION_LEN {
  122. let version = String::from_utf8_lossy(&v[..VERSION_LEN]);
  123. if version == "00" {
  124. if let Ok(v) = decrypt(&v[VERSION_LEN..]) {
  125. return (v, true, version != current_version);
  126. }
  127. }
  128. }
  129. (v.to_owned(), false, !v.is_empty())
  130. }
  131. fn encrypt(v: &[u8]) -> Result<String, ()> {
  132. if !v.is_empty() {
  133. symmetric_crypt(v, true).map(|v| base64::encode(v, base64::Variant::Original))
  134. } else {
  135. Err(())
  136. }
  137. }
  138. fn decrypt(v: &[u8]) -> Result<Vec<u8>, ()> {
  139. if !v.is_empty() {
  140. base64::decode(v, base64::Variant::Original).and_then(|v| symmetric_crypt(&v, false))
  141. } else {
  142. Err(())
  143. }
  144. }
  145. fn symmetric_crypt(data: &[u8], encrypt: bool) -> Result<Vec<u8>, ()> {
  146. use sodiumoxide::crypto::secretbox;
  147. use std::convert::TryInto;
  148. let mut keybuf = crate::get_uuid();
  149. keybuf.resize(secretbox::KEYBYTES, 0);
  150. let key = secretbox::Key(keybuf.try_into().map_err(|_| ())?);
  151. let nonce = secretbox::Nonce([0; secretbox::NONCEBYTES]);
  152. if encrypt {
  153. Ok(secretbox::seal(data, &nonce, &key))
  154. } else {
  155. secretbox::open(data, &nonce, &key)
  156. }
  157. }
  158. mod test {
  159. #[test]
  160. fn test() {
  161. use super::*;
  162. let version = "00";
  163. println!("test str");
  164. let data = "Hello World";
  165. let encrypted = encrypt_str_or_original(data, version);
  166. let (decrypted, succ, store) = decrypt_str_or_original(&encrypted, version);
  167. println!("data: {}", data);
  168. println!("encrypted: {}", encrypted);
  169. println!("decrypted: {}", decrypted);
  170. assert_eq!(data, decrypted);
  171. assert_eq!(version, &encrypted[..2]);
  172. assert_eq!(succ, true);
  173. assert_eq!(store, false);
  174. let (_, _, store) = decrypt_str_or_original(&encrypted, "99");
  175. assert_eq!(store, true);
  176. assert_eq!(decrypt_str_or_original(&decrypted, version).1, false);
  177. assert_eq!(encrypt_str_or_original(&encrypted, version), encrypted);
  178. println!("test vec");
  179. let data: Vec<u8> = vec![1, 2, 3, 4, 5, 6];
  180. let encrypted = encrypt_vec_or_original(&data, version);
  181. let (decrypted, succ, store) = decrypt_vec_or_original(&encrypted, version);
  182. println!("data: {:?}", data);
  183. println!("encrypted: {:?}", encrypted);
  184. println!("decrypted: {:?}", decrypted);
  185. assert_eq!(data, decrypted);
  186. assert_eq!(version.as_bytes(), &encrypted[..2]);
  187. assert_eq!(store, false);
  188. assert_eq!(succ, true);
  189. let (_, _, store) = decrypt_vec_or_original(&encrypted, "99");
  190. assert_eq!(store, true);
  191. assert_eq!(decrypt_vec_or_original(&decrypted, version).1, false);
  192. assert_eq!(encrypt_vec_or_original(&encrypted, version), encrypted);
  193. println!("test original");
  194. let data = version.to_string() + "Hello World";
  195. let (decrypted, succ, store) = decrypt_str_or_original(&data, version);
  196. assert_eq!(data, decrypted);
  197. assert_eq!(store, true);
  198. assert_eq!(succ, false);
  199. let verbytes = version.as_bytes();
  200. let data: Vec<u8> = vec![verbytes[0] as u8, verbytes[1] as u8, 1, 2, 3, 4, 5, 6];
  201. let (decrypted, succ, store) = decrypt_vec_or_original(&data, version);
  202. assert_eq!(data, decrypted);
  203. assert_eq!(store, true);
  204. assert_eq!(succ, false);
  205. let (_, succ, store) = decrypt_str_or_original("", version);
  206. assert_eq!(store, false);
  207. assert_eq!(succ, false);
  208. let (_, succ, store) = decrypt_vec_or_original(&vec![], version);
  209. assert_eq!(store, false);
  210. assert_eq!(succ, false);
  211. }
  212. }