crypto handshake and encryption
This commit is contained in:
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"
|
||||||
|
|||||||
+120
-1
@@ -1,7 +1,17 @@
|
|||||||
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 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 +55,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<Arc<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!(""));
|
||||||
|
};
|
||||||
|
|
||||||
|
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 = SessionCipher::new(&shared_secret)?;
|
||||||
|
|
||||||
|
Ok(Arc::new(EnclaveWebSocket::new(socket, cipher)))
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use ed25519_dalek::{Signer, VerifyingKey};
|
use ed25519_dalek::{Signer, VerifyingKey};
|
||||||
use futures_util::SinkExt;
|
|
||||||
|
|
||||||
use crate::{server::Server, ws::EnclaveWebSocket};
|
use crate::{server::Server, ws::EnclaveWebSocket};
|
||||||
|
|
||||||
@@ -14,18 +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: &Arc<EnclaveWebSocket>,
|
||||||
) -> anyhow::Result<(Arc<EnclaveWebSocket>, VerifyingKey, ClientMeta)> {
|
) -> anyhow::Result<(VerifyingKey, ClientMeta)> {
|
||||||
{
|
|
||||||
socket
|
|
||||||
.tx()
|
|
||||||
.await
|
|
||||||
.send(axum::extract::ws::Message::Binary(
|
|
||||||
server.key.verifying_key().to_bytes().to_vec().into(),
|
|
||||||
))
|
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
|
|
||||||
let Some(ServerMethod::Initialize {
|
let Some(ServerMethod::Initialize {
|
||||||
public_key: public_key_string,
|
public_key: public_key_string,
|
||||||
signature,
|
signature,
|
||||||
@@ -122,6 +111,6 @@ impl UserConnections {
|
|||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok((socket, public_key, meta))
|
Ok((public_key, meta))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-4
@@ -21,8 +21,8 @@ use crate::{
|
|||||||
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,
|
||||||
@@ -40,6 +40,7 @@ pub struct UserConnections {
|
|||||||
|
|
||||||
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 +51,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 +74,13 @@ 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 Ok(client) = crate::crypto::crypto_handshake(&s, socket).await else {
|
||||||
Ok((client, public_key, meta)) => {
|
eprintln!("Filed to initialize crypto");
|
||||||
|
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)
|
||||||
|
|||||||
@@ -1,26 +1,31 @@
|
|||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
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, MutexGuard};
|
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>>,
|
||||||
|
cihper: Mutex<SessionCipher>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EnclaveWebSocket {
|
impl EnclaveWebSocket {
|
||||||
pub fn new(ws: WebSocket) -> Self {
|
pub fn new(ws: WebSocket, cipher: 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),
|
||||||
|
cihper: Mutex::new(cipher),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,6 +44,23 @@ impl EnclaveWebSocket {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Some(Message::Binary(encrypted)) => {
|
||||||
|
let text = String::from_utf8(self.cihper.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,18 +74,16 @@ 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.cihper.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(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn tx(&self) -> MutexGuard<'_, SplitSink<WebSocket, Message>> {
|
|
||||||
self.tx.lock().await
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user