Updated Crypto to use MTP-Crypto

This commit is contained in:
Alex Emmet 2026-07-03 06:28:08 +02:00
commit 594f13e974
10 changed files with 465 additions and 513 deletions

4
.gitignore vendored
View file

@ -15,5 +15,5 @@ target
# Added by cargo # Added by cargo
/target **/target
/logs **/logs

444
Cargo.lock generated
View file

@ -12,31 +12,6 @@ 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 0.2.17",
]
[[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 = "aho-corasick" name = "aho-corasick"
version = "1.1.4" version = "1.1.4"
@ -277,9 +252,9 @@ checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
[[package]] [[package]]
name = "aws-lc-rs" name = "aws-lc-rs"
version = "1.17.0" version = "1.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ec2f1fc3ec205783a5da9a7e6c1509cc69dedf09a1949e412c1e18469326d00" checksum = "4342d8937fc7e5dd9b1c60292261c0670c882a2cd1719cfc11b1af41731e32ad"
dependencies = [ dependencies = [
"aws-lc-sys", "aws-lc-sys",
"untrusted 0.7.1", "untrusted 0.7.1",
@ -288,14 +263,15 @@ dependencies = [
[[package]] [[package]]
name = "aws-lc-sys" name = "aws-lc-sys"
version = "0.41.0" version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a2f9779ce85b93ab6170dd940ad0169b5766ff848247aff13bb788b832fe3f4" checksum = "6d9ceb1da931507a12f4fccea479dccd00da1943e1b4ae72d8e502d707361444"
dependencies = [ dependencies = [
"cc", "cc",
"cmake", "cmake",
"dunce", "dunce",
"fs_extra", "fs_extra",
"pkg-config",
] ]
[[package]] [[package]]
@ -310,6 +286,12 @@ version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]]
name = "base64ct"
version = "1.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06"
[[package]] [[package]]
name = "bit-vec" name = "bit-vec"
version = "0.9.1" version = "0.9.1"
@ -413,6 +395,30 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
[[package]]
name = "chacha20"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818"
dependencies = [
"cfg-if",
"cipher",
"cpufeatures 0.2.17",
]
[[package]]
name = "chacha20poly1305"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35"
dependencies = [
"aead",
"chacha20",
"cipher",
"poly1305",
"zeroize",
]
[[package]] [[package]]
name = "chrono" name = "chrono"
version = "0.4.45" version = "0.4.45"
@ -430,6 +436,7 @@ checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
dependencies = [ dependencies = [
"crypto-common 0.1.7", "crypto-common 0.1.7",
"inout", "inout",
"zeroize",
] ]
[[package]] [[package]]
@ -466,6 +473,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 = "const-oid" name = "const-oid"
version = "0.10.2" version = "0.10.2"
@ -553,16 +566,9 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453"
dependencies = [ dependencies = [
"getrandom 0.4.3",
"hybrid-array", "hybrid-array",
] "rand_core 0.10.1",
[[package]]
name = "ctr"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835"
dependencies = [
"cipher",
] ]
[[package]] [[package]]
@ -574,6 +580,33 @@ dependencies = [
"cmov", "cmov",
] ]
[[package]]
name = "curve25519-dalek"
version = "4.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be"
dependencies = [
"cfg-if",
"cpufeatures 0.2.17",
"curve25519-dalek-derive",
"digest 0.10.7",
"fiat-crypto",
"rustc_version",
"subtle",
"zeroize",
]
[[package]]
name = "curve25519-dalek-derive"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "dashmap" name = "dashmap"
version = "6.2.1" version = "6.2.1"
@ -594,6 +627,27 @@ version = "2.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8" checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8"
[[package]]
name = "der"
version = "0.7.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb"
dependencies = [
"const-oid 0.9.6",
"pem-rfc7468",
"zeroize",
]
[[package]]
name = "der"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71fd89660b2dc699704064e59e9dba0147b903e85319429e131620d022be411b"
dependencies = [
"const-oid 0.10.2",
"zeroize",
]
[[package]] [[package]]
name = "der-parser" name = "der-parser"
version = "10.0.0" version = "10.0.0"
@ -647,7 +701,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2"
dependencies = [ dependencies = [
"block-buffer 0.12.1", "block-buffer 0.12.1",
"const-oid", "const-oid 0.10.2",
"crypto-common 0.2.2", "crypto-common 0.2.2",
"ctutils", "ctutils",
] ]
@ -686,14 +740,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
[[package]] [[package]]
name = "ed448-goldilocks" name = "ed25519"
version = "0.7.2" version = "2.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87b5fa9e9e3dd5fe1369f380acd3dcdfa766dbd0a1cd5b048fb40e38a6a78e79" checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53"
dependencies = [ dependencies = [
"fiat-crypto", "pkcs8 0.10.2",
"hex", "signature 2.2.0",
]
[[package]]
name = "ed25519-dalek"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9"
dependencies = [
"curve25519-dalek",
"ed25519",
"serde",
"sha2 0.10.9",
"subtle", "subtle",
"zeroize",
] ]
[[package]] [[package]]
@ -765,9 +832,9 @@ checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6"
[[package]] [[package]]
name = "fiat-crypto" name = "fiat-crypto"
version = "0.1.20" 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 = "e825f6987101665dea6ec934c09ec6d721de7bc1bf92248e1d5810c8cd636b77" checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
[[package]] [[package]]
name = "find-msvc-tools" name = "find-msvc-tools"
@ -958,16 +1025,7 @@ dependencies = [
"cfg-if", "cfg-if",
"libc", "libc",
"r-efi 6.0.0", "r-efi 6.0.0",
] "rand_core 0.10.1",
[[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]]
@ -1012,12 +1070,6 @@ version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
[[package]]
name = "hex"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]] [[package]]
name = "hickory-proto" name = "hickory-proto"
version = "0.25.2" version = "0.25.2"
@ -1142,6 +1194,7 @@ version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "818356c5132c1fede50f837ca96afbe78ff42413047f4abb886217845e1b6c8c" checksum = "818356c5132c1fede50f837ca96afbe78ff42413047f4abb886217845e1b6c8c"
dependencies = [ dependencies = [
"ctutils",
"typenum", "typenum",
] ]
@ -1451,10 +1504,29 @@ dependencies = [
"js-sys", "js-sys",
"serde", "serde",
"serde_json", "serde_json",
"signature", "signature 2.2.0",
"zeroize", "zeroize",
] ]
[[package]]
name = "keccak"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653"
dependencies = [
"cpufeatures 0.2.17",
]
[[package]]
name = "keccak"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e24a010dd405bd7ed803e5253182815b41bf2e6a80cc3bfc066658e03a198aa"
dependencies = [
"cfg-if",
"cpufeatures 0.3.0",
]
[[package]] [[package]]
name = "kv-log-macro" name = "kv-log-macro"
version = "1.0.7" version = "1.0.7"
@ -1512,7 +1584,7 @@ dependencies = [
"serde", "serde",
"serde_json", "serde_json",
"sha2 0.10.9", "sha2 0.10.9",
"signature", "signature 2.2.0",
"thiserror 2.0.18", "thiserror 2.0.18",
"tokio-tungstenite", "tokio-tungstenite",
"url", "url",
@ -1520,9 +1592,9 @@ dependencies = [
[[package]] [[package]]
name = "livekit-protocol" name = "livekit-protocol"
version = "0.7.9" 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 = "35609e3b2a077801c198f4f3de70f6cee4f2ba189d02b8876b99b96be43d0284" checksum = "4d26880e94e2f9bab298445e7d86a3794453d211a12ddbd051bd9991a343f9ff"
dependencies = [ dependencies = [
"pbjson", "pbjson",
"pbjson-types", "pbjson-types",
@ -1577,6 +1649,59 @@ dependencies = [
"windows-sys 0.61.2", "windows-sys 0.61.2",
] ]
[[package]]
name = "ml-dsa"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "add6b9d92e496f16f4526d68ff29da1483aba4b119baeab8bed3b9e3544a6f3d"
dependencies = [
"const-oid 0.10.2",
"crypto-common 0.2.2",
"ctutils",
"hybrid-array",
"module-lattice",
"pkcs8 0.11.0",
"shake",
"signature 3.0.0",
]
[[package]]
name = "mlkem-rs"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b0965b8b081668ff0398dc5e9dc3f2ebb9e833393f4ab5b9f725ddce11acef8"
dependencies = [
"rand_core 0.6.4",
"serde",
"sha3",
"subtle",
"zeroize",
]
[[package]]
name = "mlkem-tls"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77b205d031298adf904d88efd6a57862d8650a4ab754aade19a9b5e87040bf4e"
dependencies = [
"mlkem-rs",
"rand_core 0.6.4",
"subtle",
"x25519-dalek",
"zeroize",
]
[[package]]
name = "module-lattice"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c61b87c9683ab7cb1c6871d261ad5479b6b10ceb52c4352aaca3b5d35a8febe"
dependencies = [
"ctutils",
"hybrid-array",
"num-traits",
]
[[package]] [[package]]
name = "moka" name = "moka"
version = "0.12.15" version = "0.12.15"
@ -1597,11 +1722,12 @@ dependencies = [
[[package]] [[package]]
name = "mtp" name = "mtp"
version = "0.1.0" version = "0.1.0"
source = "git+https://git.methanium.net/Methanium/mtp.git#15cc1d4c5e6a917f197ebf6685c8cea4e3ab668f" source = "git+https://git.methanium.net/Methanium/mtp.git#56903049b66d67a5a34f8b6fb78820f19771f2f4"
dependencies = [ dependencies = [
"mtp-client", "mtp-client",
"mtp-codec", "mtp-codec",
"mtp-common", "mtp-common",
"mtp-crypto",
"mtp-host", "mtp-host",
"mtp-transport", "mtp-transport",
"mtp-type-map", "mtp-type-map",
@ -1610,10 +1736,11 @@ dependencies = [
[[package]] [[package]]
name = "mtp-client" name = "mtp-client"
version = "0.1.0" version = "0.1.0"
source = "git+https://git.methanium.net/Methanium/mtp.git#15cc1d4c5e6a917f197ebf6685c8cea4e3ab668f" source = "git+https://git.methanium.net/Methanium/mtp.git#56903049b66d67a5a34f8b6fb78820f19771f2f4"
dependencies = [ dependencies = [
"mtp-codec", "mtp-codec",
"mtp-common", "mtp-common",
"mtp-crypto",
"mtp-transport", "mtp-transport",
"rand 0.8.6", "rand 0.8.6",
"tokio", "tokio",
@ -1622,11 +1749,12 @@ dependencies = [
[[package]] [[package]]
name = "mtp-codec" name = "mtp-codec"
version = "0.1.0" version = "0.1.0"
source = "git+https://git.methanium.net/Methanium/mtp.git#15cc1d4c5e6a917f197ebf6685c8cea4e3ab668f" source = "git+https://git.methanium.net/Methanium/mtp.git#56903049b66d67a5a34f8b6fb78820f19771f2f4"
dependencies = [ dependencies = [
"base64 0.22.1", "base64 0.22.1",
"byteorder", "byteorder",
"mtp-common", "mtp-common",
"mtp-crypto",
"mtp-type-map", "mtp-type-map",
"rand 0.8.6", "rand 0.8.6",
] ]
@ -1634,7 +1762,7 @@ dependencies = [
[[package]] [[package]]
name = "mtp-common" name = "mtp-common"
version = "0.1.0" version = "0.1.0"
source = "git+https://git.methanium.net/Methanium/mtp.git#15cc1d4c5e6a917f197ebf6685c8cea4e3ab668f" source = "git+https://git.methanium.net/Methanium/mtp.git#56903049b66d67a5a34f8b6fb78820f19771f2f4"
dependencies = [ dependencies = [
"quinn", "quinn",
"rustls", "rustls",
@ -1642,13 +1770,32 @@ dependencies = [
"wtransport", "wtransport",
] ]
[[package]]
name = "mtp-crypto"
version = "0.1.0"
source = "git+https://git.methanium.net/Methanium/mtp.git#56903049b66d67a5a34f8b6fb78820f19771f2f4"
dependencies = [
"chacha20poly1305",
"ed25519-dalek",
"getrandom 0.4.3",
"hkdf",
"ml-dsa",
"mlkem-tls",
"rand_core 0.6.4",
"serde",
"sha2 0.11.0",
"thiserror 1.0.69",
"zeroize",
]
[[package]] [[package]]
name = "mtp-host" name = "mtp-host"
version = "0.1.0" version = "0.1.0"
source = "git+https://git.methanium.net/Methanium/mtp.git#15cc1d4c5e6a917f197ebf6685c8cea4e3ab668f" source = "git+https://git.methanium.net/Methanium/mtp.git#56903049b66d67a5a34f8b6fb78820f19771f2f4"
dependencies = [ dependencies = [
"mtp-codec", "mtp-codec",
"mtp-common", "mtp-common",
"mtp-crypto",
"mtp-transport", "mtp-transport",
"rand 0.8.6", "rand 0.8.6",
"tokio", "tokio",
@ -1657,7 +1804,7 @@ dependencies = [
[[package]] [[package]]
name = "mtp-transport" name = "mtp-transport"
version = "0.1.0" version = "0.1.0"
source = "git+https://git.methanium.net/Methanium/mtp.git#15cc1d4c5e6a917f197ebf6685c8cea4e3ab668f" source = "git+https://git.methanium.net/Methanium/mtp.git#56903049b66d67a5a34f8b6fb78820f19771f2f4"
dependencies = [ dependencies = [
"log", "log",
"mtp-codec", "mtp-codec",
@ -1671,7 +1818,7 @@ dependencies = [
[[package]] [[package]]
name = "mtp-type-map" name = "mtp-type-map"
version = "0.1.0" version = "0.1.0"
source = "git+https://git.methanium.net/Methanium/mtp.git#15cc1d4c5e6a917f197ebf6685c8cea4e3ab668f" source = "git+https://git.methanium.net/Methanium/mtp.git#56903049b66d67a5a34f8b6fb78820f19771f2f4"
dependencies = [ dependencies = [
"serde", "serde",
"serde_yaml", "serde_yaml",
@ -1934,15 +2081,12 @@ dependencies = [
name = "omikron" name = "omikron"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"aes-gcm",
"ansi_term", "ansi_term",
"base64 0.22.1", "base64 0.22.1",
"dashmap", "dashmap",
"dotenv", "dotenv",
"futures", "futures",
"hex",
"hickory-resolver", "hickory-resolver",
"hkdf",
"json", "json",
"livekit-api", "livekit-api",
"livekit-protocol", "livekit-protocol",
@ -1950,17 +2094,14 @@ dependencies = [
"mtp", "mtp",
"once_cell", "once_cell",
"rand 0.8.6", "rand 0.8.6",
"rand_core 0.6.4",
"rustls", "rustls",
"serde", "serde",
"serde_json", "serde_json",
"sha2 0.11.0",
"strum", "strum",
"strum_macros", "strum_macros",
"thiserror 2.0.18", "thiserror 2.0.18",
"tokio", "tokio",
"uuid", "uuid",
"x448",
] ]
[[package]] [[package]]
@ -2114,6 +2255,15 @@ dependencies = [
"serde_core", "serde_core",
] ]
[[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.2" version = "2.3.2"
@ -2153,6 +2303,26 @@ dependencies = [
"futures-io", "futures-io",
] ]
[[package]]
name = "pkcs8"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7"
dependencies = [
"der 0.7.10",
"spki 0.7.3",
]
[[package]]
name = "pkcs8"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "451913da69c775a56034ea8d9003d27ee8948e12443eae7c038ba100a4f21cb7"
dependencies = [
"der 0.8.0",
"spki 0.8.0",
]
[[package]] [[package]]
name = "pkg-config" name = "pkg-config"
version = "0.3.33" version = "0.3.33"
@ -2174,12 +2344,11 @@ dependencies = [
] ]
[[package]] [[package]]
name = "polyval" name = "poly1305"
version = "0.6.2" version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf"
dependencies = [ dependencies = [
"cfg-if",
"cpufeatures 0.2.17", "cpufeatures 0.2.17",
"opaque-debug", "opaque-debug",
"universal-hash", "universal-hash",
@ -2405,12 +2574,6 @@ dependencies = [
"rand_core 0.9.5", "rand_core 0.9.5",
] ]
[[package]]
name = "rand_core"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
[[package]] [[package]]
name = "rand_core" name = "rand_core"
version = "0.6.4" version = "0.6.4"
@ -2429,6 +2592,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 = "rcgen" name = "rcgen"
version = "0.14.8" version = "0.14.8"
@ -2542,6 +2711,15 @@ version = "2.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe"
[[package]]
name = "rustc_version"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
dependencies = [
"semver",
]
[[package]] [[package]]
name = "rusticata-macros" name = "rusticata-macros"
version = "4.1.0" version = "4.1.0"
@ -2594,9 +2772,9 @@ dependencies = [
[[package]] [[package]]
name = "rustls-pki-types" name = "rustls-pki-types"
version = "1.14.1" version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" checksum = "764899a24af3980067ee14bc143654f297b22eaebfe3c7b6b211920a5a59b046"
dependencies = [ dependencies = [
"web-time", "web-time",
"zeroize", "zeroize",
@ -2673,6 +2851,12 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "semver"
version = "1.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.228" version = "1.0.228"
@ -2774,6 +2958,27 @@ dependencies = [
"digest 0.11.3", "digest 0.11.3",
] ]
[[package]]
name = "sha3"
version = "0.10.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77fd7028345d415a4034cf8777cd4f8ab1851274233b45f84e3d955502d93874"
dependencies = [
"digest 0.10.7",
"keccak 0.1.6",
]
[[package]]
name = "shake"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09057cb2149ad4cbd2da1e26b351f9a4c354219421229c69c3063e6f61947c4a"
dependencies = [
"digest 0.11.3",
"keccak 0.2.0",
"sponge-cursor",
]
[[package]] [[package]]
name = "shlex" name = "shlex"
version = "2.0.1" version = "2.0.1"
@ -2799,6 +3004,16 @@ dependencies = [
"rand_core 0.6.4", "rand_core 0.6.4",
] ]
[[package]]
name = "signature"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28d567dcbaf0049cb8ac2608a76cd95ff9e4412e1899d389ee400918ca7537f5"
dependencies = [
"digest 0.11.3",
"rand_core 0.10.1",
]
[[package]] [[package]]
name = "slab" name = "slab"
version = "0.4.12" version = "0.4.12"
@ -2821,6 +3036,32 @@ dependencies = [
"windows-sys 0.61.2", "windows-sys 0.61.2",
] ]
[[package]]
name = "spki"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d"
dependencies = [
"base64ct",
"der 0.7.10",
]
[[package]]
name = "spki"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d9efca8738c78ee9484207732f728b1ef517bbb1833d6fc0879ca898a522f6f"
dependencies = [
"base64ct",
"der 0.8.0",
]
[[package]]
name = "sponge-cursor"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a0219bd7d979d58245a4f41f695e1ac9f8befdffadd7f61f1bae9e39abc6620"
[[package]] [[package]]
name = "stable_deref_trait" name = "stable_deref_trait"
version = "1.2.1" version = "1.2.1"
@ -2943,9 +3184,9 @@ dependencies = [
[[package]] [[package]]
name = "time" name = "time"
version = "0.3.51" version = "0.3.53"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85c17d80feb7334b40c484e45ed1a5273dfd8bfda537c3be2e74a06a6686f327" checksum = "18dfaaeddcb932337b5e7866ee7d0ce9b76d2fd092997146f187ec09b4558a50"
dependencies = [ dependencies = [
"deranged", "deranged",
"num-conv", "num-conv",
@ -2963,9 +3204,9 @@ checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109"
[[package]] [[package]]
name = "time-macros" name = "time-macros"
version = "0.2.30" version = "0.2.31"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcef1a61bdb119096e153208ec5cbec23944ce8bca13be5c7f60c634f7403935" checksum = "c431b87111666e491a90baa837f914fb45cd5dc3c268591b0220ff5057f2085f"
dependencies = [ dependencies = [
"num-conv", "num-conv",
"time-core", "time-core",
@ -3721,14 +3962,15 @@ dependencies = [
] ]
[[package]] [[package]]
name = "x448" name = "x25519-dalek"
version = "0.6.0" version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4cd07d4fae29e07089dbcacf7077cd52dce7760125ca9a4dd5a35ca603ffebb" checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277"
dependencies = [ dependencies = [
"ed448-goldilocks", "curve25519-dalek",
"hex", "rand_core 0.6.4",
"rand_core 0.5.1", "serde",
"zeroize",
] ]
[[package]] [[package]]

View file

@ -4,30 +4,28 @@ version = "0.1.0"
edition = "2024" edition = "2024"
[dependencies] [dependencies]
mtp = { git = "https://git.methanium.net/Methanium/mtp.git", features = ["host", "client"] } mtp = { git = "https://git.methanium.net/Methanium/mtp.git", features = [
"host",
"client",
"crypto",
] }
ansi_term = "*" ansi_term = "*"
uuid = { version = "*", features = ["v4"] } uuid = { version = "*", features = ["v4"] }
base64 = "0.22.1" base64 = "0.22.1"
dashmap = "*" dashmap = "*"
futures = "*" futures = "*"
hex = "*"
once_cell = "1.21.4" once_cell = "1.21.4"
rand = "0.8" rand = "0.8"
rand_core = { version = "0.6", features = ["getrandom", "std"] }
rustls = { version = "0.23.40", default-features = false, features = [ rustls = { version = "0.23.40", default-features = false, features = [
"std", "std",
"tls12", "tls12",
"aws-lc-rs", "aws-lc-rs",
"prefer-post-quantum", "prefer-post-quantum",
] } ] }
aes-gcm = "0.10.3"
sha2 = "0.11.0"
tokio = { version = "*", features = ["full"] } tokio = { version = "*", features = ["full"] }
x448 = { version = "*" }
log = "0.4" log = "0.4"
dotenv = "0.15.0" dotenv = "0.15.0"
hkdf = "0.13"
strum = "0.28.0" strum = "0.28.0"
strum_macros = "0.28.0" strum_macros = "0.28.0"
livekit-api = { version = "0.5.0", features = ["native-tls"] } livekit-api = { version = "0.5.0", features = ["native-tls"] }

View file

@ -11,28 +11,37 @@ use std::path::PathBuf;
use dotenv::dotenv; use dotenv::dotenv;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
pub static WORKING_DIR: Lazy<PathBuf> = Lazy::new(|| { pub static WORKING_DIR: Lazy<PathBuf> =
std::env::current_dir().unwrap_or_else(|_| PathBuf::from(".")) Lazy::new(|| std::env::current_dir().unwrap_or_else(|_| PathBuf::from(".")));
});
use rustls::crypto::aws_lc_rs::default_provider; use rustls::crypto::aws_lc_rs::default_provider;
use base64::engine::general_purpose::STANDARD as BASE64_STD;
use base64::Engine as _;
use mtp::crypto::Keyring;
use crate::{ use crate::{
calls::call_util::garbage_collect_calls, calls::call_util::garbage_collect_calls,
omega::omega_connection::get_omega_connection, omega::omega_connection::get_omega_connection,
rho::server::start, rho::server::start,
util::{ util::logger::startup,
crypto_helper::{load_public_key, load_secret_key},
logger::startup,
},
}; };
static PRIVATE_KEY: Lazy<String> = Lazy::new(|| env::var("PRIVATE_KEY").unwrap()); static KEYRING: Lazy<Keyring> = Lazy::new(|| {
pub fn get_private_key() -> x448::Secret { if let Ok(encoded) = env::var("KEYRING") {
load_secret_key(&*PRIVATE_KEY).unwrap() let bytes = BASE64_STD.decode(&encoded).expect("Invalid KEYRING base64");
} Keyring::from_bytes(&bytes).expect("Invalid KEYRING data")
static PUBLIC_KEY: Lazy<String> = Lazy::new(|| env::var("PUBLIC_KEY").unwrap()); } else {
pub fn get_public_key() -> x448::PublicKey { let kr = Keyring::generate();
load_public_key(&*PUBLIC_KEY).unwrap() eprintln!(
"Generated KEYRING (save to env): {}",
BASE64_STD.encode(&kr.to_bytes())
);
kr
}
});
pub fn get_keyring() -> &'static Keyring {
&KEYRING
} }
#[tokio::main] #[tokio::main]

View file

@ -1,9 +1,12 @@
use base64::engine::general_purpose::STANDARD as BASE64_STD;
use base64::Engine as _;
use mtp::crypto::decrypt_with;
use crate::{ use crate::{
data::user::UserStatus, data::user::UserStatus,
get_private_key, log, log_cv_in, log_cv_out, log_err, log_in, get_keyring, log, log_cv_in, log_cv_out, log_err, log_in,
rho::rho_manager::{self, RHO_CONNECTIONS, connection_count}, rho::rho_manager::{self, RHO_CONNECTIONS, connection_count},
util::{ util::{
crypto_helper::{decrypt_b64, secret_key_to_base64},
file_util::load_file_vec, file_util::load_file_vec,
logger::PrintType, logger::PrintType,
}, },
@ -389,22 +392,18 @@ impl OmegaConnection {
} }
async fn handle_challenge(&self, cv: CommunicationValue) -> Result<(), String> { async fn handle_challenge(&self, cv: CommunicationValue) -> Result<(), String> {
let challenge = cv let challenge_b64 = cv
.get_data(DataType::Challenge) .get_data(DataType::Challenge)
.as_str() .as_str()
.ok_or("Challenge not found")?; .ok_or("Challenge not found")?;
let server_pub_key = cv let blob = BASE64_STD
.get_data(DataType::PublicKey) .decode(challenge_b64)
.as_str() .map_err(|e| format!("Base64 decode failed: {}", e))?;
.ok_or("Public key not found")?; let decrypted = decrypt_with(&blob, get_keyring(), b"challenge")
.map_err(|e| format!("Decryption failed: {:?}", e))?;
let decrypted_challenge = decrypt_b64( let decrypted_challenge =
&secret_key_to_base64(&get_private_key()), String::from_utf8(decrypted).map_err(|_| "Decrypted challenge not valid UTF-8")?;
server_pub_key,
challenge,
)
.map_err(|e| format!("Decryption failed: {:?}", e))?;
let response_msg = CommunicationValue::new(CommunicationType::ChallengeResponse) let response_msg = CommunicationValue::new(CommunicationType::ChallengeResponse)
.with_id(cv.get_id()) .with_id(cv.get_id())

View file

@ -5,20 +5,23 @@ use std::{collections::BTreeMap, collections::HashMap, sync::Arc, time::Duration
use tokio::sync::RwLock; use tokio::sync::RwLock;
use uuid::Uuid; use uuid::Uuid;
use base64::engine::general_purpose::STANDARD as BASE64_STD;
use base64::Engine as _;
use mtp::crypto::{
encrypt_for, EncryptionType, KemPublicKey, PublicKeyBundle, SignaturePqPublicKey,
SignaturePublicKey,
};
use crate::{ use crate::{
anonymous_clients::anonymous_client_connection::AnonymousClientConnection, anonymous_clients::anonymous_client_connection::AnonymousClientConnection,
calls::call_manager, calls::call_manager,
get_private_key, get_public_key, log_cv_in, log_cv_out, log_err, log_in, log_out, get_keyring, log_cv_in, log_cv_out, log_err, log_in, log_out,
omega::omega_connection::get_omega_connection, omega::omega_connection::get_omega_connection,
rho::{ rho::{
app_connection::AppConnection, client_connection::ClientConnection, app_connection::AppConnection, client_connection::ClientConnection,
iota_connection::IotaConnection, rho_connection::RhoConnection, rho_manager, iota_connection::IotaConnection, rho_connection::RhoConnection, rho_manager,
}, },
util::{ util::logger::PrintType,
crypto_helper::{load_public_key, public_key_to_base64},
crypto_util::{DataFormat, SecurePayload},
logger::PrintType,
},
}; };
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
@ -146,11 +149,11 @@ impl GeneralConnection {
*self.app_session.write().await = Some(app_session_id); *self.app_session.write().await = Some(app_session_id);
*self.connection_kind.write().await = Some(ConnectionKind::Phi); *self.connection_kind.write().await = Some(ConnectionKind::Phi);
let pub_key = match load_public_key(pub_key_str) { let kem_bytes = match BASE64_STD.decode(pub_key_str) {
Some(pk) => pk, Ok(b) => b,
None => return, Err(_) => return,
}; };
*self.pub_key.write().await = Some(pub_key.as_bytes().to_vec()); *self.pub_key.write().await = Some(kem_bytes.clone());
let challenge: String = rand::thread_rng() let challenge: String = rand::thread_rng()
.sample_iter(&Alphanumeric) .sample_iter(&Alphanumeric)
@ -161,18 +164,29 @@ impl GeneralConnection {
*self.challenge.write().await = challenge.clone(); *self.challenge.write().await = challenge.clone();
*self.identified.write().await = true; *self.identified.write().await = true;
let encrypted_challenge = let peer_bundle = PublicKeyBundle::new(
SecurePayload::new(challenge.as_bytes(), DataFormat::Raw, get_private_key()) KemPublicKey::new(kem_bytes),
.unwrap() SignaturePqPublicKey::new(vec![]),
.encrypt_x448(pub_key) SignaturePublicKey::new(vec![]),
.unwrap() );
.export(DataFormat::Base64); let encrypted_challenge = BASE64_STD.encode(
&encrypt_for(
EncryptionType::MlKemChaCha20Poly1305,
&peer_bundle,
challenge.as_bytes(),
b"challenge",
)
.unwrap(),
);
let our_pk = BASE64_STD.encode(
get_keyring().public_key_bundle().kem_public_key.as_bytes(),
);
let response = CommunicationValue::new(CommunicationType::AppChallenge) let response = CommunicationValue::new(CommunicationType::AppChallenge)
.with_id(cv.get_id()) .with_id(cv.get_id())
.add_typed_default( .add_typed_default(
DataType::PublicKey, DataType::PublicKey,
DataValue::Str(public_key_to_base64(&get_public_key())), DataValue::Str(our_pk),
) )
.add_typed_default(DataType::Challenge, DataValue::Str(encrypted_challenge)); .add_typed_default(DataType::Challenge, DataValue::Str(encrypted_challenge));
@ -214,20 +228,20 @@ impl GeneralConnection {
.as_str() .as_str()
.unwrap_or(""); .unwrap_or("");
let pub_key = match load_public_key(base64_pub) { let kem_bytes = match BASE64_STD.decode(base64_pub) {
Some(pk) => pk, Ok(b) => b,
None => { Err(_) => {
log_err!( log_err!(
*iota_id as i64, *iota_id as i64,
PrintType::Iota, PrintType::Iota,
"Failed to load public key for iota_id={}", "Failed to decode public key for iota_id={}",
iota_id iota_id
); );
return; return;
} }
}; };
*self.pub_key.write().await = Some(pub_key.as_bytes().to_vec()); *self.pub_key.write().await = Some(kem_bytes.clone());
let challenge: String = rand::thread_rng() let challenge: String = rand::thread_rng()
.sample_iter(&Alphanumeric) .sample_iter(&Alphanumeric)
@ -238,18 +252,29 @@ impl GeneralConnection {
*self.challenge.write().await = challenge.clone(); *self.challenge.write().await = challenge.clone();
*self.identified.write().await = true; *self.identified.write().await = true;
let encrypted_challenge = let peer_bundle = PublicKeyBundle::new(
SecurePayload::new(challenge.as_bytes(), DataFormat::Raw, get_private_key()) KemPublicKey::new(kem_bytes),
.unwrap() SignaturePqPublicKey::new(vec![]),
.encrypt_x448(pub_key) SignaturePublicKey::new(vec![]),
.unwrap() );
.export(DataFormat::Base64); let encrypted_challenge = BASE64_STD.encode(
&encrypt_for(
EncryptionType::MlKemChaCha20Poly1305,
&peer_bundle,
challenge.as_bytes(),
b"challenge",
)
.unwrap(),
);
let our_pk = BASE64_STD.encode(
get_keyring().public_key_bundle().kem_public_key.as_bytes(),
);
let response = CommunicationValue::new(CommunicationType::Challenge) let response = CommunicationValue::new(CommunicationType::Challenge)
.with_id(cv.get_id()) .with_id(cv.get_id())
.add_typed_default( .add_typed_default(
DataType::PublicKey, DataType::PublicKey,
DataValue::Str(public_key_to_base64(&get_public_key())), DataValue::Str(our_pk),
) )
.add_typed_default(DataType::Challenge, DataValue::Str(encrypted_challenge)); .add_typed_default(DataType::Challenge, DataValue::Str(encrypted_challenge));
@ -306,14 +331,14 @@ impl GeneralConnection {
.to_string(); .to_string();
} }
let pub_key = match load_public_key(&base64_pub) { let kem_bytes = match BASE64_STD.decode(&base64_pub) {
Some(pk) => pk, Ok(b) => b,
None => { Err(_) => {
return; return;
} }
}; };
*self.pub_key.write().await = Some(pub_key.as_bytes().to_vec()); *self.pub_key.write().await = Some(kem_bytes.clone());
let challenge: String = rand::thread_rng() let challenge: String = rand::thread_rng()
.sample_iter(&Alphanumeric) .sample_iter(&Alphanumeric)
@ -324,12 +349,20 @@ impl GeneralConnection {
*self.challenge.write().await = challenge.clone(); *self.challenge.write().await = challenge.clone();
*self.identified.write().await = true; *self.identified.write().await = true;
let encrypted_challenge = let peer_bundle = PublicKeyBundle::new(
SecurePayload::new(challenge.as_bytes(), DataFormat::Raw, get_private_key()) KemPublicKey::new(kem_bytes),
.unwrap() SignaturePqPublicKey::new(vec![]),
.encrypt_x448(pub_key) SignaturePublicKey::new(vec![]),
.unwrap() );
.export(DataFormat::Base64); let encrypted_challenge = BASE64_STD.encode(
&encrypt_for(
EncryptionType::MlKemChaCha20Poly1305,
&peer_bundle,
challenge.as_bytes(),
b"challenge",
)
.unwrap(),
);
let challenge_type = if cv.is_type(CommunicationType::AppIdentification) { let challenge_type = if cv.is_type(CommunicationType::AppIdentification) {
CommunicationType::AppChallenge CommunicationType::AppChallenge
@ -337,12 +370,15 @@ impl GeneralConnection {
CommunicationType::Challenge CommunicationType::Challenge
}; };
let our_pk = BASE64_STD.encode(
get_keyring().public_key_bundle().kem_public_key.as_bytes(),
);
let response = CommunicationValue::new(challenge_type) let response = CommunicationValue::new(challenge_type)
.with_id(cv.get_id()) .with_id(cv.get_id())
.with_receiver(*self.session_id.read().await) .with_receiver(*self.session_id.read().await)
.add_typed_default( .add_typed_default(
DataType::PublicKey, DataType::PublicKey,
DataValue::Str(public_key_to_base64(&get_public_key())), DataValue::Str(our_pk),
) )
.add_typed_default(DataType::Challenge, DataValue::Str(encrypted_challenge)); .add_typed_default(DataType::Challenge, DataValue::Str(encrypted_challenge));

View file

@ -20,7 +20,7 @@ use std::collections::BTreeMap;
use std::{collections::HashMap, sync::Arc, time::Duration}; use std::{collections::HashMap, sync::Arc, time::Duration};
use tokio::sync::RwLock; use tokio::sync::RwLock;
use tokio::sync::mpsc; use tokio::sync::mpsc;
use x448::PublicKey; use mtp::crypto::KemPublicKey;
use super::{rho_connection::RhoConnection, rho_manager}; use super::{rho_connection::RhoConnection, rho_manager};
use crate::omega::omega_connection::OmegaConnection; use crate::omega::omega_connection::OmegaConnection;
@ -79,12 +79,9 @@ impl IotaConnection {
} }
#[allow(dead_code)] #[allow(dead_code)]
pub async fn get_public_key(&self) -> Option<PublicKey> { pub async fn get_public_key(&self) -> Option<KemPublicKey> {
if let Some(public_key) = self.pub_key.read().await.clone() { let guard = self.pub_key.read().await;
PublicKey::from_bytes(&public_key) guard.as_ref().map(|bytes| KemPublicKey::new(bytes.clone()))
} else {
None
}
} }
/// Get the user IDs /// Get the user IDs

View file

@ -1,149 +0,0 @@
use aes_gcm::{
Aes256Gcm, Nonce,
aead::{Aead, KeyInit, OsRng},
};
use base64::{Engine as _, engine::general_purpose::STANDARD};
use rand_core::RngCore;
use sha2::{Digest, Sha256};
use x448::{PublicKey, Secret, SharedSecret};
/// Errors for crypto operations
#[allow(dead_code)]
#[derive(Debug)]
pub enum CryptoError {
Base64Decode(base64::DecodeError),
InvalidKey,
AgreementError,
EncryptionError(aes_gcm::Error),
DecryptionError(aes_gcm::Error),
}
impl From<base64::DecodeError> for CryptoError {
fn from(err: base64::DecodeError) -> Self {
CryptoError::Base64Decode(err)
}
}
#[allow(dead_code)]
pub struct KeyPair {
pub secret: Secret,
pub public: PublicKey,
}
#[allow(dead_code)]
pub fn generate_keypair() -> KeyPair {
let mut buf = [0u8; 56];
let mut rng = OsRng;
rng.fill_bytes(&mut buf);
let secret = Secret::from_bytes(&buf).unwrap();
let public = PublicKey::from(&secret);
KeyPair { secret, public }
}
pub fn public_key_to_base64(pubkey: &PublicKey) -> String {
STANDARD.encode(pubkey.as_bytes().as_ref())
}
pub fn secret_key_to_base64(secret: &Secret) -> String {
STANDARD.encode(secret.as_bytes().as_ref())
}
pub fn load_public_key(base64_pub: &str) -> Option<PublicKey> {
let bytes = STANDARD.decode(base64_pub).unwrap();
PublicKey::from_bytes(&bytes)
}
pub fn load_secret_key(base64_secret: &str) -> Option<Secret> {
let bytes = STANDARD.decode(base64_secret).unwrap();
Secret::from_bytes(&bytes)
}
fn derive_aes_key(shared: &SharedSecret) -> [u8; 32] {
let mut hasher = Sha256::new();
hasher.update(shared.as_bytes());
let result = hasher.finalize();
let mut key = [0u8; 32];
key.copy_from_slice(&result[..32]);
key
}
#[allow(dead_code)]
pub fn encrypt_b64(
base64_secret: &str,
base64_peer_pub: &str,
plaintext: &str,
) -> Result<String, CryptoError> {
let secret = load_secret_key(base64_secret).unwrap();
let peer_pub = load_public_key(base64_peer_pub).unwrap();
encrypt(secret, peer_pub, plaintext)
}
pub fn encrypt(
secret: Secret,
peer_pub: PublicKey,
plaintext: &str,
) -> Result<String, CryptoError> {
let shared = secret
.to_diffie_hellman(&peer_pub)
.ok_or(CryptoError::AgreementError)?;
let key_bytes = derive_aes_key(&shared);
let cipher = Aes256Gcm::new_from_slice(&key_bytes).expect("Key length should be correct");
let mut nonce_bytes = [0u8; 12];
OsRng.fill_bytes(&mut nonce_bytes);
let nonce = Nonce::from_slice(&nonce_bytes);
let ciphertext = cipher
.encrypt(nonce, plaintext.as_bytes())
.map_err(CryptoError::EncryptionError)?;
// prefix nonce to ciphertext
let mut out = Vec::with_capacity(nonce_bytes.len() + ciphertext.len());
out.extend_from_slice(&nonce_bytes);
out.extend_from_slice(&ciphertext);
Ok(STANDARD.encode(&out))
}
pub fn decrypt_b64(
base64_secret: &str,
base64_peer_pub: &str,
encrypted_base64: &str,
) -> Result<String, CryptoError> {
let secret = load_secret_key(base64_secret).unwrap();
let peer_pub = load_public_key(base64_peer_pub).unwrap();
decrypt(secret, peer_pub, encrypted_base64)
}
pub fn decrypt(
secret: Secret,
peer_pub: PublicKey,
encrypted_base64: &str,
) -> Result<String, CryptoError> {
let shared = secret
.to_diffie_hellman(&peer_pub)
.ok_or(CryptoError::AgreementError)?;
let key_bytes = derive_aes_key(&shared);
let cipher = Aes256Gcm::new_from_slice(&key_bytes).expect("Key length should be correct");
let encrypted = STANDARD.decode(encrypted_base64)?;
if encrypted.len() < 12 {
return Err(CryptoError::DecryptionError(aes_gcm::Error));
}
let nonce_bytes = &encrypted[..12];
let ciphertext = &encrypted[12..];
let nonce = Nonce::from_slice(nonce_bytes);
let plaintext_bytes = cipher
.decrypt(nonce, ciphertext)
.map_err(CryptoError::DecryptionError)?;
let plaintext = String::from_utf8(plaintext_bytes)
.map_err(|_| CryptoError::DecryptionError(aes_gcm::Error))?;
Ok(plaintext)
}
#[allow(dead_code)]
pub fn hash_it(input: &str) -> Vec<u8> {
let mut hasher = Sha256::new();
hasher.update(input.as_bytes());
hasher.finalize().to_vec()
}
#[allow(dead_code)]
pub fn hex_hash(input: &str) -> String {
let digest = hash_it(input);
digest.iter().map(|b| format!("{:02x}", b)).collect()
}

View file

@ -1,178 +0,0 @@
use aes_gcm::{
Aes256Gcm, Nonce,
aead::{Aead, KeyInit, Payload},
};
use base64::{Engine as _, engine::general_purpose::STANDARD as BASE64_STD};
use hkdf::Hkdf;
type HkdfSha256 = sha2::Sha256;
use sha2::{Digest, Sha256 as HashSha256};
use x448::{PublicKey, Secret};
#[derive(Debug)]
#[allow(dead_code)]
pub enum SecurePayloadError {
InvalidBase64,
InvalidHex,
EncryptionError,
DecryptionError,
InvalidKeyLength,
}
#[derive(Clone, Copy, Debug)]
#[allow(dead_code)]
pub enum DataFormat {
Raw,
Base64,
Hex,
}
pub struct SecurePayload {
inner_data: Vec<u8>,
private_key: Secret,
}
impl Clone for SecurePayload {
fn clone(&self) -> Self {
Self {
inner_data: self.inner_data.clone(),
private_key: Secret::from_bytes(self.private_key.as_bytes()).unwrap(),
}
}
}
#[allow(dead_code)]
impl SecurePayload {
pub fn new<S, T: AsRef<[u8]>>(
data: T,
format: DataFormat,
private_key: S,
) -> Result<Self, SecurePayloadError>
where
S: Into<Secret>,
{
let raw_data = match format {
DataFormat::Raw => data.as_ref().to_vec(),
DataFormat::Base64 => BASE64_STD
.decode(data.as_ref())
.map_err(|_| SecurePayloadError::InvalidBase64)?,
DataFormat::Hex => {
hex::decode(data.as_ref()).map_err(|_| SecurePayloadError::InvalidHex)?
}
};
Ok(Self {
inner_data: raw_data,
private_key: private_key.into(),
})
}
pub fn get_public_key(&self) -> [u8; 56] {
*PublicKey::from(&self.private_key).as_bytes()
}
pub fn export(&self, format: DataFormat) -> String {
match format.into() {
DataFormat::Raw => String::from_utf8_lossy(&self.inner_data).to_string(),
DataFormat::Base64 => BASE64_STD.encode(&self.inner_data),
DataFormat::Hex => hex::encode(&self.inner_data),
}
}
pub fn get_bytes(&self) -> &[u8] {
&self.inner_data
}
pub fn get_hash(&self, format: DataFormat) -> String {
let mut hasher = HashSha256::new();
hasher.update(&self.inner_data);
let result = hasher.finalize();
match format {
DataFormat::Raw => String::from_utf8_lossy(&result).to_string(),
DataFormat::Base64 => BASE64_STD.encode(result),
DataFormat::Hex => hex::encode(result),
}
}
pub fn encrypt_x448<S>(&self, public_key: S) -> Result<SecurePayload, SecurePayloadError>
where
S: Into<PublicKey>,
{
let peer_pub = public_key.into();
let shared_secret = self.private_key.as_diffie_hellman(&peer_pub).unwrap();
let hkdf = Hkdf::<HkdfSha256>::new(None, shared_secret.as_bytes());
let mut okm = [0u8; 44];
hkdf.expand(b"x448-aes-gcm-no-overhead", &mut okm)
.map_err(|_| SecurePayloadError::EncryptionError)?;
let key = &okm[..32];
let nonce_bytes = &okm[32..];
let cipher = Aes256Gcm::new(key.into());
let nonce = Nonce::from_slice(nonce_bytes);
let ciphertext = cipher
.encrypt(
nonce,
Payload {
msg: &self.inner_data,
aad: &[],
},
)
.map_err(|_| SecurePayloadError::EncryptionError)?;
Ok(SecurePayload {
inner_data: ciphertext,
private_key: Secret::from_bytes(self.private_key.as_bytes()).unwrap(),
})
}
pub fn decrypt_to_format(
&self,
peer_public_key_bytes: &[u8; 56],
output_format: DataFormat,
) -> Result<String, SecurePayloadError> {
let decrypted_instance =
self.decrypt_x448(PublicKey::from_bytes(peer_public_key_bytes).unwrap())?;
Ok(decrypted_instance.export(output_format))
}
pub fn decrypt_x448<S>(
&self,
peer_public_key_bytes: S,
) -> Result<SecurePayload, SecurePayloadError>
where
S: Into<PublicKey>,
{
let peer_pub = peer_public_key_bytes.into();
let shared_secret = self.private_key.as_diffie_hellman(&peer_pub).unwrap();
let hkdf = Hkdf::<HkdfSha256>::new(None, shared_secret.as_bytes());
let mut okm = [0u8; 44];
hkdf.expand(b"x448-aes-gcm-no-overhead", &mut okm)
.map_err(|_| SecurePayloadError::DecryptionError)?;
let key = &okm[..32];
let nonce_bytes = &okm[32..];
let cipher = Aes256Gcm::new(key.into());
let nonce = Nonce::from_slice(nonce_bytes);
let plaintext = cipher
.decrypt(
nonce,
Payload {
msg: &self.inner_data,
aad: &[],
},
)
.map_err(|_| SecurePayloadError::DecryptionError)?;
Ok(SecurePayload {
inner_data: plaintext,
private_key: Secret::from_bytes(self.private_key.as_bytes()).unwrap(),
})
}
}

View file

@ -1,4 +1,2 @@
pub mod crypto_helper;
pub mod crypto_util;
pub mod file_util; pub mod file_util;
pub mod logger; pub mod logger;