CryptoUtil
This commit is contained in:
parent
1efcb8837c
commit
912aa9491c
10 changed files with 153 additions and 35 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -1029,6 +1029,7 @@ name = "mtp-crypto"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"aes-gcm",
|
||||
"base64",
|
||||
"chacha20poly1305",
|
||||
"ed25519-dalek",
|
||||
"getrandom 0.4.3",
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ hkdf = { version = "0.13", optional = true }
|
|||
sha2 = { version = "0.11", optional = true }
|
||||
zeroize = { version = "1.9", features = ["derive"] }
|
||||
thiserror = "1"
|
||||
base64 = "0.22"
|
||||
rand_core = { version = "0.6", features = ["getrandom"] }
|
||||
getrandom = "0.4.3"
|
||||
mlkem-tls = { version = "0.2", optional = true }
|
||||
|
|
|
|||
|
|
@ -28,4 +28,6 @@ pub enum CryptoError {
|
|||
UnknownAlgorithm,
|
||||
#[error("invalid hex encoding")]
|
||||
InvalidHex,
|
||||
#[error("invalid base64 encoding")]
|
||||
InvalidBase64,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
use std::fmt;
|
||||
|
||||
use base64::Engine;
|
||||
use base64::engine::general_purpose;
|
||||
use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||
|
||||
// --- Private key types ---
|
||||
|
|
@ -197,6 +200,16 @@ fn hex_to_bytes(s: &str) -> Result<Vec<u8>, crate::error::CryptoError> {
|
|||
.collect()
|
||||
}
|
||||
|
||||
fn bytes_to_base64(bytes: &[u8]) -> String {
|
||||
general_purpose::STANDARD.encode(bytes)
|
||||
}
|
||||
|
||||
fn base64_to_bytes(s: &str) -> Result<Vec<u8>, crate::error::CryptoError> {
|
||||
general_purpose::STANDARD
|
||||
.decode(s)
|
||||
.map_err(|_| crate::error::CryptoError::InvalidBase64)
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
|
|
@ -510,6 +523,22 @@ impl Keyring {
|
|||
sig_cl_secret_key: SignaturePrivateKey::new(read_key(&mut offset)?),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn to_hex(&self) -> String {
|
||||
bytes_to_hex(&self.to_bytes())
|
||||
}
|
||||
|
||||
pub fn from_hex(s: &str) -> Result<Self, crate::error::CryptoError> {
|
||||
Self::from_bytes(&hex_to_bytes(s)?)
|
||||
}
|
||||
|
||||
pub fn to_base64(&self) -> String {
|
||||
bytes_to_base64(&self.to_bytes())
|
||||
}
|
||||
|
||||
pub fn from_base64(s: &str) -> Result<Self, crate::error::CryptoError> {
|
||||
Self::from_bytes(&base64_to_bytes(s)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&[u8]> for Keyring {
|
||||
|
|
@ -645,6 +674,14 @@ impl PublicKeyBundle {
|
|||
sig_cl_public_key: cl,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn to_base64(&self) -> String {
|
||||
bytes_to_base64(&self.as_bytes())
|
||||
}
|
||||
|
||||
pub fn from_base64(s: &str) -> Result<Self, crate::error::CryptoError> {
|
||||
Self::from_bytes(&base64_to_bytes(s)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&[u8]> for PublicKeyBundle {
|
||||
|
|
@ -760,6 +797,48 @@ mod tests {
|
|||
assert_eq!(key.as_bytes(), recovered.as_bytes());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keyring_hex_roundtrip() {
|
||||
let keyring = Keyring::new(
|
||||
KemPublicKey::new(vec![1u8; 16]),
|
||||
KemPrivateKey::new(vec![2u8; 16]),
|
||||
SignaturePqPublicKey::new(vec![3u8; 16]),
|
||||
SignaturePqPrivateKey::new(vec![4u8; 16]),
|
||||
SignaturePublicKey::new(vec![5u8; 16]),
|
||||
SignaturePrivateKey::new(vec![6u8; 16]),
|
||||
);
|
||||
let hex = keyring.to_hex();
|
||||
let recovered = Keyring::from_hex(&hex).unwrap();
|
||||
assert_eq!(keyring.to_bytes(), recovered.to_bytes());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keyring_base64_roundtrip() {
|
||||
let keyring = Keyring::new(
|
||||
KemPublicKey::new(vec![1u8; 16]),
|
||||
KemPrivateKey::new(vec![2u8; 16]),
|
||||
SignaturePqPublicKey::new(vec![3u8; 16]),
|
||||
SignaturePqPrivateKey::new(vec![4u8; 16]),
|
||||
SignaturePublicKey::new(vec![5u8; 16]),
|
||||
SignaturePrivateKey::new(vec![6u8; 16]),
|
||||
);
|
||||
let b64 = keyring.to_base64();
|
||||
let recovered = Keyring::from_base64(&b64).unwrap();
|
||||
assert_eq!(keyring.to_bytes(), recovered.to_bytes());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn public_key_bundle_base64_roundtrip() {
|
||||
let bundle = PublicKeyBundle::new(
|
||||
KemPublicKey::new(vec![1u8; 32]),
|
||||
SignaturePqPublicKey::new(vec![2u8; 64]),
|
||||
SignaturePublicKey::new(vec![3u8; 32]),
|
||||
);
|
||||
let b64 = bundle.to_base64();
|
||||
let recovered = PublicKeyBundle::from_base64(&b64).unwrap();
|
||||
assert_eq!(bundle.as_bytes(), recovered.as_bytes());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hex_invalid_returns_error() {
|
||||
assert!(KemPublicKey::from_hex("xyz").is_err());
|
||||
|
|
|
|||
67
example/Cargo.lock
generated
67
example/Cargo.lock
generated
|
|
@ -59,9 +59,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",
|
||||
|
|
@ -70,14 +70,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]]
|
||||
|
|
@ -595,9 +596,9 @@ checksum = "1a9fcbcc408c5526c3ab80d534e5c86e7967c1fb7aa0a8c76abd1edc27deb877"
|
|||
|
||||
[[package]]
|
||||
name = "hybrid-array"
|
||||
version = "0.4.12"
|
||||
version = "0.4.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9155a582abd142abc056962c29e3ce5ff2ad5469f4246b537ed42c5deba857da"
|
||||
checksum = "818356c5132c1fede50f837ca96afbe78ff42413047f4abb886217845e1b6c8c"
|
||||
dependencies = [
|
||||
"ctutils",
|
||||
"typenum",
|
||||
|
|
@ -743,9 +744,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.102"
|
||||
version = "0.3.103"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "03d04c30968dffe80775bd4d7fb676131cd04a1fb46d2686dbffbaec2d9dfd31"
|
||||
checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"futures-util",
|
||||
|
|
@ -771,6 +772,13 @@ dependencies = [
|
|||
"cpufeatures 0.3.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "keygen"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"mtp",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.5.0"
|
||||
|
|
@ -937,6 +945,7 @@ dependencies = [
|
|||
name = "mtp-crypto"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"chacha20poly1305",
|
||||
"ed25519-dalek",
|
||||
"getrandom 0.4.3",
|
||||
|
|
@ -995,9 +1004,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.4.6"
|
||||
version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
|
||||
checksum = "c863e9ab5e7bf9c99ba75e1050f1e4d624ae87ed3532d6238ffbdc7b585dbbe6"
|
||||
dependencies = [
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
|
|
@ -1134,6 +1143,12 @@ dependencies = [
|
|||
"spki 0.8.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e"
|
||||
|
||||
[[package]]
|
||||
name = "poly1305"
|
||||
version = "0.8.0"
|
||||
|
|
@ -1360,9 +1375,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "2.1.2"
|
||||
version = "2.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe"
|
||||
checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
|
|
@ -1412,9 +1427,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",
|
||||
|
|
@ -1758,9 +1773,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",
|
||||
"num-conv",
|
||||
|
|
@ -1778,9 +1793,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",
|
||||
|
|
@ -1951,9 +1966,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.125"
|
||||
version = "0.2.126"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ddb3f79143bced6de84270411622a2699cee572fc0875aeaf1e7867cf9fca1a"
|
||||
checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
|
|
@ -1964,9 +1979,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.125"
|
||||
version = "0.2.126"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e21a184b13fb19e157296e2c46056aec9092264fab83e4ba59e68c61b323c3d"
|
||||
checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
|
|
@ -1974,9 +1989,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.125"
|
||||
version = "0.2.126"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fecefd9c35bd935a20fc3fc344b5f29138961e4f47fb03297d88f2587afb5ebd"
|
||||
checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"proc-macro2",
|
||||
|
|
@ -1987,9 +2002,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.125"
|
||||
version = "0.2.126"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23939e44bb9a5d7576fa2b563dc2e136628f1224e88a8deed09e04858b77871f"
|
||||
checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[workspace]
|
||||
members = [
|
||||
"server",
|
||||
"client",
|
||||
"client", "keygen",
|
||||
]
|
||||
resolver = "3"
|
||||
|
|
|
|||
7
example/keygen/Cargo.toml
Normal file
7
example/keygen/Cargo.toml
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
[package]
|
||||
name = "keygen"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
mtp = { version = "0.1.0", path = "../../", features = ["crypto"] }
|
||||
13
example/keygen/src/main.rs
Normal file
13
example/keygen/src/main.rs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
use mtp::crypto::Keyring;
|
||||
|
||||
fn main() {
|
||||
let keyring = Keyring::generate();
|
||||
let bundle = keyring.public_key_bundle();
|
||||
|
||||
// The `Debug` impl redacts private keys by design, so use the encoding
|
||||
// methods to emit the full keyring (public + secret keys) instead.
|
||||
println!("Keyring (hex):\n{}\n", keyring.to_hex());
|
||||
println!("Keyring (base64):\n{}\n", keyring.to_base64());
|
||||
|
||||
println!("PublicKeyBundle (base64):\n{}", bundle.to_base64());
|
||||
}
|
||||
|
|
@ -3,7 +3,8 @@ mod handlers;
|
|||
mod keys;
|
||||
mod tls;
|
||||
|
||||
use mtp::host::{HostConfig, MTPHost};
|
||||
use mtp::host::{AuthenticationPolicy, HostConfig, MTPHost};
|
||||
|
||||
use mtp::type_map::TypeMap;
|
||||
use std::future::Future;
|
||||
use std::path::Path;
|
||||
|
|
@ -77,7 +78,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
Ok(()) => {}
|
||||
Err(e) => eprintln!("Failed to persist client database to {path}: {e}"),
|
||||
},
|
||||
Err(e) => eprintln!("Failed to serialize client database after registering {id}: {e}"),
|
||||
Err(e) => {
|
||||
eprintln!("Failed to serialize client database after registering {id}: {e}")
|
||||
}
|
||||
}
|
||||
println!("Registered new client with ID: {}", id);
|
||||
id
|
||||
|
|
@ -92,16 +95,14 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
cert_pem,
|
||||
key_pem,
|
||||
)
|
||||
.with_authentication(host_keyring, get_existing_user, complete_register);
|
||||
.with_authentication(host_keyring, get_existing_user, complete_register)
|
||||
.with_authentication_policy(AuthenticationPolicy::ForceAuthentication);
|
||||
|
||||
let mut host = MTPHost::new(config).await?;
|
||||
println!("Server listening on {}", host.local_addr());
|
||||
|
||||
while let Some(conn) = host.accept().await? {
|
||||
let desc = conn
|
||||
.description
|
||||
.as_deref()
|
||||
.unwrap_or("(no description)");
|
||||
let desc = conn.description.as_deref().unwrap_or("(no description)");
|
||||
println!(
|
||||
"\n--- New connection (version {}, description: {desc}) ---",
|
||||
conn.version
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
pub use mtp_codec as codec;
|
||||
pub use mtp_common as common;
|
||||
pub use mtp_transport as transport;
|
||||
pub use mtp_type_map as type_map;
|
||||
|
||||
#[cfg(feature = "crypto")]
|
||||
|
|
|
|||
Loading…
Reference in a new issue