...
This commit is contained in:
		
							
								
								
									
										708
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										708
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							| @@ -27,6 +27,49 @@ dependencies = [ | ||||
|  "generic-array", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "age" | ||||
| version = "0.10.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "77de71da1ca673855aacea507a7aed363beb8934cf61b62364fc4b479d2e8cda" | ||||
| dependencies = [ | ||||
|  "age-core", | ||||
|  "base64 0.21.7", | ||||
|  "bech32", | ||||
|  "chacha20poly1305", | ||||
|  "cookie-factory", | ||||
|  "hmac", | ||||
|  "i18n-embed", | ||||
|  "i18n-embed-fl", | ||||
|  "lazy_static", | ||||
|  "nom", | ||||
|  "pin-project", | ||||
|  "rand", | ||||
|  "rust-embed", | ||||
|  "scrypt", | ||||
|  "sha2", | ||||
|  "subtle", | ||||
|  "x25519-dalek", | ||||
|  "zeroize", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "age-core" | ||||
| version = "0.10.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "a5f11899bc2bbddd135edbc30c36b1924fa59d0746bb45beb5933fafe3fe509b" | ||||
| dependencies = [ | ||||
|  "base64 0.21.7", | ||||
|  "chacha20poly1305", | ||||
|  "cookie-factory", | ||||
|  "hkdf", | ||||
|  "io_tee", | ||||
|  "nom", | ||||
|  "rand", | ||||
|  "secrecy", | ||||
|  "sha2", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "anstream" | ||||
| version = "0.6.15" | ||||
| @@ -82,6 +125,12 @@ version = "1.0.86" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" | ||||
|  | ||||
| [[package]] | ||||
| name = "arc-swap" | ||||
| version = "1.7.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" | ||||
|  | ||||
| [[package]] | ||||
| name = "async-trait" | ||||
| version = "0.1.88" | ||||
| @@ -90,7 +139,7 @@ checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
|  "syn 2.0.69", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -114,6 +163,39 @@ dependencies = [ | ||||
|  "rustc-demangle", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "base64" | ||||
| version = "0.21.7" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" | ||||
|  | ||||
| [[package]] | ||||
| name = "base64" | ||||
| version = "0.22.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" | ||||
|  | ||||
| [[package]] | ||||
| name = "base64ct" | ||||
| version = "1.8.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" | ||||
|  | ||||
| [[package]] | ||||
| name = "basic-toml" | ||||
| version = "0.1.10" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "ba62675e8242a4c4e806d12f11d136e626e6c8361d6b829310732241652a178a" | ||||
| dependencies = [ | ||||
|  "serde", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "bech32" | ||||
| version = "0.9.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" | ||||
|  | ||||
| [[package]] | ||||
| name = "bincode" | ||||
| version = "1.3.3" | ||||
| @@ -216,7 +298,7 @@ dependencies = [ | ||||
|  "anstream", | ||||
|  "anstyle", | ||||
|  "clap_lex", | ||||
|  "strsim", | ||||
|  "strsim 0.11.1", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -228,7 +310,7 @@ dependencies = [ | ||||
|  "heck", | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
|  "syn 2.0.69", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -257,6 +339,21 @@ dependencies = [ | ||||
|  "tokio-util", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "const-oid" | ||||
| version = "0.9.6" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" | ||||
|  | ||||
| [[package]] | ||||
| name = "cookie-factory" | ||||
| version = "0.3.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "9885fa71e26b8ab7855e2ec7cae6e9b380edff76cd052e07c683a0319d51b3a2" | ||||
| dependencies = [ | ||||
|  "futures", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "cpufeatures" | ||||
| version = "0.2.17" | ||||
| @@ -277,6 +374,56 @@ dependencies = [ | ||||
|  "typenum", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "curve25519-dalek" | ||||
| version = "4.1.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" | ||||
| dependencies = [ | ||||
|  "cfg-if", | ||||
|  "cpufeatures", | ||||
|  "curve25519-dalek-derive", | ||||
|  "digest", | ||||
|  "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 2.0.69", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "dashmap" | ||||
| version = "5.5.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" | ||||
| dependencies = [ | ||||
|  "cfg-if", | ||||
|  "hashbrown", | ||||
|  "lock_api", | ||||
|  "once_cell", | ||||
|  "parking_lot_core", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "der" | ||||
| version = "0.7.10" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" | ||||
| dependencies = [ | ||||
|  "const-oid", | ||||
|  "zeroize", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "digest" | ||||
| version = "0.10.7" | ||||
| @@ -285,6 +432,7 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" | ||||
| dependencies = [ | ||||
|  "block-buffer", | ||||
|  "crypto-common", | ||||
|  "subtle", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -295,7 +443,90 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
|  "syn 2.0.69", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "ed25519" | ||||
| version = "2.2.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" | ||||
| dependencies = [ | ||||
|  "pkcs8", | ||||
|  "signature", | ||||
| ] | ||||
|  | ||||
| [[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", | ||||
|  "subtle", | ||||
|  "zeroize", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "fiat-crypto" | ||||
| version = "0.2.9" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" | ||||
|  | ||||
| [[package]] | ||||
| name = "find-crate" | ||||
| version = "0.6.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "59a98bbaacea1c0eb6a0876280051b892eb73594fd90cf3b20e9c817029c57d2" | ||||
| dependencies = [ | ||||
|  "toml", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "fluent" | ||||
| version = "0.16.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "bb74634707bebd0ce645a981148e8fb8c7bccd4c33c652aeffd28bf2f96d555a" | ||||
| dependencies = [ | ||||
|  "fluent-bundle", | ||||
|  "unic-langid", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "fluent-bundle" | ||||
| version = "0.15.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "7fe0a21ee80050c678013f82edf4b705fe2f26f1f9877593d13198612503f493" | ||||
| dependencies = [ | ||||
|  "fluent-langneg", | ||||
|  "fluent-syntax", | ||||
|  "intl-memoizer", | ||||
|  "intl_pluralrules", | ||||
|  "rustc-hash 1.1.0", | ||||
|  "self_cell 0.10.3", | ||||
|  "smallvec", | ||||
|  "unic-langid", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "fluent-langneg" | ||||
| version = "0.13.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "2c4ad0989667548f06ccd0e306ed56b61bd4d35458d54df5ec7587c0e8ed5e94" | ||||
| dependencies = [ | ||||
|  "unic-langid", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "fluent-syntax" | ||||
| version = "0.11.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "2a530c4694a6a8d528794ee9bbd8ba0122e779629ac908d15ad5a7ae7763a33d" | ||||
| dependencies = [ | ||||
|  "thiserror", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -363,7 +594,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
|  "syn 2.0.69", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -423,6 +654,12 @@ version = "0.29.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" | ||||
|  | ||||
| [[package]] | ||||
| name = "hashbrown" | ||||
| version = "0.14.5" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" | ||||
|  | ||||
| [[package]] | ||||
| name = "heck" | ||||
| version = "0.5.0" | ||||
| @@ -435,6 +672,93 @@ version = "0.3.9" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" | ||||
|  | ||||
| [[package]] | ||||
| name = "hkdf" | ||||
| version = "0.12.4" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" | ||||
| dependencies = [ | ||||
|  "hmac", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "hmac" | ||||
| version = "0.12.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" | ||||
| dependencies = [ | ||||
|  "digest", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "i18n-config" | ||||
| version = "0.4.8" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "3e06b90c8a0d252e203c94344b21e35a30f3a3a85dc7db5af8f8df9f3e0c63ef" | ||||
| dependencies = [ | ||||
|  "basic-toml", | ||||
|  "log", | ||||
|  "serde", | ||||
|  "serde_derive", | ||||
|  "thiserror", | ||||
|  "unic-langid", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "i18n-embed" | ||||
| version = "0.14.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "94205d95764f5bb9db9ea98fa77f89653365ca748e27161f5bbea2ffd50e459c" | ||||
| dependencies = [ | ||||
|  "arc-swap", | ||||
|  "fluent", | ||||
|  "fluent-langneg", | ||||
|  "fluent-syntax", | ||||
|  "i18n-embed-impl", | ||||
|  "intl-memoizer", | ||||
|  "lazy_static", | ||||
|  "log", | ||||
|  "parking_lot", | ||||
|  "rust-embed", | ||||
|  "thiserror", | ||||
|  "unic-langid", | ||||
|  "walkdir", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "i18n-embed-fl" | ||||
| version = "0.7.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "9fc1f8715195dffc4caddcf1cf3128da15fe5d8a137606ea8856c9300047d5a2" | ||||
| dependencies = [ | ||||
|  "dashmap", | ||||
|  "find-crate", | ||||
|  "fluent", | ||||
|  "fluent-syntax", | ||||
|  "i18n-config", | ||||
|  "i18n-embed", | ||||
|  "lazy_static", | ||||
|  "proc-macro-error", | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "strsim 0.10.0", | ||||
|  "syn 2.0.69", | ||||
|  "unic-langid", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "i18n-embed-impl" | ||||
| version = "0.8.4" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "0f2cc0e0523d1fe6fc2c6f66e5038624ea8091b3e7748b5e8e0c84b1698db6c2" | ||||
| dependencies = [ | ||||
|  "find-crate", | ||||
|  "i18n-config", | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn 2.0.69", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "icu_collections" | ||||
| version = "2.0.0" | ||||
| @@ -551,6 +875,31 @@ dependencies = [ | ||||
|  "generic-array", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "intl-memoizer" | ||||
| version = "0.5.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "310da2e345f5eb861e7a07ee182262e94975051db9e4223e909ba90f392f163f" | ||||
| dependencies = [ | ||||
|  "type-map", | ||||
|  "unic-langid", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "intl_pluralrules" | ||||
| version = "7.0.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "078ea7b7c29a2b4df841a7f6ac8775ff6074020c6776d48491ce2268e068f972" | ||||
| dependencies = [ | ||||
|  "unic-langid", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "io_tee" | ||||
| version = "0.1.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "4b3f7cef34251886990511df1c61443aa928499d598a9473929ab5a90a527304" | ||||
|  | ||||
| [[package]] | ||||
| name = "is_terminal_polyfill" | ||||
| version = "1.70.1" | ||||
| @@ -563,6 +912,12 @@ version = "1.0.15" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" | ||||
|  | ||||
| [[package]] | ||||
| name = "lazy_static" | ||||
| version = "1.5.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" | ||||
|  | ||||
| [[package]] | ||||
| name = "libc" | ||||
| version = "0.2.155" | ||||
| @@ -585,12 +940,24 @@ dependencies = [ | ||||
|  "scopeguard", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "log" | ||||
| version = "0.4.27" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" | ||||
|  | ||||
| [[package]] | ||||
| name = "memchr" | ||||
| version = "2.7.4" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" | ||||
|  | ||||
| [[package]] | ||||
| name = "minimal-lexical" | ||||
| version = "0.2.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" | ||||
|  | ||||
| [[package]] | ||||
| name = "miniz_oxide" | ||||
| version = "0.7.4" | ||||
| @@ -611,6 +978,16 @@ dependencies = [ | ||||
|  "windows-sys 0.48.0", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "nom" | ||||
| version = "7.1.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" | ||||
| dependencies = [ | ||||
|  "memchr", | ||||
|  "minimal-lexical", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "num_cpus" | ||||
| version = "1.16.0" | ||||
| @@ -630,6 +1007,12 @@ dependencies = [ | ||||
|  "memchr", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "once_cell" | ||||
| version = "1.21.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" | ||||
|  | ||||
| [[package]] | ||||
| name = "opaque-debug" | ||||
| version = "0.3.1" | ||||
| @@ -659,12 +1042,42 @@ dependencies = [ | ||||
|  "windows-targets 0.52.6", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "pbkdf2" | ||||
| version = "0.12.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" | ||||
| dependencies = [ | ||||
|  "digest", | ||||
|  "hmac", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "percent-encoding" | ||||
| version = "2.3.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" | ||||
|  | ||||
| [[package]] | ||||
| name = "pin-project" | ||||
| version = "1.1.10" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" | ||||
| dependencies = [ | ||||
|  "pin-project-internal", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "pin-project-internal" | ||||
| version = "1.1.10" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn 2.0.69", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "pin-project-lite" | ||||
| version = "0.2.14" | ||||
| @@ -677,6 +1090,16 @@ version = "0.1.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" | ||||
|  | ||||
| [[package]] | ||||
| name = "pkcs8" | ||||
| version = "0.10.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" | ||||
| dependencies = [ | ||||
|  "der", | ||||
|  "spki", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "poly1305" | ||||
| version = "0.8.0" | ||||
| @@ -706,6 +1129,30 @@ dependencies = [ | ||||
|  "zerocopy", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "proc-macro-error" | ||||
| version = "1.0.4" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" | ||||
| dependencies = [ | ||||
|  "proc-macro-error-attr", | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn 1.0.109", | ||||
|  "version_check", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "proc-macro-error-attr" | ||||
| version = "1.0.4" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "version_check", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "proc-macro2" | ||||
| version = "1.0.86" | ||||
| @@ -788,16 +1235,20 @@ dependencies = [ | ||||
| name = "redis-rs" | ||||
| version = "0.0.1" | ||||
| dependencies = [ | ||||
|  "age", | ||||
|  "anyhow", | ||||
|  "base64 0.22.1", | ||||
|  "bincode", | ||||
|  "byteorder", | ||||
|  "bytes", | ||||
|  "chacha20poly1305", | ||||
|  "clap", | ||||
|  "ed25519-dalek", | ||||
|  "futures", | ||||
|  "rand", | ||||
|  "redb", | ||||
|  "redis", | ||||
|  "secrecy", | ||||
|  "serde", | ||||
|  "serde_json", | ||||
|  "sha2", | ||||
| @@ -814,24 +1265,138 @@ dependencies = [ | ||||
|  "bitflags", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "rust-embed" | ||||
| version = "8.7.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "025908b8682a26ba8d12f6f2d66b987584a4a87bc024abc5bbc12553a8cd178a" | ||||
| dependencies = [ | ||||
|  "rust-embed-impl", | ||||
|  "rust-embed-utils", | ||||
|  "walkdir", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "rust-embed-impl" | ||||
| version = "8.7.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "6065f1a4392b71819ec1ea1df1120673418bf386f50de1d6f54204d836d4349c" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "rust-embed-utils", | ||||
|  "syn 2.0.69", | ||||
|  "walkdir", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "rust-embed-utils" | ||||
| version = "8.7.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "f6cc0c81648b20b70c491ff8cce00c1c3b223bb8ed2b5d41f0e54c6c4c0a3594" | ||||
| dependencies = [ | ||||
|  "sha2", | ||||
|  "walkdir", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "rustc-demangle" | ||||
| version = "0.1.24" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" | ||||
|  | ||||
| [[package]] | ||||
| name = "rustc-hash" | ||||
| version = "1.1.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" | ||||
|  | ||||
| [[package]] | ||||
| name = "rustc-hash" | ||||
| version = "2.1.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" | ||||
|  | ||||
| [[package]] | ||||
| name = "rustc_version" | ||||
| version = "0.4.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" | ||||
| dependencies = [ | ||||
|  "semver", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "ryu" | ||||
| version = "1.0.20" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" | ||||
|  | ||||
| [[package]] | ||||
| name = "salsa20" | ||||
| version = "0.10.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" | ||||
| dependencies = [ | ||||
|  "cipher", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "same-file" | ||||
| version = "1.0.6" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" | ||||
| dependencies = [ | ||||
|  "winapi-util", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "scopeguard" | ||||
| version = "1.2.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" | ||||
|  | ||||
| [[package]] | ||||
| name = "scrypt" | ||||
| version = "0.11.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "0516a385866c09368f0b5bcd1caff3366aace790fcd46e2bb032697bb172fd1f" | ||||
| dependencies = [ | ||||
|  "pbkdf2", | ||||
|  "salsa20", | ||||
|  "sha2", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "secrecy" | ||||
| version = "0.8.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" | ||||
| dependencies = [ | ||||
|  "zeroize", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "self_cell" | ||||
| version = "0.10.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "e14e4d63b804dc0c7ec4a1e52bcb63f02c7ac94476755aa579edac21e01f915d" | ||||
| dependencies = [ | ||||
|  "self_cell 1.2.0", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "self_cell" | ||||
| version = "1.2.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "0f7d95a54511e0c7be3f51e8867aa8cf35148d7b9445d44de2f943e2b206e749" | ||||
|  | ||||
| [[package]] | ||||
| name = "semver" | ||||
| version = "1.0.26" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" | ||||
|  | ||||
| [[package]] | ||||
| name = "serde" | ||||
| version = "1.0.210" | ||||
| @@ -849,7 +1414,7 @@ checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
|  "syn 2.0.69", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -890,6 +1455,15 @@ dependencies = [ | ||||
|  "libc", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "signature" | ||||
| version = "2.2.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" | ||||
| dependencies = [ | ||||
|  "rand_core", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "slab" | ||||
| version = "0.4.9" | ||||
| @@ -925,12 +1499,28 @@ dependencies = [ | ||||
|  "windows-sys 0.52.0", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "spki" | ||||
| version = "0.7.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" | ||||
| dependencies = [ | ||||
|  "base64ct", | ||||
|  "der", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "stable_deref_trait" | ||||
| version = "1.2.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" | ||||
|  | ||||
| [[package]] | ||||
| name = "strsim" | ||||
| version = "0.10.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" | ||||
|  | ||||
| [[package]] | ||||
| name = "strsim" | ||||
| version = "0.11.1" | ||||
| @@ -943,6 +1533,16 @@ version = "2.6.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" | ||||
|  | ||||
| [[package]] | ||||
| name = "syn" | ||||
| version = "1.0.109" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "unicode-ident", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "syn" | ||||
| version = "2.0.69" | ||||
| @@ -962,7 +1562,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
|  "syn 2.0.69", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -982,7 +1582,7 @@ checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
|  "syn 2.0.69", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -1022,7 +1622,7 @@ checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
|  "syn 2.0.69", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -1038,12 +1638,49 @@ dependencies = [ | ||||
|  "tokio", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "toml" | ||||
| version = "0.5.11" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" | ||||
| dependencies = [ | ||||
|  "serde", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "type-map" | ||||
| version = "0.5.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "cb30dbbd9036155e74adad6812e9898d03ec374946234fbcebd5dfc7b9187b90" | ||||
| dependencies = [ | ||||
|  "rustc-hash 2.1.1", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "typenum" | ||||
| version = "1.18.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" | ||||
|  | ||||
| [[package]] | ||||
| name = "unic-langid" | ||||
| version = "0.9.6" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "a28ba52c9b05311f4f6e62d5d9d46f094bd6e84cb8df7b3ef952748d752a7d05" | ||||
| dependencies = [ | ||||
|  "unic-langid-impl", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "unic-langid-impl" | ||||
| version = "0.9.6" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "dce1bf08044d4b7a94028c93786f8566047edc11110595914de93362559bc658" | ||||
| dependencies = [ | ||||
|  "serde", | ||||
|  "tinystr", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "unicode-ident" | ||||
| version = "1.0.12" | ||||
| @@ -1089,6 +1726,16 @@ version = "0.9.5" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" | ||||
|  | ||||
| [[package]] | ||||
| name = "walkdir" | ||||
| version = "2.5.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" | ||||
| dependencies = [ | ||||
|  "same-file", | ||||
|  "winapi-util", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "wasi" | ||||
| version = "0.11.0+wasi-snapshot-preview1" | ||||
| @@ -1111,6 +1758,15 @@ version = "0.4.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" | ||||
|  | ||||
| [[package]] | ||||
| name = "winapi-util" | ||||
| version = "0.1.9" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" | ||||
| dependencies = [ | ||||
|  "windows-sys 0.52.0", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "winapi-x86_64-pc-windows-gnu" | ||||
| version = "0.4.0" | ||||
| @@ -1262,6 +1918,18 @@ version = "0.6.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" | ||||
|  | ||||
| [[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", | ||||
|  "serde", | ||||
|  "zeroize", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "yoke" | ||||
| version = "0.8.0" | ||||
| @@ -1282,7 +1950,7 @@ checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
|  "syn 2.0.69", | ||||
|  "synstructure", | ||||
| ] | ||||
|  | ||||
| @@ -1303,7 +1971,7 @@ checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
|  "syn 2.0.69", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -1323,7 +1991,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
|  "syn 2.0.69", | ||||
|  "synstructure", | ||||
| ] | ||||
|  | ||||
| @@ -1332,6 +2000,20 @@ name = "zeroize" | ||||
| version = "1.8.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" | ||||
| dependencies = [ | ||||
|  "zeroize_derive", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "zeroize_derive" | ||||
| version = "1.4.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn 2.0.69", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "zerotrie" | ||||
| @@ -1363,5 +2045,5 @@ checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
|  "syn 2.0.69", | ||||
| ] | ||||
|   | ||||
| @@ -19,6 +19,10 @@ bincode = "1.3.3" | ||||
| chacha20poly1305 = "0.10.1" | ||||
| rand = "0.8" | ||||
| sha2 = "0.10" | ||||
| age = "0.10" | ||||
| secrecy = "0.8" | ||||
| ed25519-dalek = "2" | ||||
| base64 = "0.22" | ||||
|  | ||||
| [dev-dependencies] | ||||
| redis = { version = "0.24", features = ["aio", "tokio-comp"] } | ||||
|   | ||||
							
								
								
									
										83
									
								
								examples/age_persist_demo.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								examples/age_persist_demo.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,83 @@ | ||||
| use std::io::{Read, Write}; | ||||
| use std::net::TcpStream; | ||||
|  | ||||
| // Minimal RESP helpers | ||||
| fn arr(parts: &[&str]) -> String { | ||||
|     let mut out = format!("*{}\r\n", parts.len()); | ||||
|     for p in parts { | ||||
|         out.push_str(&format!("${}\r\n{}\r\n", p.len(), p)); | ||||
|     } | ||||
|     out | ||||
| } | ||||
| fn read_reply(s: &mut TcpStream) -> String { | ||||
|     let mut buf = [0u8; 65536]; | ||||
|     let n = s.read(&mut buf).unwrap(); | ||||
|     String::from_utf8_lossy(&buf[..n]).to_string() | ||||
| } | ||||
| fn parse_two_bulk(reply: &str) -> Option<(String,String)> { | ||||
|     let mut lines = reply.split("\r\n"); | ||||
|     if lines.next()? != "*2" { return None; } | ||||
|     let _n = lines.next()?; | ||||
|     let a = lines.next()?.to_string(); | ||||
|     let _m = lines.next()?; | ||||
|     let b = lines.next()?.to_string(); | ||||
|     Some((a,b)) | ||||
| } | ||||
| fn parse_bulk(reply: &str) -> Option<String> { | ||||
|     let mut lines = reply.split("\r\n"); | ||||
|     let hdr = lines.next()?; | ||||
|     if !hdr.starts_with('$') { return None; } | ||||
|     Some(lines.next()?.to_string()) | ||||
| } | ||||
| fn parse_simple(reply: &str) -> Option<String> { | ||||
|     let mut lines = reply.split("\r\n"); | ||||
|     let hdr = lines.next()?; | ||||
|     if !hdr.starts_with('+') { return None; } | ||||
|     Some(hdr[1..].to_string()) | ||||
| } | ||||
|  | ||||
| fn main() { | ||||
|     let mut args = std::env::args().skip(1); | ||||
|     let host = args.next().unwrap_or_else(|| "127.0.0.1".into()); | ||||
|     let port = args.next().unwrap_or_else(|| "6379".into()); | ||||
|     let addr = format!("{host}:{port}"); | ||||
|     println!("Connecting to {addr}..."); | ||||
|     let mut s = TcpStream::connect(addr).expect("connect"); | ||||
|  | ||||
|     // Generate & persist X25519 enc keys under name "alice" | ||||
|     s.write_all(arr(&["age","keygen","alice"]).as_bytes()).unwrap(); | ||||
|     let (_alice_recip, _alice_ident) = parse_two_bulk(&read_reply(&mut s)).expect("gen enc"); | ||||
|  | ||||
|     // Generate & persist Ed25519 signing key under name "signer" | ||||
|     s.write_all(arr(&["age","signkeygen","signer"]).as_bytes()).unwrap(); | ||||
|     let (_verify, _secret) = parse_two_bulk(&read_reply(&mut s)).expect("gen sign"); | ||||
|  | ||||
|     // Encrypt by name | ||||
|     let msg = "hello from persistent keys"; | ||||
|     s.write_all(arr(&["age","encryptname","alice", msg]).as_bytes()).unwrap(); | ||||
|     let ct_b64 = parse_bulk(&read_reply(&mut s)).expect("ct b64"); | ||||
|     println!("ciphertext b64: {}", ct_b64); | ||||
|  | ||||
|     // Decrypt by name | ||||
|     s.write_all(arr(&["age","decryptname","alice", &ct_b64]).as_bytes()).unwrap(); | ||||
|     let pt = parse_bulk(&read_reply(&mut s)).expect("pt"); | ||||
|     assert_eq!(pt, msg); | ||||
|     println!("decrypted ok"); | ||||
|  | ||||
|     // Sign by name | ||||
|     s.write_all(arr(&["age","signname","signer", msg]).as_bytes()).unwrap(); | ||||
|     let sig_b64 = parse_bulk(&read_reply(&mut s)).expect("sig b64"); | ||||
|  | ||||
|     // Verify by name | ||||
|     s.write_all(arr(&["age","verifyname","signer", msg, &sig_b64]).as_bytes()).unwrap(); | ||||
|     let ok = parse_simple(&read_reply(&mut s)).expect("verify"); | ||||
|     assert_eq!(ok, "1"); | ||||
|     println!("signature verified"); | ||||
|  | ||||
|     // List names | ||||
|     s.write_all(arr(&["age","list"]).as_bytes()).unwrap(); | ||||
|     let list = read_reply(&mut s); | ||||
|     println!("LIST -> {list}"); | ||||
|  | ||||
|     println!("✔ persistent AGE workflow complete."); | ||||
| } | ||||
							
								
								
									
										308
									
								
								src/age.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										308
									
								
								src/age.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,308 @@ | ||||
| //! age.rs — AGE (rage) helpers + persistent key management for your mini-Redis. | ||||
| // | ||||
| // Features: | ||||
| // - X25519 encryption/decryption (age style) | ||||
| // - Ed25519 detached signatures + verification | ||||
| // - Persistent named keys in DB (strings): | ||||
| //      age:key:{name}       -> X25519 recipient (public encryption key, "age1...") | ||||
| //      age:privkey:{name}   -> X25519 identity (secret encryption key, "AGE-SECRET-KEY-1...") | ||||
| //      age:signpub:{name}   -> Ed25519 verify pubkey (public, used to verify signatures) | ||||
| //      age:signpriv:{name}  -> Ed25519 signing secret key (private, used to sign) | ||||
| // - Base64 wrapping for ciphertext/signature binary blobs. | ||||
|  | ||||
| use std::str::FromStr; | ||||
|  | ||||
| use secrecy::ExposeSecret; | ||||
| use age::{Decryptor, Encryptor}; | ||||
| use age::x25519; | ||||
|  | ||||
| use ed25519_dalek::{Signature, Signer, Verifier, SigningKey, VerifyingKey}; | ||||
|  | ||||
| use base64::{engine::general_purpose::STANDARD as B64, Engine as _}; | ||||
|  | ||||
| use crate::protocol::Protocol; | ||||
| use crate::server::Server; | ||||
| use crate::error::DBError; | ||||
|  | ||||
| // ---------- Internal helpers ---------- | ||||
|  | ||||
| #[derive(Debug)] | ||||
| pub enum AgeWireError { | ||||
|     ParseKey, | ||||
|     Crypto(String), | ||||
|     Utf8, | ||||
|     SignatureLen, | ||||
|     NotFound(&'static str),     // which kind of key was missing | ||||
|     Storage(String), | ||||
| } | ||||
|  | ||||
| impl AgeWireError { | ||||
|     fn to_protocol(self) -> Protocol { | ||||
|         match self { | ||||
|             AgeWireError::ParseKey => Protocol::err("ERR age: invalid key"), | ||||
|             AgeWireError::Crypto(e) => Protocol::err(&format!("ERR age: {e}")), | ||||
|             AgeWireError::Utf8 => Protocol::err("ERR age: invalid UTF-8 plaintext"), | ||||
|             AgeWireError::SignatureLen => Protocol::err("ERR age: bad signature length"), | ||||
|             AgeWireError::NotFound(w) => Protocol::err(&format!("ERR age: missing {w}")), | ||||
|             AgeWireError::Storage(e) => Protocol::err(&format!("ERR storage: {e}")), | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| fn parse_recipient(s: &str) -> Result<x25519::Recipient, AgeWireError> { | ||||
|     x25519::Recipient::from_str(s).map_err(|_| AgeWireError::ParseKey) | ||||
| } | ||||
| fn parse_identity(s: &str) -> Result<x25519::Identity, AgeWireError> { | ||||
|     x25519::Identity::from_str(s).map_err(|_| AgeWireError::ParseKey) | ||||
| } | ||||
| fn parse_ed25519_signing_key(s: &str) -> Result<SigningKey, AgeWireError> { | ||||
|     // Parse base64-encoded signing key | ||||
|     let bytes = B64.decode(s).map_err(|_| AgeWireError::ParseKey)?; | ||||
|     if bytes.len() != 32 { | ||||
|         return Err(AgeWireError::ParseKey); | ||||
|     } | ||||
|     let key_bytes: [u8; 32] = bytes.try_into().map_err(|_| AgeWireError::ParseKey)?; | ||||
|     Ok(SigningKey::from_bytes(&key_bytes)) | ||||
| } | ||||
| fn parse_ed25519_verifying_key(s: &str) -> Result<VerifyingKey, AgeWireError> { | ||||
|     // Parse base64-encoded verifying key | ||||
|     let bytes = B64.decode(s).map_err(|_| AgeWireError::ParseKey)?; | ||||
|     if bytes.len() != 32 { | ||||
|         return Err(AgeWireError::ParseKey); | ||||
|     } | ||||
|     let key_bytes: [u8; 32] = bytes.try_into().map_err(|_| AgeWireError::ParseKey)?; | ||||
|     VerifyingKey::from_bytes(&key_bytes).map_err(|_| AgeWireError::ParseKey) | ||||
| } | ||||
|  | ||||
| // ---------- Stateless crypto helpers (string in/out) ---------- | ||||
|  | ||||
| pub fn gen_enc_keypair() -> (String, String) { | ||||
|     let id = x25519::Identity::generate(); | ||||
|     let pk = id.to_public(); | ||||
|     (pk.to_string(), id.to_string().expose_secret().to_string()) // (recipient, identity) | ||||
| } | ||||
|  | ||||
| pub fn gen_sign_keypair() -> (String, String) { | ||||
|     use rand::RngCore; | ||||
|     use rand::rngs::OsRng; | ||||
|      | ||||
|     // Generate random 32 bytes for the signing key | ||||
|     let mut secret_bytes = [0u8; 32]; | ||||
|     OsRng.fill_bytes(&mut secret_bytes); | ||||
|      | ||||
|     let signing_key = SigningKey::from_bytes(&secret_bytes); | ||||
|     let verifying_key = signing_key.verifying_key(); | ||||
|      | ||||
|     // Encode as base64 for storage | ||||
|     let signing_key_b64 = B64.encode(signing_key.to_bytes()); | ||||
|     let verifying_key_b64 = B64.encode(verifying_key.to_bytes()); | ||||
|      | ||||
|     (verifying_key_b64, signing_key_b64) // (verify_pub, signing_secret) | ||||
| } | ||||
|  | ||||
| /// Encrypt `msg` for `recipient_str` (X25519). Returns base64(ciphertext). | ||||
| pub fn encrypt_b64(recipient_str: &str, msg: &str) -> Result<String, AgeWireError> { | ||||
|     let recipient = parse_recipient(recipient_str)?; | ||||
|     let enc = Encryptor::with_recipients(vec![Box::new(recipient)]) | ||||
|         .expect("failed to create encryptor"); // Handle Option<Encryptor> | ||||
|     let mut out = Vec::new(); | ||||
|     { | ||||
|         use std::io::Write; | ||||
|         let mut w = enc.wrap_output(&mut out).map_err(|e| AgeWireError::Crypto(e.to_string()))?; | ||||
|         w.write_all(msg.as_bytes()).map_err(|e| AgeWireError::Crypto(e.to_string()))?; | ||||
|         w.finish().map_err(|e| AgeWireError::Crypto(e.to_string()))?; | ||||
|     } | ||||
|     Ok(B64.encode(out)) | ||||
| } | ||||
|  | ||||
| /// Decrypt base64(ciphertext) with `identity_str`. Returns plaintext String. | ||||
| pub fn decrypt_b64(identity_str: &str, ct_b64: &str) -> Result<String, AgeWireError> { | ||||
|     let id = parse_identity(identity_str)?; | ||||
|     let ct = B64.decode(ct_b64.as_bytes()).map_err(|e| AgeWireError::Crypto(e.to_string()))?; | ||||
|     let dec = Decryptor::new(&ct[..]).map_err(|e| AgeWireError::Crypto(e.to_string()))?; | ||||
|      | ||||
|     // The decrypt method returns a Result<StreamReader, DecryptError> | ||||
|     let mut r = match dec { | ||||
|         Decryptor::Recipients(d) => d.decrypt(std::iter::once(&id as &dyn age::Identity)) | ||||
|             .map_err(|e| AgeWireError::Crypto(e.to_string()))?, | ||||
|         Decryptor::Passphrase(_) => return Err(AgeWireError::Crypto("Expected recipients, got passphrase".to_string())), | ||||
|     }; | ||||
|      | ||||
|     let mut pt = Vec::new(); | ||||
|     use std::io::Read; | ||||
|     r.read_to_end(&mut pt).map_err(|e| AgeWireError::Crypto(e.to_string()))?; | ||||
|     String::from_utf8(pt).map_err(|_| AgeWireError::Utf8) | ||||
| } | ||||
|  | ||||
| /// Sign bytes of `msg` (detached). Returns base64(signature bytes, 64 bytes). | ||||
| pub fn sign_b64(signing_secret_str: &str, msg: &str) -> Result<String, AgeWireError> { | ||||
|     let signing_key = parse_ed25519_signing_key(signing_secret_str)?; | ||||
|     let sig = signing_key.sign(msg.as_bytes()); | ||||
|     Ok(B64.encode(sig.to_bytes())) | ||||
| } | ||||
|  | ||||
| /// Verify detached signature (base64) for `msg` with pubkey. | ||||
| pub fn verify_b64(verify_pub_str: &str, msg: &str, sig_b64: &str) -> Result<bool, AgeWireError> { | ||||
|     let verifying_key = parse_ed25519_verifying_key(verify_pub_str)?; | ||||
|     let sig_bytes = B64.decode(sig_b64.as_bytes()).map_err(|e| AgeWireError::Crypto(e.to_string()))?; | ||||
|     if sig_bytes.len() != 64 { | ||||
|         return Err(AgeWireError::SignatureLen); | ||||
|     } | ||||
|     let sig = Signature::from_bytes(sig_bytes[..].try_into().unwrap()); | ||||
|     Ok(verifying_key.verify(msg.as_bytes(), &sig).is_ok()) | ||||
| } | ||||
|  | ||||
| // ---------- Storage helpers ---------- | ||||
|  | ||||
| fn sget(server: &Server, key: &str) -> Result<Option<String>, AgeWireError> { | ||||
|     let st = server.current_storage().map_err(|e| AgeWireError::Storage(e.0))?; | ||||
|     st.get(key).map_err(|e| AgeWireError::Storage(e.0)) | ||||
| } | ||||
| fn sset(server: &Server, key: &str, val: &str) -> Result<(), AgeWireError> { | ||||
|     let st = server.current_storage().map_err(|e| AgeWireError::Storage(e.0))?; | ||||
|     st.set(key.to_string(), val.to_string()).map_err(|e| AgeWireError::Storage(e.0)) | ||||
| } | ||||
|  | ||||
| fn enc_pub_key_key(name: &str) -> String { format!("age:key:{name}") } | ||||
| fn enc_priv_key_key(name: &str) -> String { format!("age:privkey:{name}") } | ||||
| fn sign_pub_key_key(name: &str) -> String { format!("age:signpub:{name}") } | ||||
| fn sign_priv_key_key(name: &str) -> String { format!("age:signpriv:{name}") } | ||||
|  | ||||
| // ---------- Command handlers (RESP Protocol) ---------- | ||||
| // Basic (stateless) ones kept for completeness | ||||
|  | ||||
| pub async fn cmd_age_genenc() -> Protocol { | ||||
|     let (recip, ident) = gen_enc_keypair(); | ||||
|     Protocol::Array(vec![Protocol::BulkString(recip), Protocol::BulkString(ident)]) | ||||
| } | ||||
|  | ||||
| pub async fn cmd_age_gensign() -> Protocol { | ||||
|     let (verify, secret) = gen_sign_keypair(); | ||||
|     Protocol::Array(vec![Protocol::BulkString(verify), Protocol::BulkString(secret)]) | ||||
| } | ||||
|  | ||||
| pub async fn cmd_age_encrypt(recipient: &str, message: &str) -> Protocol { | ||||
|     match encrypt_b64(recipient, message) { | ||||
|         Ok(b64) => Protocol::BulkString(b64), | ||||
|         Err(e) => e.to_protocol(), | ||||
|     } | ||||
| } | ||||
|  | ||||
| pub async fn cmd_age_decrypt(identity: &str, ct_b64: &str) -> Protocol { | ||||
|     match decrypt_b64(identity, ct_b64) { | ||||
|         Ok(pt) => Protocol::BulkString(pt), | ||||
|         Err(e) => e.to_protocol(), | ||||
|     } | ||||
| } | ||||
|  | ||||
| pub async fn cmd_age_sign(secret: &str, message: &str) -> Protocol { | ||||
|     match sign_b64(secret, message) { | ||||
|         Ok(b64sig) => Protocol::BulkString(b64sig), | ||||
|         Err(e) => e.to_protocol(), | ||||
|     } | ||||
| } | ||||
|  | ||||
| pub async fn cmd_age_verify(verify_pub: &str, message: &str, sig_b64: &str) -> Protocol { | ||||
|     match verify_b64(verify_pub, message, sig_b64) { | ||||
|         Ok(true) => Protocol::SimpleString("1".to_string()), | ||||
|         Ok(false) => Protocol::SimpleString("0".to_string()), | ||||
|         Err(e) => e.to_protocol(), | ||||
|     } | ||||
| } | ||||
|  | ||||
| // ---------- NEW: Persistent, named-key commands ---------- | ||||
|  | ||||
| pub async fn cmd_age_keygen(server: &Server, name: &str) -> Protocol { | ||||
|     let (recip, ident) = gen_enc_keypair(); | ||||
|     if let Err(e) = sset(server, &enc_pub_key_key(name), &recip) { return e.to_protocol(); } | ||||
|     if let Err(e) = sset(server, &enc_priv_key_key(name), &ident) { return e.to_protocol(); } | ||||
|     Protocol::Array(vec![Protocol::BulkString(recip), Protocol::BulkString(ident)]) | ||||
| } | ||||
|  | ||||
| pub async fn cmd_age_signkeygen(server: &Server, name: &str) -> Protocol { | ||||
|     let (verify, secret) = gen_sign_keypair(); | ||||
|     if let Err(e) = sset(server, &sign_pub_key_key(name), &verify) { return e.to_protocol(); } | ||||
|     if let Err(e) = sset(server, &sign_priv_key_key(name), &secret) { return e.to_protocol(); } | ||||
|     Protocol::Array(vec![Protocol::BulkString(verify), Protocol::BulkString(secret)]) | ||||
| } | ||||
|  | ||||
| pub async fn cmd_age_encrypt_name(server: &Server, name: &str, message: &str) -> Protocol { | ||||
|     let recip = match sget(server, &enc_pub_key_key(name)) { | ||||
|         Ok(Some(v)) => v, | ||||
|         Ok(None) => return AgeWireError::NotFound("recipient (age:key:{name})").to_protocol(), | ||||
|         Err(e) => return e.to_protocol(), | ||||
|     }; | ||||
|     match encrypt_b64(&recip, message) { | ||||
|         Ok(ct) => Protocol::BulkString(ct), | ||||
|         Err(e) => e.to_protocol(), | ||||
|     } | ||||
| } | ||||
|  | ||||
| pub async fn cmd_age_decrypt_name(server: &Server, name: &str, ct_b64: &str) -> Protocol { | ||||
|     let ident = match sget(server, &enc_priv_key_key(name)) { | ||||
|         Ok(Some(v)) => v, | ||||
|         Ok(None) => return AgeWireError::NotFound("identity (age:privkey:{name})").to_protocol(), | ||||
|         Err(e) => return e.to_protocol(), | ||||
|     }; | ||||
|     match decrypt_b64(&ident, ct_b64) { | ||||
|         Ok(pt) => Protocol::BulkString(pt), | ||||
|         Err(e) => e.to_protocol(), | ||||
|     } | ||||
| } | ||||
|  | ||||
| pub async fn cmd_age_sign_name(server: &Server, name: &str, message: &str) -> Protocol { | ||||
|     let sec = match sget(server, &sign_priv_key_key(name)) { | ||||
|         Ok(Some(v)) => v, | ||||
|         Ok(None) => return AgeWireError::NotFound("signing secret (age:signpriv:{name})").to_protocol(), | ||||
|         Err(e) => return e.to_protocol(), | ||||
|     }; | ||||
|     match sign_b64(&sec, message) { | ||||
|         Ok(sig) => Protocol::BulkString(sig), | ||||
|         Err(e) => e.to_protocol(), | ||||
|     } | ||||
| } | ||||
|  | ||||
| pub async fn cmd_age_verify_name(server: &Server, name: &str, message: &str, sig_b64: &str) -> Protocol { | ||||
|     let pubk = match sget(server, &sign_pub_key_key(name)) { | ||||
|         Ok(Some(v)) => v, | ||||
|         Ok(None) => return AgeWireError::NotFound("verify pubkey (age:signpub:{name})").to_protocol(), | ||||
|         Err(e) => return e.to_protocol(), | ||||
|     }; | ||||
|     match verify_b64(&pubk, message, sig_b64) { | ||||
|         Ok(true) => Protocol::SimpleString("1".to_string()), | ||||
|         Ok(false) => Protocol::SimpleString("0".to_string()), | ||||
|         Err(e) => e.to_protocol(), | ||||
|     } | ||||
| } | ||||
|  | ||||
| pub async fn cmd_age_list(server: &Server) -> Protocol { | ||||
|     // Returns 4 arrays: ["encpub", <names...>], ["encpriv", ...], ["signpub", ...], ["signpriv", ...] | ||||
|     let st = match server.current_storage() { Ok(s) => s, Err(e) => return Protocol::err(&e.0) }; | ||||
|  | ||||
|     let pull = |pat: &str, prefix: &str| -> Result<Vec<String>, DBError> { | ||||
|         let keys = st.keys(pat)?; | ||||
|         let mut names: Vec<String> = keys.into_iter() | ||||
|             .filter_map(|k| k.strip_prefix(prefix).map(|x| x.to_string())) | ||||
|             .collect(); | ||||
|         names.sort(); | ||||
|         Ok(names) | ||||
|     }; | ||||
|  | ||||
|     let encpub  = match pull("age:key:*",      "age:key:")      { Ok(v) => v, Err(e)=> return Protocol::err(&e.0) }; | ||||
|     let encpriv = match pull("age:privkey:*",  "age:privkey:")  { Ok(v) => v, Err(e)=> return Protocol::err(&e.0) }; | ||||
|     let signpub = match pull("age:signpub:*",  "age:signpub:")  { Ok(v) => v, Err(e)=> return Protocol::err(&e.0) }; | ||||
|     let signpriv= match pull("age:signpriv:*", "age:signpriv:") { Ok(v) => v, Err(e)=> return Protocol::err(&e.0) }; | ||||
|  | ||||
|     let to_arr = |label: &str, v: Vec<String>| { | ||||
|         let mut out = vec![Protocol::BulkString(label.to_string())]; | ||||
|         out.push(Protocol::Array(v.into_iter().map(Protocol::BulkString).collect())); | ||||
|         Protocol::Array(out) | ||||
|     }; | ||||
|  | ||||
|     Protocol::Array(vec![ | ||||
|         to_arr("encpub", encpub), | ||||
|         to_arr("encpriv", encpriv), | ||||
|         to_arr("signpub", signpub), | ||||
|         to_arr("signpriv", signpriv), | ||||
|     ]) | ||||
| } | ||||
							
								
								
									
										69
									
								
								src/cmd.rs
									
									
									
									
									
								
							
							
						
						
									
										69
									
								
								src/cmd.rs
									
									
									
									
									
								
							| @@ -50,6 +50,22 @@ pub enum Cmd { | ||||
|     LRange(String, i64, i64), | ||||
|     FlushDb, | ||||
|     Unknow(String), | ||||
|     // AGE (rage) commands — stateless | ||||
|     AgeGenEnc, | ||||
|     AgeGenSign, | ||||
|     AgeEncrypt(String, String),            // recipient, message | ||||
|     AgeDecrypt(String, String),            // identity, ciphertext_b64 | ||||
|     AgeSign(String, String),               // signing_secret, message | ||||
|     AgeVerify(String, String, String),     // verify_pub, message, signature_b64 | ||||
|  | ||||
|     // NEW: persistent named-key commands | ||||
|     AgeKeygen(String),                     // name | ||||
|     AgeSignKeygen(String),                 // name | ||||
|     AgeEncryptName(String, String),        // name, message | ||||
|     AgeDecryptName(String, String),        // name, ciphertext_b64 | ||||
|     AgeSignName(String, String),           // name, message | ||||
|     AgeVerifyName(String, String, String), // name, message, signature_b64 | ||||
|     AgeList, | ||||
| } | ||||
|  | ||||
| impl Cmd { | ||||
| @@ -402,6 +418,43 @@ impl Cmd { | ||||
|                             } | ||||
|                             Cmd::FlushDb | ||||
|                         } | ||||
|                         "age" => { | ||||
|                             if cmd.len() < 2 { | ||||
|                                 return Err(DBError("wrong number of arguments for AGE".to_string())); | ||||
|                             } | ||||
|                             match cmd[1].to_lowercase().as_str() { | ||||
|                                 // stateless | ||||
|                                 "genenc"   => { if cmd.len() != 2 { return Err(DBError("AGE GENENC takes no args".to_string())); } | ||||
|                                                 Cmd::AgeGenEnc } | ||||
|                                 "gensign"  => { if cmd.len() != 2 { return Err(DBError("AGE GENSIGN takes no args".to_string())); } | ||||
|                                                 Cmd::AgeGenSign } | ||||
|                                 "encrypt"  => { if cmd.len() != 4 { return Err(DBError("AGE ENCRYPT <recipient> <message>".to_string())); } | ||||
|                                                 Cmd::AgeEncrypt(cmd[2].clone(), cmd[3].clone()) } | ||||
|                                 "decrypt"  => { if cmd.len() != 4 { return Err(DBError("AGE DECRYPT <identity> <ciphertext_b64>".to_string())); } | ||||
|                                                 Cmd::AgeDecrypt(cmd[2].clone(), cmd[3].clone()) } | ||||
|                                 "sign"     => { if cmd.len() != 4 { return Err(DBError("AGE SIGN <signing_secret> <message>".to_string())); } | ||||
|                                                 Cmd::AgeSign(cmd[2].clone(), cmd[3].clone()) } | ||||
|                                 "verify"   => { if cmd.len() != 5 { return Err(DBError("AGE VERIFY <verify_pub> <message> <signature_b64>".to_string())); } | ||||
|                                                 Cmd::AgeVerify(cmd[2].clone(), cmd[3].clone(), cmd[4].clone()) } | ||||
|  | ||||
|                                 // persistent names | ||||
|                                 "keygen"       => { if cmd.len() != 3 { return Err(DBError("AGE KEYGEN <name>".to_string())); } | ||||
|                                                      Cmd::AgeKeygen(cmd[2].clone()) } | ||||
|                                 "signkeygen"   => { if cmd.len() != 3 { return Err(DBError("AGE SIGNKEYGEN <name>".to_string())); } | ||||
|                                                      Cmd::AgeSignKeygen(cmd[2].clone()) } | ||||
|                                 "encryptname"  => { if cmd.len() != 4 { return Err(DBError("AGE ENCRYPTNAME <name> <message>".to_string())); } | ||||
|                                                      Cmd::AgeEncryptName(cmd[2].clone(), cmd[3].clone()) } | ||||
|                                 "decryptname"  => { if cmd.len() != 4 { return Err(DBError("AGE DECRYPTNAME <name> <ciphertext_b64>".to_string())); } | ||||
|                                                      Cmd::AgeDecryptName(cmd[2].clone(), cmd[3].clone()) } | ||||
|                                 "signname"     => { if cmd.len() != 4 { return Err(DBError("AGE SIGNNAME <name> <message>".to_string())); } | ||||
|                                                      Cmd::AgeSignName(cmd[2].clone(), cmd[3].clone()) } | ||||
|                                 "verifyname"   => { if cmd.len() != 5 { return Err(DBError("AGE VERIFYNAME <name> <message> <signature_b64>".to_string())); } | ||||
|                                                      Cmd::AgeVerifyName(cmd[2].clone(), cmd[3].clone(), cmd[4].clone()) } | ||||
|                                 "list"         => { if cmd.len() != 2 { return Err(DBError("AGE LIST".to_string())); } | ||||
|                                                      Cmd::AgeList } | ||||
|                                 _ => return Err(DBError(format!("unsupported AGE subcommand {:?}", cmd))), | ||||
|                             } | ||||
|                         } | ||||
|                         _ => Cmd::Unknow(cmd[0].clone()), | ||||
|                     }, | ||||
|                     protocol, | ||||
| @@ -484,6 +537,22 @@ impl Cmd { | ||||
|             Cmd::LIndex(key, index) => lindex_cmd(server, &key, index).await, | ||||
|             Cmd::LRange(key, start, stop) => lrange_cmd(server, &key, start, stop).await, | ||||
|             Cmd::FlushDb => flushdb_cmd(server).await, | ||||
|             // AGE (rage): stateless | ||||
|             Cmd::AgeGenEnc => Ok(crate::age::cmd_age_genenc().await), | ||||
|             Cmd::AgeGenSign => Ok(crate::age::cmd_age_gensign().await), | ||||
|             Cmd::AgeEncrypt(recipient, message) => Ok(crate::age::cmd_age_encrypt(&recipient, &message).await), | ||||
|             Cmd::AgeDecrypt(identity, ct_b64) => Ok(crate::age::cmd_age_decrypt(&identity, &ct_b64).await), | ||||
|             Cmd::AgeSign(secret, message) => Ok(crate::age::cmd_age_sign(&secret, &message).await), | ||||
|             Cmd::AgeVerify(vpub, msg, sig_b64) => Ok(crate::age::cmd_age_verify(&vpub, &msg, &sig_b64).await), | ||||
|  | ||||
|             // AGE (rage): persistent named keys | ||||
|             Cmd::AgeKeygen(name) => Ok(crate::age::cmd_age_keygen(server, &name).await), | ||||
|             Cmd::AgeSignKeygen(name) => Ok(crate::age::cmd_age_signkeygen(server, &name).await), | ||||
|             Cmd::AgeEncryptName(name, message) => Ok(crate::age::cmd_age_encrypt_name(server, &name, &message).await), | ||||
|             Cmd::AgeDecryptName(name, ct_b64) => Ok(crate::age::cmd_age_decrypt_name(server, &name, &ct_b64).await), | ||||
|             Cmd::AgeSignName(name, message) => Ok(crate::age::cmd_age_sign_name(server, &name, &message).await), | ||||
|             Cmd::AgeVerifyName(name, message, sig_b64) => Ok(crate::age::cmd_age_verify_name(server, &name, &message, &sig_b64).await), | ||||
|             Cmd::AgeList => Ok(crate::age::cmd_age_list(server).await), | ||||
|             Cmd::Unknow(s) => Ok(Protocol::err(&format!("ERR unknown command `{}`", s))), | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| pub mod age;   // NEW | ||||
| pub mod cmd; | ||||
| pub mod crypto; | ||||
| pub mod error; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user