Generated
+209
-12
@@ -2,6 +2,16 @@
|
|||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 4
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aead"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1973cfbc1a2daf9cf550e74e1f088c28e7f7d8c1e1418fb6c9dc5184b7e84c99"
|
||||||
|
dependencies = [
|
||||||
|
"crypto-common 0.2.2",
|
||||||
|
"inout",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ahash"
|
name = "ahash"
|
||||||
version = "0.8.12"
|
version = "0.8.12"
|
||||||
@@ -108,6 +118,15 @@ dependencies = [
|
|||||||
"generic-array",
|
"generic-array",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "block-buffer"
|
||||||
|
version = "0.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa"
|
||||||
|
dependencies = [
|
||||||
|
"hybrid-array",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bs58"
|
name = "bs58"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
@@ -145,12 +164,58 @@ version = "1.0.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "chacha20"
|
||||||
|
version = "0.10.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "65c35e4b699c7e15ccbe7ee35c005e4fc0a278d22238a2857e6ce2dadeda1b06"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cipher",
|
||||||
|
"cpufeatures 0.3.1",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "chacha20poly1305"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9b89e1c441e926b9c82a8d023f6e1b7ae0adcfaa7d621814e4d60789bac751cb"
|
||||||
|
dependencies = [
|
||||||
|
"aead",
|
||||||
|
"chacha20",
|
||||||
|
"cipher",
|
||||||
|
"poly1305",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cipher"
|
||||||
|
version = "0.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e8cf2a2c93cd704877c0858356ed03480ff301ee950b43f1cbe4573b088bfa6c"
|
||||||
|
dependencies = [
|
||||||
|
"block-buffer 0.12.1",
|
||||||
|
"crypto-common 0.2.2",
|
||||||
|
"inout",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cmov"
|
||||||
|
version = "0.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "const-oid"
|
name = "const-oid"
|
||||||
version = "0.9.6"
|
version = "0.9.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
|
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "const-oid"
|
||||||
|
version = "0.10.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cpufeatures"
|
name = "cpufeatures"
|
||||||
version = "0.2.17"
|
version = "0.2.17"
|
||||||
@@ -160,6 +225,15 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cpufeatures"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crypto-common"
|
name = "crypto-common"
|
||||||
version = "0.1.7"
|
version = "0.1.7"
|
||||||
@@ -170,6 +244,26 @@ dependencies = [
|
|||||||
"typenum",
|
"typenum",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crypto-common"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom 0.4.3",
|
||||||
|
"hybrid-array",
|
||||||
|
"rand_core 0.10.1",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ctutils"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e"
|
||||||
|
dependencies = [
|
||||||
|
"cmov",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "curve25519-dalek"
|
name = "curve25519-dalek"
|
||||||
version = "4.1.3"
|
version = "4.1.3"
|
||||||
@@ -177,10 +271,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be"
|
checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"cpufeatures",
|
"cpufeatures 0.2.17",
|
||||||
"curve25519-dalek-derive",
|
"curve25519-dalek-derive",
|
||||||
"digest",
|
"digest 0.10.7",
|
||||||
"fiat-crypto",
|
"fiat-crypto 0.2.9",
|
||||||
|
"rustc_version",
|
||||||
|
"subtle",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "curve25519-dalek"
|
||||||
|
version = "5.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b5eed333089e2e1c1ac8c6c0398e5e2497b4c9926ca6d0365ed1e099afa5bc23"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cpufeatures 0.3.1",
|
||||||
|
"curve25519-dalek-derive",
|
||||||
|
"fiat-crypto 0.3.0",
|
||||||
"rustc_version",
|
"rustc_version",
|
||||||
"subtle",
|
"subtle",
|
||||||
"zeroize",
|
"zeroize",
|
||||||
@@ -209,7 +318,7 @@ version = "0.7.10"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb"
|
checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"const-oid",
|
"const-oid 0.9.6",
|
||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -219,8 +328,19 @@ version = "0.10.7"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"block-buffer",
|
"block-buffer 0.10.4",
|
||||||
"crypto-common",
|
"crypto-common 0.1.7",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "digest"
|
||||||
|
version = "0.11.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2"
|
||||||
|
dependencies = [
|
||||||
|
"block-buffer 0.12.1",
|
||||||
|
"const-oid 0.10.2",
|
||||||
|
"crypto-common 0.2.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -239,11 +359,11 @@ version = "2.2.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9"
|
checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"curve25519-dalek",
|
"curve25519-dalek 4.1.3",
|
||||||
"ed25519",
|
"ed25519",
|
||||||
"rand_core 0.6.4",
|
"rand_core 0.6.4",
|
||||||
"serde",
|
"serde",
|
||||||
"sha2",
|
"sha2 0.10.9",
|
||||||
"subtle",
|
"subtle",
|
||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
@@ -255,15 +375,19 @@ dependencies = [
|
|||||||
"anyhow",
|
"anyhow",
|
||||||
"axum",
|
"axum",
|
||||||
"bs58",
|
"bs58",
|
||||||
|
"chacha20poly1305",
|
||||||
|
"curve25519-dalek 5.0.0",
|
||||||
"ed25519-dalek",
|
"ed25519-dalek",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"rand 0.8.7",
|
"rand 0.8.7",
|
||||||
"rusqlite",
|
"rusqlite",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"sha2 0.11.0",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tower-http",
|
"tower-http",
|
||||||
"uuid",
|
"uuid",
|
||||||
|
"x25519-dalek",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -284,6 +408,12 @@ version = "0.2.9"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
|
checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fiat-crypto"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "64cd1e32ddd350061ae6edb1b082d7c54915b5c672c389143b9a63403a109f24"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "find-msvc-tools"
|
name = "find-msvc-tools"
|
||||||
version = "0.1.11"
|
version = "0.1.11"
|
||||||
@@ -393,6 +523,7 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"r-efi 6.0.0",
|
"r-efi 6.0.0",
|
||||||
|
"rand_core 0.10.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -464,6 +595,15 @@ version = "1.0.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
|
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hybrid-array"
|
||||||
|
version = "0.4.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "707114b52a152fa7bdb290cd7cd5912d9467273b6d74e21b8d81aca1f8533f6b"
|
||||||
|
dependencies = [
|
||||||
|
"typenum",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper"
|
name = "hyper"
|
||||||
version = "1.11.0"
|
version = "1.11.0"
|
||||||
@@ -499,6 +639,15 @@ dependencies = [
|
|||||||
"tower-service",
|
"tower-service",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "inout"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4250ce6452e92010fdf7268ccc5d14faa80bb12fc741938534c58f16804e03c7"
|
||||||
|
dependencies = [
|
||||||
|
"hybrid-array",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.18"
|
version = "1.0.18"
|
||||||
@@ -612,6 +761,16 @@ version = "0.3.34"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548"
|
checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "poly1305"
|
||||||
|
version = "0.9.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6e2d0073b297041425c7c3df6eb4792d598a15323fe63346852b092eca02904c"
|
||||||
|
dependencies = [
|
||||||
|
"cpufeatures 0.3.1",
|
||||||
|
"universal-hash",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ppv-lite86"
|
name = "ppv-lite86"
|
||||||
version = "0.2.21"
|
version = "0.2.21"
|
||||||
@@ -710,6 +869,12 @@ dependencies = [
|
|||||||
"getrandom 0.3.4",
|
"getrandom 0.3.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rusqlite"
|
name = "rusqlite"
|
||||||
version = "0.31.0"
|
version = "0.31.0"
|
||||||
@@ -824,8 +989,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "a978451301f4db1d02937a4ab3ccce137717b81826e79b7d49ffe3244a13c3b8"
|
checksum = "a978451301f4db1d02937a4ab3ccce137717b81826e79b7d49ffe3244a13c3b8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"cpufeatures",
|
"cpufeatures 0.2.17",
|
||||||
"digest",
|
"digest 0.10.7",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -835,8 +1000,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
|
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"cpufeatures",
|
"cpufeatures 0.2.17",
|
||||||
"digest",
|
"digest 0.10.7",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha2"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cpufeatures 0.3.1",
|
||||||
|
"digest 0.11.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1113,6 +1289,16 @@ version = "1.0.24"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "universal-hash"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f4987bdc12753382e0bec4a65c50738ffaabc998b9cdd1f952fb5f39b0048a96"
|
||||||
|
dependencies = [
|
||||||
|
"crypto-common 0.2.2",
|
||||||
|
"ctutils",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uuid"
|
name = "uuid"
|
||||||
version = "1.24.1"
|
version = "1.24.1"
|
||||||
@@ -1217,6 +1403,17 @@ version = "0.57.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e"
|
checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "x25519-dalek"
|
||||||
|
version = "3.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e7e8131a03190127fb2263afc72b322ecadae46b6ff8c6f399ff5d02f5559af6"
|
||||||
|
dependencies = [
|
||||||
|
"curve25519-dalek 5.0.0",
|
||||||
|
"rand_core 0.10.1",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy"
|
name = "zerocopy"
|
||||||
version = "0.8.56"
|
version = "0.8.56"
|
||||||
|
|||||||
@@ -16,3 +16,7 @@ tower-http = { version = "0.7.0", features = ["fs", "cors"] }
|
|||||||
rusqlite = { version = "0.31", features = ["bundled"] }
|
rusqlite = { version = "0.31", features = ["bundled"] }
|
||||||
uuid = { version = "1.24.1", features = ["v4"] }
|
uuid = { version = "1.24.1", features = ["v4"] }
|
||||||
futures-util = "0.3.34"
|
futures-util = "0.3.34"
|
||||||
|
x25519-dalek = { version = "3.0.0", features = ["static_secrets"] }
|
||||||
|
curve25519-dalek = "5.0.0"
|
||||||
|
sha2 = "0.11.0"
|
||||||
|
chacha20poly1305 = "0.11.0"
|
||||||
|
|||||||
+121
-1
@@ -1,7 +1,18 @@
|
|||||||
use std::path::PathBuf;
|
use std::{path::PathBuf, sync::Arc};
|
||||||
|
|
||||||
|
use axum::extract::ws::WebSocket;
|
||||||
|
use chacha20poly1305::{
|
||||||
|
ChaCha20Poly1305, Key, Nonce,
|
||||||
|
aead::{Aead, KeyInit},
|
||||||
|
};
|
||||||
|
use curve25519_dalek::edwards::CompressedEdwardsY;
|
||||||
use ed25519_dalek::{Signature, SigningKey, VerifyingKey};
|
use ed25519_dalek::{Signature, SigningKey, VerifyingKey};
|
||||||
use rand::rngs::OsRng;
|
use rand::rngs::OsRng;
|
||||||
|
use sha2::{Digest, Sha512};
|
||||||
|
use tokio::sync::Mutex;
|
||||||
|
use x25519_dalek::{PublicKey as X25519Public, SharedSecret, StaticSecret as X25519Secret};
|
||||||
|
|
||||||
|
use crate::{server::Server, ws::EnclaveWebSocket};
|
||||||
|
|
||||||
pub async fn get() -> anyhow::Result<SigningKey> {
|
pub async fn get() -> anyhow::Result<SigningKey> {
|
||||||
let private_key_path = PathBuf::from("private.key");
|
let private_key_path = PathBuf::from("private.key");
|
||||||
@@ -45,3 +56,112 @@ pub fn from_string_sig(signature: &str) -> anyhow::Result<Signature> {
|
|||||||
.map_err(|_| anyhow::anyhow!("Invalid signature"))?,
|
.map_err(|_| anyhow::anyhow!("Invalid signature"))?,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn ed25519_signing_key_to_x25519(signing_key: &SigningKey) -> X25519Secret {
|
||||||
|
let hash = Sha512::digest(signing_key.as_bytes());
|
||||||
|
let mut scalar_bytes = [0u8; 32];
|
||||||
|
scalar_bytes.copy_from_slice(&hash[..32]);
|
||||||
|
X25519Secret::from(scalar_bytes) // clamping happens internally
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ed25519_verifying_key_to_x25519(verifying_key: &VerifyingKey) -> Option<X25519Public> {
|
||||||
|
let compressed = CompressedEdwardsY(verifying_key.to_bytes());
|
||||||
|
let edwards_point = compressed.decompress()?;
|
||||||
|
Some(X25519Public::from(edwards_point.to_montgomery().to_bytes()))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SessionCipher {
|
||||||
|
cipher: ChaCha20Poly1305,
|
||||||
|
send_counter: u64,
|
||||||
|
recv_counter: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SessionCipher {
|
||||||
|
pub fn new(shared_secret: &SharedSecret) -> anyhow::Result<Self> {
|
||||||
|
// SharedSecret's raw bytes ARE suitable for direct use as a ChaCha20Poly1305 key
|
||||||
|
// (both are 32 bytes), though in a hardened design you'd typically run this
|
||||||
|
// through a KDF (e.g. HKDF) rather than using the raw ECDH output directly.
|
||||||
|
let key = Key::try_from(shared_secret.as_bytes().as_slice())?;
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
cipher: ChaCha20Poly1305::new(&key),
|
||||||
|
send_counter: 0,
|
||||||
|
recv_counter: 0,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn next_send_nonce(&mut self) -> [u8; 12] {
|
||||||
|
let mut nonce = [0u8; 12];
|
||||||
|
nonce[..8].copy_from_slice(&self.send_counter.to_be_bytes());
|
||||||
|
// top bit distinguishes "send" direction from "recv" direction,
|
||||||
|
// so client-send and server-send counters never collide even if
|
||||||
|
// both happened to reach the same numeric value
|
||||||
|
nonce[11] |= 0b1000_0000;
|
||||||
|
self.send_counter += 1;
|
||||||
|
nonce
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn next_recv_nonce(&mut self) -> [u8; 12] {
|
||||||
|
let mut nonce = [0u8; 12];
|
||||||
|
nonce[..8].copy_from_slice(&self.recv_counter.to_be_bytes());
|
||||||
|
self.recv_counter += 1;
|
||||||
|
nonce
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn encrypt(&mut self, plaintext: &[u8]) -> anyhow::Result<Vec<u8>> {
|
||||||
|
let nonce_bytes = self.next_send_nonce();
|
||||||
|
let nonce = Nonce::try_from(nonce_bytes)?;
|
||||||
|
|
||||||
|
let ciphertext = self
|
||||||
|
.cipher
|
||||||
|
.encrypt(&nonce, plaintext)
|
||||||
|
.map_err(|_| anyhow::anyhow!("encryption failed"))?;
|
||||||
|
|
||||||
|
// prepend the nonce so the other side can reconstruct it on decrypt
|
||||||
|
let mut out = nonce_bytes.to_vec();
|
||||||
|
out.extend(ciphertext);
|
||||||
|
Ok(out)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn decrypt(&mut self, data: &[u8]) -> anyhow::Result<Vec<u8>> {
|
||||||
|
if data.len() < 12 {
|
||||||
|
anyhow::bail!("message too short to contain a nonce");
|
||||||
|
}
|
||||||
|
let (nonce_bytes, ciphertext) = data.split_at(12);
|
||||||
|
let nonce = Nonce::try_from(nonce_bytes)?;
|
||||||
|
|
||||||
|
self.cipher
|
||||||
|
.decrypt(&nonce, ciphertext)
|
||||||
|
.map_err(|_| anyhow::anyhow!("decryption failed"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn crypto_handshake(
|
||||||
|
server: &Arc<Server>,
|
||||||
|
mut socket: WebSocket,
|
||||||
|
) -> anyhow::Result<EnclaveWebSocket> {
|
||||||
|
socket
|
||||||
|
.send(axum::extract::ws::Message::Binary(
|
||||||
|
server.x_keypair.0.to_bytes().to_vec().into(),
|
||||||
|
))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let axum::extract::ws::Message::Binary(raw_pubkey) = socket
|
||||||
|
.recv()
|
||||||
|
.await
|
||||||
|
.transpose()?
|
||||||
|
.ok_or(anyhow::anyhow!("Failed to get client x key"))?
|
||||||
|
else {
|
||||||
|
return Err(anyhow::anyhow!("WS message is not binary"));
|
||||||
|
};
|
||||||
|
|
||||||
|
let client_pubkey = X25519Public::from(*raw_pubkey.as_array().ok_or(anyhow::anyhow!(
|
||||||
|
"Failed to get proper length of client x key"
|
||||||
|
))?);
|
||||||
|
|
||||||
|
let shared_secret = server.x_keypair.1.diffie_hellman(&client_pubkey);
|
||||||
|
|
||||||
|
let cipher = Arc::new(Mutex::new(SessionCipher::new(&shared_secret)?));
|
||||||
|
|
||||||
|
Ok(EnclaveWebSocket::new(socket, cipher))
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ use crate::types::{Channel, ChannelKind, ServerMeta};
|
|||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub meta: ServerMeta,
|
pub meta: ServerMeta,
|
||||||
pub port: u16,
|
pub port: u16,
|
||||||
pub public_hostname: String,
|
|
||||||
pub hostnames: HashSet<String>,
|
pub hostnames: HashSet<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,8 +48,6 @@ impl Config {
|
|||||||
|
|
||||||
port: 3415,
|
port: 3415,
|
||||||
|
|
||||||
public_hostname: "localhost:3415".to_string(),
|
|
||||||
|
|
||||||
hostnames: HashSet::from_iter(["localhost:3415".to_string()]),
|
hostnames: HashSet::from_iter(["localhost:3415".to_string()]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ use crate::server::UserConnections;
|
|||||||
impl UserConnections {
|
impl UserConnections {
|
||||||
pub async fn initialize(
|
pub async fn initialize(
|
||||||
server: &Arc<Server>,
|
server: &Arc<Server>,
|
||||||
socket: Arc<EnclaveWebSocket>,
|
socket: &EnclaveWebSocket,
|
||||||
) -> anyhow::Result<(Arc<EnclaveWebSocket>, VerifyingKey, ClientMeta)> {
|
) -> anyhow::Result<(VerifyingKey, ClientMeta)> {
|
||||||
let Some(ServerMethod::Initialize {
|
let Some(ServerMethod::Initialize {
|
||||||
public_key: public_key_string,
|
public_key: public_key_string,
|
||||||
signature,
|
signature,
|
||||||
@@ -48,11 +48,10 @@ impl UserConnections {
|
|||||||
return Err(anyhow::anyhow!("Client tampstamp wasn't correct"));
|
return Err(anyhow::anyhow!("Client tampstamp wasn't correct"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if hostname != server.config.public_hostname || !server.config.hostnames.contains(&hostname)
|
if !server.config.hostnames.contains(&hostname) {
|
||||||
{
|
|
||||||
socket.send(
|
socket.send(
|
||||||
&ClientMethod::Error {
|
&ClientMethod::Error {
|
||||||
error: Cow::Owned(format!("Invalid Hostname, to avoid man-in-the-middle attacks, please use the correct hostname: {}", server.config.public_hostname)),
|
error: Cow::Owned(format!("Invalid Hostname, to avoid man-in-the-middle attacks, please use the correct hostname(s): {}", server.config.hostnames.clone().into_iter().collect::<Vec<_>>().join(", "))),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
@@ -112,6 +111,6 @@ impl UserConnections {
|
|||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok((socket, public_key, meta))
|
Ok((public_key, meta))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+26
-6
@@ -18,11 +18,12 @@ use tokio::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
crypto::SessionCipher,
|
||||||
data::{config::Config, messages::MessageStore, users::UserMetaStore},
|
data::{config::Config, messages::MessageStore, users::UserMetaStore},
|
||||||
protocol::{ClientMethod, read_loop},
|
protocol::{ClientMethod, read_loop},
|
||||||
types::ClientMeta,
|
types::ClientMeta,
|
||||||
ws::EnclaveWebSocket,
|
|
||||||
};
|
};
|
||||||
|
use x25519_dalek::{PublicKey as X25519Public, StaticSecret as X25519Secret};
|
||||||
|
|
||||||
pub struct VoiceConnection {
|
pub struct VoiceConnection {
|
||||||
pub addr: SocketAddr,
|
pub addr: SocketAddr,
|
||||||
@@ -35,11 +36,13 @@ pub struct UserConnections {
|
|||||||
pub counter: AtomicU16,
|
pub counter: AtomicU16,
|
||||||
pub public_key: VerifyingKey,
|
pub public_key: VerifyingKey,
|
||||||
pub connections: Mutex<HashMap<u16, Arc<crate::ws::EnclaveWebSocket>>>,
|
pub connections: Mutex<HashMap<u16, Arc<crate::ws::EnclaveWebSocket>>>,
|
||||||
|
pub cihper: Arc<Mutex<SessionCipher>>,
|
||||||
pub voice: Mutex<Option<VoiceConnection>>,
|
pub voice: Mutex<Option<VoiceConnection>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Server {
|
pub struct Server {
|
||||||
pub key: SigningKey,
|
pub key: SigningKey,
|
||||||
|
pub x_keypair: (X25519Public, X25519Secret),
|
||||||
pub config: Config,
|
pub config: Config,
|
||||||
pub clients: Mutex<HashMap<VerifyingKey, Arc<UserConnections>>>,
|
pub clients: Mutex<HashMap<VerifyingKey, Arc<UserConnections>>>,
|
||||||
pub voice_pins: Mutex<HashMap<u64, (VerifyingKey, String)>>,
|
pub voice_pins: Mutex<HashMap<u64, (VerifyingKey, String)>>,
|
||||||
@@ -50,8 +53,14 @@ pub struct Server {
|
|||||||
|
|
||||||
impl Server {
|
impl Server {
|
||||||
pub async fn new() -> anyhow::Result<Arc<Self>> {
|
pub async fn new() -> anyhow::Result<Arc<Self>> {
|
||||||
|
let key = crate::crypto::get().await?;
|
||||||
Ok(Arc::new(Self {
|
Ok(Arc::new(Self {
|
||||||
key: crate::crypto::get().await?,
|
x_keypair: (
|
||||||
|
crate::crypto::ed25519_verifying_key_to_x25519(&key.verifying_key())
|
||||||
|
.ok_or(anyhow::anyhow!("Failed to convert ed pubkey to x"))?,
|
||||||
|
crate::crypto::ed25519_signing_key_to_x25519(&key),
|
||||||
|
),
|
||||||
|
key,
|
||||||
config: Config::get().await?,
|
config: Config::get().await?,
|
||||||
clients: Mutex::new(HashMap::new()),
|
clients: Mutex::new(HashMap::new()),
|
||||||
voice_pins: Mutex::new(HashMap::new()),
|
voice_pins: Mutex::new(HashMap::new()),
|
||||||
@@ -67,8 +76,16 @@ impl Server {
|
|||||||
let s = self.clone();
|
let s = self.clone();
|
||||||
|
|
||||||
ws.on_upgrade(move |socket: WebSocket| async move {
|
ws.on_upgrade(move |socket: WebSocket| async move {
|
||||||
match UserConnections::initialize(&s, Arc::new(EnclaveWebSocket::new(socket))).await {
|
let mut client = match crate::crypto::crypto_handshake(&s, socket).await {
|
||||||
Ok((client, public_key, meta)) => {
|
Ok(client) => client,
|
||||||
|
Err(err) => {
|
||||||
|
eprintln!("Failed to initialize crypto: {err}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
match UserConnections::initialize(&s, &client).await {
|
||||||
|
Ok((public_key, meta)) => {
|
||||||
if let Err(e) = s
|
if let Err(e) = s
|
||||||
.user_store
|
.user_store
|
||||||
.upsert_user(&crate::crypto::to_string(&public_key), &meta)
|
.upsert_user(&crate::crypto::to_string(&public_key), &meta)
|
||||||
@@ -88,10 +105,15 @@ impl Server {
|
|||||||
counter: AtomicU16::new(0),
|
counter: AtomicU16::new(0),
|
||||||
connections: Mutex::new(HashMap::new()),
|
connections: Mutex::new(HashMap::new()),
|
||||||
voice: Mutex::new(None),
|
voice: Mutex::new(None),
|
||||||
|
cihper: client.cipher.clone(),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.clone();
|
.clone();
|
||||||
|
|
||||||
|
client.cipher = clients.cihper.clone();
|
||||||
|
|
||||||
|
let client = Arc::new(client);
|
||||||
|
|
||||||
let conid = clients
|
let conid = clients
|
||||||
.counter
|
.counter
|
||||||
.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
|
.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
|
||||||
@@ -106,8 +128,6 @@ impl Server {
|
|||||||
|
|
||||||
if let Err(e) = read_loop(&s, public_key, &client).await {
|
if let Err(e) = read_loop(&s, public_key, &client).await {
|
||||||
eprintln!("Failed to handle client: {e}");
|
eprintln!("Failed to handle client: {e}");
|
||||||
} else {
|
|
||||||
println!("Client connection closed")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut clients_meta = s.clients.lock().await;
|
let mut clients_meta = s.clients.lock().await;
|
||||||
|
|||||||
+46
-10
@@ -2,9 +2,9 @@ use std::{net::SocketAddr, sync::Arc};
|
|||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use ed25519_dalek::VerifyingKey;
|
use ed25519_dalek::VerifyingKey;
|
||||||
use tokio::net::UdpSocket;
|
use tokio::{net::UdpSocket, sync::Mutex};
|
||||||
|
|
||||||
use crate::{protocol::ClientMethod, server::Server};
|
use crate::{crypto::SessionCipher, protocol::ClientMethod, server::Server};
|
||||||
|
|
||||||
use tokio::time::Instant;
|
use tokio::time::Instant;
|
||||||
|
|
||||||
@@ -31,16 +31,18 @@ impl Server {
|
|||||||
let pin_bytes: [u8; 8] = buf[..8].try_into().unwrap();
|
let pin_bytes: [u8; 8] = buf[..8].try_into().unwrap();
|
||||||
let pin = u64::from_be_bytes(pin_bytes);
|
let pin = u64::from_be_bytes(pin_bytes);
|
||||||
|
|
||||||
let (sender_pubkey, channel_id, payload) = {
|
// is_first_packet distinguishes the plaintext pin-bootstrap packet
|
||||||
|
// from subsequent encrypted audio packets.
|
||||||
|
let (sender_pubkey, channel_id, payload, is_first_packet) = {
|
||||||
let mut pins = self.voice_pins.lock().await;
|
let mut pins = self.voice_pins.lock().await;
|
||||||
|
|
||||||
if let Some((pubkey, channel_id)) = pins.remove(&pin) {
|
if let Some((pubkey, channel_id)) = pins.remove(&pin) {
|
||||||
(pubkey, channel_id, &buf[8..len])
|
(pubkey, channel_id, &buf[8..len], true)
|
||||||
} else {
|
} else {
|
||||||
drop(pins);
|
drop(pins);
|
||||||
|
|
||||||
match self.find_voice_sender(&addr).await {
|
match self.find_voice_sender(&addr).await {
|
||||||
Some((pubkey, channel_id)) => (pubkey, channel_id, &buf[..]),
|
Some((pubkey, channel_id)) => (pubkey, channel_id, &buf[..len], false),
|
||||||
None => {
|
None => {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -69,8 +71,31 @@ impl Server {
|
|||||||
|
|
||||||
drop(voice);
|
drop(voice);
|
||||||
|
|
||||||
self.relay_voice(&sender_pubkey, &channel_id, payload)
|
// The pin-bearing bootstrap packet carries no payload to decrypt —
|
||||||
.await?;
|
// it's purely "here's my pin, bind my address." Everything after
|
||||||
|
// this first packet is the real, encrypted audio stream.
|
||||||
|
if is_first_packet {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let decrypted_payload = match user.cihper.lock().await.decrypt(payload) {
|
||||||
|
Ok(pt) => pt,
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("[vc] dropping packet: decryption failed: {e}");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let s = self.clone();
|
||||||
|
|
||||||
|
tokio::spawn(async move {
|
||||||
|
if let Err(e) = s
|
||||||
|
.relay_voice(&sender_pubkey, &channel_id, &decrypted_payload)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
eprintln!("{e}");
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,7 +146,11 @@ impl Server {
|
|||||||
voice.last_speaking_sent = now;
|
voice.last_speaking_sent = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = self.udp_send_to(&voice.addr, payload).await;
|
if *sender == user.public_key {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let _ = self.udp_send_to(&user.cihper, &voice.addr, payload).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -133,10 +162,17 @@ impl Server {
|
|||||||
.context("Failed to get voice socket")
|
.context("Failed to get voice socket")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn udp_send_to(&self, addr: &SocketAddr, payload: &[u8]) -> anyhow::Result<()> {
|
pub async fn udp_send_to(
|
||||||
|
&self,
|
||||||
|
cipher: &Arc<Mutex<SessionCipher>>,
|
||||||
|
addr: &SocketAddr,
|
||||||
|
payload: &[u8],
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
let socket = self.get_voice_socket()?;
|
let socket = self.get_voice_socket()?;
|
||||||
|
|
||||||
socket.send_to(payload, addr).await?;
|
socket
|
||||||
|
.send_to(&cipher.lock().await.encrypt(payload)?, addr)
|
||||||
|
.await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +1,31 @@
|
|||||||
use std::borrow::Cow;
|
use std::{borrow::Cow, sync::Arc};
|
||||||
|
|
||||||
use axum::extract::ws::{Message, Utf8Bytes, WebSocket};
|
use axum::extract::ws::{Message, WebSocket};
|
||||||
use futures_util::{
|
use futures_util::{
|
||||||
SinkExt, StreamExt,
|
SinkExt, StreamExt,
|
||||||
stream::{SplitSink, SplitStream},
|
stream::{SplitSink, SplitStream},
|
||||||
};
|
};
|
||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
|
|
||||||
use crate::protocol::{ClientMethod, ServerMethod};
|
use crate::{
|
||||||
|
crypto::SessionCipher,
|
||||||
|
protocol::{ClientMethod, ServerMethod},
|
||||||
|
};
|
||||||
|
|
||||||
pub struct EnclaveWebSocket {
|
pub struct EnclaveWebSocket {
|
||||||
tx: Mutex<SplitSink<WebSocket, Message>>,
|
tx: Mutex<SplitSink<WebSocket, Message>>,
|
||||||
rx: Mutex<SplitStream<WebSocket>>,
|
rx: Mutex<SplitStream<WebSocket>>,
|
||||||
|
pub cipher: Arc<Mutex<SessionCipher>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EnclaveWebSocket {
|
impl EnclaveWebSocket {
|
||||||
pub fn new(ws: WebSocket) -> Self {
|
pub fn new(ws: WebSocket, cipher: Arc<Mutex<SessionCipher>>) -> Self {
|
||||||
let (tx, rx) = ws.split();
|
let (tx, rx) = ws.split();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
tx: Mutex::new(tx),
|
tx: Mutex::new(tx),
|
||||||
rx: Mutex::new(rx),
|
rx: Mutex::new(rx),
|
||||||
|
cipher,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,6 +44,23 @@ impl EnclaveWebSocket {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Some(Message::Binary(encrypted)) => {
|
||||||
|
let text = String::from_utf8(self.cipher.lock().await.decrypt(&encrypted)?)?;
|
||||||
|
|
||||||
|
match serde_json::from_str(&text.to_string()) {
|
||||||
|
Ok(msg) => Ok(Some(msg)),
|
||||||
|
|
||||||
|
Err(e) => {
|
||||||
|
self.send(&ClientMethod::Error {
|
||||||
|
error: Cow::Owned(format!("Unable to parse message: {e}")),
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Some(Message::Ping(v)) => {
|
Some(Message::Ping(v)) => {
|
||||||
self.tx.lock().await.send(Message::Pong(v)).await?;
|
self.tx.lock().await.send(Message::Pong(v)).await?;
|
||||||
|
|
||||||
@@ -52,12 +74,14 @@ impl EnclaveWebSocket {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send(&self, message: &ClientMethod) -> anyhow::Result<()> {
|
pub async fn send(&self, message: &ClientMethod) -> anyhow::Result<()> {
|
||||||
|
let text = serde_json::to_string(message)?;
|
||||||
|
|
||||||
|
let encrypted = self.cipher.lock().await.encrypt(text.as_bytes())?;
|
||||||
|
|
||||||
self.tx
|
self.tx
|
||||||
.lock()
|
.lock()
|
||||||
.await
|
.await
|
||||||
.send(Message::Text(Utf8Bytes::from(serde_json::to_string(
|
.send(Message::Binary(encrypted.into()))
|
||||||
message,
|
|
||||||
)?)))
|
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
Reference in New Issue
Block a user