Updated Crypto to use MTP-Crypto

This commit is contained in:
Alex Emmet 2026-07-03 06:28:09 +02:00
commit 275d1cb4c4
7 changed files with 358 additions and 371 deletions

358
Cargo.lock generated
View file

@ -674,6 +674,17 @@ 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]] [[package]]
name = "chacha20" name = "chacha20"
version = "0.10.1" version = "0.10.1"
@ -685,6 +696,19 @@ dependencies = [
"rand_core 0.10.1", "rand_core 0.10.1",
] ]
[[package]]
name = "chacha20poly1305"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35"
dependencies = [
"aead",
"chacha20 0.9.1",
"cipher",
"poly1305",
"zeroize",
]
[[package]] [[package]]
name = "cipher" name = "cipher"
version = "0.4.4" version = "0.4.4"
@ -693,6 +717,7 @@ checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
dependencies = [ dependencies = [
"crypto-common 0.1.7", "crypto-common 0.1.7",
"inout", "inout",
"zeroize",
] ]
[[package]] [[package]]
@ -704,6 +729,12 @@ dependencies = [
"cc", "cc",
] ]
[[package]]
name = "cmov"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a"
[[package]] [[package]]
name = "combine" name = "combine"
version = "4.6.7" version = "4.6.7"
@ -861,7 +892,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]] [[package]]
@ -873,6 +906,42 @@ dependencies = [
"cipher", "cipher",
] ]
[[package]]
name = "ctutils"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e"
dependencies = [
"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 0.2.9",
"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"
@ -910,6 +979,16 @@ dependencies = [
"zeroize", "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"
@ -985,6 +1064,7 @@ dependencies = [
"block-buffer 0.12.1", "block-buffer 0.12.1",
"const-oid 0.10.2", "const-oid 0.10.2",
"crypto-common 0.2.2", "crypto-common 0.2.2",
"ctutils",
] ]
[[package]] [[package]]
@ -1016,13 +1096,37 @@ version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
[[package]]
name = "ed25519"
version = "2.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53"
dependencies = [
"pkcs8 0.10.2",
"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",
"zeroize",
]
[[package]] [[package]]
name = "ed448-goldilocks" name = "ed448-goldilocks"
version = "0.7.2" version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87b5fa9e9e3dd5fe1369f380acd3dcdfa766dbd0a1cd5b048fb40e38a6a78e79" checksum = "87b5fa9e9e3dd5fe1369f380acd3dcdfa766dbd0a1cd5b048fb40e38a6a78e79"
dependencies = [ dependencies = [
"fiat-crypto", "fiat-crypto 0.1.20",
"hex", "hex",
"subtle", "subtle",
] ]
@ -1120,6 +1224,12 @@ version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e825f6987101665dea6ec934c09ec6d721de7bc1bf92248e1d5810c8cd636b77" checksum = "e825f6987101665dea6ec934c09ec6d721de7bc1bf92248e1d5810c8cd636b77"
[[package]]
name = "fiat-crypto"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
[[package]] [[package]]
name = "find-msvc-tools" name = "find-msvc-tools"
version = "0.1.9" version = "0.1.9"
@ -1451,7 +1561,16 @@ version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7"
dependencies = [ dependencies = [
"hmac", "hmac 0.12.1",
]
[[package]]
name = "hkdf"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4aaa26c720c68b866f2c96ef5c1264b3e6f473fe5d4ce61cd44bbe913e553018"
dependencies = [
"hmac 0.13.0",
] ]
[[package]] [[package]]
@ -1463,6 +1582,15 @@ dependencies = [
"digest 0.10.7", "digest 0.10.7",
] ]
[[package]]
name = "hmac"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6303bc9732ae41b04cb554b844a762b4115a61bfaa81e3e83050991eeb56863f"
dependencies = [
"digest 0.11.3",
]
[[package]] [[package]]
name = "home" name = "home"
version = "0.5.12" version = "0.5.12"
@ -1540,6 +1668,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",
] ]
@ -1846,6 +1975,25 @@ version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "078e285eafdfb6c4b434e0d31e8cfcb5115b651496faca5749b88fafd4f23bfd" checksum = "078e285eafdfb6c4b434e0d31e8cfcb5115b651496faca5749b88fafd4f23bfd"
[[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"
@ -2029,16 +2177,84 @@ 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 = "mtp" name = "mtp"
version = "0.1.0" version = "0.1.0"
source = "git+https://git.methanium.net/methanium/mtp#41528ef7178982e70cb5789a437d863a7a35426c" source = "git+https://git.methanium.net/methanium/mtp#41528ef7178982e70cb5789a437d863a7a35426c"
dependencies = [
"mtp-client",
"mtp-codec",
"mtp-common",
"mtp-crypto",
"mtp-host",
"mtp-transport",
"mtp-type-map",
]
[[package]]
name = "mtp-client"
version = "0.1.0"
source = "git+https://git.methanium.net/methanium/mtp#41528ef7178982e70cb5789a437d863a7a35426c"
dependencies = [ dependencies = [
"mtp-codec", "mtp-codec",
"mtp-common", "mtp-common",
"mtp-host", "mtp-crypto",
"mtp-transport", "mtp-transport",
"mtp-type-map", "rand 0.8.6",
"tokio",
] ]
[[package]] [[package]]
@ -2049,6 +2265,7 @@ dependencies = [
"base64", "base64",
"byteorder", "byteorder",
"mtp-common", "mtp-common",
"mtp-crypto",
"mtp-type-map", "mtp-type-map",
"rand 0.8.6", "rand 0.8.6",
] ]
@ -2064,6 +2281,23 @@ dependencies = [
"wtransport", "wtransport",
] ]
[[package]]
name = "mtp-crypto"
version = "0.1.0"
source = "git+https://git.methanium.net/methanium/mtp#41528ef7178982e70cb5789a437d863a7a35426c"
dependencies = [
"chacha20poly1305",
"ed25519-dalek",
"getrandom 0.4.3",
"hkdf 0.13.0",
"ml-dsa",
"mlkem-tls",
"rand_core 0.6.4",
"serde",
"sha2 0.11.0",
"zeroize",
]
[[package]] [[package]]
name = "mtp-host" name = "mtp-host"
version = "0.1.0" version = "0.1.0"
@ -2071,6 +2305,7 @@ source = "git+https://git.methanium.net/methanium/mtp#41528ef7178982e70cb5789a43
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",
@ -2198,9 +2433,10 @@ dependencies = [
"dashmap", "dashmap",
"dotenv", "dotenv",
"hex", "hex",
"hkdf", "hkdf 0.12.4",
"json", "json",
"mtp", "mtp",
"mtp-crypto",
"once_cell", "once_cell",
"rand 0.8.6", "rand 0.8.6",
"rand_core 0.6.4", "rand_core 0.6.4",
@ -2272,7 +2508,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2"
dependencies = [ dependencies = [
"digest 0.10.7", "digest 0.10.7",
"hmac", "hmac 0.12.1",
] ]
[[package]] [[package]]
@ -2329,9 +2565,9 @@ version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f"
dependencies = [ dependencies = [
"der", "der 0.7.10",
"pkcs8", "pkcs8 0.10.2",
"spki", "spki 0.7.3",
] ]
[[package]] [[package]]
@ -2340,8 +2576,18 @@ version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7"
dependencies = [ dependencies = [
"der", "der 0.7.10",
"spki", "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]]
@ -2386,6 +2632,17 @@ dependencies = [
"windows-sys 0.61.2", "windows-sys 0.61.2",
] ]
[[package]]
name = "poly1305"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf"
dependencies = [
"cpufeatures 0.2.17",
"opaque-debug",
"universal-hash",
]
[[package]] [[package]]
name = "polyval" name = "polyval"
version = "0.6.2" version = "0.6.2"
@ -2541,7 +2798,7 @@ version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207"
dependencies = [ dependencies = [
"chacha20", "chacha20 0.10.1",
"getrandom 0.4.3", "getrandom 0.4.3",
"rand_core 0.10.1", "rand_core 0.10.1",
] ]
@ -2726,10 +2983,10 @@ dependencies = [
"num-integer", "num-integer",
"num-traits", "num-traits",
"pkcs1", "pkcs1",
"pkcs8", "pkcs8 0.10.2",
"rand_core 0.6.4", "rand_core 0.6.4",
"signature", "signature 2.2.0",
"spki", "spki 0.7.3",
"subtle", "subtle",
"zeroize", "zeroize",
] ]
@ -3048,6 +3305,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"
@ -3074,6 +3352,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 = "simd-adler32" name = "simd-adler32"
version = "0.3.9" version = "0.3.9"
@ -3157,9 +3445,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d"
dependencies = [ dependencies = [
"base64ct", "base64ct",
"der", "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 = "sqlx" name = "sqlx"
version = "0.8.6" version = "0.8.6"
@ -3266,8 +3570,8 @@ dependencies = [
"futures-util", "futures-util",
"generic-array", "generic-array",
"hex", "hex",
"hkdf", "hkdf 0.12.4",
"hmac", "hmac 0.12.1",
"itoa", "itoa",
"log", "log",
"md-5", "md-5",
@ -3304,8 +3608,8 @@ dependencies = [
"futures-core", "futures-core",
"futures-util", "futures-util",
"hex", "hex",
"hkdf", "hkdf 0.12.4",
"hmac", "hmac 0.12.1",
"home", "home",
"itoa", "itoa",
"log", "log",
@ -4246,6 +4550,18 @@ dependencies = [
"url", "url",
] ]
[[package]]
name = "x25519-dalek"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277"
dependencies = [
"curve25519-dalek",
"rand_core 0.6.4",
"serde",
"zeroize",
]
[[package]] [[package]]
name = "x448" name = "x448"
version = "0.6.0" version = "0.6.0"
@ -4416,7 +4732,7 @@ dependencies = [
"deflate64", "deflate64",
"flate2", "flate2",
"getrandom 0.3.4", "getrandom 0.3.4",
"hmac", "hmac 0.12.1",
"indexmap", "indexmap",
"lzma-rust2", "lzma-rust2",
"memchr", "memchr",

View file

@ -4,7 +4,10 @@ version = "0.1.0"
edition = "2024" edition = "2024"
[dependencies] [dependencies]
mtp = { git = "https://git.methanium.net/methanium/mtp", features = ["host"] } mtp = { git = "https://git.methanium.net/methanium/mtp", features = [
"host",
"crypto",
] }
actix-web = { version = "4.12.1", features = ["rustls-0_23"] } actix-web = { version = "4.12.1", features = ["rustls-0_23"] }
aes-gcm = "*" aes-gcm = "*"
@ -36,3 +39,4 @@ uuid = { version = "1.19.0", features = ["v4"] }
x448 = "0.6.0" x448 = "0.6.0"
zip = "6.0.0" zip = "6.0.0"
thiserror = "2.0.18" thiserror = "2.0.18"
mtp-crypto = { git = "https://git.methanium.net/methanium/mtp", version = "0.1.0", features = ["pqc"] }

View file

@ -8,24 +8,30 @@ use crate::notifications::tauri;
use crate::sql::sql::initialize_db; use crate::sql::sql::initialize_db;
use crate::sql::sql::print_users; use crate::sql::sql::print_users;
use crate::transport::omikron_connection; use crate::transport::omikron_connection;
use crate::util::crypto_helper::load_public_key;
use crate::util::crypto_helper::load_secret_key;
use crate::util::file_util::get_directory; use crate::util::file_util::get_directory;
use crate::util::logger::PrintType; use crate::util::logger::PrintType;
use crate::util::logger::startup; use crate::util::logger::startup;
use base64::Engine as _;
use dotenv::from_path; use dotenv::from_path;
use mtp_crypto::{Keyring, PublicKeyBundle};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use rustls::crypto::aws_lc_rs::default_provider; use rustls::crypto::aws_lc_rs::default_provider;
use std::env; use std::env;
use std::path::Path; use std::path::Path;
static PRIVATE_KEY: Lazy<String> = Lazy::new(|| env::var("PRIVATE_KEY").unwrap()); static KEYRING_ENV: Lazy<String> = Lazy::new(|| env::var("KEYRING").unwrap());
pub fn get_private_key() -> x448::Secret { fn load_keyring() -> Keyring {
load_secret_key(&*PRIVATE_KEY).unwrap() let bytes = base64::engine::general_purpose::STANDARD
.decode(&*KEYRING_ENV)
.expect("Invalid KEYRING env var: not valid base64");
Keyring::from_bytes(&bytes).expect("Invalid KEYRING env var: failed to deserialize")
} }
static PUBLIC_KEY: Lazy<String> = Lazy::new(|| env::var("PUBLIC_KEY").unwrap()); pub fn get_keyring() -> &'static Keyring {
pub fn get_public_key() -> x448::PublicKey { static KEYRING: Lazy<Keyring> = Lazy::new(load_keyring);
load_public_key(&*PUBLIC_KEY).unwrap() &KEYRING
}
pub fn get_public_key_bundle() -> PublicKeyBundle {
get_keyring().public_key_bundle()
} }
#[tokio::main] #[tokio::main]

View file

@ -1,16 +1,16 @@
use crate::get_public_key; use crate::get_public_key_bundle;
use crate::sql::sql; use crate::sql::sql;
use crate::sql::user_online_tracker::get_iota_primary_omikron_connection; use crate::sql::user_online_tracker::get_iota_primary_omikron_connection;
use crate::transport::omikron_manager::get_random_omikron; use crate::transport::omikron_manager::get_random_omikron;
use crate::util::file_util::get_directory; use crate::util::file_util::get_directory;
use crate::{ use crate::{
sql::sql::{get_by_user_id, get_omikron_by_id}, sql::sql::{get_by_user_id, get_omikron_by_id},
util::crypto_helper::public_key_to_base64,
}; };
use actix_web::HttpResponse; use actix_web::HttpResponse;
use actix_web::http::{StatusCode, header}; use actix_web::http::{StatusCode, header};
use base64::Engine as _; use base64::Engine as _;
use json::JsonValue; use json::JsonValue;
use mtp_crypto::PublicKeyBundle;
pub async fn handle(path: &str, body_string: Option<String>) -> HttpResponse { pub async fn handle(path: &str, body_string: Option<String>) -> HttpResponse {
if path == "OPTIONS" { if path == "OPTIONS" {
@ -195,7 +195,8 @@ pub async fn handle(path: &str, body_string: Option<String>) -> HttpResponse {
["api", "get", "public_key"] => { ["api", "get", "public_key"] => {
let mut res = JsonValue::new_object(); let mut res = JsonValue::new_object();
res["status"] = "success".into(); res["status"] = "success".into();
res["public_key"] = public_key_to_base64(&get_public_key()).into(); let bundle = get_public_key_bundle();
res["public_key"] = base64::engine::general_purpose::STANDARD.encode(bundle.to_bytes()).into();
(StatusCode::OK, res.dump()) (StatusCode::OK, res.dump())
} }

View file

@ -1,137 +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
#[derive(Debug)]
pub enum CryptoError {
Base64Decode,
AgreementError,
EncryptionError(aes_gcm::Error),
DecryptionError(aes_gcm::Error),
}
impl From<base64::DecodeError> for CryptoError {
fn from(_: base64::DecodeError) -> Self {
CryptoError::Base64Decode
}
}
pub fn generate_keypair() -> (Secret, PublicKey) {
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);
(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
}
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)
}
pub fn hash_it(input: &str) -> Vec<u8> {
let mut hasher = Sha256::new();
hasher.update(input.as_bytes());
hasher.finalize().to_vec()
}
pub fn hex_hash(input: &str) -> String {
let digest = hash_it(input);
digest.iter().map(|b| format!("{:02x}", b)).collect()
}

View file

@ -1,201 +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;
use sha2::{Digest, Sha256};
use x448::{PublicKey, Secret};
// --- Custom Errors ---
#[derive(Debug)]
pub enum SecurePayloadError {
InvalidBase64,
InvalidHex,
EncryptionError,
DecryptionError,
InvalidKeyLength,
}
// --- Data Format Enum ---
#[derive(Clone, Copy, Debug)]
pub enum DataFormat {
Raw,
Base64,
Hex,
}
// --- Main Class Structure ---
pub struct SecurePayload {
/// The internal canonical representation is always raw bytes.
inner_data: Vec<u8>,
/// The private key of the user associated with this payload instance.
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(),
}
}
}
impl SecurePayload {
/// Clear Constructor: Takes data in any format and the user's private key.
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(),
})
}
/// Helper to get the public key associated with this instance's private key.
pub fn get_public_key(&self) -> [u8; 56] {
*PublicKey::from(&self.private_key).as_bytes()
}
/// Exports the internal data to the requested format
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),
}
}
/// Access raw bytes directly
pub fn get_bytes(&self) -> &[u8] {
&self.inner_data
}
/// Returns the SHA-256 Hash of the data in the requested format
pub fn get_hash(&self, format: DataFormat) -> String {
let mut hasher = Sha256::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),
}
}
/// Encrypts the held data for a specific recipient using AES-256-GCM.
/// The message will contain ONLY the ciphertext.
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();
println!(
"Encryption Shared Secret (Hex): {}",
hex::encode(shared_secret.as_bytes())
);
// 3. Key & Nonce Derivation (HKDF)
// We derive 32 bytes for the key and 12 bytes for a deterministic nonce.
let hkdf = Hkdf::<Sha256>::new(None, shared_secret.as_bytes());
let mut okm = [0u8; 44]; // 32 (Key) + 12 (Nonce)
hkdf.expand(b"x448-aes-gcm-no-overhead", &mut okm)
.map_err(|_| SecurePayloadError::EncryptionError)?;
let key = &okm[..32];
let nonce_bytes = &okm[32..];
// 4. Encrypt with AES-256-GCM
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)?;
// 5. Result is ONLY the ciphertext. No key or nonce is packed.
Ok(SecurePayload {
inner_data: ciphertext,
private_key: Secret::from_bytes(self.private_key.as_bytes()).unwrap(),
})
}
/// Decrypts the held data providing the sender's public key manually.
pub fn decrypt_to_format(
&self,
peer_public_key_bytes: &[u8; 56],
output_format: DataFormat,
) -> Result<String, SecurePayloadError> {
let decrypted_instance = self.decrypt_x448(peer_public_key_bytes)?;
Ok(decrypted_instance.export(output_format))
}
/// Decrypts the held data using the internal Private Key and the provided Peer Public Key.
pub fn decrypt_x448(
&self,
peer_public_key_bytes: &[u8; 56],
) -> Result<SecurePayload, SecurePayloadError> {
// 1. Perform Exchange
let peer_pub = PublicKey::from_bytes(peer_public_key_bytes).unwrap();
let shared_secret = self.private_key.as_diffie_hellman(&peer_pub).unwrap();
// LOGGING: Shared Secret
println!(
"Decryption Shared Secret (Hex): {}",
hex::encode(shared_secret.as_bytes())
);
// 2. Key & Nonce Derivation (Must match encryption exactly)
let hkdf = Hkdf::<Sha256>::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..];
// 3. Decrypt with AES-256-GCM
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;