A lot
This commit is contained in:
parent
c2a7afe6c1
commit
ade0c3cde4
24 changed files with 1701 additions and 321 deletions
2
example-usage/.gitignore
vendored
2
example-usage/.gitignore
vendored
|
|
@ -1,4 +1,6 @@
|
|||
client_keys.json
|
||||
host_keys.json
|
||||
host_sig_pk.bin
|
||||
host_sig_pq_pk.bin
|
||||
host_enc_kem_pk.bin
|
||||
clients.json
|
||||
|
|
|
|||
|
|
@ -1,16 +1,14 @@
|
|||
[package]
|
||||
name = "mtp-example-client"
|
||||
name = "client"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[[bin]]
|
||||
name = "mtp-example-client"
|
||||
name = "client"
|
||||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
mtp-client = { path = "../../client", features = ["crypto"] }
|
||||
mtp-codec = { path = "../../codec" }
|
||||
mtp-crypto = { path = "../../crypto" }
|
||||
mtp = { path = "../../", features = ["client", "crypto"] }
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
serde_json = "1"
|
||||
hex = "0.4"
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
use std::fs;
|
||||
|
||||
use mtp_client::{ClientConfig, MTPClient, MTPConnection};
|
||||
use mtp_codec::{CommunicationType, CommunicationValue, DataType, DataValue};
|
||||
use mtp_crypto::{
|
||||
Ed25519Signer, EncryptionPrivateKey, EncryptionPublicKey, KeyGroup, Keyring,
|
||||
KemPrivateKey, KemPublicKey, SignaturePqPrivateKey, SignaturePqPublicKey,
|
||||
SignaturePrivateKey, SignaturePublicKey,
|
||||
use mtp::client::{ClientConfig, MTPClient, MTPConnection};
|
||||
use mtp::codec::{CommunicationType, CommunicationValue, DataType, DataValue};
|
||||
use mtp::crypto::{
|
||||
Ed25519Signer, KemPublicKey, Keyring, MlDsaSigner, PublicKeyBundle, SignaturePqPublicKey,
|
||||
SignaturePublicKey,
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -14,45 +13,39 @@ use mtp_crypto::{
|
|||
* connection and the local keyring.
|
||||
*/
|
||||
async fn connect_or_register(
|
||||
config: ClientConfig,
|
||||
host_public_key: SignaturePublicKey,
|
||||
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"))?,
|
||||
)?;
|
||||
let keyring = Keyring::from_bytes(&hex::decode(
|
||||
json["keyring"].as_str().expect("Missing keyring"),
|
||||
)?)?;
|
||||
|
||||
println!("Loaded client keys (ID: {})", client_id);
|
||||
|
||||
let keygroup = KeyGroup::new(
|
||||
EncryptionPublicKey::new(vec![]),
|
||||
EncryptionPrivateKey::new(vec![]),
|
||||
keyring.sig_cl_public_key.clone(),
|
||||
SignaturePrivateKey::new(keyring.sig_cl_secret_key.as_bytes().to_vec()),
|
||||
);
|
||||
|
||||
let conn = MTPClient::auth_connect(config, client_id, keygroup, host_public_key).await?;
|
||||
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");
|
||||
println!("No existing keys found: registering new client");
|
||||
|
||||
let (_signer, sig_sk, sig_pk) = Ed25519Signer::generate();
|
||||
let (_ed_signer, sig_sk, sig_pk) = Ed25519Signer::generate();
|
||||
let (_pq_signer, sig_pq_sk, sig_pq_pk) = MlDsaSigner::generate();
|
||||
let keyring = Keyring::new(
|
||||
KemPublicKey::new(vec![]),
|
||||
KemPrivateKey::new(vec![]),
|
||||
SignaturePqPublicKey::new(vec![]),
|
||||
SignaturePqPrivateKey::new(vec![]),
|
||||
mtp::crypto::KemPublicKey::new(vec![]),
|
||||
mtp::crypto::KemPrivateKey::new(vec![]),
|
||||
sig_pq_pk,
|
||||
sig_pq_sk,
|
||||
sig_pk,
|
||||
sig_sk,
|
||||
);
|
||||
|
||||
// Serialise before the move so we can persist and return the keyring
|
||||
let keyring_bytes = keyring.to_bytes();
|
||||
let conn = MTPClient::auth_register(config, keyring, host_public_key).await?;
|
||||
let conn = MTPClient::auth_register(config, &keyring, &host_public_key).await?;
|
||||
println!("Registered with ID: {}", conn.client_id);
|
||||
|
||||
let json = serde_json::json!({
|
||||
|
|
@ -79,7 +72,10 @@ async fn send_ping_and_receive(conn: &MTPConnection) -> Result<(), Box<dyn std::
|
|||
|
||||
let greeting = CommunicationValue::new(CommunicationType::Ping)
|
||||
.add_typed_default(DataType::Description, DataValue::Str("Hello MTP!".into()))
|
||||
.add_typed_default(DataType::Timestamp, DataValue::UnsignedNumber(timestamp as u128))
|
||||
.add_typed_default(
|
||||
DataType::Timestamp,
|
||||
DataValue::UnsignedNumber(timestamp as u128),
|
||||
)
|
||||
.add_typed_default(DataType::Data, DataValue::UnsignedNumber(42))
|
||||
.with_sender(conn.client_id);
|
||||
|
||||
|
|
@ -97,9 +93,17 @@ async fn send_ping_and_receive(conn: &MTPConnection) -> Result<(), Box<dyn std::
|
|||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let cert_pem = fs::read("server.pem").expect("Missing server.pem - run server first");
|
||||
let host_public_key = SignaturePublicKey::new(
|
||||
fs::read("host_sig_pk.bin").expect("Missing host_sig_pk.bin - run server first"),
|
||||
let cert_pem = fs::read("server.pem").expect("Missing server.pem: run server first");
|
||||
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 ...");
|
||||
|
|
@ -107,6 +111,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
let config = ClientConfig {
|
||||
url: "https://127.0.0.1:8080".into(),
|
||||
server_cert: Some(cert_pem),
|
||||
client_id: 0,
|
||||
};
|
||||
|
||||
let (conn, _keyring) = connect_or_register(config, host_public_key, "client_keys.json").await?;
|
||||
|
|
|
|||
|
|
@ -1,17 +1,16 @@
|
|||
[package]
|
||||
name = "mtp-example-server"
|
||||
name = "server"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[[bin]]
|
||||
name = "mtp-example-server"
|
||||
name = "server"
|
||||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
mtp-host = { path = "../../host", features = ["crypto"] }
|
||||
mtp-codec = { path = "../../codec" }
|
||||
mtp-crypto = { path = "../../crypto", features = ["serde"] }
|
||||
mtp = { path = "../../", features = ["crypto", "host"] }
|
||||
rcgen = "0.14"
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
serde_json = "1"
|
||||
serde_json = { version = "1" }
|
||||
hex = "0.4"
|
||||
serde_core = "1.0.228"
|
||||
|
|
|
|||
|
|
@ -2,19 +2,19 @@ use std::collections::HashMap;
|
|||
use std::fs;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use mtp_codec::{CommunicationType, CommunicationValue, DataType, DataTypeId, DataValue, TypeMap};
|
||||
use mtp_host::{HostConfig, MTPHost};
|
||||
use mtp_crypto::{
|
||||
Ed25519Signer, KemPrivateKey, KemPublicKey, Keyring, PublicKeyBundle,
|
||||
SignaturePqPrivateKey, SignaturePqPublicKey,
|
||||
};
|
||||
use mtp::codec::{CommunicationType, CommunicationValue, DataType, DataTypeId, DataValue, TypeMap};
|
||||
use mtp::crypto::{Ed25519Signer, Keyring, MlDsaSigner, PublicKeyBundle, kem::HybridKem};
|
||||
use mtp::host::{HostConfig, MTPHost};
|
||||
|
||||
/*
|
||||
* Load an existing TLS certificate and key pair from disk. If neither
|
||||
* file exists, generate a self-signed certificate so the server is
|
||||
* immediately usable without external tooling.
|
||||
*/
|
||||
fn load_or_generate_tls(cert_path: &str, key_path: &str) -> Result<(Vec<u8>, Vec<u8>), Box<dyn std::error::Error>> {
|
||||
fn load_or_generate_tls(
|
||||
cert_path: &str,
|
||||
key_path: &str,
|
||||
) -> Result<(Vec<u8>, Vec<u8>), Box<dyn std::error::Error>> {
|
||||
if let (Ok(c), Ok(k)) = (fs::read(cert_path), fs::read(key_path)) {
|
||||
println!("Using existing TLS cert from {cert_path}");
|
||||
return Ok((c, k));
|
||||
|
|
@ -50,15 +50,10 @@ fn load_or_generate_host_keys(path: &str) -> Result<(u64, Keyring), Box<dyn std:
|
|||
return Ok((hid, keyring));
|
||||
}
|
||||
|
||||
let (_signer, sig_sk, sig_pk) = Ed25519Signer::generate();
|
||||
let keyring = Keyring::new(
|
||||
KemPublicKey::new(vec![]),
|
||||
KemPrivateKey::new(vec![]),
|
||||
SignaturePqPublicKey::new(vec![]),
|
||||
SignaturePqPrivateKey::new(vec![]),
|
||||
sig_pk,
|
||||
sig_sk,
|
||||
);
|
||||
let (_ed_signer, sig_sk, sig_pk) = Ed25519Signer::generate();
|
||||
let (_pq_signer, sig_pq_sk, sig_pq_pk) = MlDsaSigner::generate();
|
||||
let (kem_sk, kem_pk) = HybridKem::generate_keypair();
|
||||
let keyring = Keyring::new(kem_pk, kem_sk, sig_pq_pk, sig_pq_sk, sig_pk, sig_sk);
|
||||
|
||||
let json = serde_json::json!({
|
||||
"host_id": 1,
|
||||
|
|
@ -76,20 +71,14 @@ fn load_or_generate_host_keys(path: &str) -> Result<(u64, Keyring), Box<dyn std:
|
|||
*/
|
||||
fn load_client_db(
|
||||
path: &str,
|
||||
) -> Result<
|
||||
(
|
||||
Arc<Mutex<HashMap<u64, PublicKeyBundle>>>,
|
||||
Arc<Mutex<u64>>,
|
||||
),
|
||||
Box<dyn std::error::Error>,
|
||||
> {
|
||||
let clients: Arc<Mutex<HashMap<u64, PublicKeyBundle>>> = Arc::new(Mutex::new(
|
||||
if let Ok(data) = fs::read_to_string(path) {
|
||||
) -> Result<(Arc<Mutex<HashMap<u64, PublicKeyBundle>>>, Arc<Mutex<u64>>), Box<dyn std::error::Error>>
|
||||
{
|
||||
let clients: Arc<Mutex<HashMap<u64, PublicKeyBundle>>> =
|
||||
Arc::new(Mutex::new(if let Ok(data) = fs::read_to_string(path) {
|
||||
serde_json::from_str(&data).unwrap_or_default()
|
||||
} else {
|
||||
HashMap::new()
|
||||
},
|
||||
));
|
||||
}));
|
||||
let next_id = Arc::new(Mutex::new(
|
||||
clients.lock().unwrap().keys().max().unwrap_or(&999) + 1,
|
||||
));
|
||||
|
|
@ -126,10 +115,15 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
let (cert_pem, key_pem) = load_or_generate_tls("server.pem", "server.key")?;
|
||||
let (host_id, host_keyring) = load_or_generate_host_keys("host_keys.json")?;
|
||||
|
||||
// Export the host's Ed25519 public key so clients can verify it
|
||||
// Export the host's public keys so clients can verify it
|
||||
fs::write(
|
||||
"host_sig_pk.bin",
|
||||
host_keyring.sig_cl_public_key.as_bytes(),
|
||||
"host_enc_kem_pk.bin",
|
||||
host_keyring.kem_public_key.as_bytes(),
|
||||
)?;
|
||||
fs::write("host_sig_pk.bin", host_keyring.sig_cl_public_key.as_bytes())?;
|
||||
fs::write(
|
||||
"host_sig_pq_pk.bin",
|
||||
host_keyring.sig_pq_public_key.as_bytes(),
|
||||
)?;
|
||||
|
||||
let (clients, next_id) = load_client_db("clients.json")?;
|
||||
|
|
@ -157,6 +151,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
println!("Starting MTP server on port 8080 ...");
|
||||
|
||||
let config = HostConfig {
|
||||
ip: std::net::IpAddr::V4(std::net::Ipv4Addr::UNSPECIFIED),
|
||||
port: 8080,
|
||||
tls_fullchain: cert_pem,
|
||||
tls_key: key_pem,
|
||||
|
|
|
|||
Loading…
Reference in a new issue