Updated Crypto to use MTP-Crypto

This commit is contained in:
Alex Emmet 2026-07-03 06:28:06 +02:00
commit 5625c5db5f
10 changed files with 558 additions and 453 deletions

449
Cargo.lock generated
View file

@ -73,7 +73,7 @@ dependencies = [
"mime",
"percent-encoding",
"pin-project-lite",
"rand 0.10.1",
"rand 0.10.2",
"sha1 0.11.0",
"smallvec",
"tokio",
@ -424,9 +424,9 @@ checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
[[package]]
name = "aws-lc-rs"
version = "1.17.0"
version = "1.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ec2f1fc3ec205783a5da9a7e6c1509cc69dedf09a1949e412c1e18469326d00"
checksum = "4342d8937fc7e5dd9b1c60292261c0670c882a2cd1719cfc11b1af41731e32ad"
dependencies = [
"aws-lc-sys",
"untrusted 0.7.1",
@ -435,14 +435,15 @@ dependencies = [
[[package]]
name = "aws-lc-sys"
version = "0.41.0"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a2f9779ce85b93ab6170dd940ad0169b5766ff848247aff13bb788b832fe3f4"
checksum = "6d9ceb1da931507a12f4fccea479dccd00da1943e1b4ae72d8e502d707361444"
dependencies = [
"cc",
"cmake",
"dunce",
"fs_extra",
"pkg-config",
]
[[package]]
@ -451,6 +452,12 @@ version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]]
name = "base64ct"
version = "1.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06"
[[package]]
name = "bit-set"
version = "0.5.3"
@ -607,6 +614,17 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
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 = "chacha20"
version = "0.10.1"
@ -618,6 +636,19 @@ dependencies = [
"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]]
name = "chrono"
version = "0.4.45"
@ -639,6 +670,7 @@ checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
dependencies = [
"crypto-common 0.1.7",
"inout",
"zeroize",
]
[[package]]
@ -656,7 +688,7 @@ dependencies = [
"futures",
"futures-util",
"hex",
"hkdf",
"hkdf 0.12.4",
"hyper",
"hyper-util",
"iota-auth",
@ -701,6 +733,12 @@ dependencies = [
"cc",
]
[[package]]
name = "cmov"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a"
[[package]]
name = "combine"
version = "4.6.7"
@ -725,6 +763,12 @@ dependencies = [
"static_assertions",
]
[[package]]
name = "const-oid"
version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
[[package]]
name = "const-oid"
version = "0.10.2"
@ -890,7 +934,9 @@ 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]]
@ -912,6 +958,42 @@ dependencies = [
"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 2.0.118",
]
[[package]]
name = "darling"
version = "0.23.0"
@ -978,6 +1060,27 @@ version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5729f5117e208430e437df2f4843f5e5952997175992d1414f94c57d61e270b4"
[[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]]
name = "der-parser"
version = "10.0.0"
@ -1050,8 +1153,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2"
dependencies = [
"block-buffer 0.12.1",
"const-oid",
"const-oid 0.10.2",
"crypto-common 0.2.2",
"ctutils",
]
[[package]]
@ -1080,13 +1184,37 @@ version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
name = "ed448-goldilocks"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87b5fa9e9e3dd5fe1369f380acd3dcdfa766dbd0a1cd5b048fb40e38a6a78e79"
dependencies = [
"fiat-crypto",
"fiat-crypto 0.1.20",
"hex",
"subtle",
]
@ -1171,6 +1299,12 @@ version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e825f6987101665dea6ec934c09ec6d721de7bc1bf92248e1d5810c8cd636b77"
[[package]]
name = "fiat-crypto"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
[[package]]
name = "filedescriptor"
version = "0.8.3"
@ -1523,7 +1657,16 @@ version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7"
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]]
@ -1535,6 +1678,15 @@ dependencies = [
"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]]
name = "httlib-huffman"
version = "0.3.4"
@ -1603,6 +1755,7 @@ version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "818356c5132c1fede50f837ca96afbe78ff42413047f4abb886217845e1b6c8c"
dependencies = [
"ctutils",
"typenum",
]
@ -1660,7 +1813,7 @@ dependencies = [
"libc",
"percent-encoding",
"pin-project-lite",
"socket2 0.6.4",
"socket2 0.5.10",
"system-configuration",
"tokio",
"tower-service",
@ -1867,7 +2020,7 @@ dependencies = [
"futures",
"futures-util",
"hex",
"hkdf",
"hkdf 0.12.4",
"hyper",
"hyper-util",
"iota-logger",
@ -1917,7 +2070,7 @@ dependencies = [
"futures",
"futures-util",
"hex",
"hkdf",
"hkdf 0.12.4",
"hyper",
"hyper-util",
"iota-logger",
@ -2009,7 +2162,7 @@ dependencies = [
"aes-gcm",
"base64",
"hex",
"hkdf",
"hkdf 0.12.4",
"iota-logger",
"iota-state",
"iota-util",
@ -2048,7 +2201,7 @@ dependencies = [
"anyhow",
"base64",
"hex",
"hkdf",
"hkdf 0.12.4",
"iota-logger",
"json",
"mtp",
@ -2074,19 +2227,15 @@ dependencies = [
name = "iota-util"
version = "0.1.0"
dependencies = [
"aes-gcm",
"base64",
"hex",
"hkdf",
"mtp",
"rand_core 0.6.4",
"mtp-crypto",
"reqwest",
"sha2 0.10.9",
"sysinfo",
"tokio",
"uuid",
"walkdir",
"x448",
"zip",
]
@ -2226,6 +2375,25 @@ dependencies = [
"thiserror 2.0.18",
]
[[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]]
name = "lab"
version = "0.11.0"
@ -2431,10 +2599,63 @@ dependencies = [
"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]]
name = "mtp"
version = "0.1.0"
source = "git+https://git.methanium.net/Methanium/mtp.git#15cc1d4c5e6a917f197ebf6685c8cea4e3ab668f"
source = "git+https://git.methanium.net/Methanium/mtp.git#5bfcccc056a2a491a72e4315aa95effb2243ad3c"
dependencies = [
"mtp-codec",
"mtp-common",
@ -2445,7 +2666,7 @@ dependencies = [
[[package]]
name = "mtp-codec"
version = "0.1.0"
source = "git+https://git.methanium.net/Methanium/mtp.git#15cc1d4c5e6a917f197ebf6685c8cea4e3ab668f"
source = "git+https://git.methanium.net/Methanium/mtp.git#5bfcccc056a2a491a72e4315aa95effb2243ad3c"
dependencies = [
"base64",
"byteorder",
@ -2457,7 +2678,7 @@ dependencies = [
[[package]]
name = "mtp-common"
version = "0.1.0"
source = "git+https://git.methanium.net/Methanium/mtp.git#15cc1d4c5e6a917f197ebf6685c8cea4e3ab668f"
source = "git+https://git.methanium.net/Methanium/mtp.git#5bfcccc056a2a491a72e4315aa95effb2243ad3c"
dependencies = [
"quinn",
"rustls",
@ -2465,10 +2686,27 @@ dependencies = [
"wtransport",
]
[[package]]
name = "mtp-crypto"
version = "0.1.0"
source = "git+https://git.methanium.net/Methanium/mtp.git#5bfcccc056a2a491a72e4315aa95effb2243ad3c"
dependencies = [
"chacha20poly1305",
"ed25519-dalek",
"getrandom 0.4.3",
"hkdf 0.13.0",
"ml-dsa",
"mlkem-tls",
"rand_core 0.6.4",
"sha2 0.11.0",
"thiserror 1.0.69",
"zeroize",
]
[[package]]
name = "mtp-transport"
version = "0.1.0"
source = "git+https://git.methanium.net/Methanium/mtp.git#15cc1d4c5e6a917f197ebf6685c8cea4e3ab668f"
source = "git+https://git.methanium.net/Methanium/mtp.git#5bfcccc056a2a491a72e4315aa95effb2243ad3c"
dependencies = [
"log",
"mtp-codec",
@ -2482,7 +2720,7 @@ dependencies = [
[[package]]
name = "mtp-type-map"
version = "0.1.0"
source = "git+https://git.methanium.net/Methanium/mtp.git#15cc1d4c5e6a917f197ebf6685c8cea4e3ab668f"
source = "git+https://git.methanium.net/Methanium/mtp.git#5bfcccc056a2a491a72e4315aa95effb2243ad3c"
dependencies = [
"serde",
"serde_yaml",
@ -2666,13 +2904,12 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
[[package]]
name = "open"
version = "5.3.5"
version = "5.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fbaa89d2ddc8473c78a3adf69eea8cffa28c483b8e02a971ef31527cd0fc92c"
checksum = "cd8d3b65c44123a56e0133d2cd06ce4361bd3ca99d41198b2f25e3c3db9b8b4a"
dependencies = [
"is-wsl",
"libc",
"pathdiff",
]
[[package]]
@ -2742,7 +2979,7 @@ dependencies = [
"futures",
"futures-util",
"hex",
"hkdf",
"hkdf 0.12.4",
"hyper",
"hyper-util",
"iota-auth",
@ -2825,12 +3062,6 @@ dependencies = [
"windows-link",
]
[[package]]
name = "pathdiff"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3"
[[package]]
name = "pbkdf2"
version = "0.12.2"
@ -2838,7 +3069,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2"
dependencies = [
"digest 0.10.7",
"hmac",
"hmac 0.12.1",
]
[[package]]
@ -2851,6 +3082,15 @@ dependencies = [
"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]]
name = "percent-encoding"
version = "2.3.2"
@ -2978,6 +3218,26 @@ version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
[[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]]
name = "pkg-config"
version = "0.3.33"
@ -3075,6 +3335,17 @@ dependencies = [
"pnet_sys",
]
[[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]]
name = "polyval"
version = "0.6.2"
@ -3145,7 +3416,7 @@ dependencies = [
"quinn-udp",
"rustc-hash",
"rustls",
"socket2 0.6.4",
"socket2 0.5.10",
"thiserror 2.0.18",
"tokio",
"tracing",
@ -3183,7 +3454,7 @@ dependencies = [
"cfg_aliases",
"libc",
"once_cell",
"socket2 0.6.4",
"socket2 0.5.10",
"tracing",
"windows-sys 0.60.2",
]
@ -3232,11 +3503,11 @@ dependencies = [
[[package]]
name = "rand"
version = "0.10.1"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207"
checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80"
dependencies = [
"chacha20",
"chacha20 0.10.1",
"getrandom 0.4.3",
"rand_core 0.10.1",
]
@ -3602,9 +3873,9 @@ dependencies = [
[[package]]
name = "rustls-pki-types"
version = "1.14.1"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9"
checksum = "764899a24af3980067ee14bc143654f297b22eaebfe3c7b6b211920a5a59b046"
dependencies = [
"web-time",
"zeroize",
@ -3843,6 +4114,27 @@ dependencies = [
"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]]
name = "shlex"
version = "2.0.1"
@ -3880,6 +4172,25 @@ dependencies = [
"libc",
]
[[package]]
name = "signature"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
dependencies = [
"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]]
name = "simd-adler32"
version = "0.3.9"
@ -3940,6 +4251,32 @@ dependencies = [
"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]]
name = "sqlite-wasm-rs"
version = "0.5.5"
@ -4223,9 +4560,9 @@ dependencies = [
[[package]]
name = "time"
version = "0.3.51"
version = "0.3.53"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85c17d80feb7334b40c484e45ed1a5273dfd8bfda537c3be2e74a06a6686f327"
checksum = "18dfaaeddcb932337b5e7866ee7d0ce9b76d2fd092997146f187ec09b4558a50"
dependencies = [
"deranged",
"libc",
@ -4245,9 +4582,9 @@ checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109"
[[package]]
name = "time-macros"
version = "0.2.30"
version = "0.2.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcef1a61bdb119096e153208ec5cbec23944ce8bca13be5c7f60c634f7403935"
checksum = "c431b87111666e491a90baa837f914fb45cd5dc3c268591b0220ff5057f2085f"
dependencies = [
"num-conv",
"time-core",
@ -4749,7 +5086,7 @@ dependencies = [
"futures",
"futures-util",
"hex",
"hkdf",
"hkdf 0.12.4",
"hyper",
"hyper-util",
"iota-logger",
@ -5222,6 +5559,18 @@ dependencies = [
"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]]
name = "x448"
version = "0.6.0"
@ -5392,7 +5741,7 @@ dependencies = [
"deflate64",
"flate2",
"getrandom 0.3.4",
"hmac",
"hmac 0.12.1",
"indexmap",
"lzma-rust2",
"memchr",
@ -5407,9 +5756,9 @@ dependencies = [
[[package]]
name = "zlib-rs"
version = "0.6.4"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "977347db8caa080403f6b6b7c1cda9479a8e869316f7e13a59b19076a40f94e3"
checksum = "5431d5661c32445236631278f27946e444ddafe4684cac70b185272d4f9c52d5"
[[package]]
name = "zmij"

View file

@ -7,8 +7,8 @@ use iota_storage::util::chats_util::{get_user, mod_user};
use iota_storage::util::communities_util::CommunitiesUtil;
use iota_storage::util::config_util::CONFIG;
use iota_storage::util::{chat_files, chats_util};
use iota_util::crypto_helper;
use iota_util::crypto_util::{DataFormat, SecurePayload};
use iota_util::crypto_helper::keyring_from_base64;
use iota_util::crypto_util::{self};
use iota_util::file_util::{get_children, load_file, save_file};
use mtp::codec::{CommunicationType, CommunicationValue, DataType, DataValue};
use mtp::transport::{Receiver, Sender};
@ -889,33 +889,18 @@ impl ClientConnection {
async fn handle_challenge(&self, cv: &CommunicationValue) {
let conf = CONFIG.read().await;
let private_key = conf.get_private_key().unwrap();
let kr_str = conf.get_keyring().unwrap();
drop(conf);
let omikron_public_key = cv.get_data(DataType::PublicKey).as_str().unwrap();
let encrypted_challenge = cv.get_data(DataType::Challenge).as_str().unwrap();
let solved_challenge = {
if let Ok(decrypted) = SecurePayload::new(
encrypted_challenge,
DataFormat::Base64,
crypto_helper::load_secret_key(&private_key).unwrap(),
) {
if let Ok(decrypted) = decrypted
.decrypt_x448(crypto_helper::load_public_key(omikron_public_key).unwrap())
{
Some(decrypted)
} else {
None
}
} else {
None
}
let Some(keyring) = keyring_from_base64(&kr_str) else {
return;
};
if let Some(decrypted) = solved_challenge {
let solved = decrypted.export(DataFormat::Raw);
let encrypted_challenge = cv.get_data(DataType::Challenge).as_str().unwrap();
let solved = crypto_util::decrypt_challenge(encrypted_challenge, &keyring).ok();
if let Some(solved) = solved {
let response = CommunicationValue::new(CommunicationType::ChallengeResponse)
.with_id(cv.get_id())
.add_typed_default(DataType::Challenge, DataValue::Str(solved));

View file

@ -3,7 +3,7 @@ use iota_logger::{log, log_command, log_cv};
use iota_state::{ACTIVE_TASKS, RELOAD, SHUTDOWN};
use iota_storage::users::{user_manager, user_profile::UserProfile};
use iota_storage::util::config_util::CONFIG;
use iota_util::{crypto_helper, file_util};
use iota_util::file_util;
use mtp::codec::{CommunicationType, CommunicationValue};
use omikron_connector::omikron_connection::OMIKRON_CONNECTION;
use ratatui::{

View file

@ -1,14 +1,12 @@
use crate::users::user_profile::UserProfile;
use base64::{Engine as _, engine::general_purpose::STANDARD};
use iota_util::crypto_helper::{self};
use iota_util::crypto_helper::{self, hex_hash, keyring_from_base64, public_key_bundle_to_base64};
use iota_util::file_util::{load_file, save_file};
use json::JsonValue;
use once_cell::sync::Lazy;
use rand::Rng;
use rand_core::OsRng;
use rand_core::{OsRng, RngCore};
use std::io::{self};
use std::sync::Mutex;
use x448::{PublicKey, Secret};
static USERS: Lazy<Mutex<Vec<UserProfile>>> = Lazy::new(|| Mutex::new(Vec::new()));
static UNIQUE: Lazy<Mutex<bool>> = Lazy::new(|| Mutex::new(false));
@ -20,19 +18,20 @@ pub async fn load_from_tu(username: &str) -> Result<(), ()> {
let uuid = segments[0].parse::<i64>().unwrap_or(0);
let b64_private_key = segments[1];
let secret: Secret = crypto_helper::load_secret_key(b64_private_key).unwrap();
let public_key = PublicKey::from(&secret);
let keyring = keyring_from_base64(b64_private_key).unwrap();
let pub_key_bundle = keyring.public_key_bundle();
let keyring_b64 = crypto_helper::keyring_to_base64(&keyring);
let mut bytes = [0u8; 192];
OsRng.fill(bytes.as_mut());
OsRng.fill_bytes(&mut bytes);
let reset_token = STANDARD.encode(&bytes);
let user_profile = UserProfile::new(
uuid,
username.to_string(),
Some(username.to_string()),
crypto_helper::public_key_to_base64(&public_key),
crypto_helper::hex_hash(b64_private_key),
public_key_bundle_to_base64(&pub_key_bundle),
hex_hash(&keyring_b64),
reset_token,
);
USERS.lock().unwrap().push(user_profile);

View file

@ -50,6 +50,10 @@ impl ConfigUtil {
self.config["port"].as_u16().unwrap_or(1984)
}
pub fn get_keyring(&self) -> Option<String> {
self.config["keyring"].as_str().map(String::from)
}
pub fn get_public_key(&self) -> Option<String> {
self.config["public_key"].as_str().map(String::from)
}

View file

@ -5,6 +5,7 @@ edition = "2024"
[dependencies]
mtp = { git = "https://git.methanium.net/Methanium/mtp.git" }
mtp-crypto = { git = "https://git.methanium.net/Methanium/mtp.git", features = ["pqc"] }
reqwest = "0.13.2"
tokio = { version = "1.50.0", features = ["full"] }
@ -12,10 +13,5 @@ sysinfo = "0.38.3"
uuid = { version = "*", features = ["v4"] }
walkdir = "2.5.0"
zip = "6.0.0"
aes-gcm = "0.10.3"
base64 = "0.22.1"
rand_core = { version = "0.6", features = ["getrandom", "std"] }
sha2 = "0.10.9"
x448 = { version = "*" }
hkdf = "0.12.4"
hex = "*"

View file

@ -1,133 +1,28 @@
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 opertions
#[derive(Debug)]
#[allow(dead_code)]
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)
}
}
pub struct KeyPair {
pub secret: Secret,
pub public: PublicKey,
}
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)
}
#[allow(dead_code)]
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(
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();
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))
}
#[allow(dead_code)]
pub fn decrypt(
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();
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()
}
use base64::{Engine as _, engine::general_purpose::STANDARD};
use mtp_crypto::{Keyring, PublicKeyBundle};
pub fn generate_keyring() -> Keyring {
Keyring::generate()
}
pub fn keyring_to_base64(keyring: &Keyring) -> String {
STANDARD.encode(keyring.to_bytes())
}
pub fn keyring_from_base64(s: &str) -> Option<Keyring> {
let bytes = STANDARD.decode(s).ok()?;
Keyring::from_bytes(&bytes).ok()
}
pub fn public_key_bundle_to_base64(bundle: &PublicKeyBundle) -> String {
STANDARD.encode(bundle.as_bytes())
}
pub fn public_key_bundle_from_base64(s: &str) -> Option<PublicKeyBundle> {
let bytes = STANDARD.decode(s).ok()?;
PublicKeyBundle::from_bytes(&bytes).ok()
}
pub fn hex_hash(input: &str) -> String {
hex::encode(mtp_crypto::sha256(input.as_bytes()))
}

View file

@ -1,178 +1,58 @@
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,
}
use base64::{Engine as _, engine::general_purpose::STANDARD};
use mtp_crypto::{EncryptionType, Keyring, PublicKeyBundle, encrypt_for, decrypt_with};
#[derive(Clone, Copy, Debug)]
#[allow(dead_code)]
pub enum DataFormat {
Raw,
Base64,
Hex,
}
pub struct SecurePayload {
inner_data: Vec<u8>,
private_key: Secret,
pub fn encrypt(
plaintext: &[u8],
aad: &[u8],
recipient_pub_key_bundle: &PublicKeyBundle,
) -> Result<Vec<u8>, String> {
encrypt_for(
EncryptionType::MlKemChaCha20Poly1305,
recipient_pub_key_bundle,
plaintext,
aad,
)
.map_err(|e| format!("encryption error: {:?}", e))
}
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(),
}
}
pub fn decrypt(
ciphertext: &[u8],
aad: &[u8],
keyring: &Keyring,
) -> Result<Vec<u8>, String> {
decrypt_with(ciphertext, keyring, aad)
.map_err(|e| format!("decryption error: {:?}", e))
}
#[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)?
}
};
pub fn encrypt_challenge(
challenge: &str,
recipient_pub_key_bundle: &PublicKeyBundle,
) -> Result<String, String> {
let blob = encrypt(challenge.as_bytes(), b"challenge", recipient_pub_key_bundle)?;
Ok(STANDARD.encode(&blob))
}
Ok(Self {
inner_data: raw_data,
private_key: private_key.into(),
})
}
pub fn decrypt_challenge(
encrypted: &str,
keyring: &Keyring,
) -> Result<String, String> {
let blob =
STANDARD.decode(encrypted).map_err(|e| format!("base64 decode error: {}", e))?;
let pt = decrypt(&blob, b"challenge", keyring)?;
String::from_utf8(pt).map_err(|e| format!("utf8 decode error: {}", e))
}
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(),
})
pub fn export(data: &[u8], format: DataFormat) -> String {
match format {
DataFormat::Raw => String::from_utf8_lossy(data).to_string(),
DataFormat::Base64 => STANDARD.encode(data),
DataFormat::Hex => hex::encode(data),
}
}

View file

@ -6,8 +6,8 @@ use iota_storage::util::chat_files::{self, MessageState, change_message_state};
use iota_storage::util::chats_util::{self, get_user, mod_user};
use iota_storage::util::communities_util::CommunitiesUtil;
use iota_storage::util::config_util::CONFIG;
use iota_util::crypto_helper;
use iota_util::crypto_util::{DataFormat, SecurePayload};
use iota_util::crypto_helper::{self, keyring_from_base64};
use iota_util::crypto_util::{self};
use iota_util::file_util::{get_children, has_file, load_file, save_file};
use json::JsonValue;
use mtp::codec::{CommunicationType, CommunicationValue, DataType, DataValue};
@ -347,30 +347,41 @@ impl OmikronConnection {
async fn handle_authentication(&self) {
let conf = CONFIG.read().await;
let iota_id = conf.get_iota_id();
let public_key = conf.get_public_key();
let private_key = conf.get_private_key();
let keyring_b64 = conf.get_keyring();
drop(conf);
if iota_id == 0 {
log_t!("iota_register_new");
let (pub_k, _priv_k) = if let (Some(pk), Some(sk)) = (public_key, private_key) {
(pk, sk)
let pub_key_b64 = if let Some(kr) = keyring_b64 {
if let Some(keyring) = keyring_from_base64(&kr) {
let bundle = keyring.public_key_bundle();
crypto_helper::public_key_bundle_to_base64(&bundle)
} else {
let keyring = crypto_helper::generate_keyring();
let kb64 = crypto_helper::keyring_to_base64(&keyring);
let bundle = keyring.public_key_bundle();
let pk_b64 = crypto_helper::public_key_bundle_to_base64(&bundle);
let mut conf_write = CONFIG.write().await;
conf_write.change("keyring", JsonValue::from(kb64));
conf_write.update();
drop(conf_write);
pk_b64
}
} else {
let key_pair = crypto_helper::generate_keypair();
let public_key_base64 = crypto_helper::public_key_to_base64(&key_pair.public);
let private_key_base64 = crypto_helper::secret_key_to_base64(&key_pair.secret);
let keyring = crypto_helper::generate_keyring();
let kb64 = crypto_helper::keyring_to_base64(&keyring);
let bundle = keyring.public_key_bundle();
let pk_b64 = crypto_helper::public_key_bundle_to_base64(&bundle);
let mut conf_write = CONFIG.write().await;
conf_write.change("public_key", JsonValue::from(public_key_base64.clone()));
conf_write.change("private_key", JsonValue::from(private_key_base64.clone()));
conf_write.change("keyring", JsonValue::from(kb64));
conf_write.update();
drop(conf_write);
(public_key_base64, private_key_base64)
pk_b64
};
let register_msg = CommunicationValue::new(CommunicationType::RegisterIota)
.add_typed_default(DataType::PublicKey, DataValue::Str(pub_k));
.add_typed_default(DataType::PublicKey, DataValue::Str(pub_key_b64));
let msg_id = register_msg.get_id();
@ -522,8 +533,6 @@ impl OmikronConnection {
}
if trusted {
use iota_util::crypto_util::{DataFormat, SecurePayload};
let challenge = Uuid::new_v4().to_string();
self.app_challenges
@ -535,31 +544,36 @@ impl OmikronConnection {
.await
.insert(sender_id, (user_id, app_identifier.clone()));
if let Some(pub_key) = iota_util::crypto_helper::load_public_key(&app_public_key) {
if let Some(app_pub_bundle) =
iota_util::crypto_helper::public_key_bundle_from_base64(&app_public_key)
{
let conf = CONFIG.read().await;
let priv_k_str = conf.get_private_key().unwrap_or_default();
let pub_k_str = conf.get_public_key().unwrap_or_default();
let kr_str = conf.get_keyring().unwrap_or_default();
drop(conf);
if let Some(priv_key) = iota_util::crypto_helper::load_secret_key(&priv_k_str) {
let encrypted_challenge =
SecurePayload::new(challenge.as_bytes(), DataFormat::Raw, priv_key)
.unwrap()
.encrypt_x448(pub_key)
.unwrap()
.export(DataFormat::Base64);
if let Some(keyring) = keyring_from_base64(&kr_str) {
if let Ok(encrypted_challenge) = crypto_util::encrypt_challenge(
&challenge,
&app_pub_bundle,
) {
let bundle = keyring.public_key_bundle();
let pub_k_b64 = crypto_helper::public_key_bundle_to_base64(&bundle);
let res = CommunicationValue::new(CommunicationType::AppChallenge)
.with_id(cv.get_id())
.with_receiver(sender_id)
.add_typed_default(DataType::PublicKey, DataValue::Str(pub_k_str))
.add_typed_default(
DataType::Challenge,
DataValue::Str(encrypted_challenge),
);
let res = CommunicationValue::new(CommunicationType::AppChallenge)
.with_id(cv.get_id())
.with_receiver(sender_id)
.add_typed_default(
DataType::PublicKey,
DataValue::Str(pub_k_b64),
)
.add_typed_default(
DataType::Challenge,
DataValue::Str(encrypted_challenge),
);
self.send_message(&res).await;
return;
self.send_message(&res).await;
return;
}
}
}
}
@ -1686,17 +1700,17 @@ impl OmikronConnection {
async fn handle_challenge(&self, cv: &CommunicationValue) {
let conf = CONFIG.read().await;
let Some(private_key) = conf.get_private_key() else {
let Some(kr_str) = conf.get_keyring() else {
drop(conf);
log_t!("omikron_challenge_decryption_failed");
*self.auth_failure.write().await = Some(
"Challenge decryption failed: no private key configured on this Iota.".to_string(),
"Challenge decryption failed: no keyring configured on this Iota.".to_string(),
);
return;
};
drop(conf);
let Some(omikron_public_key) = cv.get_data(DataType::PublicKey).as_str() else {
let Some(_omikron_pub_key_bundle) = cv.get_data(DataType::PublicKey).as_str() else {
log_t!("omikron_challenge_decryption_failed");
return;
};
@ -1705,23 +1719,14 @@ impl OmikronConnection {
return;
};
let Some(secret_key) = crypto_helper::load_secret_key(&private_key) else {
log_t!("omikron_challenge_decryption_failed");
return;
};
let Some(pub_key) = crypto_helper::load_public_key(omikron_public_key) else {
let Some(keyring) = keyring_from_base64(&kr_str) else {
log_t!("omikron_challenge_decryption_failed");
return;
};
let solved_challenge =
SecurePayload::new(encrypted_challenge, DataFormat::Base64, secret_key)
.ok()
.and_then(|decrypted| decrypted.decrypt_x448(pub_key).ok());
if let Some(decrypted) = solved_challenge {
let solved = decrypted.export(DataFormat::Raw);
let solved_challenge = crypto_util::decrypt_challenge(encrypted_challenge, &keyring).ok();
if let Some(solved) = solved_challenge {
let response = CommunicationValue::new(CommunicationType::ChallengeResponse)
.with_id(cv.get_id())
.add_typed_default(DataType::Challenge, DataValue::Str(solved));
@ -1730,7 +1735,7 @@ impl OmikronConnection {
} else {
log_t!("omikron_challenge_decryption_failed");
*self.auth_failure.write().await = Some(
"Challenge decryption failed — your Iota private key may not match the registered key on the server."
"Challenge decryption failed — your Iota keyring may not match the registered keys on the server."
.to_string(),
);
}

View file

@ -1,16 +1,13 @@
use base64::{Engine as _, engine::general_purpose::STANDARD};
use hex;
use iota_logger::{PrintType, log, log_cv, log_t};
use iota_state::{RELOAD, SHUTDOWN};
use iota_storage::users::user_manager::{add_user, save_users};
use iota_storage::users::user_profile::UserProfile;
use iota_util::crypto_helper::public_key_to_base64;
use iota_util::crypto_helper::{self, hex_hash, public_key_bundle_to_base64};
use iota_util::file_util::save_file;
use mtp::codec::{CommunicationType, CommunicationValue, DataType, DataValue};
use rand_core::{OsRng, RngCore};
use sha2::{Digest, Sha256};
use std::time::Duration;
use x448::{PublicKey, Secret};
use crate::omikron_connection::OMIKRON_CONNECTION;
@ -41,16 +38,11 @@ pub async fn create_user(username: &str) -> (Option<UserProfile>, Option<String>
return (None, None);
}
};
let mut buffer = [0u8; 56];
let mut rng = OsRng;
rng.fill_bytes(&mut buffer);
let private_key = Secret::from_bytes(&buffer).unwrap();
let public_key = PublicKey::from(&private_key);
let keyring = crypto_helper::generate_keyring();
let pub_key_bundle = keyring.public_key_bundle();
let keyring_b64 = crypto_helper::keyring_to_base64(&keyring);
let mut hasher = Sha256::new();
hasher.update(&STANDARD.encode(&private_key.as_bytes()).as_bytes());
let result = hasher.finalize();
let private_key_hash = hex::encode(result);
let private_key_hash = hex_hash(&keyring_b64);
let mut bytes = [0u8; 192];
OsRng.fill_bytes(&mut bytes);
@ -60,7 +52,7 @@ pub async fn create_user(username: &str) -> (Option<UserProfile>, Option<String>
user_id as i64,
username.to_string(),
None,
STANDARD.encode(&public_key.as_bytes()),
public_key_bundle_to_base64(&pub_key_bundle),
private_key_hash,
reset_token.clone(),
);
@ -70,7 +62,7 @@ pub async fn create_user(username: &str) -> (Option<UserProfile>, Option<String>
.add_typed_default(DataType::Username, DataValue::Str(username.to_string()))
.add_typed_default(
DataType::PublicKey,
DataValue::Str(public_key_to_base64(&public_key)),
DataValue::Str(public_key_bundle_to_base64(&pub_key_bundle)),
)
.add_typed_default(DataType::IotaId, DataValue::SignedNumber(user_id as i128))
.add_typed_default(DataType::ResetToken, DataValue::Str(reset_token));
@ -94,13 +86,13 @@ pub async fn create_user(username: &str) -> (Option<UserProfile>, Option<String>
save_file(
"",
&format!("{}.tu", username),
&format!("{}::{}", user_id, STANDARD.encode(&private_key.as_bytes())),
&format!("{}::{}", user_id, keyring_b64),
);
add_user(user_profile.clone());
save_users();
(
Some(user_profile),
Some(STANDARD.encode(&private_key.as_bytes())),
Some(keyring_b64),
)
}