diff --git a/Cargo.lock b/Cargo.lock index 1813630..69a166c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "adler" @@ -34,6 +34,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "ansi_term" version = "0.12.1" @@ -61,7 +70,7 @@ checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.98", ] [[package]] @@ -72,7 +81,7 @@ checksum = "96cf8829f67d2eab0b2dfa42c5d0ef737e0724e4a82b01b3e292456202b19716" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.98", ] [[package]] @@ -107,7 +116,7 @@ dependencies = [ "hex", "http", "hyper", - "ring", + "ring 0.16.20", "tokio", "tower", "tracing", @@ -238,8 +247,8 @@ dependencies = [ "once_cell", "percent-encoding", "regex", - "ring", - "time 0.3.11", + "ring 0.16.20", + "time", "tracing", ] @@ -342,7 +351,7 @@ dependencies = [ "itoa", "num-integer", "ryu", - "time 0.3.11", + "time", ] [[package]] @@ -376,7 +385,7 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55d7e5deac5e49330042b4e174dafe84ebf71685bfcd94f285bac7aa31e0aeb1" dependencies = [ - "base64", + "base64 0.13.0", "bytes", "chrono", "http", @@ -460,6 +469,31 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "base64ct" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" + +[[package]] +name = "bcrypt" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e65938ed058ef47d92cf8b346cc76ef48984572ade631927e9937b5ffc7662c7" +dependencies = [ + "base64 0.22.1", + "blowfish", + "getrandom", + "subtle", + "zeroize", +] + [[package]] name = "bit_field" version = "0.10.1" @@ -472,6 +506,15 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest 0.10.3", +] + [[package]] name = "block-buffer" version = "0.7.3" @@ -502,6 +545,16 @@ dependencies = [ "byte-tools", ] +[[package]] +name = "blowfish" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e412e2cd0f2b2d93e02543ceae7917b3c70331573df19ee046bcbc35e45e87d7" +dependencies = [ + "byteorder", + "cipher", +] + [[package]] name = "bumpalo" version = "3.10.0" @@ -547,9 +600,13 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.73" +version = "1.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" +checksum = "65193589c6404eb80b450d618eaf9a2cafaaafd57ecce47370519ef674a7bd44" +dependencies = [ + "find-msvc-tools", + "shlex", +] [[package]] name = "cfg-if" @@ -557,18 +614,39 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chacha20" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + [[package]] name = "chrono" -version = "0.4.19" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" dependencies = [ - "libc", - "num-integer", + "iana-time-zone", + "js-sys", "num-traits", "serde", - "time 0.1.44", - "winapi", + "wasm-bindgen", + "windows-link 0.2.0", +] + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", ] [[package]] @@ -586,7 +664,7 @@ dependencies = [ "async-trait", "json5", "lazy_static", - "nom", + "nom 7.1.1", "pathdiff", "ron", "rust-ini", @@ -596,6 +674,12 @@ dependencies = [ "yaml-rust", ] +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + [[package]] name = "constant_time_eq" version = "0.2.3" @@ -614,15 +698,15 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.3" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.2" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ "libc", ] @@ -683,9 +767,9 @@ dependencies = [ [[package]] name = "crypto-common" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ccfd8c0ee4cce11e45b3fd6f9d5e69e0cc62912aa6a0cb1bf4617b0eba5a12f" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array 0.14.5", "typenum", @@ -700,6 +784,33 @@ dependencies = [ "sct", ] +[[package]] +name = "curve25519-dalek" +version = "4.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest 0.10.3", + "fiat-crypto", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + [[package]] name = "deflate" version = "1.0.0" @@ -709,6 +820,16 @@ dependencies = [ "adler32", ] +[[package]] +name = "der" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +dependencies = [ + "const-oid", + "zeroize", +] + [[package]] name = "digest" version = "0.8.1" @@ -735,6 +856,30 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257" +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8", + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9" +dependencies = [ + "curve25519-dalek", + "ed25519", + "serde", + "sha2", + "subtle", + "zeroize", +] + [[package]] name = "either" version = "1.7.0" @@ -750,6 +895,16 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "erased-serde" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e004d887f51fcb9fef17317a2f3525c887d8aa3f4f50fed920816a688284a5b7" +dependencies = [ + "serde", + "typeid", +] + [[package]] name = "exr" version = "1.4.2" @@ -781,6 +936,18 @@ dependencies = [ "instant", ] +[[package]] +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + +[[package]] +name = "find-msvc-tools" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fd99930f64d146689264c637b5af2f0233a933bef0d8570e2526bf9e083192d" + [[package]] name = "flate2" version = "1.0.24" @@ -843,7 +1010,7 @@ checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.98", ] [[package]] @@ -893,14 +1060,14 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.7" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "js-sys", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", "wasm-bindgen", ] @@ -1082,6 +1249,30 @@ dependencies = [ "webpki", ] +[[package]] +name = "iana-time-zone" +version = "0.1.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + [[package]] name = "idna" version = "0.2.3" @@ -1132,6 +1323,15 @@ dependencies = [ "adler32", ] +[[package]] +name = "inout" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +dependencies = [ + "generic-array 0.14.5", +] + [[package]] name = "instant" version = "0.1.12" @@ -1141,6 +1341,15 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "iso8601" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1082f0c48f143442a1ac6122f67e360ceee130b967af4d50996e5154a45df46" +dependencies = [ + "nom 8.0.0", +] + [[package]] name = "itoa" version = "1.0.2" @@ -1158,10 +1367,11 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.58" +version = "0.3.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3fac17f7123a73ca62df411b1bf727ccc805daa070338fda671c86dac1bdc27" +checksum = "0c0b063578492ceec17683ef2f8c5e89121fbd0b172cbc280635ab7567db2738" dependencies = [ + "once_cell", "wasm-bindgen", ] @@ -1192,7 +1402,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b5c60a2d2d3f8e88dda6e3d999137ea42d685551af04aa0c5910c6478640335" dependencies = [ "aws_lambda_events", - "base64", + "base64 0.13.0", "bytes", "http", "http-body", @@ -1210,7 +1420,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a540048486ccfaa407ef7d2b50b7ff7b8c18abfbf351731a4ff7ccd165fc43fa" dependencies = [ "aws_lambda_events", - "base64", + "base64 0.13.0", "bytes", "encoding_rs", "http", @@ -1300,9 +1510,9 @@ checksum = "7efd1d698db0759e6ef11a7cd44407407399a910c774dd804c64c032da7826ff" [[package]] name = "libc" -version = "0.2.126" +version = "0.2.175" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" [[package]] name = "linked-hash-map" @@ -1391,8 +1601,8 @@ checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" dependencies = [ "libc", "log", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys", + "wasi", + "windows-sys 0.36.1", ] [[package]] @@ -1414,6 +1624,15 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + [[package]] name = "num-integer" version = "0.1.45" @@ -1543,7 +1762,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn", + "syn 1.0.98", ] [[package]] @@ -1574,7 +1793,7 @@ checksum = "710faf75e1b33345361201d36d04e98ac1ed8909151a017ed384700836104c74" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.98", ] [[package]] @@ -1589,6 +1808,16 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + [[package]] name = "png" version = "0.17.5" @@ -1609,9 +1838,9 @@ checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "proc-macro2" -version = "1.0.40" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" dependencies = [ "unicode-ident", ] @@ -1646,9 +1875,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.20" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] @@ -1734,18 +1963,32 @@ dependencies = [ "libc", "once_cell", "spin 0.5.2", - "untrusted", + "untrusted 0.7.1", "web-sys", "winapi", ] +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "untrusted 0.9.0", + "windows-sys 0.52.0", +] + [[package]] name = "ron" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88073939a61e5b7680558e6be56b419e208420c2adb92be54921fa6b72283f1a" dependencies = [ - "base64", + "base64 0.13.0", "bitflags", "serde", ] @@ -1775,9 +2018,9 @@ version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7" dependencies = [ - "base64", + "base64 0.13.0", "log", - "ring", + "ring 0.16.20", "sct", "webpki", ] @@ -1794,6 +2037,35 @@ dependencies = [ "security-framework", ] +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "rusty_paseto" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05501841a4cac5c065cb6a501a62207c4c235e37d2882579a2505a2aa2837826" +dependencies = [ + "base64 0.22.1", + "blake2", + "chacha20", + "digest 0.10.3", + "ed25519-dalek", + "erased-serde", + "hex", + "iso8601", + "rand_core", + "ring 0.17.14", + "serde", + "serde_json", + "thiserror", + "time", + "zeroize", +] + [[package]] name = "ryu" version = "1.0.10" @@ -1807,7 +2079,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" dependencies = [ "lazy_static", - "windows-sys", + "windows-sys 0.36.1", ] [[package]] @@ -1828,8 +2100,8 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce" dependencies = [ - "ring", - "untrusted", + "ring 0.16.20", + "untrusted 0.7.1", ] [[package]] @@ -1863,22 +2135,22 @@ checksum = "a2333e6df6d6598f2b1974829f853c2b4c5f4a6e503c10af918081aa6f8564e1" [[package]] name = "serde" -version = "1.0.139" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0171ebb889e45aa68b44aee0859b3eede84c6f5f5c228e6f140c0b2a0a46cad6" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.139" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc1d3230c1de7932af58ad8ffbe1d784bd55efd5a9d84ac24f69c72d83543dfb" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.106", ] [[package]] @@ -1947,6 +2219,12 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "signal-hook-registry" version = "1.4.0" @@ -1956,6 +2234,12 @@ dependencies = [ "libc", ] +[[package]] +name = "signature" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" + [[package]] name = "slab" version = "0.4.6" @@ -1993,6 +2277,16 @@ dependencies = [ "lock_api", ] +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + [[package]] name = "subtle" version = "2.4.1" @@ -2010,12 +2304,43 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "2.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "sync_wrapper" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20518fe4a4c9acf048008599e464deb21beeae3d3578418951a189c235a7a9a8" +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + [[package]] name = "thread_local" version = "1.1.4" @@ -2045,23 +2370,13 @@ dependencies = [ "weezl", ] -[[package]] -name = "time" -version = "0.1.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" -dependencies = [ - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi", -] - [[package]] name = "time" version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72c91f41dcb2f096c05f0873d667dceec1087ce5bcf984ec8ffb19acddbb3217" dependencies = [ + "itoa", "libc", "num_threads", ] @@ -2108,7 +2423,7 @@ checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.98", ] [[package]] @@ -2175,7 +2490,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9254defd2c9202c8e5a03e4120faa0c1e0cb8ed365fb5d7305a33d0b4cf571c" dependencies = [ "base32", - "base64", + "base64 0.13.0", "constant_time_eq", "hmac", "image", @@ -2196,16 +2511,18 @@ dependencies = [ "aws-types", "axum", "axum-aws-lambda", + "bcrypt", + "chrono", "config", "http", "hyper", "koibumi-base32", "lambda_http 0.6.0", - "lazy_static", "once_cell", "qrcode-generator", "rand", "regex", + "rusty_paseto", "serde", "serde_json", "tokio", @@ -2290,7 +2607,7 @@ checksum = "11c75893af559bc8e10716548bdef5cb2b983f8e637db9d0e15126b61b484ee2" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.98", ] [[package]] @@ -2335,6 +2652,12 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" +[[package]] +name = "typeid" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" + [[package]] name = "typenum" version = "1.15.0" @@ -2355,9 +2678,9 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" [[package]] name = "unicode-ident" -version = "1.0.1" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c" +checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" [[package]] name = "unicode-normalization" @@ -2374,6 +2697,12 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.2.2" @@ -2430,12 +2759,6 @@ dependencies = [ "try-lock", ] -[[package]] -name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -2444,34 +2767,36 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.81" +version = "0.2.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c53b543413a17a202f4be280a7e5c62a1c69345f5de525ee64f8cfdbc954994" +checksum = "7e14915cadd45b529bb8d1f343c4ed0ac1de926144b746e2710f9cd05df6603b" dependencies = [ "cfg-if", + "once_cell", + "rustversion", "wasm-bindgen-macro", + "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.81" +version = "0.2.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5491a68ab4500fa6b4d726bd67408630c3dbe9c4fe7bda16d5c82a1fd8c7340a" +checksum = "e28d1ba982ca7923fd01448d5c30c6864d0a14109560296a162f80f305fb93bb" dependencies = [ "bumpalo", - "lazy_static", "log", "proc-macro2", "quote", - "syn", + "syn 2.0.106", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.81" +version = "0.2.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c441e177922bc58f1e12c022624b6216378e5febc2f0533e41ba443d505b80aa" +checksum = "7c3d463ae3eff775b0c45df9da45d68837702ac35af998361e2c84e7c5ec1b0d" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2479,22 +2804,25 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.81" +version = "0.2.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048" +checksum = "7bb4ce89b08211f923caf51d527662b75bdc9c9c7aab40f86dcb9fb85ac552aa" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.106", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.81" +version = "0.2.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a89911bd99e5f3659ec4acf9c4d93b0a90fe4a2a11f15328472058edc5261be" +checksum = "f143854a3b13752c6950862c906306adb27c7e839f7414cec8fea35beab624c1" +dependencies = [ + "unicode-ident", +] [[package]] name = "web-sys" @@ -2512,8 +2840,8 @@ version = "0.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" dependencies = [ - "ring", - "untrusted", + "ring 0.16.20", + "untrusted 0.7.1", ] [[package]] @@ -2544,49 +2872,187 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-core" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link 0.1.3", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "windows-interface" +version = "0.59.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + +[[package]] +name = "windows-link" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" + +[[package]] +name = "windows-result" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows-strings" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +dependencies = [ + "windows-link 0.1.3", +] + [[package]] name = "windows-sys" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" dependencies = [ - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_msvc", + "windows_aarch64_msvc 0.36.1", + "windows_i686_gnu 0.36.1", + "windows_i686_msvc 0.36.1", + "windows_x86_64_gnu 0.36.1", + "windows_x86_64_msvc 0.36.1", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", ] +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + [[package]] name = "windows_aarch64_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + [[package]] name = "windows_i686_gnu" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + [[package]] name = "windows_i686_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + [[package]] name = "windows_x86_64_gnu" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + [[package]] name = "windows_x86_64_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + [[package]] name = "xmlparser" version = "0.13.3" @@ -2607,3 +3073,17 @@ name = "zeroize" version = "1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20b578acffd8516a6c3f2a1bdefc1ec37e547bb4e0fb8b6b01a4cafc886b4442" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] diff --git a/Cargo.toml b/Cargo.toml index 5fa7e53..d051cb1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,9 +39,10 @@ http = "0.2.8" rand = "0.8.5" -lazy_static = "1.4.0" - qrcode-generator = "4.1.6" config = "0.13.1" +rusty_paseto = "0.7.2" +bcrypt = "0.15.1" +chrono = { version = "0.4.38", features = ["serde"] } diff --git a/src/auth.rs b/src/auth.rs index 72a773b..039f7ff 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -1,254 +1,93 @@ -use aws_sdk_dynamodb::model::{AttributeValue, Select}; -use axum::body::HttpBody; -use axum::{http::StatusCode, response::IntoResponse, Json}; -use http::header::HeaderMap; -use http::header::{CONTENT_DISPOSITION, CONTENT_TYPE}; -use totp_rs::{Algorithm, TOTP}; - -use crate::db::DynamoDBClient; -use crate::eval_constants::{get_step_size_value, get_totp_size_value}; -use crate::obj::KEY_MAP; use crate::{ + config::Config, + db::{Db, DbUser}, + error::{Error, Result}, obj::{User, VerifyUser}, operation::{generate_secret, get_secret}, }; +use axum::{ + extract::Extension, + http::StatusCode, + response::IntoResponse, + Json, +}; +use http::header::{HeaderMap, CONTENT_DISPOSITION, CONTENT_TYPE}; use qrcode_generator::QrCodeEcc; +use std::sync::Arc; +use totp_rs::{Algorithm, TOTP}; -async fn get_user_key(email: &String) -> Option { - let client = &DynamoDBClient.to_owned(); - - let key = "user_email".to_string(); - let user_av = AttributeValue::S(email.to_owned()); - - let table_name: String = KEY_MAP - .get(&"auth-table".to_string()) - .unwrap_or(&"auth-totp".to_string()) - .to_owned(); - - match client - .query() - .table_name(table_name) - .key_condition_expression("#key = :value".to_string()) - .expression_attribute_names("#key".to_string(), key) - .expression_attribute_values(":value".to_string(), user_av) - .select(Select::AllAttributes) - .send() - .await - { - Ok(resp) => { - if resp.count > 0 { - tracing::log::info!("User entry found in the table:"); - - let mut ans = None; - - let u = resp.items.unwrap(); - - ans = Some(u[0].get("secret").unwrap().as_s().unwrap().to_owned()); - - if ans.is_none() { - return None; - } - - return ans; - } else { - println!("not found in the table"); - return None; - } - } - Err(e) => { - eprintln!("error -> {}", e); - return None; - } - } -} +pub async fn verification( + Extension(db): Extension>, + Extension(config): Extension>, + Json(payload): Json, +) -> Result { + tracing::log::info!("verification of user"); -pub async fn verification(Json(payload): Json) -> impl IntoResponse { - tracing::log::info!("verfication of user"); + if !payload.is_valid(config.totp_size) { + return Err(Error::DbRecordNotFound); + } - if payload.is_valid() { - match get_user_key(&payload.email).await { - Some(secret) => { - println!(" payload:{payload:?}"); + let secret = db + .get_user_secret(&config.auth_table, &payload.email) + .await?; - let server_token = match get_secret(&secret) { - Ok(token) => token, - Err(_) => { - return (StatusCode::BAD_REQUEST, "bad format".to_string()); - } - }; + if let Some(secret) = secret { + let server_token = get_secret(&secret, config.key_size, config.totp_size)?; + if server_token == payload.token { + return Ok((StatusCode::ACCEPTED, format!("welcome : {}", payload.email))); + } + } - println!("server_tok:{server_token}"); + Err(Error::DbRecordNotFound) +} - if server_token == payload.token { - return (StatusCode::ACCEPTED, format!("welcome : {}", payload.email)); - } +pub async fn register_user( + Extension(db): Extension>, + Extension(config): Extension>, + Json(payload): Json, +) -> Result { + tracing::log::info!("registration of token"); - return (StatusCode::NOT_FOUND, "invalid user".to_string()); - } - None => { - return (StatusCode::NOT_FOUND, "invalid user".to_string()); - } - } + if !payload.is_valid() { + return Err(Error::DbRecordNotFound); } - return (StatusCode::BAD_REQUEST, "bad format".to_string()); -} -async fn discover_user(email: &String) -> Option<()> { - let email_av = AttributeValue::S(email.to_owned()); - let key = "user_email".to_string(); - - let client = &DynamoDBClient.to_owned(); - - let table_name: String = KEY_MAP - .get(&"auth-table".to_string()) - .unwrap_or(&"auth-totp".to_string()) - .to_owned(); - - match client - .query() - .table_name(table_name) - .key_condition_expression("#key = :value".to_string()) - .expression_attribute_names("#key".to_string(), key) - .expression_attribute_values(":value".to_string(), email_av) - .select(Select::AllAttributes) - .send() - .await - { - Ok(resp) => { - if resp.count > 0 { - tracing::log::info!("User entry is present in the table"); - return Some(()); - } else { - tracing::log::error!("User entry not found"); - return None; - } - } - Err(e) => { - tracing::log::info!("error querying the user record: {e}"); - return None; - } + let user_presence = db + .get_user_secret(&config.auth_table, &payload.email) + .await?; + + if user_presence.is_some() { + return Err(Error::DbRecordNotFound); } -} -async fn insert_user(email: &String, secret: &String) -> Option<()> { - let email_av = AttributeValue::S(email.to_owned()); - let secret_av = AttributeValue::S(secret.to_owned()); - - let client = &DynamoDBClient.to_owned(); - - let table_name: String = KEY_MAP - .get(&"auth-table".to_string()) - .unwrap_or(&"auth-totp".to_string()) - .to_owned(); - - let request = client - .put_item() - .table_name(table_name) - .item("user_email", email_av) - .item("secret", secret_av); - - match request.send().await { - Ok(output) => { - if output.attributes.is_none() { - println!("insertion succesfull"); - return Some(()); - } else { - println!("value already present"); - return None; - } - } - Err(_) => { - println!(" Insertion invalid"); - return None; - } - }; -} + let secret_key = generate_secret(config.key_size); -pub async fn register_user(Json(payload): Json) -> impl IntoResponse { - tracing::log::info!("registration of token"); - let mut hm = HeaderMap::new(); + let db_user = DbUser { + email: payload.email.clone(), + secret: secret_key.clone(), + }; - hm.insert(CONTENT_TYPE, "text/plain".parse().unwrap()); - - if payload.is_valid() { - //acquire the secret the key for the token registeration and insertion in database - let secret_key = generate_secret(); - println!("secret_key: {secret_key} payload:{payload:?}"); - let user_presence = discover_user(&payload.email).await; - - if user_presence.is_some() { - return ( - hm, - "unauthorized insertion" - .to_string() - .chars() - .map(|x| x as u8) - .collect::>(), - ); - } + db.insert_user(&config.auth_table, &db_user).await?; - let db_state_update = insert_user(&payload.email, &secret_key).await; - //perform the insertion in the database - match db_state_update { - None => { - //return the error if value is already found - return ( - hm, - "insertion invalid" - .to_string() - .chars() - .map(|x| x as u8) - .collect::>(), - ); - } - Some(_) => { - //otherwise insert the value in DB - tracing::log::info!("insertion succesfull"); - } - } + let totp = TOTP::new( + Algorithm::SHA1, + config.totp_size as usize, + 0, + config.step_size, + secret_key.clone(), + Some("Rust server".to_string()), + payload.email, + ) + .map_err(|_| Error::TotpError)?; - let totp = match TOTP::new( - Algorithm::SHA1, - get_totp_size_value() as usize, - 0, - get_step_size_value(), - secret_key.clone(), - Some("Rust server".to_string()), - payload.email, - ) { - Ok(totp) => totp, - Err(_) => { - return ( - hm, - "insertion invalid" - .to_string() - .chars() - .map(|x| x as u8) - .collect::>(), - ); - } - }; - - //get the QR in the form of vec - let result: Vec = - qrcode_generator::to_png_to_vec(totp.get_url(), QrCodeEcc::Low, 240).unwrap(); - - hm.insert(CONTENT_TYPE, "image/png ; base64".parse().unwrap()); - //hm.insert(CONTENT_ENCODING, "base64".parse().unwrap()); - hm.insert( - CONTENT_DISPOSITION, - "attachment; filename=\"qr.png\"".parse().unwrap(), - ); - - return (hm, result); - } + let result: Vec = qrcode_generator::to_png_to_vec(totp.get_url(), QrCodeEcc::Low, 240)?; - return ( - hm, - "insertion invalid" - .to_string() - .chars() - .map(|x| x as u8) - .collect::>(), + let mut hm = HeaderMap::new(); + hm.insert(CONTENT_TYPE, "image/png ; base64".parse()?); + hm.insert( + CONTENT_DISPOSITION, + "attachment; filename=\"qr.png\"".parse()?, ); + + Ok((hm, result)) } diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..afd4545 --- /dev/null +++ b/src/config.rs @@ -0,0 +1,27 @@ +use serde::Deserialize; + +#[derive(Debug, Deserialize, Clone)] +pub struct Config { + pub aws_region: String, + pub aws_region_url: String, + pub db_access_key: String, + pub db_secret_access_key: String, + pub auth_table: String, + #[serde(rename = "KEY_SIZE")] + pub key_size: usize, + #[serde(rename = "STEP_SIZE")] + pub step_size: u64, + #[serde(rename = "TOTP_SIZE")] + pub totp_size: u32, +} + +impl Config { + pub fn from_env() -> Result { + let cfg = config::Config::builder() + .add_source(config::File::with_name("./settings.toml")) + .add_source(config::Environment::with_prefix("APP")) + .build()?; + + cfg.try_deserialize() + } +} diff --git a/src/db.rs b/src/db.rs index c9435b3..ba10150 100644 --- a/src/db.rs +++ b/src/db.rs @@ -1,54 +1,85 @@ -use aws_sdk_dynamodb::{Client, Endpoint, Region}; +use aws_sdk_dynamodb::{ + model::{AttributeValue, Select}, + Client, Endpoint, Region, +}; use aws_types::Credentials; use http::Uri; -use once_cell::sync::Lazy; - -use crate::obj::KEY_MAP; - -pub static DynamoDBClient: Lazy = Lazy::new(|| { - let region = KEY_MAP - .get(&"aws-region".to_string()) - .unwrap_or(&"ap-south-1".to_string()) - .to_owned(); - - let url = KEY_MAP - .get(&"aws-region-url".to_string()) - .unwrap_or(&format!("https://dynamodb.{}.amazonaws.com/", region)) - .to_owned() - .parse::() - .unwrap(); - - let db_key = match KEY_MAP.get(&"db-access-key".to_string()) { - Some(v) => { - tracing::log::info!("access key present"); - v - } - None => { - tracing::log::warn!("access key is not present"); - panic!(); - } - }; +use serde::{Deserialize, Serialize}; - let db_sec = match KEY_MAP.get(&"db-secret-access-key".to_string()) { - Some(v) => { - tracing::log::info!("secret key present"); - v - } - None => { - tracing::log::warn!("secret key is not present"); - panic!(); - } - }; +use crate::config::Config; +use crate::error::Result; + +#[derive(Clone)] +pub struct Db { + pub client: Client, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct DbUser { + pub email: String, + pub secret: String, +} + +impl Db { + pub async fn new(config: &Config) -> Result { + let creds = Credentials::from_keys( + config.db_access_key.clone(), + config.db_secret_access_key.clone(), + None, + ); - let creds = Credentials::from_keys(db_key, db_sec, None); + let dynamodb_local_config = aws_sdk_dynamodb::config::Builder::new() + .credentials_provider(creds) + .region(Region::new(config.aws_region.clone())) + .endpoint_resolver(Endpoint::immutable( + config.aws_region_url.clone().parse::()?, + )) + .build(); + + let client = Client::from_conf(dynamodb_local_config); + + Ok(Self { client }) + } + + pub async fn get_user_secret(&self, table_name: &str, email: &str) -> Result> { + let key = "user_email".to_string(); + let user_av = AttributeValue::S(email.to_owned()); + + let res = self + .client + .query() + .table_name(table_name) + .key_condition_expression("#key = :value".to_string()) + .expression_attribute_names("#key".to_string(), key) + .expression_attribute_values(":value".to_string(), user_av) + .select(Select::AllAttributes) + .send() + .await?; + + if let Some(items) = res.items { + if !items.is_empty() { + if let Some(secret_av) = items[0].get("secret") { + if let Ok(secret) = secret_av.as_s() { + return Ok(Some(secret.to_string())); + } + } + } + } + Ok(None) + } - let dynamodb_local_config = aws_sdk_dynamodb::config::Builder::new() - .credentials_provider(creds) - .region(Region::new(region)) - .endpoint_resolver(Endpoint::immutable(url)) - .build(); + pub async fn insert_user(&self, table_name: &str, user: &DbUser) -> Result<()> { + let email_av = AttributeValue::S(user.email.clone()); + let secret_av = AttributeValue::S(user.secret.clone()); - let client = Client::from_conf(dynamodb_local_config); + self.client + .put_item() + .table_name(table_name) + .item("user_email", email_av) + .item("secret", secret_av) + .send() + .await?; - return client; -}); + Ok(()) + } +} diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 0000000..cbdfba5 --- /dev/null +++ b/src/error.rs @@ -0,0 +1,86 @@ +use axum::{ + http::StatusCode, + response::{IntoResponse, Response}, +}; +use aws_sdk_dynamodb::error::{PutItemError, QueryError}; +use aws_sdk_dynamodb::types::SdkError; + +pub type Result = std::result::Result; + +#[derive(Debug)] +pub enum Error { + Config(config::ConfigError), + DynamoDb(aws_sdk_dynamodb::Error), + InvalidUri(http::uri::InvalidUri), + DbRecordNotFound, + Bcrypt(bcrypt::BcryptError), + Paseto, + TotpError, + ChronoParse(chrono::format::ParseError), + QrError(String), + InvalidHeaderValue(http::header::InvalidHeaderValue), + DynamoDbQuery(SdkError), + DynamoDbPutItem(SdkError), +} + +impl IntoResponse for Error { + fn into_response(self) -> Response { + tracing::error!("Error: {:?}", self); + (StatusCode::INTERNAL_SERVER_ERROR, "UNHANDLED_CLIENT_ERROR").into_response() + } +} + +impl From for Error { + fn from(err: config::ConfigError) -> Self { + Error::Config(err) + } +} + +impl From for Error { + fn from(err: aws_sdk_dynamodb::Error) -> Self { + Error::DynamoDb(err) + } +} + +impl From for Error { + fn from(err: http::uri::InvalidUri) -> Self { + Error::InvalidUri(err) + } +} + +impl From for Error { + fn from(err: bcrypt::BcryptError) -> Self { + Error::Bcrypt(err) + } +} + +impl From for Error { + fn from(err: chrono::format::ParseError) -> Self { + Error::ChronoParse(err) + } +} + +use qrcode_generator::QRCodeError; +impl From for Error { + fn from(err: QRCodeError) -> Self { + Error::QrError(err.to_string()) + } +} + +impl From for Error { + fn from(err: http::header::InvalidHeaderValue) -> Self { + Error::InvalidHeaderValue(err) + } +} + +impl From> for Error { + fn from(err: SdkError) -> Self { + Error::DynamoDbQuery(err) + } +} + +impl From> for Error { + fn from(err: SdkError) -> Self { + Error::DynamoDbPutItem(err) + } +} diff --git a/src/eval_constants.rs b/src/eval_constants.rs deleted file mode 100644 index 9ace864..0000000 --- a/src/eval_constants.rs +++ /dev/null @@ -1,71 +0,0 @@ -use crate::obj::FILE_PATH; -use crate::obj::KEY_MAP; - -pub fn get_key_size_value() -> usize { - lazy_static! { - pub static ref VALUE: String = match KEY_MAP.get("KEY_SIZE") { - Some(v) => v.to_owned(), - None => { - tracing::log::error!("KEY_SIZE value not present in the : {}", FILE_PATH); - panic!(); - } - }; - pub static ref KEY_SIZE: usize = match VALUE.parse::() { - Ok(v) => v, - Err(e) => { - tracing::log::error!( - "Invalid value found under KEY_SIZE param in {FILE_PATH} file" - ); - panic!("{e}"); - } - }; - } - - return *KEY_SIZE; -} - -pub fn get_step_size_value() -> u64 { - lazy_static! { - pub static ref VALUE: String = match KEY_MAP.get("STEP_SIZE") { - Some(v) => v.to_owned(), - None => { - tracing::log::error!("KEY_SIZE value not present in the : {}", FILE_PATH); - panic!(); - } - }; - pub static ref STEP_SIZE: u64 = match VALUE.parse::() { - Ok(v) => v, - Err(e) => { - tracing::log::error!( - "Invalid value found under KEY_SIZE param in {FILE_PATH} file" - ); - panic!("{e}"); - } - }; - } - - return *STEP_SIZE; -} - -pub fn get_totp_size_value() -> u32 { - lazy_static! { - pub static ref VALUE: String = match KEY_MAP.get("TOTP_SIZE") { - Some(v) => v.to_owned(), - None => { - tracing::log::error!("KEY_SIZE value not present in the : {}", FILE_PATH); - panic!(); - } - }; - pub static ref STEP_SIZE: u32 = match VALUE.parse::() { - Ok(v) => v, - Err(e) => { - tracing::log::error!( - "Invalid value found under KEY_SIZE param in {FILE_PATH} file" - ); - panic!("{e}"); - } - }; - } - - return *STEP_SIZE; -} diff --git a/src/main.rs b/src/main.rs index a86c5db..5eba97e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,34 +1,40 @@ use axum::{routing::get, Router}; - -#[macro_use] -extern crate lazy_static; //crate required for using lazy_static! macro - -extern crate rand; +use std::sync::Arc; mod auth; +mod config; mod db; -mod eval_constants; +mod error; mod obj; mod operation; mod test; -use crate::auth::{authentication, otp_verification, register_user, verification}; +use crate::{ + auth::{register_user, verification}, + config::Config, + db::Db, +}; #[tokio::main] async fn main() { tracing_subscriber::fmt::init(); + let config = Config::from_env().expect("failed to load config"); + let db = Db::new(&config).await.expect("failed to connect to db"); + + let shared_state = Arc::new(db); + let config_state = Arc::new(config); + // setup the routes which will going to be passed to the respective debug assertion let app = Router::new() .route("/signin", get(register_user)) .route("/login", get(verification)) - .route("/verify", get(otp_verification)) - .route("/authorize", get(authentication)); + .layer(axum::extract::Extension(shared_state)) + .layer(axum::extract::Extension(config_state)); #[cfg(debug_assertions)] // select the following block if the --release flag is not present { axum::Server::bind(&"0.0.0.0:3000".parse().unwrap()) - .http2_enable_connect_protocol() //enable http2 connection procedure for the axum server .serve(app.into_make_service()) //serve our application on this route .await .unwrap(); diff --git a/src/obj.rs b/src/obj.rs index 5796c6c..6d77f6c 100644 --- a/src/obj.rs +++ b/src/obj.rs @@ -1,47 +1,11 @@ -use std::collections::HashMap; - -use config::Config; use once_cell::sync::Lazy; use regex::Regex; use serde::{Deserialize, Serialize}; -use crate::eval_constants::get_totp_size_value; //================================================================================================================== -pub const FILE_PATH: &str = "./settings.toml"; - -pub static KEY_MAP: Lazy> = Lazy::new(|| { - let settings = match Config::builder() - // Add in `./Settings.toml` - .add_source(config::File::with_name(FILE_PATH)) - // Add in settings from the environment (with a prefix of APP) - // Eg.. `APP_DEBUG=1 ./target/app` would set the `debug` key - .add_source(config::Environment::with_prefix("APP")) - .build() - { - Ok(v) => { - tracing::log::info!("settings.toml read"); - v - } - Err(e) => { - tracing::log::error!("cannot open the file: {}", e); - panic!(); - } - }; - - let hm = match settings.try_deserialize::>() { - Ok(v) => { - tracing::log::info!("deserialization succesfull"); - v - } - Err(e) => { - tracing::log::error!("error deserialization of values: {}", e); - panic!(); - } - }; - - return hm; -}); +static EMAIL_REGEX: Lazy = + Lazy::new(|| Regex::new(r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)").unwrap()); //================================================================================================================== #[derive(Debug, Serialize, Deserialize)] @@ -51,19 +15,16 @@ pub struct VerifyUser { } impl VerifyUser { - pub fn is_valid(&self) -> bool { + pub fn is_valid(&self, totp_size: u32) -> bool { if self.email.is_empty() || self.token.is_empty() { return false; } - if self.token.chars().count() != (get_totp_size_value() as usize) { + if self.token.chars().count() != (totp_size as usize) { return false; } - lazy_static! {//todo evaluate the email constrain too - static ref RE: Regex = Regex::new(r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)").unwrap(); - } - RE.is_match(self.email.as_str()) + EMAIL_REGEX.is_match(self.email.as_str()) } } //================================================================================================================== @@ -78,11 +39,7 @@ impl User { return false; } - lazy_static! {//todo evaluate the email constrain too - static ref RE: Regex = Regex::new(r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)").unwrap(); - } - - let res = (*RE).is_match(&self.email); + let res = EMAIL_REGEX.is_match(&self.email); println!("called validation on email: {res}"); return res; } diff --git a/src/operation.rs b/src/operation.rs index 2f8f331..fa2b44c 100644 --- a/src/operation.rs +++ b/src/operation.rs @@ -1,20 +1,14 @@ -use std::{str::FromStr, time::SystemTime}; -use totp_lite::{totp_custom, Sha1, DEFAULT_STEP}; - +use crate::error::{Error, Result}; use rand::distributions::Alphanumeric; use rand::Rng; - -use crate::{ - eval_constants::{get_key_size_value, get_totp_size_value}, - obj::KEY_MAP, -}; +use std::time::SystemTime; +use totp_lite::{totp_custom, Sha1, DEFAULT_STEP}; //return a random set of string which we can use to create a QR code -pub fn generate_secret() -> String { - // const STR_LEN: usize = 10; - let rand_str = rand::thread_rng() +pub fn generate_secret(key_size: usize) -> String { + let rand_str: String = rand::thread_rng() .sample_iter(&Alphanumeric) - .take(get_key_size_value()) + .take(key_size) .map(char::from) .collect(); @@ -22,18 +16,18 @@ pub fn generate_secret() -> String { } //create the on time based OTP out of the given secret -pub fn get_secret(input: &String) -> Result { +pub fn get_secret(input: &str, key_size: usize, totp_size: u32) -> Result { let length = input.trim().chars().count(); - if length != (get_key_size_value()) { + if length != key_size { tracing::log::error!("Invalid TOTP secret key size "); - return Err(()); + return Err(Error::Paseto); // Using Paseto error for now, will create a better error later } // The number of seconds since the Unix Epoch, used to calcuate a TOTP secret. let seconds: u64 = SystemTime::now() .duration_since(SystemTime::UNIX_EPOCH) - .unwrap() + .map_err(|_| Error::Paseto)? // Using Paseto error for now .as_secs(); let base = input.as_bytes().to_vec(); @@ -43,102 +37,68 @@ pub fn get_secret(input: &String) -> Result { // Calculate a new code every 30 seconds. DEFAULT_STEP, // Calculate a 6 digit code. - get_totp_size_value(), + totp_size, // Convert the secret into bytes using base32::decode(). &base, // Seconds since the Unix Epoch. seconds, ); - return Ok(token); + Ok(token) } -pub fn get_hash(client_secret: &String) -> String { - let hash = match bcrypt::hash(client_secret.as_ref() as &str, 5) { - Ok(f) => f, - Err(e) => { - tracing::log::error!("error in creating a hash of client secret: {}", e); - panic!(); - } - }; - - hash +pub fn get_hash(client_secret: &str) -> Result { + let hash = bcrypt::hash(client_secret, 5)?; + Ok(hash) } -pub fn generate_token(data: &String, encrypt_key: &String, nonce_key: &String) -> Result { +pub fn generate_token(data: &str, encrypt_key: &str, nonce_key: &str) -> Result { use rusty_paseto::core::*; let key = PasetoSymmetricKey::::from( - Key::<32>::try_from( - encrypt_key.as_str(), - ) - .unwrap(), + Key::<32>::try_from(encrypt_key).map_err(|_| Error::Paseto)?, ); - let nonce = Key::<32>::try_from( - nonce_key.as_str(), - ) - .unwrap(); - // let nonce = Key::<32>::try_new_random().unwrap(); + let nonce = Key::<32>::try_from(nonce_key).map_err(|_| Error::Paseto)?; let paseto_nonce = PasetoNonce::::from(&nonce); - let payload = Payload::from(data.as_str()); + let payload = Payload::from(data); - let token = match Paseto::::builder() + let token = Paseto::::builder() .set_payload(payload) .try_encrypt(&key, &paseto_nonce) - { - Ok(v) => v, - Err(e) => { - tracing::log::error!(" generate token error: {e}"); - return Err(()); - } - }; - - return Ok(token.to_string()); + .map_err(|_| Error::Paseto)?; + + Ok(token.to_string()) } -pub fn validate_token(prev_utc: &str, mins: u8) -> bool { +pub fn validate_token(prev_utc: &str, mins: u8) -> Result { + let prev_time = chrono::DateTime::parse_from_rfc3339(prev_utc)?; - let prev_time = chrono::DateTime::from_str(prev_utc).unwrap(); + let duration = chrono::Utc::now().signed_duration_since(prev_time); - let duration = chrono::Utc::now() - prev_time; - - let time = 60 * (mins as i64); + let time = 60 * (mins as i64); if duration < chrono::Duration::seconds(time) { - return true; + return Ok(true); } - return false; + Ok(false) } -pub fn decrypt_token(token: &String, encrypt_key: &String) -> Result { - let get_key = match rusty_paseto::prelude::Key::<32>::try_from( - encrypt_key.as_str() - ) { - Ok(v) => v, - Err(e) => { - tracing::log::error!(" key generation error : {e}"); - return Err(()); - } - }; +pub fn decrypt_token(token: &str, encrypt_key: &str) -> Result { + let get_key = + rusty_paseto::prelude::Key::<32>::try_from(encrypt_key).map_err(|_| Error::Paseto)?; let key = rusty_paseto::prelude::PasetoSymmetricKey::< rusty_paseto::prelude::V4, rusty_paseto::prelude::Local, >::from(get_key); - let val = match rusty_paseto::prelude::Paseto::< + let val = rusty_paseto::prelude::Paseto::< rusty_paseto::prelude::V4, rusty_paseto::prelude::Local, >::try_decrypt(token, &key, None, None) - { - Ok(v) => v, - Err(e) => { - tracing::log::error!(" decryption error: {e} "); - return Err(()); - } - }; - - return Ok(val); + .map_err(|_| Error::Paseto)?; + + Ok(val) } diff --git a/src/test.rs b/src/test.rs index cfbb5d6..3e65310 100644 --- a/src/test.rs +++ b/src/test.rs @@ -1,19 +1,17 @@ #[cfg(test)] mod tests { use crate::{ - obj::{VerifyUser, KEY_MAP}, + obj::VerifyUser, operation::{generate_secret, get_secret}, }; + const KEY_SIZE: usize = 10; + const TOTP_SIZE: u32 = 6; + #[test] fn totp_key_attribute() { - let rand_secret = generate_secret(); - let key_size = KEY_MAP - .get(&"KEY_SIZE".to_string()) - .expect("key not found") - .parse::() - .unwrap(); - assert_eq!(rand_secret.chars().count(), key_size); + let rand_secret = generate_secret(KEY_SIZE); + assert_eq!(rand_secret.chars().count(), KEY_SIZE); for ch in rand_secret.chars() { assert!(ch.is_alphanumeric()); } @@ -74,32 +72,28 @@ mod tests { ]; for v in verify_user.iter() { - assert_eq!(v.0.is_valid(), v.1); + assert_eq!(v.0.is_valid(TOTP_SIZE), v.1); } } - // #[test] - // #[should_panic(expected = "invalid secret based totp generation call")] - // fn validate_totp() { - // let secret = generate_secret(); - // let totp = get_secret(&secret).unwrap(); - // let totp_vec = vec![ - // ("aaabbbccc".to_string(), true), - // ("aaa$bbccc".to_string(), false), - // ("aaa12bccc".to_string(), true), - // ("aaa12#ccc".to_string(), false), - // ("aaabbbcccd".to_string(), false), - // ("aaabbbccc*1".to_string(), false), - // ("12345678".to_string(), true), - // ("123456789".to_string(), false), - // ("".to_string(), false), - // ]; + #[test] + fn validate_totp() { + let totp_vec = vec![ + ("aaabbbccc1".to_string(), true), + ("aaabbbccc".to_string(), false), + ("aaa$bbccc".to_string(), false), + ("aaa12bccc1".to_string(), true), + ("aaa12#ccc".to_string(), false), + ("aaabbbcccd".to_string(), true), + ("aaabbbccc*1".to_string(), false), + ("1234567890".to_string(), true), + ("123456789".to_string(), false), + ("".to_string(), false), + ]; - // for I in totp_vec.iter() { - // let totp_sec = get_secret(&(I.0)); - // if totp_sec.is_ok() { - // let _ = totp_sec.unwrap(); - // } - // } - // } + for i in totp_vec.iter() { + let totp_sec = get_secret(&i.0, KEY_SIZE, TOTP_SIZE); + assert_eq!(totp_sec.is_ok(), i.1); + } + } }