1pub mod hasher {
2 use std::io::{Error, ErrorKind};
3 use argon2::{
4 password_hash::{
5 rand_core::OsRng,
6 PasswordHash, PasswordHasher, PasswordVerifier, SaltString
7 },
8 Argon2
9 };
10
11 pub fn hash(passwd:&str) -> Result<String, Error> {
12 let salt:SaltString = SaltString::generate(&mut OsRng);
13 let argon:Argon2 = Argon2::default();
14 match argon.hash_password(passwd.as_bytes(), &salt) {
15 Ok(pass) => Ok(pass.to_string()),
16 Err(e) => Err(Error::new(ErrorKind::Other, e.to_string()))
17 }
18 }
19
20 pub fn verify(plain:&str, hashed: &str) -> Result<bool, std::io::Error> {
21 let argon:Argon2 = Argon2::default();
22 match PasswordHash::new(hashed) {
23 Ok(ph) => {
24 Ok(argon.verify_password(plain.as_bytes(), &ph).is_ok())
25 },
26 Err(e) => Err(Error::new(ErrorKind::Other, e.to_string()))
27 }
28 }
29
30}
31
32pub mod jwt {
33
34 const PRIVATE:&str = "private_key.pem";
35 const PUBLIC:&str = "public_key.pem";
36
37 use std::{result::Result::Ok, str::FromStr, fmt::Display, collections::HashSet};
38 use openssl::pkey::{PKey, Private};
39 use std::{io::{Error, ErrorKind}, fs, path::Path};
40 use jwt_simple::{prelude::{Ed25519KeyPair,Claims, VerificationOptions, Ed25519PublicKey, NoCustomClaims, EdDSAPublicKeyLike, Duration, EdDSAKeyPairLike, JWTClaims}};
41
42 pub struct SignOptions<'a, T:ToString> {
43 pub issuer: Option<&'a str>,
44 pub expiry: Option<Duration>,
45 pub audience: Option<T>
46 }
47
48 #[derive(Default)]
49 pub struct VerifyOptions {
50 pub valid_audiences: Option<HashSet<String>>,
51 pub valid_issuers: Option<HashSet<String>>,
52 pub valid_after_expiry: Option<Duration>
53 }
54
55 impl<'a, T:ToString+Copy> SignOptions<'a, T> {
56 fn get_claim(&self) -> JWTClaims<NoCustomClaims> {
57 let mut claim = Claims::create(match self.expiry {
58 Some(exp) => exp,
59 None => std::time::Duration::MAX.into()
60 });
61
62 claim = match self.audience {
63 Some(audience) => claim.with_audience(audience),
64 None => claim,
65 };
66
67 match self.issuer {
68 Some(iss) => claim.with_issuer(iss),
69 None => claim
70 }
71 }
72 }
73
74 pub fn generate_key_pair_if_absent() -> Result<(), Error> {
75
76 let priv_key:PKey<Private> = match fs::read(PRIVATE) {
77 Ok(key_in_bytes) => match PKey::private_key_from_pem(key_in_bytes.as_slice()){
78 Ok(k) => k,
79 Err(_) => match PKey::generate_ed25519() {
80 Ok(vv) => vv,
81 Err(e) => {
82 return Err(Error::new(ErrorKind::Other, e.to_string()));
83 }
84 },
85 },
86 Err(_) => match PKey::generate_ed25519() {
87 Ok(val) => val,
88 Err(e) => {
89 return Err(Error::new(ErrorKind::Other, e.to_string()));
90 }
91 }
92 };
93
94 match priv_key.private_key_to_pem_pkcs8() {
95 Ok(str) => {
96 match fs::write(PRIVATE, str) {
97 Ok(_) => {},
98 Err(e) => {
99 return Err(Error::new(ErrorKind::Other, e.to_string()));
100 }
101 }
102 },
103 Err(e) => {
104 return Err(Error::new(ErrorKind::Other, e.to_string()));
105 }
106 };
107
108 match priv_key.public_key_to_pem() {
109 Ok(str) => {
110 match fs::write(PUBLIC, str) {
111 Ok(_) => {},
112 Err(e) => {
113 return Err(Error::new(ErrorKind::Other, e.to_string()));
114 }
115 }
116 },
117 Err(e) => {
118 return Err(Error::new(ErrorKind::Other, e.to_string()));
119 }
120 };
121
122 Ok(())
123
124 }
125
126
127 pub fn get_keys_as_str() -> Result<(String,String), Error> {
128 let pub_bytes = match fs::read(Path::new("public_key.pem")) {
129 Ok(bts) => bts,
130 Err(e) => {return Err(Error::new(ErrorKind::Other, e.to_string()));}
131 };
132
133 let priv_bytes = match fs::read(Path::new("private_key.pem")) {
134 Ok(bts) => bts,
135 Err(e) => {return Err(Error::new(ErrorKind::Other, e.to_string()));}
136 };
137
138 Ok((String::from_utf8(priv_bytes).unwrap(),String::from_utf8(pub_bytes).unwrap()))
139 }
140
141 pub fn sign<T:ToString+Copy>(pem_str:&str, options:SignOptions<T>) -> Result<String, Error> {
142 let key_pair = match Ed25519KeyPair::from_pem(pem_str) {
143 Ok(pair) => pair,
144 Err(e) => {
145 return Err(Error::new(ErrorKind::Other, e.to_string()))
146 }
147 };
148
149 let claim = options.get_claim();
150
151 match key_pair.sign(claim) {
152 Ok(token) => Ok(token),
153 Err(e) => Err(Error::new(ErrorKind::Other, e.to_string()))
154 }
155 }
156
157 pub fn verify<T>(token:&str, pub_pem_str:&str, options:VerifyOptions) -> Result<T, Error>
158 where
159 <T as FromStr>::Err:Display,
160 T:FromStr
161 {
162 let opts:VerificationOptions = VerificationOptions { accept_future:false, time_tolerance: options.valid_after_expiry, allowed_issuers: options.valid_issuers, allowed_audiences: options.valid_audiences, ..Default::default() };
163 let pub_key = match Ed25519PublicKey::from_pem(pub_pem_str) {
164 Ok(key) => key,
165 Err(e) => {return Err(Error::new(ErrorKind::Other, e.to_string()))}
166 };
167 match pub_key.verify_token::<NoCustomClaims>(token, Some(opts)) {
168 Ok(clm) => {
169 let aud = match clm.audiences {
170 Some(adienc) => adienc,
171 None => {return Err(Error::new(ErrorKind::Other, "Empty audience"))}
172 };
173 match aud.into_string() {
174 Ok(au_clm) => match T::from_str(&au_clm) {
175 Ok(id) => Ok(id),
176 Err(e) => Err(Error::new(ErrorKind::Other, e.to_string()))
177 },
178 Err(e) => Err(Error::new(ErrorKind::Other, e.to_string()))
179 }
180 },
181 Err(e) => Err(Error::new(ErrorKind::Other, e.to_string()))
182 }
183 }
184}