start working on generalizing credential logic
This commit is contained in:
parent
0491cb5790
commit
d0a2532c27
4
.gitignore
vendored
4
.gitignore
vendored
@ -5,7 +5,3 @@ src-tauri/target/
|
|||||||
# .env is system-specific
|
# .env is system-specific
|
||||||
.env
|
.env
|
||||||
.vscode
|
.vscode
|
||||||
|
|
||||||
# just in case
|
|
||||||
credentials*
|
|
||||||
!credentials.rs
|
|
||||||
|
590
src-tauri/Cargo.lock
generated
590
src-tauri/Cargo.lock
generated
@ -27,6 +27,31 @@ dependencies = [
|
|||||||
"generic-array",
|
"generic-array",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aes"
|
||||||
|
version = "0.8.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cipher",
|
||||||
|
"cpufeatures",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aes-gcm"
|
||||||
|
version = "0.10.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1"
|
||||||
|
dependencies = [
|
||||||
|
"aead",
|
||||||
|
"aes",
|
||||||
|
"cipher",
|
||||||
|
"ctr",
|
||||||
|
"ghash",
|
||||||
|
"subtle",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ahash"
|
name = "ahash"
|
||||||
version = "0.7.6"
|
version = "0.7.6"
|
||||||
@ -296,9 +321,9 @@ checksum = "ecc7ab41815b3c653ccd2978ec3255c81349336702dfdf62ee6f7069b12a3aae"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-trait"
|
name = "async-trait"
|
||||||
version = "0.1.73"
|
version = "0.1.80"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0"
|
checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -653,6 +678,12 @@ dependencies = [
|
|||||||
"rustc-demangle",
|
"rustc-demangle",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base16ct"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "base64"
|
name = "base64"
|
||||||
version = "0.21.4"
|
version = "0.21.4"
|
||||||
@ -680,6 +711,17 @@ version = "1.6.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
|
checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bcrypt-pbkdf"
|
||||||
|
version = "0.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6aeac2e1fe888769f34f05ac343bbef98b14d1ffb292ab69d4608b3abc86f2a2"
|
||||||
|
dependencies = [
|
||||||
|
"blowfish",
|
||||||
|
"pbkdf2",
|
||||||
|
"sha2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "1.3.2"
|
version = "1.3.2"
|
||||||
@ -719,6 +761,15 @@ dependencies = [
|
|||||||
"generic-array",
|
"generic-array",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "block-padding"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "block2"
|
name = "block2"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
@ -743,6 +794,16 @@ dependencies = [
|
|||||||
"log",
|
"log",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "blowfish"
|
||||||
|
version = "0.9.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e412e2cd0f2b2d93e02543ceae7917b3c70331573df19ee046bcbc35e45e87d7"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
"cipher",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "brotli"
|
name = "brotli"
|
||||||
version = "3.3.4"
|
version = "3.3.4"
|
||||||
@ -868,6 +929,15 @@ dependencies = [
|
|||||||
"toml 0.8.2",
|
"toml 0.8.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cbc"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6"
|
||||||
|
dependencies = [
|
||||||
|
"cipher",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.83"
|
version = "1.0.83"
|
||||||
@ -1053,6 +1123,12 @@ dependencies = [
|
|||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "const-oid"
|
||||||
|
version = "0.9.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "convert_case"
|
name = "convert_case"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
@ -1150,8 +1226,11 @@ dependencies = [
|
|||||||
"rfd",
|
"rfd",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"signature 2.2.0",
|
||||||
"sodiumoxide",
|
"sodiumoxide",
|
||||||
"sqlx",
|
"sqlx",
|
||||||
|
"ssh-agent-lib",
|
||||||
|
"ssh-key",
|
||||||
"strum",
|
"strum",
|
||||||
"strum_macros",
|
"strum_macros",
|
||||||
"sysinfo",
|
"sysinfo",
|
||||||
@ -1219,6 +1298,18 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crypto-bigint"
|
||||||
|
version = "0.5.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
"rand_core 0.6.4",
|
||||||
|
"subtle",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crypto-common"
|
name = "crypto-common"
|
||||||
version = "0.1.6"
|
version = "0.1.6"
|
||||||
@ -1267,6 +1358,42 @@ dependencies = [
|
|||||||
"syn 2.0.66",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ctr"
|
||||||
|
version = "0.9.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835"
|
||||||
|
dependencies = [
|
||||||
|
"cipher",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "curve25519-dalek"
|
||||||
|
version = "4.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cpufeatures",
|
||||||
|
"curve25519-dalek-derive",
|
||||||
|
"digest",
|
||||||
|
"fiat-crypto",
|
||||||
|
"platforms",
|
||||||
|
"rustc_version",
|
||||||
|
"subtle",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[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.66",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "darling"
|
name = "darling"
|
||||||
version = "0.20.3"
|
version = "0.20.3"
|
||||||
@ -1302,6 +1429,16 @@ dependencies = [
|
|||||||
"syn 2.0.66",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "der"
|
||||||
|
version = "0.7.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0"
|
||||||
|
dependencies = [
|
||||||
|
"const-oid",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deranged"
|
name = "deranged"
|
||||||
version = "0.3.11"
|
version = "0.3.11"
|
||||||
@ -1343,6 +1480,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"block-buffer",
|
"block-buffer",
|
||||||
|
"const-oid",
|
||||||
"crypto-common",
|
"crypto-common",
|
||||||
"subtle",
|
"subtle",
|
||||||
]
|
]
|
||||||
@ -1489,13 +1627,48 @@ version = "1.0.17"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125"
|
checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ecdsa"
|
||||||
|
version = "0.16.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca"
|
||||||
|
dependencies = [
|
||||||
|
"der",
|
||||||
|
"digest",
|
||||||
|
"elliptic-curve",
|
||||||
|
"rfc6979",
|
||||||
|
"signature 2.2.0",
|
||||||
|
"spki",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ed25519"
|
name = "ed25519"
|
||||||
version = "1.5.3"
|
version = "1.5.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7"
|
checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"signature",
|
"signature 1.6.4",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ed25519"
|
||||||
|
version = "2.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53"
|
||||||
|
dependencies = [
|
||||||
|
"signature 2.2.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ed25519-dalek"
|
||||||
|
version = "2.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1f628eaec48bfd21b865dc2950cfa014450c01d2fa2b69a86c2fd5844ec523c0"
|
||||||
|
dependencies = [
|
||||||
|
"curve25519-dalek",
|
||||||
|
"ed25519 2.2.3",
|
||||||
|
"sha2",
|
||||||
|
"subtle",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1504,6 +1677,25 @@ version = "1.9.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "elliptic-curve"
|
||||||
|
version = "0.13.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47"
|
||||||
|
dependencies = [
|
||||||
|
"base16ct",
|
||||||
|
"crypto-bigint",
|
||||||
|
"digest",
|
||||||
|
"ff",
|
||||||
|
"generic-array",
|
||||||
|
"group",
|
||||||
|
"pkcs8",
|
||||||
|
"rand_core 0.6.4",
|
||||||
|
"sec1",
|
||||||
|
"subtle",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "embed-resource"
|
name = "embed-resource"
|
||||||
version = "2.3.0"
|
version = "2.3.0"
|
||||||
@ -1649,6 +1841,22 @@ dependencies = [
|
|||||||
"simd-adler32",
|
"simd-adler32",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ff"
|
||||||
|
version = "0.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449"
|
||||||
|
dependencies = [
|
||||||
|
"rand_core 0.6.4",
|
||||||
|
"subtle",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fiat-crypto"
|
||||||
|
version = "0.2.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1676f435fc1dadde4d03e43f5d62b259e1ce5f40bd4ffb21db2b42ebe59c1382"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "field-offset"
|
name = "field-offset"
|
||||||
version = "0.3.6"
|
version = "0.3.6"
|
||||||
@ -1755,10 +1963,25 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-channel"
|
name = "futures"
|
||||||
version = "0.3.28"
|
version = "0.3.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2"
|
checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0"
|
||||||
|
dependencies = [
|
||||||
|
"futures-channel",
|
||||||
|
"futures-core",
|
||||||
|
"futures-executor",
|
||||||
|
"futures-io",
|
||||||
|
"futures-sink",
|
||||||
|
"futures-task",
|
||||||
|
"futures-util",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-channel"
|
||||||
|
version = "0.3.30"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-sink",
|
"futures-sink",
|
||||||
@ -1766,15 +1989,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-core"
|
name = "futures-core"
|
||||||
version = "0.3.28"
|
version = "0.3.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c"
|
checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-executor"
|
name = "futures-executor"
|
||||||
version = "0.3.28"
|
version = "0.3.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0"
|
checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-task",
|
"futures-task",
|
||||||
@ -1794,9 +2017,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-io"
|
name = "futures-io"
|
||||||
version = "0.3.28"
|
version = "0.3.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964"
|
checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-lite"
|
name = "futures-lite"
|
||||||
@ -1830,9 +2053,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-macro"
|
name = "futures-macro"
|
||||||
version = "0.3.28"
|
version = "0.3.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
|
checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -1841,22 +2064,23 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-sink"
|
name = "futures-sink"
|
||||||
version = "0.3.28"
|
version = "0.3.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e"
|
checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-task"
|
name = "futures-task"
|
||||||
version = "0.3.28"
|
version = "0.3.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65"
|
checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-util"
|
name = "futures-util"
|
||||||
version = "0.3.28"
|
version = "0.3.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533"
|
checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-io",
|
"futures-io",
|
||||||
"futures-macro",
|
"futures-macro",
|
||||||
@ -1997,6 +2221,7 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"typenum",
|
"typenum",
|
||||||
"version_check",
|
"version_check",
|
||||||
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -2021,6 +2246,16 @@ dependencies = [
|
|||||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ghash"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1"
|
||||||
|
dependencies = [
|
||||||
|
"opaque-debug",
|
||||||
|
"polyval",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gimli"
|
name = "gimli"
|
||||||
version = "0.28.0"
|
version = "0.28.0"
|
||||||
@ -2141,6 +2376,17 @@ dependencies = [
|
|||||||
"system-deps",
|
"system-deps",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "group"
|
||||||
|
version = "0.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63"
|
||||||
|
dependencies = [
|
||||||
|
"ff",
|
||||||
|
"rand_core 0.6.4",
|
||||||
|
"subtle",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gtk"
|
name = "gtk"
|
||||||
version = "0.18.1"
|
version = "0.18.1"
|
||||||
@ -2538,6 +2784,7 @@ version = "0.1.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
|
checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"block-padding",
|
||||||
"generic-array",
|
"generic-array",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -2682,6 +2929,9 @@ name = "lazy_static"
|
|||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
dependencies = [
|
||||||
|
"spin 0.5.2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libappindicator"
|
name = "libappindicator"
|
||||||
@ -2723,6 +2973,12 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libm"
|
||||||
|
version = "0.2.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libsodium-sys"
|
name = "libsodium-sys"
|
||||||
version = "0.2.7"
|
version = "0.2.7"
|
||||||
@ -2996,6 +3252,23 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-bigint-dig"
|
||||||
|
version = "0.8.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
"lazy_static",
|
||||||
|
"libm",
|
||||||
|
"num-integer",
|
||||||
|
"num-iter",
|
||||||
|
"num-traits",
|
||||||
|
"rand 0.8.5",
|
||||||
|
"smallvec",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-integer"
|
name = "num-integer"
|
||||||
version = "0.1.45"
|
version = "0.1.45"
|
||||||
@ -3006,6 +3279,17 @@ dependencies = [
|
|||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-iter"
|
||||||
|
version = "0.1.44"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.2.16"
|
version = "0.2.16"
|
||||||
@ -3013,6 +3297,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2"
|
checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
|
"libm",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -3245,6 +3530,44 @@ version = "0.1.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
|
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "p256"
|
||||||
|
version = "0.13.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b"
|
||||||
|
dependencies = [
|
||||||
|
"ecdsa",
|
||||||
|
"elliptic-curve",
|
||||||
|
"primeorder",
|
||||||
|
"sha2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "p384"
|
||||||
|
version = "0.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "70786f51bcc69f6a4c0360e063a4cac5419ef7c5cd5b3c99ad70f3be5ba79209"
|
||||||
|
dependencies = [
|
||||||
|
"ecdsa",
|
||||||
|
"elliptic-curve",
|
||||||
|
"primeorder",
|
||||||
|
"sha2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "p521"
|
||||||
|
version = "0.13.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0fc9e2161f1f215afdfce23677034ae137bbd45016a880c2eb3ba8eb95f085b2"
|
||||||
|
dependencies = [
|
||||||
|
"base16ct",
|
||||||
|
"ecdsa",
|
||||||
|
"elliptic-curve",
|
||||||
|
"primeorder",
|
||||||
|
"rand_core 0.6.4",
|
||||||
|
"sha2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pango"
|
name = "pango"
|
||||||
version = "0.18.3"
|
version = "0.18.3"
|
||||||
@ -3341,6 +3664,24 @@ version = "1.0.14"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
|
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pbkdf2"
|
||||||
|
version = "0.12.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2"
|
||||||
|
dependencies = [
|
||||||
|
"digest",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pem-rfc7468"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412"
|
||||||
|
dependencies = [
|
||||||
|
"base64ct",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "percent-encoding"
|
name = "percent-encoding"
|
||||||
version = "2.3.0"
|
version = "2.3.0"
|
||||||
@ -3513,12 +3854,39 @@ version = "0.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pkcs1"
|
||||||
|
version = "0.7.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f"
|
||||||
|
dependencies = [
|
||||||
|
"der",
|
||||||
|
"pkcs8",
|
||||||
|
"spki",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pkcs8"
|
||||||
|
version = "0.10.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7"
|
||||||
|
dependencies = [
|
||||||
|
"der",
|
||||||
|
"spki",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pkg-config"
|
name = "pkg-config"
|
||||||
version = "0.3.27"
|
version = "0.3.27"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
|
checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "platforms"
|
||||||
|
version = "3.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "626dec3cac7cc0e1577a2ec3fc496277ec2baa084bebad95bb6fdbfae235f84c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "plist"
|
name = "plist"
|
||||||
version = "1.5.0"
|
version = "1.5.0"
|
||||||
@ -3577,6 +3945,18 @@ dependencies = [
|
|||||||
"universal-hash",
|
"universal-hash",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "polyval"
|
||||||
|
version = "0.6.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cpufeatures",
|
||||||
|
"opaque-debug",
|
||||||
|
"universal-hash",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "powerfmt"
|
name = "powerfmt"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
@ -3595,6 +3975,15 @@ version = "0.1.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
|
checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "primeorder"
|
||||||
|
version = "0.13.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6"
|
||||||
|
dependencies = [
|
||||||
|
"elliptic-curve",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro-crate"
|
name = "proc-macro-crate"
|
||||||
version = "1.3.1"
|
version = "1.3.1"
|
||||||
@ -3753,6 +4142,15 @@ dependencies = [
|
|||||||
"rand_core 0.5.1",
|
"rand_core 0.5.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "raunch"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1a67226789ccd419c55f5c826e04f7d58690b0593364f61bc8ed6e7dbbab49c5"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "raw-window-handle"
|
name = "raw-window-handle"
|
||||||
version = "0.5.2"
|
version = "0.5.2"
|
||||||
@ -3906,6 +4304,16 @@ dependencies = [
|
|||||||
"winreg 0.52.0",
|
"winreg 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rfc6979"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2"
|
||||||
|
dependencies = [
|
||||||
|
"hmac",
|
||||||
|
"subtle",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rfd"
|
name = "rfd"
|
||||||
version = "0.14.1"
|
version = "0.14.1"
|
||||||
@ -3944,6 +4352,27 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rsa"
|
||||||
|
version = "0.9.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc"
|
||||||
|
dependencies = [
|
||||||
|
"const-oid",
|
||||||
|
"digest",
|
||||||
|
"num-bigint-dig",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
"pkcs1",
|
||||||
|
"pkcs8",
|
||||||
|
"rand_core 0.6.4",
|
||||||
|
"sha2",
|
||||||
|
"signature 2.2.0",
|
||||||
|
"spki",
|
||||||
|
"subtle",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-demangle"
|
name = "rustc-demangle"
|
||||||
version = "0.1.23"
|
version = "0.1.23"
|
||||||
@ -4089,6 +4518,20 @@ dependencies = [
|
|||||||
"untrusted",
|
"untrusted",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sec1"
|
||||||
|
version = "0.7.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc"
|
||||||
|
dependencies = [
|
||||||
|
"base16ct",
|
||||||
|
"der",
|
||||||
|
"generic-array",
|
||||||
|
"pkcs8",
|
||||||
|
"subtle",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "security-framework"
|
name = "security-framework"
|
||||||
version = "2.9.2"
|
version = "2.9.2"
|
||||||
@ -4266,6 +4709,15 @@ dependencies = [
|
|||||||
"syn 1.0.109",
|
"syn 1.0.109",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "service-binding"
|
||||||
|
version = "2.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e5580e177917150862f941023eb13ff219acc59daefa42b76fa747612723402c"
|
||||||
|
dependencies = [
|
||||||
|
"raunch",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "servo_arc"
|
name = "servo_arc"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
@ -4289,9 +4741,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha2"
|
name = "sha2"
|
||||||
version = "0.10.7"
|
version = "0.10.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8"
|
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"cpufeatures",
|
"cpufeatures",
|
||||||
@ -4322,6 +4774,16 @@ version = "1.6.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c"
|
checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "signature"
|
||||||
|
version = "2.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
|
||||||
|
dependencies = [
|
||||||
|
"digest",
|
||||||
|
"rand_core 0.6.4",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "simd-abstraction"
|
name = "simd-abstraction"
|
||||||
version = "0.7.1"
|
version = "0.7.1"
|
||||||
@ -4384,7 +4846,7 @@ version = "0.2.7"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e26be3acb6c2d9a7aac28482586a7856436af4cfe7100031d219de2d2ecb0028"
|
checksum = "e26be3acb6c2d9a7aac28482586a7856436af4cfe7100031d219de2d2ecb0028"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ed25519",
|
"ed25519 1.5.3",
|
||||||
"libc",
|
"libc",
|
||||||
"libsodium-sys",
|
"libsodium-sys",
|
||||||
"serde",
|
"serde",
|
||||||
@ -4455,6 +4917,16 @@ dependencies = [
|
|||||||
"lock_api",
|
"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]]
|
[[package]]
|
||||||
name = "sqlformat"
|
name = "sqlformat"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
@ -4552,6 +5024,74 @@ dependencies = [
|
|||||||
"tokio-rustls",
|
"tokio-rustls",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ssh-agent-lib"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9ae60055310a897706ffeffdd82cc8d5bb6ae8a50481157fb2407f579d404df1"
|
||||||
|
dependencies = [
|
||||||
|
"async-trait",
|
||||||
|
"byteorder",
|
||||||
|
"bytes",
|
||||||
|
"futures",
|
||||||
|
"log",
|
||||||
|
"serde",
|
||||||
|
"service-binding",
|
||||||
|
"tokio",
|
||||||
|
"tokio-util",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ssh-cipher"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "caac132742f0d33c3af65bfcde7f6aa8f62f0e991d80db99149eb9d44708784f"
|
||||||
|
dependencies = [
|
||||||
|
"aes",
|
||||||
|
"aes-gcm",
|
||||||
|
"cbc",
|
||||||
|
"chacha20",
|
||||||
|
"cipher",
|
||||||
|
"ctr",
|
||||||
|
"poly1305",
|
||||||
|
"ssh-encoding",
|
||||||
|
"subtle",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ssh-encoding"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eb9242b9ef4108a78e8cd1a2c98e193ef372437f8c22be363075233321dd4a15"
|
||||||
|
dependencies = [
|
||||||
|
"base64ct",
|
||||||
|
"pem-rfc7468",
|
||||||
|
"sha2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ssh-key"
|
||||||
|
version = "0.6.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ca9b366a80cf18bb6406f4cf4d10aebfb46140a8c0c33f666a144c5c76ecbafc"
|
||||||
|
dependencies = [
|
||||||
|
"bcrypt-pbkdf",
|
||||||
|
"ed25519-dalek",
|
||||||
|
"num-bigint-dig",
|
||||||
|
"p256",
|
||||||
|
"p384",
|
||||||
|
"p521",
|
||||||
|
"rand_core 0.6.4",
|
||||||
|
"rsa",
|
||||||
|
"sec1",
|
||||||
|
"sha2",
|
||||||
|
"signature 2.2.0",
|
||||||
|
"ssh-cipher",
|
||||||
|
"ssh-encoding",
|
||||||
|
"subtle",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "stable_deref_trait"
|
name = "stable_deref_trait"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
@ -6338,9 +6878,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zeroize"
|
name = "zeroize"
|
||||||
version = "1.6.0"
|
version = "1.8.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9"
|
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zvariant"
|
name = "zvariant"
|
||||||
|
@ -50,6 +50,9 @@ time = "0.3.31"
|
|||||||
tauri-plugin-single-instance = "2.0.0-beta.9"
|
tauri-plugin-single-instance = "2.0.0-beta.9"
|
||||||
tauri-plugin-global-shortcut = "2.0.0-beta.6"
|
tauri-plugin-global-shortcut = "2.0.0-beta.6"
|
||||||
rfd = "0.14.1"
|
rfd = "0.14.1"
|
||||||
|
ssh-agent-lib = "0.4.0"
|
||||||
|
ssh-key = { version = "0.6.6", features = ["rsa", "ed25519", "encryption"] }
|
||||||
|
signature = "2.2.0"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
# by default Tauri runs in production mode
|
# by default Tauri runs in production mode
|
||||||
|
11
src-tauri/migrations/20240612192956_kv.sql
Normal file
11
src-tauri/migrations/20240612192956_kv.sql
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
-- key-value store, will be used for various one-off values, serialized to bytes
|
||||||
|
CREATE TABLE kv (
|
||||||
|
name TEXT PRIMARY KEY,
|
||||||
|
value BLOB
|
||||||
|
);
|
||||||
|
|
||||||
|
-- config is currently stored in its own table, as text
|
||||||
|
INSERT INTO kv (name, value)
|
||||||
|
SELECT 'config', CAST(data AS BLOB) FROM config;
|
||||||
|
|
||||||
|
DROP TABLE config;
|
@ -100,7 +100,7 @@ async fn setup(app: &mut App) -> Result<(), Box<dyn Error>> {
|
|||||||
|
|
||||||
let mut conf = match AppConfig::load(&pool).await {
|
let mut conf = match AppConfig::load(&pool).await {
|
||||||
Ok(c) => c,
|
Ok(c) => c,
|
||||||
Err(SetupError::ConfigParseError(_)) => {
|
Err(LoadKvError::Invalid(_)) => {
|
||||||
setup_errors.push(
|
setup_errors.push(
|
||||||
"Could not load configuration from database. Reverting to defaults.".into()
|
"Could not load configuration from database. Reverting to defaults.".into()
|
||||||
);
|
);
|
||||||
|
7
src-tauri/src/bin/agent.rs
Normal file
7
src-tauri/src/bin/agent.rs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
use creddy::server::ssh_agent;
|
||||||
|
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() {
|
||||||
|
ssh_agent::run().await;
|
||||||
|
}
|
13
src-tauri/src/bin/key.rs
Normal file
13
src-tauri/src/bin/key.rs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
use ssh_key::private::PrivateKey;
|
||||||
|
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// let passphrase = std::env::var("PRIVKEY_PASSPHRASE").unwrap();
|
||||||
|
let p = AsRef::<std::path::Path>::as_ref("/home/joe/.ssh/test");
|
||||||
|
let privkey = PrivateKey::read_openssh_file(p)
|
||||||
|
.unwrap();
|
||||||
|
// .decrypt(passphrase.as_bytes())
|
||||||
|
// .unwrap();
|
||||||
|
|
||||||
|
dbg!(String::from_utf8_lossy(&privkey.to_bytes().unwrap()));
|
||||||
|
}
|
@ -7,6 +7,7 @@ use serde::{Serialize, Deserialize};
|
|||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
|
|
||||||
use crate::errors::*;
|
use crate::errors::*;
|
||||||
|
use crate::kv;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
@ -77,31 +78,16 @@ impl Default for AppConfig {
|
|||||||
|
|
||||||
|
|
||||||
impl AppConfig {
|
impl AppConfig {
|
||||||
pub async fn load(pool: &SqlitePool) -> Result<AppConfig, SetupError> {
|
pub async fn load(pool: &SqlitePool) -> Result<AppConfig, LoadKvError> {
|
||||||
let res = sqlx::query!("SELECT * from config where name = 'main'")
|
let config = kv::load(pool, "config")
|
||||||
.fetch_optional(pool)
|
.await?
|
||||||
.await?;
|
.unwrap_or_else(|| AppConfig::default());
|
||||||
|
|
||||||
let row = match res {
|
Ok(config)
|
||||||
Some(row) => row,
|
|
||||||
None => return Ok(AppConfig::default()),
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(serde_json::from_str(&row.data)?)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn save(&self, pool: &SqlitePool) -> Result<(), sqlx::error::Error> {
|
pub async fn save(&self, pool: &SqlitePool) -> Result<(), sqlx::error::Error> {
|
||||||
let data = serde_json::to_string(self).unwrap();
|
kv::save(pool, "config", self).await
|
||||||
sqlx::query(
|
|
||||||
"INSERT INTO config (name, data) VALUES ('main', ?)
|
|
||||||
ON CONFLICT (name) DO UPDATE SET data = ?"
|
|
||||||
)
|
|
||||||
.bind(&data)
|
|
||||||
.bind(&data)
|
|
||||||
.execute(pool)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
174
src-tauri/src/credentials/aws.rs
Normal file
174
src-tauri/src/credentials/aws.rs
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
use serde::{
|
||||||
|
Serialize,
|
||||||
|
Deserialize,
|
||||||
|
Serializer,
|
||||||
|
Deserializer,
|
||||||
|
};
|
||||||
|
use sqlx::SqlitePool;
|
||||||
|
|
||||||
|
use super::{Crypto, PersistentCredential};
|
||||||
|
|
||||||
|
use crate::errors::*;
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "PascalCase")]
|
||||||
|
pub struct AwsBaseCredential {
|
||||||
|
#[serde(default = "default_credentials_version")]
|
||||||
|
pub version: usize,
|
||||||
|
pub access_key_id: String,
|
||||||
|
pub secret_access_key: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AwsBaseCredential {
|
||||||
|
pub fn new(access_key_id: String, secret_access_key: String) -> Self {
|
||||||
|
Self {version: 1, access_key_id, secret_access_key}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PersistentCredential for AwsBaseCredential {
|
||||||
|
pub async fn save(&self, crypt: &Crypto, pool: &SqlitePool) -> Result<(), SaveCredentialsError> {
|
||||||
|
let (nonce, ciphertext) = crypto.encrypt(self.secret_access_key.as_bytes())?;
|
||||||
|
sqlx::query!(
|
||||||
|
"INSERT INTO aws_credentials (
|
||||||
|
name,
|
||||||
|
key_id,
|
||||||
|
secret_key_enc,
|
||||||
|
nonce,
|
||||||
|
updated_at
|
||||||
|
)
|
||||||
|
VALUES ('main', ?, ?, ? strftime('%s'))
|
||||||
|
ON CONFLICT DO UPDATE SET
|
||||||
|
key_id = excluded.key_id,
|
||||||
|
secret_key_enc = excluded.secret_key_enc,
|
||||||
|
nonce = excluded.nonce
|
||||||
|
updated_at = excluded.updated_at",
|
||||||
|
self.access_key_id,
|
||||||
|
ciphertext,
|
||||||
|
nonce,
|
||||||
|
).execute(pool).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn load(crypt: &Crypto, pool: &SqlitePool) -> Result<Self, LoadCredentialsError> {
|
||||||
|
let row = sqlx::query!("SELECT * FROM aws_credentials WHERE name = 'main'")
|
||||||
|
.fetch_optional(pool)
|
||||||
|
.await?
|
||||||
|
.ok_or(LoadCredentialsError::NoCredentials);
|
||||||
|
|
||||||
|
let secret_key = crypto.decrypt(&row.nonce, &row.secret_key_enc)?;
|
||||||
|
let creds = Self {
|
||||||
|
version: 1,
|
||||||
|
access_key_id: row.key_id,
|
||||||
|
secret_access_key: secret_key,
|
||||||
|
};
|
||||||
|
Ok(creds)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "PascalCase")]
|
||||||
|
pub struct AwsSessionCredential {
|
||||||
|
#[serde(default = "default_credentials_version")]
|
||||||
|
pub version: usize,
|
||||||
|
pub access_key_id: String,
|
||||||
|
pub secret_access_key: String,
|
||||||
|
pub session_token: String,
|
||||||
|
#[serde(serialize_with = "serialize_expiration")]
|
||||||
|
#[serde(deserialize_with = "deserialize_expiration")]
|
||||||
|
pub expiration: DateTime,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AwsSessionCredential {
|
||||||
|
pub async fn from_base(base: &BaseCredentials) -> Result<Self, GetSessionError> {
|
||||||
|
let req_creds = aws_sdk_sts::Credentials::new(
|
||||||
|
&base.access_key_id,
|
||||||
|
&base.secret_access_key,
|
||||||
|
None, // token
|
||||||
|
None, //expiration
|
||||||
|
"Creddy", // "provider name" apparently
|
||||||
|
);
|
||||||
|
let config = aws_config::from_env()
|
||||||
|
.credentials_provider(req_creds)
|
||||||
|
.load()
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let client = aws_sdk_sts::Client::new(&config);
|
||||||
|
let resp = client.get_session_token()
|
||||||
|
.duration_seconds(43_200)
|
||||||
|
.send()
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let aws_session = resp.credentials().ok_or(GetSessionError::EmptyResponse)?;
|
||||||
|
|
||||||
|
let access_key_id = aws_session.access_key_id()
|
||||||
|
.ok_or(GetSessionError::EmptyResponse)?
|
||||||
|
.to_string();
|
||||||
|
let secret_access_key = aws_session.secret_access_key()
|
||||||
|
.ok_or(GetSessionError::EmptyResponse)?
|
||||||
|
.to_string();
|
||||||
|
let session_token = aws_session.session_token()
|
||||||
|
.ok_or(GetSessionError::EmptyResponse)?
|
||||||
|
.to_string();
|
||||||
|
let expiration = aws_session.expiration()
|
||||||
|
.ok_or(GetSessionError::EmptyResponse)?
|
||||||
|
.clone();
|
||||||
|
|
||||||
|
let session_creds = SessionCredentials {
|
||||||
|
version: 1,
|
||||||
|
access_key_id,
|
||||||
|
secret_access_key,
|
||||||
|
session_token,
|
||||||
|
expiration,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
println!("Got new session:\n{}", serde_json::to_string(&session_creds).unwrap());
|
||||||
|
|
||||||
|
Ok(session_creds)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_expired(&self) -> bool {
|
||||||
|
let current_ts = SystemTime::now()
|
||||||
|
.duration_since(UNIX_EPOCH)
|
||||||
|
.unwrap() // doesn't panic because UNIX_EPOCH won't be later than now()
|
||||||
|
.as_secs();
|
||||||
|
|
||||||
|
let expire_ts = self.expiration.secs();
|
||||||
|
let remaining = expire_ts - (current_ts as i64);
|
||||||
|
remaining < 60
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct DateTimeVisitor;
|
||||||
|
|
||||||
|
impl<'de> Visitor<'de> for DateTimeVisitor {
|
||||||
|
type Value = DateTime;
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
|
||||||
|
write!(formatter, "an RFC 3339 UTC string, e.g. \"2014-01-05T10:17:34Z\"")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_str<E: de::Error>(self, v: &str) -> Result<DateTime, E> {
|
||||||
|
DateTime::from_str(v, Format::DateTime)
|
||||||
|
.map_err(|_| E::custom(format!("Invalid date/time: {v}")))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn deserialize_expiration<'de, D>(deserializer: D) -> Result<DateTime, D::Error>
|
||||||
|
where D: Deserializer<'de>
|
||||||
|
{
|
||||||
|
deserializer.deserialize_str(DateTimeVisitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_expiration<S>(exp: &DateTime, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where S: Serializer
|
||||||
|
{
|
||||||
|
// this only fails if the d/t is out of range, which it can't be for this format
|
||||||
|
let time_str = exp.fmt(Format::DateTime).unwrap();
|
||||||
|
serializer.serialize_str(&time_str)
|
||||||
|
}
|
193
src-tauri/src/credentials/mod.rs
Normal file
193
src-tauri/src/credentials/mod.rs
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
use argon2::{
|
||||||
|
Argon2,
|
||||||
|
Algorithm,
|
||||||
|
Version,
|
||||||
|
ParamsBuilder,
|
||||||
|
password_hash::rand_core::{RngCore, OsRng},
|
||||||
|
};
|
||||||
|
use chacha20poly1305::{
|
||||||
|
XChaCha20Poly1305,
|
||||||
|
XNonce,
|
||||||
|
aead::{
|
||||||
|
Aead,
|
||||||
|
AeadCore,
|
||||||
|
KeyInit,
|
||||||
|
Error as AeadError,
|
||||||
|
generic_array::GenericArray,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use serde::{Serialize, Deserialize};
|
||||||
|
use sqlx::{FromRow, SqlitePool};
|
||||||
|
|
||||||
|
use crate::kv;
|
||||||
|
|
||||||
|
mod aws;
|
||||||
|
pub use aws::{AwsBaseCredential, AwsSessionCredential};
|
||||||
|
|
||||||
|
|
||||||
|
pub enum CredentialKind {
|
||||||
|
AwsBase,
|
||||||
|
AwsSession,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub trait PersistentCredential {
|
||||||
|
async fn load(crypt: &Crypto, pool: &SqlitePool) -> Result<Self, LoadCredentialsError>;
|
||||||
|
async fn save(&self, crypt: &Crypto, pool: &SqlitePool) -> Result<(), SaveCredentialsError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum AppSession {
|
||||||
|
Unlocked {
|
||||||
|
salt: [u8; 32],
|
||||||
|
crypto: Crypto,
|
||||||
|
},
|
||||||
|
Locked {
|
||||||
|
salt: [u8; 32],
|
||||||
|
verify_nonce: XNonce,
|
||||||
|
verify_blob: Vec<u8>
|
||||||
|
},
|
||||||
|
Empty,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AppSession {
|
||||||
|
pub fn new(passphrase: &str) -> Result<Self, CryptoError> {
|
||||||
|
let salt = Crypto::salt();
|
||||||
|
let crypto = Crypto::new(passphrase, &salt);
|
||||||
|
Ok(Self::Unlocked {salt, crypto})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unlock(self, passphrase: &str) -> Result<Self, UnlockError> {
|
||||||
|
let (salt, nonce, blob) = match self {
|
||||||
|
Self::Empty => return Err(UnlockError::NoCredentials),
|
||||||
|
Self::Unlocked => return Err(UnlockError::NotLocked),
|
||||||
|
Self::Locked {salt, verify_nonce, verify_blob} => (salt, verify_nonce, verify_blob),
|
||||||
|
};
|
||||||
|
|
||||||
|
let crypto = Crypto::new(passphrase, salt)
|
||||||
|
.map_err(|e| CryptoError::Argon2(e))?;
|
||||||
|
|
||||||
|
// if passphrase is incorrect, this will fail
|
||||||
|
let verify = crypto.decrypt(&nonce, &blob)?;
|
||||||
|
|
||||||
|
Ok(Self::Unlocked{crypto, salt})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn load(pool: &SqlitePool) -> Result<Self, LoadKvError> {
|
||||||
|
match kv::load_bytes_multi!(pool, "salt", "verify_nonce", "verify_blob").await? {
|
||||||
|
Some((salt, verify_nonce, verify_blob)) => {
|
||||||
|
Ok(Self::Locked {salt, verify_nonce, verify_blob}),
|
||||||
|
},
|
||||||
|
None => Ok(Self::Empty),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn save(&self, pool: &SqlitePool) -> Result<(), LockError> {
|
||||||
|
let (salt, nonce, blob) = match self {
|
||||||
|
Self::Unlocked {salt, crypto} => {
|
||||||
|
let (nonce, blob) = crypto.encrypt(b"correct horse battery staple")
|
||||||
|
.map_err(|e| CryptoError::Aead(e))?;
|
||||||
|
(salt, nonce, blob)
|
||||||
|
},
|
||||||
|
Self::Locked {salt, verify_nonce, verify_blob} => (salt, verify_nonce, verify_blob),
|
||||||
|
// "saving" an empty session just means doing nothing
|
||||||
|
Self::Empty => return Ok(()),
|
||||||
|
};
|
||||||
|
|
||||||
|
kv::save(pool, "salt", salt).await?;
|
||||||
|
kv::save(pool, "verify_nonce", nonce).await?;
|
||||||
|
kv::save(pool, "verify_blob", blob).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn try_encrypt(&self, data: &[u8]) -> Result<(XNonce, Vec<u8>), CryptoError> {
|
||||||
|
let crypto = match self {
|
||||||
|
Self::Empty => Err(GetCredentialsError::Empty),
|
||||||
|
Self::Locked => Err(GetCredentialsError::Locked),
|
||||||
|
Self::Unlocked {crypto, ..} => crypto,
|
||||||
|
}?;
|
||||||
|
let res = crypto.encrypt(data)?;
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn try_decrypt(&self, nonce: XNonce, data: &[u8]) -> Result<Vec<u8>, CryptoError> {
|
||||||
|
let crypto = match self {
|
||||||
|
Self::Empty => Err(GetCredentialsError::Empty),
|
||||||
|
Self::Locked => Err(GetCredentialsError::Locked),
|
||||||
|
Self::Unlocked {crypto, ..} => crypto,
|
||||||
|
}?;
|
||||||
|
let res = crypto.decrypt(nonce, data)?;
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub struct Crypto {
|
||||||
|
cipher: XChaCha20Poly1305,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Crypto {
|
||||||
|
/// Argon2 params rationale:
|
||||||
|
///
|
||||||
|
/// m_cost is measured in KiB, so 128 * 1024 gives us 128MiB.
|
||||||
|
/// This should roughly double the memory usage of the application
|
||||||
|
/// while deriving the key.
|
||||||
|
///
|
||||||
|
/// p_cost is irrelevant since (at present) there isn't any parallelism
|
||||||
|
/// implemented, so we leave it at 1.
|
||||||
|
///
|
||||||
|
/// With the above m_cost, t_cost = 8 results in about 800ms to derive
|
||||||
|
/// a key on my (somewhat older) CPU. This is probably overkill, but
|
||||||
|
/// given that it should only have to happen ~once a day for most
|
||||||
|
/// usage, it should be acceptable.
|
||||||
|
#[cfg(not(debug_assertions))]
|
||||||
|
const MEM_COST: u32 = 128 * 1024;
|
||||||
|
#[cfg(not(debug_assertions))]
|
||||||
|
const TIME_COST: u32 = 8;
|
||||||
|
|
||||||
|
/// But since this takes a million years without optimizations,
|
||||||
|
/// we turn it way down in debug builds.
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
const MEM_COST: u32 = 48 * 1024;
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
const TIME_COST: u32 = 1;
|
||||||
|
|
||||||
|
|
||||||
|
fn new(passphrase: &str, salt: &[u8]) -> argon2::Result<Crypto> {
|
||||||
|
let params = ParamsBuilder::new()
|
||||||
|
.m_cost(Self::MEM_COST)
|
||||||
|
.p_cost(1)
|
||||||
|
.t_cost(Self::TIME_COST)
|
||||||
|
.build()
|
||||||
|
.unwrap(); // only errors if the given params are invalid
|
||||||
|
|
||||||
|
let hasher = Argon2::new(
|
||||||
|
Algorithm::Argon2id,
|
||||||
|
Version::V0x13,
|
||||||
|
params,
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut key = [0; 32];
|
||||||
|
hasher.hash_password_into(passphrase.as_bytes(), &salt, &mut key)?;
|
||||||
|
let cipher = XChaCha20Poly1305::new(GenericArray::from_slice(&key));
|
||||||
|
Ok(Crypto { cipher })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn salt() -> [u8; 32] {
|
||||||
|
let mut salt = [0; 32];
|
||||||
|
OsRng.fill_bytes(&mut salt);
|
||||||
|
salt
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encrypt(&self, data: &[u8]) -> Result<(XNonce, Vec<u8>), AeadError> {
|
||||||
|
let nonce = XChaCha20Poly1305::generate_nonce(&mut OsRng);
|
||||||
|
let ciphertext = self.cipher.encrypt(&nonce, data)?;
|
||||||
|
Ok((nonce, ciphertext))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decrypt(&self, nonce: &XNonce, data: &[u8]) -> Result<Vec<u8>, AeadError> {
|
||||||
|
self.cipher.decrypt(nonce, data)
|
||||||
|
}
|
||||||
|
}
|
@ -127,10 +127,10 @@ pub enum SetupError {
|
|||||||
InvalidRecord, // e.g. wrong size blob for nonce or salt
|
InvalidRecord, // e.g. wrong size blob for nonce or salt
|
||||||
#[error("Error from database: {0}")]
|
#[error("Error from database: {0}")]
|
||||||
DbError(#[from] SqlxError),
|
DbError(#[from] SqlxError),
|
||||||
|
#[error("Error loading data: {0}")]
|
||||||
|
KvError(#[from] LoadKvError),
|
||||||
#[error("Error running migrations: {0}")]
|
#[error("Error running migrations: {0}")]
|
||||||
MigrationError(#[from] MigrateError),
|
MigrationError(#[from] MigrateError),
|
||||||
#[error("Error parsing configuration from database")]
|
|
||||||
ConfigParseError(#[from] serde_json::Error),
|
|
||||||
#[error("Failed to set up start-on-login: {0}")]
|
#[error("Failed to set up start-on-login: {0}")]
|
||||||
AutoLaunchError(#[from] auto_launch::Error),
|
AutoLaunchError(#[from] auto_launch::Error),
|
||||||
#[error("Failed to start listener: {0}")]
|
#[error("Failed to start listener: {0}")]
|
||||||
@ -251,6 +251,38 @@ pub enum LockError {
|
|||||||
Setup(#[from] SetupError),
|
Setup(#[from] SetupError),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
TauriError(#[from] tauri::Error),
|
TauriError(#[from] tauri::Error),
|
||||||
|
#[error(transparent)]
|
||||||
|
Crypto(#[from] CryptoError),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug, ThisError, AsRefStr)]
|
||||||
|
pub enum SaveCredentialsError {
|
||||||
|
#[error("Database error: {0}")]
|
||||||
|
DbError(#[from] SqlxError),
|
||||||
|
#[error("Encryption error: {0}")]
|
||||||
|
Encryption(#[from] chacha20poly1305::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, ThisError, AsRefStr)]
|
||||||
|
pub enum LoadCredentialsError {
|
||||||
|
#[error("Database error: {0}")]
|
||||||
|
DbError(#[from] SqlxError),
|
||||||
|
#[error("Encryption error: {0}")]
|
||||||
|
Encryption(#[from] chacha20poly1305::Error),
|
||||||
|
#[error("Credentials not found")]
|
||||||
|
NoCredentials,
|
||||||
|
#[error("Could not decode credentials: {0}")]
|
||||||
|
Invalid(#[from] serde_json::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug, ThisError, AsRefStr)]
|
||||||
|
pub enum LoadKvError {
|
||||||
|
#[error("Database error: {0}")]
|
||||||
|
DbError(#[from] SqlxError),
|
||||||
|
#[error("Could not parse value from database: {0}")]
|
||||||
|
Invalid(#[from] serde_json::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
103
src-tauri/src/kv.rs
Normal file
103
src-tauri/src/kv.rs
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
use serde::Serialize;
|
||||||
|
use serde::de::DeserializeOwned;
|
||||||
|
use sqlx::SqlitePool;
|
||||||
|
|
||||||
|
use crate::errors::*;
|
||||||
|
|
||||||
|
|
||||||
|
pub async fn save<T>(pool: &SqlitePool, name: &str, value: &T) -> Result<(), sqlx::Error>
|
||||||
|
where T: Serialize
|
||||||
|
{
|
||||||
|
let bytes = serde_json::to_vec(value).unwrap();
|
||||||
|
save_bytes(pool, name, &bytes).await
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub async fn save_bytes(pool: &SqlitePool, name: &str, bytes: &[u8]) -> Result<(), sqlx::Error> {
|
||||||
|
sqlx::query!(
|
||||||
|
"INSERT INTO kv (name, value) VALUES (?, ?)
|
||||||
|
ON CONFLICT(name) DO UPDATE SET value = excluded.value;",
|
||||||
|
name,
|
||||||
|
bytes,
|
||||||
|
).execute(pool).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub async fn load<T>(pool: &SqlitePool, name: &str) -> Result<Option<T>, LoadKvError>
|
||||||
|
where T: DeserializeOwned
|
||||||
|
{
|
||||||
|
let v = load_bytes(pool, name)
|
||||||
|
.await?
|
||||||
|
.map(|bytes| serde_json::from_slice(&bytes))
|
||||||
|
.transpose()?;
|
||||||
|
Ok(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub async fn load_bytes(pool: &SqlitePool, name: &str) -> Result<Option<Vec<u8>>, sqlx::Error> {
|
||||||
|
sqlx::query!("SELECT name, value FROM kv WHERE name = ?", name)
|
||||||
|
.map(|row| row.value)
|
||||||
|
.fetch_optional(pool)
|
||||||
|
.await
|
||||||
|
.map(|o| o.flatten())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// pub async fn load_bytes_multi<const N: usize>(
|
||||||
|
// pool: &SqlitePool,
|
||||||
|
// names: [&str; N],
|
||||||
|
// ) -> Result<Option<[Vec<u8>; N]>, sqlx::Error> {
|
||||||
|
// // just use multiple queries, who cares
|
||||||
|
// let res: [Vec<u8>; N] = Default::default();
|
||||||
|
// for (i, name) in names.as_slice().iter().enumerate() {
|
||||||
|
// match load_bytes(pool, name).await? {
|
||||||
|
// Some(bytes) => res[i] = bytes,
|
||||||
|
// None => return Ok(None),
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// Ok(res);
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
macro_rules! load_bytes_multi {
|
||||||
|
(
|
||||||
|
$pool:ident,
|
||||||
|
$($name:literal),*
|
||||||
|
) => {
|
||||||
|
// wrap everything up in an immediately-invoked closure for easy short-circuiting
|
||||||
|
(|| {
|
||||||
|
// a tuple, with one item for each repetition of $name
|
||||||
|
(
|
||||||
|
// repeat this match block for every name
|
||||||
|
$(
|
||||||
|
// load_bytes returns Result<Option<_>>, the Result is handled by
|
||||||
|
// the ? and we match on the Option
|
||||||
|
match load_bytes(pool, $name)? {
|
||||||
|
Some(v) => v,
|
||||||
|
None => return Ok(None)
|
||||||
|
},
|
||||||
|
)*
|
||||||
|
)
|
||||||
|
})()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// macro_rules! load_multi {
|
||||||
|
// (
|
||||||
|
// $pool:ident,
|
||||||
|
// $($name:literal),*
|
||||||
|
// ) => {
|
||||||
|
// (|| {
|
||||||
|
// (
|
||||||
|
// $(
|
||||||
|
// match load(pool, $name)? {
|
||||||
|
// Some(v) => v,
|
||||||
|
// None => return Ok(None)
|
||||||
|
// },
|
||||||
|
// )*
|
||||||
|
// )
|
||||||
|
// })()
|
||||||
|
// }
|
||||||
|
// }
|
@ -5,8 +5,9 @@ mod credentials;
|
|||||||
pub mod errors;
|
pub mod errors;
|
||||||
mod clientinfo;
|
mod clientinfo;
|
||||||
mod ipc;
|
mod ipc;
|
||||||
|
mod kv;
|
||||||
mod state;
|
mod state;
|
||||||
mod server;
|
pub mod server;
|
||||||
mod shortcuts;
|
mod shortcuts;
|
||||||
mod terminal;
|
mod terminal;
|
||||||
mod tray;
|
mod tray;
|
||||||
|
@ -26,6 +26,8 @@ pub use server_unix::Server;
|
|||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use server_unix::Stream;
|
use server_unix::Stream;
|
||||||
|
|
||||||
|
pub mod ssh_agent;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub enum Request {
|
pub enum Request {
|
||||||
|
77
src-tauri/src/server/ssh_agent.rs
Normal file
77
src-tauri/src/server/ssh_agent.rs
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
use signature::Signer;
|
||||||
|
use ssh_agent_lib::agent::{Agent, Session};
|
||||||
|
use ssh_agent_lib::proto::message::Message;
|
||||||
|
use ssh_key::public::PublicKey;
|
||||||
|
use ssh_key::private::PrivateKey;
|
||||||
|
use tokio::net::UnixListener;
|
||||||
|
|
||||||
|
|
||||||
|
struct SshAgent;
|
||||||
|
|
||||||
|
impl std::default::Default for SshAgent {
|
||||||
|
fn default() -> Self {
|
||||||
|
SshAgent {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[ssh_agent_lib::async_trait]
|
||||||
|
impl Session for SshAgent {
|
||||||
|
async fn handle(&mut self, message: Message) -> Result<Message, Box<dyn std::error::Error>> {
|
||||||
|
println!("Received message");
|
||||||
|
match message {
|
||||||
|
Message::RequestIdentities => {
|
||||||
|
let p = std::path::PathBuf::from("/home/joe/.ssh/id_ed25519.pub");
|
||||||
|
let pubkey = PublicKey::read_openssh_file(&p).unwrap();
|
||||||
|
let id = ssh_agent_lib::proto::message::Identity {
|
||||||
|
pubkey_blob: pubkey.to_bytes().unwrap(),
|
||||||
|
comment: pubkey.comment().to_owned(),
|
||||||
|
};
|
||||||
|
Ok(Message::IdentitiesAnswer(vec![id]))
|
||||||
|
},
|
||||||
|
Message::SignRequest(req) => {
|
||||||
|
println!("Received sign request");
|
||||||
|
let mut req_bytes = vec![13];
|
||||||
|
encode_string(&mut req_bytes, &req.pubkey_blob);
|
||||||
|
encode_string(&mut req_bytes, &req.data);
|
||||||
|
req_bytes.extend(req.flags.to_be_bytes());
|
||||||
|
std::fs::File::create("/tmp/signreq").unwrap().write(&req_bytes).unwrap();
|
||||||
|
|
||||||
|
let p = std::path::PathBuf::from("/home/joe/.ssh/id_ed25519");
|
||||||
|
let passphrase = std::env::var("PRIVKEY_PASSPHRASE").unwrap();
|
||||||
|
let privkey = PrivateKey::read_openssh_file(&p)
|
||||||
|
.unwrap()
|
||||||
|
.decrypt(passphrase.as_bytes())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
let sig = Signer::sign(&privkey, &req.data);
|
||||||
|
use std::io::Write;
|
||||||
|
std::fs::File::create("/tmp/sig").unwrap().write(sig.as_bytes()).unwrap();
|
||||||
|
|
||||||
|
let mut payload = Vec::with_capacity(128);
|
||||||
|
encode_string(&mut payload, "ssh-ed25519".as_bytes());
|
||||||
|
encode_string(&mut payload, sig.as_bytes());
|
||||||
|
println!("Payload length: {}", payload.len());
|
||||||
|
std::fs::File::create("/tmp/payload").unwrap().write(&payload).unwrap();
|
||||||
|
Ok(Message::SignResponse(payload))
|
||||||
|
},
|
||||||
|
_ => Ok(Message::Failure),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn encode_string(buf: &mut Vec<u8>, s: &[u8]) {
|
||||||
|
let len = s.len() as u32;
|
||||||
|
buf.extend(len.to_be_bytes());
|
||||||
|
buf.extend(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub async fn run() {
|
||||||
|
let socket = "/tmp/creddy-agent.sock";
|
||||||
|
let _ = std::fs::remove_file(socket);
|
||||||
|
let listener = UnixListener::bind(socket).unwrap();
|
||||||
|
SshAgent.listen(listener).await.unwrap();
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user