(feat): rename example-usage to just example
Some checks failed
CI / rustfmt (push) Successful in 17s
CI / clippy (push) Failing after 1m16s
CI / wasm build (push) Successful in 1m17s
CI / example (push) Successful in 1m29s
CI / test (push) Successful in 1m49s
CI / duplicate code (push) Successful in 12s
CI / web client (push) Failing after 27s
CI / cargo-machete (push) Successful in 1m10s
CI / cargo-deny (push) Failing after 2m20s
Some checks failed
CI / rustfmt (push) Successful in 17s
CI / clippy (push) Failing after 1m16s
CI / wasm build (push) Successful in 1m17s
CI / example (push) Successful in 1m29s
CI / test (push) Successful in 1m49s
CI / duplicate code (push) Successful in 12s
CI / web client (push) Failing after 27s
CI / cargo-machete (push) Successful in 1m10s
CI / cargo-deny (push) Failing after 2m20s
(feat): add the example's web-client dist folder to a gitignore (fix): format issues (fix): a lot of duplicate code
This commit is contained in:
parent
22245e673d
commit
89a20044a5
43 changed files with 528 additions and 1619 deletions
52
example/client/src/auth.rs
Normal file
52
example/client/src/auth.rs
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
use std::fs;
|
||||
|
||||
use mtp::client::{ClientConfig, MTPClient, MTPConnection};
|
||||
use mtp::crypto::{Ed25519Signer, Keyring, MlDsaSigner, PublicKeyBundle};
|
||||
|
||||
pub async fn connect_or_register(
|
||||
mut config: ClientConfig,
|
||||
host_public_key: PublicKeyBundle,
|
||||
client_key_path: &str,
|
||||
) -> Result<(MTPConnection, Keyring), Box<dyn std::error::Error>> {
|
||||
if let Ok(data) = fs::read_to_string(client_key_path) {
|
||||
let json: serde_json::Value = serde_json::from_str(&data)?;
|
||||
let client_id = json["client_id"].as_u64().expect("Invalid client_id");
|
||||
let keyring = Keyring::from_bytes(&hex::decode(
|
||||
json["keyring"].as_str().expect("Missing keyring"),
|
||||
)?)?;
|
||||
|
||||
println!("Loaded client keys (ID: {})", client_id);
|
||||
|
||||
config.client_id = client_id;
|
||||
let conn = MTPClient::auth_connect(config, &keyring, &host_public_key).await?;
|
||||
println!("Authenticated (version {})", conn.version);
|
||||
Ok((conn, keyring))
|
||||
} else {
|
||||
println!("No existing keys found: registering new client");
|
||||
|
||||
let (_ed_signer, sig_sk, sig_pk) = Ed25519Signer::generate();
|
||||
let (_pq_signer, sig_pq_sk, sig_pq_pk) = MlDsaSigner::generate();
|
||||
let keyring = Keyring::new(
|
||||
mtp::crypto::KemPublicKey::new(vec![]),
|
||||
mtp::crypto::KemPrivateKey::new(vec![]),
|
||||
sig_pq_pk,
|
||||
sig_pq_sk,
|
||||
sig_pk,
|
||||
sig_sk,
|
||||
);
|
||||
|
||||
let keyring_bytes = keyring.to_bytes();
|
||||
let conn = MTPClient::auth_register(config, &keyring, &host_public_key).await?;
|
||||
println!("Registered with ID: {}", conn.client_id);
|
||||
|
||||
let json = serde_json::json!({
|
||||
"client_id": conn.client_id,
|
||||
"keyring": hex::encode(&keyring_bytes),
|
||||
});
|
||||
fs::write(client_key_path, serde_json::to_string_pretty(&json)?)?;
|
||||
println!("Saved client keys -> {client_key_path}");
|
||||
|
||||
let keyring = Keyring::from_bytes(&keyring_bytes)?;
|
||||
Ok((conn, keyring))
|
||||
}
|
||||
}
|
||||
57
example/client/src/main.rs
Normal file
57
example/client/src/main.rs
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
mod auth;
|
||||
mod messages;
|
||||
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
use mtp::client::ClientConfig;
|
||||
use mtp::crypto::{KemPublicKey, PublicKeyBundle, SignaturePqPublicKey, SignaturePublicKey};
|
||||
|
||||
fn dev_cert_path() -> String {
|
||||
std::env::var("MTP_DEV_CERT").unwrap_or_else(|_| {
|
||||
if Path::new("example/dev-cert/cert.pem").exists() {
|
||||
"example/dev-cert/cert.pem".to_string()
|
||||
} else {
|
||||
"dev-cert/cert.pem".to_string()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let cert_path = dev_cert_path();
|
||||
let cert_pem = fs::read(&cert_path).unwrap_or_else(|e| {
|
||||
panic!(
|
||||
"Missing TLS certificate at {cert_path}: enter the Nix shell first or run the server to generate it: {e}"
|
||||
)
|
||||
});
|
||||
let host_public_key = PublicKeyBundle::new(
|
||||
KemPublicKey::new(
|
||||
fs::read("host_enc_kem_pk.bin")
|
||||
.expect("Missing host_enc_kem_pk.bin: run server first"),
|
||||
),
|
||||
SignaturePqPublicKey::new(
|
||||
fs::read("host_sig_pq_pk.bin")
|
||||
.expect("Missing host_sig_pq_pk.bin: run server first"),
|
||||
),
|
||||
SignaturePublicKey::new(
|
||||
fs::read("host_sig_pk.bin").expect("Missing host_sig_pk.bin: run server first"),
|
||||
),
|
||||
);
|
||||
|
||||
println!("Connecting to 127.0.0.1:8080 ...");
|
||||
|
||||
let config = ClientConfig {
|
||||
url: "https://127.0.0.1:8080".into(),
|
||||
server_cert: Some(cert_pem),
|
||||
client_id: 0,
|
||||
};
|
||||
|
||||
let server_bundle = host_public_key.clone();
|
||||
let (conn, keyring) =
|
||||
auth::connect_or_register(config, host_public_key, "client_keys.json").await?;
|
||||
messages::send_and_receive(&conn, &keyring, &server_bundle).await?;
|
||||
|
||||
println!("\nDone");
|
||||
Ok(())
|
||||
}
|
||||
96
example/client/src/messages.rs
Normal file
96
example/client/src/messages.rs
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
use mtp::client::MTPConnection;
|
||||
use mtp::codec::{CommunicationType, CommunicationValue, DataType, DataValue};
|
||||
use mtp::crypto::{Ed25519Signer, EncryptionType, Keyring, PublicKeyBundle, SigAlgorithm};
|
||||
use mtp::type_map::TypeMap;
|
||||
|
||||
pub fn build_demo_message(
|
||||
client_id: u64,
|
||||
keyring: &Keyring,
|
||||
server_bundle: &PublicKeyBundle,
|
||||
) -> CommunicationValue {
|
||||
// Encrypt to the server's KEM public key; the server decrypts with its keyring.
|
||||
let enc_type = EncryptionType::MlKemChaCha20Poly1305;
|
||||
let signer = Ed25519Signer::new(&keyring.sig_cl_secret_key)
|
||||
.expect("Ed25519 signer from keyring");
|
||||
|
||||
let tm = TypeMap::latest();
|
||||
|
||||
let inner_enc = DataValue::Container(vec![
|
||||
(DataType::Version.to_id(&tm), DataValue::Str("secret inner data".into())),
|
||||
(DataType::Id.to_id(&tm), DataValue::UnsignedNumber(42)),
|
||||
]);
|
||||
let mut dv_enc = inner_enc;
|
||||
dv_enc.encrypt_container(enc_type, server_bundle, b"demo-aad");
|
||||
|
||||
let inner_sig = DataValue::Container(vec![
|
||||
(DataType::Version.to_id(&tm), DataValue::Str("signed by client".into())),
|
||||
(DataType::Id.to_id(&tm), DataValue::UnsignedNumber(99)),
|
||||
]);
|
||||
let mut dv_sig = inner_sig;
|
||||
dv_sig.sign_container(SigAlgorithm::ED25519, &signer);
|
||||
|
||||
let inner_sec = DataValue::Container(vec![
|
||||
(
|
||||
DataType::Version.to_id(&tm),
|
||||
DataValue::Str("signed+encrypted payload".into()),
|
||||
),
|
||||
(DataType::Id.to_id(&tm), DataValue::UnsignedNumber(7)),
|
||||
]);
|
||||
let mut dv_sec = inner_sec;
|
||||
dv_sec.sign_and_encrypt_container(SigAlgorithm::ED25519, &signer, enc_type, server_bundle, b"demo-aad");
|
||||
|
||||
let timestamp = std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_secs();
|
||||
|
||||
let msg = CommunicationValue::new(CommunicationType::Ping)
|
||||
.add_typed_default(
|
||||
DataType::Description,
|
||||
DataValue::Str("MTP Data Type Demo".into()),
|
||||
)
|
||||
.add_typed_default(
|
||||
DataType::Timestamp,
|
||||
DataValue::UnsignedNumber(timestamp as u128),
|
||||
)
|
||||
.add_typed_default(DataType::Data, DataValue::Str("Hello, MTP!".into()))
|
||||
.add_typed_default(DataType::Flags, DataValue::BoolTrue)
|
||||
.add_typed_default(DataType::Value, DataValue::Float(2, 12345))
|
||||
.add_typed_default(
|
||||
DataType::BinaryData,
|
||||
DataValue::Bytes(vec![0xDE, 0xAD, 0xBE, 0xEF, 0x42]),
|
||||
)
|
||||
.add_typed_default(
|
||||
DataType::Items,
|
||||
DataValue::Array(vec![
|
||||
DataValue::Str("alpha".into()),
|
||||
DataValue::Str("beta".into()),
|
||||
DataValue::Str("gamma".into()),
|
||||
]),
|
||||
)
|
||||
.add_typed_default(DataType::EncryptedPayload, dv_enc)
|
||||
.add_typed_default(DataType::SignedPayload, dv_sig)
|
||||
.add_typed_default(DataType::SecurePayload, dv_sec)
|
||||
.with_sender(client_id);
|
||||
msg
|
||||
}
|
||||
|
||||
pub async fn send_and_receive(
|
||||
conn: &MTPConnection,
|
||||
keyring: &Keyring,
|
||||
server_bundle: &PublicKeyBundle,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let msg = build_demo_message(conn.client_id, keyring, server_bundle);
|
||||
println!("Sending: {msg}");
|
||||
conn.sender.send(&msg).await?;
|
||||
|
||||
match conn.receiver.receive().await {
|
||||
Ok(resp) => {
|
||||
println!("Received: {resp}");
|
||||
}
|
||||
Err(e) => eprintln!("Receive error: {e}"),
|
||||
}
|
||||
|
||||
conn.sender.close();
|
||||
Ok(())
|
||||
}
|
||||
Loading…
Reference in a new issue