From 9e4e074e4e4f48e9c4388abd8c31df8bad377253 Mon Sep 17 00:00:00 2001 From: Michiel Date: Tue, 3 Sep 2024 10:01:06 +0200 Subject: [PATCH 1/5] Change message type to crypto+signature type Signed-off-by: Michiel --- examples/src/cli.rs | 20 +++++++++--- examples/src/server.rs | 2 +- tsp-javascript/src/lib.rs | 37 +++++++++++++++------ tsp-node/test.js | 17 ++++++---- tsp-node/tsp.js | 17 +++++++--- tsp-python/src/lib.rs | 41 +++++++++++++++++------- tsp-python/test.py | 15 +++++---- tsp-python/tsp.py | 7 ++-- tsp/src/cesr/packet.rs | 2 +- tsp/src/crypto/mod.rs | 13 ++++++-- tsp/src/crypto/nonconfidential.rs | 15 ++++++--- tsp/src/crypto/tsp_hpke.rs | 7 +++- tsp/src/crypto/tsp_nacl.rs | 7 +++- tsp/src/definitions/mod.rs | 8 ++--- tsp/src/store.rs | 53 ++++++++++++++++++++++++------- tsp/src/test.rs | 45 ++++++++++++++++++++------ 16 files changed, 225 insertions(+), 81 deletions(-) diff --git a/examples/src/cli.rs b/examples/src/cli.rs index 22dda9f..340b423 100644 --- a/examples/src/cli.rs +++ b/examples/src/cli.rs @@ -447,13 +447,23 @@ async fn run() -> Result<(), Error> { message, message_type, } => { - use tsp::definitions::MessageType; - let status = match message_type { - MessageType::Signed => "NON-CONFIDENTIAL", - MessageType::SignedAndEncrypted => "confidential", + let status = match message_type.crypto_type { + tsp::cesr::CryptoType::Plaintext => "NON-CONFIDENTIAL", + _ => "confidential", + }; + let crypto_type = match message_type.crypto_type { + tsp::cesr::CryptoType::Plaintext => "Plain text", + tsp::cesr::CryptoType::HpkeAuth => "HPKE Auth", + tsp::cesr::CryptoType::HpkeEssr => "HPKE ESSR", + tsp::cesr::CryptoType::NaclAuth => "NaCl Auth", + tsp::cesr::CryptoType::NaclEssr => "NaCl ESSR", + }; + let signature_type = match message_type.signature_type { + tsp::cesr::SignatureType::NoSignature => "no signature", + tsp::cesr::SignatureType::Ed25519 => "Ed25519 signature", }; info!( - "received {status} message ({} bytes) from {}", + "received {status} message ({} bytes) from {} ({crypto_type}, {signature_type})", message.len(), sender, ); diff --git a/examples/src/server.rs b/examples/src/server.rs index 1122a8a..2f1434c 100644 --- a/examples/src/server.rs +++ b/examples/src/server.rs @@ -596,7 +596,7 @@ async fn websocket(stream: WebSocket, state: Arc) { // if the sender is verified, decrypt the message let result = if let Some(sender_vid) = incoming_senders_read.get(&sender_id) { - let Ok((_, payload)) = + let Ok((_, payload, _, _)) = tsp::crypto::open(receiver_vid, sender_vid, &mut encrypted_message) else { continue; diff --git a/tsp-javascript/src/lib.rs b/tsp-javascript/src/lib.rs index bc1b40f..fb448ab 100644 --- a/tsp-javascript/src/lib.rs +++ b/tsp-javascript/src/lib.rs @@ -442,9 +442,19 @@ impl From<&tsp::ReceivedTspMessage> for ReceivedTspMessageVariant { #[wasm_bindgen] #[derive(Debug, Clone, Copy, Serialize, Deserialize)] -pub enum MessageType { - Signed, - SignedAndEncrypted, +pub enum CryptoType { + Plaintext = 0, + HpkeAuth = 1, + HpkeEssr = 2, + NaclAuth = 3, + NaclEssr = 4, +} + +#[wasm_bindgen] +#[derive(Debug, Clone, Copy, Serialize, Deserialize)] +pub enum SignatureType { + NoSignature = 0, + Ed25519 = 1, } #[wasm_bindgen(inspectable)] @@ -454,7 +464,8 @@ pub struct FlatReceivedTspMessage { sender: Option, nonconfidential_data: Option>>, message: Option>, - pub message_type: Option, + pub crypto_type: Option, + pub signature_type: Option, route: Option>>>, nested_vid: Option>, thread_id: Option>, @@ -555,7 +566,8 @@ impl From for FlatReceivedTspMessage { sender: None, nonconfidential_data: None, message: None, - message_type: None, + crypto_type: None, + signature_type: None, route: None, nested_vid: None, thread_id: None, @@ -577,11 +589,16 @@ impl From for FlatReceivedTspMessage { this.sender = Some(sender); this.nonconfidential_data = Some(nonconfidential_data); this.message = Some(message); - this.message_type = match message_type { - tsp::definitions::MessageType::Signed => Some(MessageType::Signed), - tsp::definitions::MessageType::SignedAndEncrypted => { - Some(MessageType::SignedAndEncrypted) - } + this.crypto_type = match message_type.crypto_type { + tsp::cesr::CryptoType::Plaintext => Some(CryptoType::Plaintext), + tsp::cesr::CryptoType::HpkeAuth => Some(CryptoType::HpkeAuth), + tsp::cesr::CryptoType::HpkeEssr => Some(CryptoType::HpkeEssr), + tsp::cesr::CryptoType::NaclAuth => Some(CryptoType::NaclAuth), + tsp::cesr::CryptoType::NaclEssr => Some(CryptoType::NaclEssr), + }; + this.signature_type = match message_type.signature_type { + tsp::cesr::SignatureType::NoSignature => Some(SignatureType::NoSignature), + tsp::cesr::SignatureType::Ed25519 => Some(SignatureType::Ed25519), }; } tsp::ReceivedTspMessage::RequestRelationship { diff --git a/tsp-node/test.js b/tsp-node/test.js index 1510a07..aaadf12 100644 --- a/tsp-node/test.js +++ b/tsp-node/test.js @@ -1,7 +1,7 @@ const assert = require('assert'); const tsp = require('./tsp'); -const { Store, OwnedVid, MessageType, GenericMessage, RequestRelationship, AcceptRelationship, CancelRelationship, ForwardRequest} = tsp; +const { Store, OwnedVid, CryptoType, SignatureType, GenericMessage, RequestRelationship, AcceptRelationship, CancelRelationship, ForwardRequest} = tsp; function new_vid() { return OwnedVid.new_did_peer("tcp://127.0.0.1:1337"); @@ -29,11 +29,12 @@ describe('tsp node tests', function() { let received = store.open_message(sealed); if (received instanceof GenericMessage) { - const { sender, message: messageBytes, message_type } = received; + const { sender, message: messageBytes, crypto_type, signature_type } = received; assert.strictEqual(sender, alice_identifier, "Sender does not match Alice's identifier"); let receivedMessage = String.fromCharCode.apply(null, messageBytes); assert.strictEqual(receivedMessage, message, "Received message does not match"); - assert.strictEqual(message_type, MessageType.SignedAndEncrypted, "Message type does not match SignedAndEncrypted"); + assert.notStrictEqual(crypto_type, CryptoType.Plaintext, "Crypto type should not be Plaintext"); + assert.notStrictEqual(signature_type, SignatureType.NoSignature, "Signature type should not be NoSignature"); } else { assert.fail(`Unexpected message type: ${received}`); } @@ -205,11 +206,12 @@ describe('tsp node tests', function() { // Check the final received message in d_store if (received instanceof GenericMessage) { - const { sender, nonconfidential_data: _, message: messageBytes, message_type } = received; + const { sender, nonconfidential_data: _, message: messageBytes, crypto_type, signature_type } = received; assert.strictEqual(sender, sneaky_a.identifier()); message = String.fromCharCode.apply(null, messageBytes); assert.strictEqual(message, hello_world, "Received message does not match"); - assert.strictEqual(message_type, MessageType.SignedAndEncrypted, "Message type does not match SignedAndEncrypted"); + assert.notStrictEqual(crypto_type, CryptoType.Plaintext, "Crypto type should not be Plaintext"); + assert.notStrictEqual(signature_type, SignatureType.NoSignature, "Signature type should not be NoSignature"); } else { assert.fail(`Unexpected message type in d_store: ${received.type}`); } @@ -279,14 +281,15 @@ describe('tsp node tests', function() { // Pattern match for GenericMessage in received message if (received_3 instanceof GenericMessage) { - let { sender, nonconfidential_data, message: messageBytes, message_type } = received_3; + let { sender, nonconfidential_data, message: messageBytes, crypto_type, signature_type } = received_3; // Assertions for GenericMessage assert.strictEqual(sender, nested_vid_1); assert.strictEqual(nonconfidential_data, null); message = String.fromCharCode.apply(null, messageBytes); assert.strictEqual(message, hello_world, "Received message does not match"); - assert.strictEqual(message_type, MessageType.SignedAndEncrypted); + assert.notStrictEqual(crypto_type, CryptoType.Plaintext, "Crypto type should not be Plaintext"); + assert.notStrictEqual(signature_type, SignatureType.NoSignature, "Signature type should not be NoSignature"); } else { throw new Error("Unexpected message type"); } diff --git a/tsp-node/tsp.js b/tsp-node/tsp.js index 5cfe03d..ab1815f 100644 --- a/tsp-node/tsp.js +++ b/tsp-node/tsp.js @@ -1,11 +1,19 @@ const wasm = require('tsp-javascript'); const { OwnedVid } = wasm; -const MessageType = { - Signed: 0, - SignedAndEncrypted: 1, +const CryptoType = { + Plaintext: 0, + HpkeAuth: 1, + HpkeEssr: 2, + NaclAuth: 3, + NaclEssr: 4, }; +const SignatureType = { + NoSignature: 0, + Ed25519: 1, +} + class Store { constructor() { this.inner = new wasm.Store(); @@ -169,7 +177,8 @@ class ForwardRequest extends ReceivedTspMessage { } module.exports = { - MessageType, + CryptoType, + SignatureType, Store, OwnedVid, ReceivedTspMessage, diff --git a/tsp-python/src/lib.rs b/tsp-python/src/lib.rs index 42bb430..97144e9 100644 --- a/tsp-python/src/lib.rs +++ b/tsp-python/src/lib.rs @@ -5,7 +5,8 @@ fn tsp_python(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_class::()?; m.add_class::()?; - m.add_class::()?; + m.add_class::()?; + m.add_class::()?; m.add_class::()?; m.add_class::()?; @@ -237,9 +238,19 @@ impl From<&tsp::ReceivedTspMessage> for ReceivedTspMessageVariant { #[pyclass] #[derive(Debug, Clone, Copy)] -enum MessageType { - Signed, - SignedAndEncrypted, +pub enum CryptoType { + Plaintext = 0, + HpkeAuth = 1, + HpkeEssr = 2, + NaclAuth = 3, + NaclEssr = 4, +} + +#[pyclass] +#[derive(Debug, Clone, Copy)] +pub enum SignatureType { + NoSignature = 0, + Ed25519 = 1, } #[pyclass] @@ -254,7 +265,9 @@ struct FlatReceivedTspMessage { #[pyo3(get, set)] message: Option>, #[pyo3(get, set)] - message_type: Option, + crypto_type: Option, + #[pyo3(get, set)] + signature_type: Option, #[pyo3(get, set)] route: Option>>>, #[pyo3(get, set)] @@ -291,7 +304,8 @@ impl From for FlatReceivedTspMessage { sender: None, nonconfidential_data: None, message: None, - message_type: None, + crypto_type: None, + signature_type: None, route: None, nested_vid: None, thread_id: None, @@ -313,11 +327,16 @@ impl From for FlatReceivedTspMessage { this.sender = Some(sender); this.nonconfidential_data = Some(nonconfidential_data); this.message = Some(message); - this.message_type = match message_type { - tsp::definitions::MessageType::Signed => Some(MessageType::Signed), - tsp::definitions::MessageType::SignedAndEncrypted => { - Some(MessageType::SignedAndEncrypted) - } + this.crypto_type = match message_type.crypto_type { + tsp::cesr::CryptoType::Plaintext => Some(CryptoType::Plaintext), + tsp::cesr::CryptoType::HpkeAuth => Some(CryptoType::HpkeAuth), + tsp::cesr::CryptoType::HpkeEssr => Some(CryptoType::HpkeEssr), + tsp::cesr::CryptoType::NaclAuth => Some(CryptoType::NaclAuth), + tsp::cesr::CryptoType::NaclEssr => Some(CryptoType::NaclEssr), + }; + this.signature_type = match message_type.signature_type { + tsp::cesr::SignatureType::NoSignature => Some(SignatureType::NoSignature), + tsp::cesr::SignatureType::Ed25519 => Some(SignatureType::Ed25519), }; } tsp::ReceivedTspMessage::RequestRelationship { diff --git a/tsp-python/test.py b/tsp-python/test.py index edef7d5..281b800 100644 --- a/tsp-python/test.py +++ b/tsp-python/test.py @@ -23,10 +23,11 @@ def test_open_seal(self): received = self.store.open_message(sealed) match received: - case GenericMessage(sender, _, received_message, message_type): + case GenericMessage(sender, _, received_message, crypto_type, signature_type): self.assertEqual(sender, self.alice.identifier()) self.assertEqual(received_message, message) - self.assertEqual(message_type, MessageType.SignedAndEncrypted) + self.assertNotEqual(crypto_type, CryptoType.Plaintext) + self.assertNotEqual(signature_type, SignatureType.NoSignature) case other: self.fail(f"unexpected message type {other}") @@ -182,11 +183,12 @@ def test_routed(self): received = d_store.open_message(sealed) match received: - case GenericMessage(sender, nonconfidential_data, message, message_type): + case GenericMessage(sender, nonconfidential_data, message, crypto_type, signature_type): self.assertEqual(sender, sneaky_a.identifier()) self.assertEqual(nonconfidential_data, None) self.assertEqual(message, hello_world) - self.assertEqual(message_type, MessageType.SignedAndEncrypted) + self.assertNotEqual(crypto_type, CryptoType.Plaintext) + self.assertNotEqual(signature_type, SignatureType.NoSignature) case other: self.fail(f"unexpected message type {other}") @@ -254,10 +256,11 @@ def test_nested_automatic(self): received = b_store.open_message(sealed) match received: - case GenericMessage(sender, _, received_message, message_type): + case GenericMessage(sender, _, received_message, crypto_type, signature_type): self.assertEqual(sender, nested_a.identifier()) self.assertEqual(received_message, hello_world) - self.assertEqual(message_type, MessageType.SignedAndEncrypted) + self.assertNotEqual(crypto_type, CryptoType.Plaintext) + self.assertNotEqual(signature_type, SignatureType.NoSignature) case other: self.fail(f"unexpected message type {other}") diff --git a/tsp-python/tsp.py b/tsp-python/tsp.py index ae668f4..733df0f 100644 --- a/tsp-python/tsp.py +++ b/tsp-python/tsp.py @@ -1,7 +1,7 @@ from dataclasses import dataclass import tsp_python -from tsp_python import OwnedVid, ReceivedTspMessageVariant, FlatReceivedTspMessage, MessageType +from tsp_python import OwnedVid, ReceivedTspMessageVariant, FlatReceivedTspMessage, CryptoType, SignatureType class Store: inner: tsp_python.Store @@ -51,7 +51,7 @@ class ReceivedTspMessage: def from_flat(msg: FlatReceivedTspMessage): match msg.variant: case ReceivedTspMessageVariant.GenericMessage: - return GenericMessage(msg.sender, msg.nonconfidential_data, bytes(msg.message), msg.message_type) + return GenericMessage(msg.sender, msg.nonconfidential_data, bytes(msg.message), msg.crypto_type, msg.signature_type) case ReceivedTspMessageVariant.RequestRelationship: return RequestRelationship(msg.sender, msg.route, msg.nested_vid, msg.thread_id) @@ -76,7 +76,8 @@ class GenericMessage(ReceivedTspMessage): sender: str nonconfidential_data: str message: str - message_type: str + crypto_type: str + signature_type: str @dataclass class AcceptRelationship(ReceivedTspMessage): diff --git a/tsp/src/cesr/packet.rs b/tsp/src/cesr/packet.rs index 6f18e76..5ce6589 100644 --- a/tsp/src/cesr/packet.rs +++ b/tsp/src/cesr/packet.rs @@ -149,7 +149,7 @@ impl CryptoType { } } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] #[repr(u8)] pub enum SignatureType { NoSignature = 0, diff --git a/tsp/src/crypto/mod.rs b/tsp/src/crypto/mod.rs index 63751df..18ebeb6 100644 --- a/tsp/src/crypto/mod.rs +++ b/tsp/src/crypto/mod.rs @@ -68,6 +68,8 @@ pub fn seal_and_hash( pub type MessageContents<'a> = ( Option>, Payload<'a, &'a [u8], &'a mut [u8]>, + crate::cesr::CryptoType, + crate::cesr::SignatureType, ); /// Decode a CESR Authentic Confidential Message, verify the signature and decrypt its contents @@ -96,7 +98,14 @@ pub fn sign( pub fn verify<'a>( sender: &dyn VerifiedVid, tsp_message: &'a mut [u8], -) -> Result<&'a [u8], CryptoError> { +) -> Result< + ( + &'a [u8], + crate::cesr::CryptoType, + crate::cesr::SignatureType, + ), + CryptoError, +> { nonconfidential::verify(sender, tsp_message) } @@ -184,7 +193,7 @@ mod tests { ) .unwrap(); - let (received_nonconfidential_data, received_secret_message) = + let (received_nonconfidential_data, received_secret_message, _, _) = open(&alice, &bob, &mut message).unwrap(); assert_eq!(received_nonconfidential_data.unwrap(), nonconfidential_data); diff --git a/tsp/src/crypto/nonconfidential.rs b/tsp/src/crypto/nonconfidential.rs index ee9bb7e..99319dc 100644 --- a/tsp/src/crypto/nonconfidential.rs +++ b/tsp/src/crypto/nonconfidential.rs @@ -37,7 +37,14 @@ pub fn sign( pub fn verify<'a>( sender: &dyn VerifiedVid, tsp_message: &'a mut [u8], -) -> Result<&'a [u8], CryptoError> { +) -> Result< + ( + &'a [u8], + crate::cesr::CryptoType, + crate::cesr::SignatureType, + ), + CryptoError, +> { let view = crate::cesr::decode_envelope(tsp_message)?; // verify outer signature @@ -51,8 +58,8 @@ pub fn verify<'a>( raw_header: _, envelope: Envelope { - crypto_type: _, - signature_type: _, + crypto_type, + signature_type, sender: _, receiver: _, nonconfidential_data: Some(nonconfidential_data), @@ -65,5 +72,5 @@ pub fn verify<'a>( return Err(CryptoError::MissingCiphertext); }; - Ok(nonconfidential_data) + Ok((nonconfidential_data, crypto_type, signature_type)) } diff --git a/tsp/src/crypto/tsp_hpke.rs b/tsp/src/crypto/tsp_hpke.rs index d8d2507..6e7a088 100644 --- a/tsp/src/crypto/tsp_hpke.rs +++ b/tsp/src/crypto/tsp_hpke.rs @@ -275,7 +275,12 @@ where } }; - Ok((envelope.nonconfidential_data, secret_payload)) + Ok(( + envelope.nonconfidential_data, + secret_payload, + envelope.crypto_type, + envelope.signature_type, + )) } /// Generate N random bytes using the provided RNG diff --git a/tsp/src/crypto/tsp_nacl.rs b/tsp/src/crypto/tsp_nacl.rs index d8dacc0..bd74ed0 100644 --- a/tsp/src/crypto/tsp_nacl.rs +++ b/tsp/src/crypto/tsp_nacl.rs @@ -215,7 +215,12 @@ pub(crate) fn open<'a>( crate::cesr::Payload::RoutedMessage(hops, data) => Payload::RoutedMessage(hops, data as _), }; - Ok((envelope.nonconfidential_data, secret_payload)) + Ok(( + envelope.nonconfidential_data, + secret_payload, + envelope.crypto_type, + envelope.signature_type, + )) } /// Generate N random bytes using the provided RNG diff --git a/tsp/src/definitions/mod.rs b/tsp/src/definitions/mod.rs index e2cfc10..df66ed3 100644 --- a/tsp/src/definitions/mod.rs +++ b/tsp/src/definitions/mod.rs @@ -45,10 +45,10 @@ pub type TSPMessage = Vec; #[cfg(feature = "async")] pub type TSPStream = std::pin::Pin> + Send>>; -#[derive(Debug, PartialEq, Eq)] -pub enum MessageType { - Signed, - SignedAndEncrypted, +#[derive(Debug)] +pub struct MessageType { + pub crypto_type: crate::cesr::CryptoType, + pub signature_type: crate::cesr::SignatureType, } #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))] diff --git a/tsp/src/store.rs b/tsp/src/store.rs index 0c5e54d..0f43033 100644 --- a/tsp/src/store.rs +++ b/tsp/src/store.rs @@ -480,7 +480,7 @@ impl Store { return Err(CryptoError::UnexpectedRecipient.into()); }; - let (_, payload) = crate::crypto::open(&*receiver, &*sender, message)?; + let (_, payload, _, _) = crate::crypto::open(&*receiver, &*sender, message)?; let (next_hop, path, inner_message) = match payload { Payload::RoutedMessage(hops, inner_message) => { @@ -583,7 +583,7 @@ impl Store { return Err(Error::UnverifiedSource(sender)); }; - let (nonconfidential_data, payload) = + let (nonconfidential_data, payload, crypto_type, signature_type) = crate::crypto::open(&*intended_receiver, &*sender_vid, message)?; match payload { @@ -591,7 +591,10 @@ impl Store { sender, nonconfidential_data, message, - message_type: MessageType::SignedAndEncrypted, + message_type: MessageType { + crypto_type, + signature_type, + }, }), Payload::NestedMessage(inner) => { // in case the inner vid isn't recognized (which can realistically happen in Routed mode), @@ -609,14 +612,20 @@ impl Store { let mut received_message = self.open_message(inner)?; + // if inner message was not encrypted, but outer message was encrypted by the same sender, + // then inner message was also sufficiently encrypted if let ReceivedTspMessage::GenericMessage { - message_type: ref mut message_type @ MessageType::Signed, + message_type: + ref mut message_type @ MessageType { + crypto_type: crate::cesr::CryptoType::Plaintext, + signature_type: _, + }, sender: ref inner_sender, .. } = received_message { if self.get_vid(inner_sender)?.get_parent_vid() == Some(&sender) { - *message_type = MessageType::SignedAndEncrypted; + message_type.crypto_type = crypto_type; } } @@ -769,13 +778,17 @@ impl Store { return Err(Error::UnverifiedVid(sender.to_string())); }; - let message = crate::crypto::verify(&*sender_vid, message)?; + let (message, crypto_type, signature_type) = + crate::crypto::verify(&*sender_vid, message)?; Ok(ReceivedTspMessage::GenericMessage { sender, nonconfidential_data: None, message, - message_type: MessageType::Signed, + message_type: MessageType { + crypto_type, + signature_type, + }, }) } } @@ -1129,7 +1142,7 @@ impl Store { mod test { use wasm_bindgen_test::wasm_bindgen_test; - use crate::{definitions::MessageType, OwnedVid, ReceivedTspMessage, Store, VerifiedVid}; + use crate::{OwnedVid, ReceivedTspMessage, Store, VerifiedVid}; fn new_vid() -> OwnedVid { OwnedVid::new_did_peer("tcp://127.0.0.1:1337".parse().unwrap()) @@ -1201,7 +1214,11 @@ mod test { { assert_eq!(sender, alice.identifier()); assert_eq!(received_message, message); - assert_eq!(message_type, MessageType::SignedAndEncrypted); + assert_ne!(message_type.crypto_type, crate::cesr::CryptoType::Plaintext); + assert_ne!( + message_type.signature_type, + crate::cesr::SignatureType::NoSignature + ); } else { panic!("unexpected message type"); } @@ -1530,7 +1547,11 @@ mod test { assert_eq!(sender, sneaky_a.identifier()); assert!(nonconfidential_data.is_none()); assert_eq!(message, hello_world); - assert_eq!(message_type, MessageType::SignedAndEncrypted); + assert_ne!(message_type.crypto_type, crate::cesr::CryptoType::Plaintext); + assert_ne!( + message_type.signature_type, + crate::cesr::SignatureType::NoSignature + ); } #[test] @@ -1599,7 +1620,11 @@ mod test { assert_eq!(sender, nested_a.identifier()); assert!(nonconfidential_data.is_none()); assert_eq!(message, hello_world); - assert_eq!(message_type, MessageType::SignedAndEncrypted); + assert_ne!(message_type.crypto_type, crate::cesr::CryptoType::Plaintext); + assert_ne!( + message_type.signature_type, + crate::cesr::SignatureType::NoSignature + ); } #[cfg(not(feature = "pq"))] @@ -1729,6 +1754,10 @@ mod test { assert_eq!(sender, nested_a.identifier()); assert!(nonconfidential_data.is_none()); assert_eq!(message, hello_world); - assert_eq!(message_type, MessageType::SignedAndEncrypted); + assert_ne!(message_type.crypto_type, crate::cesr::CryptoType::Plaintext); + assert_ne!( + message_type.signature_type, + crate::cesr::SignatureType::NoSignature + ); } } diff --git a/tsp/src/test.rs b/tsp/src/test.rs index 262ca8b..d7974a6 100644 --- a/tsp/src/test.rs +++ b/tsp/src/test.rs @@ -1,7 +1,4 @@ -use crate::{ - definitions::MessageType::{Signed, SignedAndEncrypted}, - AsyncStore, OwnedVid, VerifiedVid, -}; +use crate::{AsyncStore, OwnedVid, VerifiedVid}; use futures::StreamExt; #[tokio::test] @@ -48,13 +45,19 @@ async fn test_direct_mode() { // receive a message let crate::definitions::ReceivedTspMessage::GenericMessage { message, - message_type: SignedAndEncrypted, + message_type, .. } = bobs_messages.next().await.unwrap().unwrap() else { panic!("bob did not receive a generic message") }; + assert_ne!(message_type.crypto_type, crate::cesr::CryptoType::Plaintext); + assert_ne!( + message_type.signature_type, + crate::cesr::SignatureType::NoSignature + ); + assert_eq!(message, b"hello world"); } @@ -104,13 +107,19 @@ async fn test_large_messages() { // receive a message let crate::definitions::ReceivedTspMessage::GenericMessage { message, - message_type: SignedAndEncrypted, + message_type, .. } = bobs_messages.next().await.unwrap().unwrap() else { panic!("bob did not receive a generic message") }; + assert_ne!(message_type.crypto_type, crate::cesr::CryptoType::Plaintext); + assert_ne!( + message_type.signature_type, + crate::cesr::SignatureType::NoSignature + ); + assert_eq!(sent_message.as_bytes(), message); } } @@ -158,13 +167,19 @@ async fn test_anycast() { // receive a message let crate::definitions::ReceivedTspMessage::GenericMessage { message, - message_type: Signed, + message_type, .. } = bobs_messages.next().await.unwrap().unwrap() else { panic!("bob did not receive a broadcast message") }; + assert_eq!(message_type.crypto_type, crate::cesr::CryptoType::Plaintext); + assert_ne!( + message_type.signature_type, + crate::cesr::SignatureType::NoSignature + ); + assert_eq!(message, b"hello world"); } @@ -244,13 +259,19 @@ async fn test_nested_mode() { // receive message using inner vid let crate::definitions::ReceivedTspMessage::GenericMessage { message, - message_type: SignedAndEncrypted, + message_type, .. } = bobs_inner_messages.next().await.unwrap().unwrap() else { panic!("bob did not receive a generic message inner") }; + assert_ne!(message_type.crypto_type, crate::cesr::CryptoType::Plaintext); + assert_ne!( + message_type.signature_type, + crate::cesr::SignatureType::NoSignature + ); + assert_eq!(&message, b"hello nested world"); } @@ -424,13 +445,19 @@ async fn test_routed_mode() { let crate::definitions::ReceivedTspMessage::GenericMessage { sender, message, - message_type: SignedAndEncrypted, + message_type, .. } = alice_messages.next().await.unwrap().unwrap() else { panic!("alice did not receive message"); }; + assert_ne!(message_type.crypto_type, crate::cesr::CryptoType::Plaintext); + assert_ne!( + message_type.signature_type, + crate::cesr::SignatureType::NoSignature + ); + assert_eq!(sender, "did:web:did.tsp-test.org:user:alice"); assert_eq!(message, b"hello self (via bob)"); } From f1577bbcacd2974c7fd07a9aff94ab0ae3c53033 Mon Sep 17 00:00:00 2001 From: Michiel Date: Tue, 3 Sep 2024 13:57:42 +0200 Subject: [PATCH 2/5] Allow decoding any crypto type Signed-off-by: Michiel --- examples/Cargo.toml | 3 ++ examples/cli-test-cross-type.sh | 51 +++++++++++++++++++++++ tsp/Cargo.toml | 8 ++-- tsp/src/crypto/digest.rs | 1 - tsp/src/crypto/error.rs | 8 ++-- tsp/src/crypto/mod.rs | 58 ++++++++++++++++++++------ tsp/src/crypto/tsp_hpke.rs | 73 +++++++++++++++------------------ tsp/src/crypto/tsp_nacl.rs | 61 +++++++++++---------------- 8 files changed, 164 insertions(+), 99 deletions(-) create mode 100755 examples/cli-test-cross-type.sh diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 8b1c7e7..bba4b2d 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -8,6 +8,9 @@ homepage.workspace = true publish.workspace = true rust-version.workspace = true +[features] +nacl = ["tsp/nacl"] + [[bin]] name = "create-did-web" path = "src/create-did-web.rs" diff --git a/examples/cli-test-cross-type.sh b/examples/cli-test-cross-type.sh new file mode 100755 index 0000000..0c6d778 --- /dev/null +++ b/examples/cli-test-cross-type.sh @@ -0,0 +1,51 @@ +#!/bin/bash +HPKE="./build-hpke" +NACL="./build-nacl" + +HPKE_TPS="$HPKE/bin/tsp" +NACL_TPS="$NACL/bin/tsp" + +# install two different versions of the TSP command line example tool +cargo install --path . --bin tsp --root "$HPKE" +cargo install --path . --bin tsp --features nacl --root "$NACL" + +randuser() { + head -c4 /dev/urandom | shasum | head -c8 +} + +echo "---- cleanup the database" +rm -f marlon.sqlite marc.sqlite + +echo "---- create a new sender identity" +$HPKE_TPS --database marlon create --alias marlon `randuser` + +echo "---- create a new receiver identity" +$NACL_TPS --database marc create --alias marc `randuser` + +DID_MARC=$($NACL_TPS --database marc print marc) +DID_MARLON=$($HPKE_TPS --database marlon print marlon) + +echo "---- verify the address of the receiver" +$HPKE_TPS --database marlon verify --alias marc "$DID_MARC" + +echo "---- verify the address of the sender" +$NACL_TPS --database marc verify --alias marlon "$DID_MARLON" + +echo "---- wait 2 seconds and then send a message to the receiver" +sleep 2 && echo "Oh hi Marc" | $HPKE_TPS --database marlon send -s marlon -r marc & + +echo "---- receive the message" +$NACL_TPS --database marc receive --one marc + +echo "---- wait 1 seconds and then send a message back" +sleep 1 && echo "Oh hello Marlon" | $NACL_TPS --database marc send -s marc -r marlon & + +echo "---- receive the message" +$HPKE_TPS --database marlon receive --one marlon + +echo "---- cleanup databases" +rm -f marc.sqlite marlon.sqlite + +echo "---- cleanup install" +rm -rf "$HPKE" +rm -rf "$NACL" diff --git a/tsp/Cargo.toml b/tsp/Cargo.toml index e206d17..ed72cc1 100644 --- a/tsp/Cargo.toml +++ b/tsp/Cargo.toml @@ -17,7 +17,7 @@ essr = [] strict = [] fuzzing = ["dep:arbitrary"] demo = [] -nacl = ["dep:crypto_box", "dep:blake2", "dep:typenum", "essr"] +nacl = ["essr"] pq = ["dep:hpke_pq", "essr"] async = [ "resolve", @@ -52,9 +52,9 @@ hpke = { workspace = true } hpke_pq = { workspace = true, optional = true } rand = { workspace = true } sha2 = { workspace = true } -blake2 = { workspace = true, optional = true } -typenum = { workspace = true, optional = true } -crypto_box = { workspace = true, optional = true } +blake2 = { workspace = true } +typenum = { workspace = true } +crypto_box = { workspace = true } # async aries-askar = { workspace = true, optional = true } async-stream = { workspace = true, optional = true } diff --git a/tsp/src/crypto/digest.rs b/tsp/src/crypto/digest.rs index 4afdc1c..a3c1752 100644 --- a/tsp/src/crypto/digest.rs +++ b/tsp/src/crypto/digest.rs @@ -4,7 +4,6 @@ pub fn sha256(content: &[u8]) -> [u8; 32] { sha2::Sha256::digest(content).into() } -#[cfg(feature = "nacl")] pub fn blake2b256(content: &[u8]) -> [u8; 32] { use blake2::Digest; type Blake2b256 = blake2::Blake2b; diff --git a/tsp/src/crypto/error.rs b/tsp/src/crypto/error.rs index 0667cb6..434360d 100644 --- a/tsp/src/crypto/error.rs +++ b/tsp/src/crypto/error.rs @@ -6,13 +6,11 @@ pub enum CryptoError { Decode(#[from] crate::cesr::error::DecodeError), #[cfg(feature = "pq")] #[error("encryption or decryption failed: {0}")] - Cryptographic(#[from] hpke_pq::HpkeError), - #[cfg(all(not(feature = "nacl"), not(feature = "pq")))] + CryptographicHpkePq(#[from] hpke_pq::HpkeError), #[error("encryption or decryption failed: {0}")] - Cryptographic(#[from] hpke::HpkeError), - #[cfg(feature = "nacl")] + CryptographicHpke(#[from] hpke::HpkeError), #[error("encryption or decryption failed")] - Cryptographic(#[from] crypto_box::aead::Error), + CryptographicNacl(#[from] crypto_box::aead::Error), #[error("could not verify signature: {0}")] Verify(#[from] ed25519_dalek::ed25519::Error), #[error("unexpected recipient")] diff --git a/tsp/src/crypto/mod.rs b/tsp/src/crypto/mod.rs index 18ebeb6..a55625a 100644 --- a/tsp/src/crypto/mod.rs +++ b/tsp/src/crypto/mod.rs @@ -2,7 +2,7 @@ use crate::definitions::{ Digest, NonConfidentialData, Payload, PrivateKeyData, PrivateSigningKeyData, PrivateVid, PublicKeyData, PublicVerificationKeyData, TSPMessage, VerifiedVid, }; -#[cfg(feature = "nacl")] + pub use digest::blake2b256; pub use digest::sha256; use rand::rngs::OsRng; @@ -11,21 +11,22 @@ mod digest; pub mod error; mod nonconfidential; -#[cfg(feature = "nacl")] -mod tsp_nacl; - -#[cfg(not(feature = "nacl"))] mod tsp_hpke; +#[cfg(not(feature = "pq"))] +mod tsp_nacl; pub use error::CryptoError; -#[cfg(all(not(feature = "nacl"), not(feature = "pq")))] +#[cfg(not(feature = "pq"))] +use crate::cesr::CryptoType; + +#[cfg(not(feature = "pq"))] pub type Aead = hpke::aead::ChaCha20Poly1305; -#[cfg(all(not(feature = "nacl"), not(feature = "pq")))] +#[cfg(not(feature = "pq"))] pub type Kdf = hpke::kdf::HkdfSha256; -#[cfg(all(not(feature = "nacl"), not(feature = "pq")))] +#[cfg(not(feature = "pq"))] pub type Kem = hpke::kem::X25519HkdfSha256; #[cfg(feature = "pq")] @@ -78,11 +79,44 @@ pub fn open<'a>( sender: &dyn VerifiedVid, tsp_message: &'a mut [u8], ) -> Result, CryptoError> { - #[cfg(not(feature = "nacl"))] - return tsp_hpke::open::(receiver, sender, tsp_message); + let view = crate::cesr::decode_envelope(tsp_message)?; + + // verify outer signature + let verification_challenge = view.as_challenge(); + let signature = ed25519_dalek::Signature::from(verification_challenge.signature); + let verifying_key = ed25519_dalek::VerifyingKey::from_bytes(sender.verifying_key())?; + verifying_key.verify_strict(verification_challenge.signed_data, &signature)?; + + // decode envelope + let crate::cesr::DecodedEnvelope { + raw_header, + envelope, + ciphertext: Some(ciphertext), + } = view + .into_opened::<&[u8]>() + .map_err(|_| crate::cesr::error::DecodeError::VidError)? + else { + return Err(CryptoError::MissingCiphertext); + }; + + // verify the message was intended for the specified receiver + if envelope.receiver != Some(receiver.identifier().as_bytes()) { + return Err(CryptoError::UnexpectedRecipient); + } - #[cfg(feature = "nacl")] - return tsp_nacl::open(receiver, sender, tsp_message); + #[cfg(feature = "pq")] + return tsp_hpke::open::(receiver, sender, raw_header, envelope, ciphertext); + + #[cfg(not(feature = "pq"))] + match envelope.crypto_type { + CryptoType::HpkeAuth | CryptoType::HpkeEssr => { + tsp_hpke::open::(receiver, sender, raw_header, envelope, ciphertext) + } + CryptoType::NaclAuth | CryptoType::NaclEssr => { + tsp_nacl::open(receiver, sender, raw_header, envelope, ciphertext) + } + CryptoType::Plaintext => Err(CryptoError::MissingCiphertext), // TODO: better error code? + } } /// Construct and sign a non-confidential TSP message diff --git a/tsp/src/crypto/tsp_hpke.rs b/tsp/src/crypto/tsp_hpke.rs index 6e7a088..dc5305c 100644 --- a/tsp/src/crypto/tsp_hpke.rs +++ b/tsp/src/crypto/tsp_hpke.rs @@ -1,16 +1,27 @@ use crate::{ - cesr::{CryptoType, DecodedEnvelope, DecodedPayload, SignatureType}, - definitions::{NonConfidentialData, Payload, PrivateVid, TSPMessage, VerifiedVid}, + cesr::{CryptoType, DecodedPayload, Envelope}, + definitions::{Payload, PrivateVid, VerifiedVid}, }; + +#[cfg(not(feature = "nacl"))] +use crate::{ + cesr::SignatureType, + definitions::{NonConfidentialData, TSPMessage}, +}; + +#[cfg(not(feature = "nacl"))] use ed25519_dalek::Signer; +#[cfg(not(feature = "nacl"))] use rand::{rngs::StdRng, SeedableRng}; #[cfg(not(feature = "pq"))] use hpke::{ - aead, kdf, kem, single_shot_open_in_place_detached, single_shot_seal_in_place_detached, - Deserializable, OpModeR, OpModeS, Serializable, + aead, kdf, kem, single_shot_open_in_place_detached, Deserializable, OpModeR, Serializable, }; +#[cfg(all(not(feature = "nacl"), not(feature = "pq")))] +use hpke::{single_shot_seal_in_place_detached, OpModeS}; + #[cfg(feature = "pq")] use hpke_pq::{ aead, kdf, kem, single_shot_open_in_place_detached, single_shot_seal_in_place_detached, @@ -19,6 +30,7 @@ use hpke_pq::{ use super::{CryptoError, MessageContents}; +#[cfg(not(feature = "nacl"))] pub(crate) fn seal( sender: &dyn PrivateVid, receiver: &dyn VerifiedVid, @@ -155,38 +167,15 @@ where pub(crate) fn open<'a, A, Kdf, Kem>( receiver: &dyn PrivateVid, sender: &dyn VerifiedVid, - tsp_message: &'a mut [u8], + raw_header: &'a [u8], + envelope: Envelope<'a, &[u8]>, + ciphertext: &'a mut [u8], ) -> Result, CryptoError> where A: aead::Aead, Kdf: kdf::Kdf, Kem: kem::Kem, { - let view = crate::cesr::decode_envelope(tsp_message)?; - - // verify outer signature - let verification_challenge = view.as_challenge(); - let signature = ed25519_dalek::Signature::from(verification_challenge.signature); - let verifying_key = ed25519_dalek::VerifyingKey::from_bytes(sender.verifying_key())?; - verifying_key.verify_strict(verification_challenge.signed_data, &signature)?; - - // decode envelope - let DecodedEnvelope { - raw_header: info, - envelope, - ciphertext: Some(ciphertext), - } = view - .into_opened::<&[u8]>() - .map_err(|_| crate::cesr::error::DecodeError::VidError)? - else { - return Err(CryptoError::MissingCiphertext); - }; - - // verify the message was intended for the specified receiver - if envelope.receiver != Some(receiver.identifier().as_bytes()) { - return Err(CryptoError::UnexpectedRecipient); - } - // split encapsulated key and authenticated encryption tag length let (ciphertext, footer) = ciphertext .split_at_mut(ciphertext.len() - aead::AeadTag::::size() - Kem::EncappedKey::size()); @@ -197,11 +186,13 @@ where let encapped_key = Kem::EncappedKey::from_bytes(encapped_key)?; let tag = aead::AeadTag::from_bytes(tag)?; - #[cfg(any(feature = "essr", feature = "pq"))] + #[cfg(feature = "pq")] let mode = OpModeR::Base; - #[cfg(all(not(feature = "essr"), not(feature = "pq")))] - let mode = { + #[cfg(not(feature = "pq"))] + let mode = if envelope.crypto_type == CryptoType::HpkeEssr { + OpModeR::Base + } else { let sender_encryption_key = Kem::PublicKey::from_bytes(sender.encryption_key().as_ref())?; OpModeR::Auth(sender_encryption_key) }; @@ -211,7 +202,7 @@ where &mode, &receiver_decryption_key, &encapped_key, - info, + raw_header, ciphertext, &[], &tag, @@ -231,14 +222,15 @@ where sender_identity, } = crate::cesr::decode_payload(ciphertext)?; - #[cfg(feature = "essr")] - match sender_identity { - Some(id) => { - if id != sender.identifier().as_bytes() { - return Err(CryptoError::UnexpectedSender); + if envelope.crypto_type == CryptoType::HpkeEssr { + match sender_identity { + Some(id) => { + if id != sender.identifier().as_bytes() { + return Err(CryptoError::UnexpectedSender); + } } + None => return Err(CryptoError::MissingSender), } - None => return Err(CryptoError::MissingSender), } let secret_payload = match payload { @@ -284,6 +276,7 @@ where } /// Generate N random bytes using the provided RNG +#[cfg(not(feature = "nacl"))] fn fresh_nonce(csprng: &mut (impl rand::RngCore + rand::CryptoRng)) -> crate::cesr::Nonce { crate::cesr::Nonce::generate(|dst| csprng.fill_bytes(dst)) } diff --git a/tsp/src/crypto/tsp_nacl.rs b/tsp/src/crypto/tsp_nacl.rs index bd74ed0..1432b19 100644 --- a/tsp/src/crypto/tsp_nacl.rs +++ b/tsp/src/crypto/tsp_nacl.rs @@ -1,16 +1,24 @@ use crate::{ - cesr::{CryptoType, DecodedEnvelope, DecodedPayload, SignatureType}, - definitions::{NonConfidentialData, Payload, PrivateVid, TSPMessage, VerifiedVid}, + cesr::{CryptoType, DecodedPayload, Envelope}, + definitions::{Payload, PrivateVid, VerifiedVid}, }; -use crypto_box::{ - aead::{AeadCore, AeadInPlace, OsRng}, - ChaChaBox, PublicKey, SecretKey, +use crypto_box::{aead::AeadInPlace, ChaChaBox, PublicKey, SecretKey}; + +#[cfg(feature = "nacl")] +use crate::{ + cesr::SignatureType, + definitions::{NonConfidentialData, TSPMessage}, }; +#[cfg(feature = "nacl")] +use crypto_box::aead::{AeadCore, OsRng}; +#[cfg(feature = "nacl")] use ed25519_dalek::Signer; +#[cfg(feature = "nacl")] use rand::{rngs::StdRng, SeedableRng}; use super::{CryptoError, MessageContents}; +#[cfg(feature = "nacl")] pub(crate) fn seal( sender: &dyn PrivateVid, receiver: &dyn VerifiedVid, @@ -123,33 +131,10 @@ pub(crate) fn seal( pub(crate) fn open<'a>( receiver: &dyn PrivateVid, sender: &dyn VerifiedVid, - tsp_message: &'a mut [u8], + _raw_header: &'a [u8], + envelope: Envelope<'a, &[u8]>, + ciphertext: &'a mut [u8], ) -> Result, CryptoError> { - let view = crate::cesr::decode_envelope(tsp_message)?; - - // verify outer signature - let verification_challenge = view.as_challenge(); - let signature = ed25519_dalek::Signature::from(verification_challenge.signature); - let verifying_key = ed25519_dalek::VerifyingKey::from_bytes(sender.verifying_key())?; - verifying_key.verify_strict(verification_challenge.signed_data, &signature)?; - - // decode envelope - let DecodedEnvelope { - raw_header: _data, - envelope, - ciphertext: Some(ciphertext), - } = view - .into_opened::<&[u8]>() - .map_err(|_| crate::cesr::error::DecodeError::VidError)? - else { - return Err(CryptoError::MissingCiphertext); - }; - - // verify the message was intended for the specified receiver - if envelope.receiver != Some(receiver.identifier().as_bytes()) { - return Err(CryptoError::UnexpectedRecipient); - } - let (ciphertext, footer) = ciphertext.split_at_mut(ciphertext.len() - 16 - 24); let (tag, nonce) = footer.split_at(16); @@ -167,14 +152,15 @@ pub(crate) fn open<'a>( sender_identity, } = crate::cesr::decode_payload(ciphertext)?; - #[cfg(feature = "essr")] - match sender_identity { - Some(id) => { - if id != sender.identifier().as_bytes() { - return Err(CryptoError::UnexpectedSender); + if envelope.crypto_type == CryptoType::NaclEssr { + match sender_identity { + Some(id) => { + if id != sender.identifier().as_bytes() { + return Err(CryptoError::UnexpectedSender); + } } + None => return Err(CryptoError::MissingSender), } - None => return Err(CryptoError::MissingSender), } let secret_payload = match payload { @@ -224,6 +210,7 @@ pub(crate) fn open<'a>( } /// Generate N random bytes using the provided RNG +#[cfg(feature = "nacl")] fn fresh_nonce(csprng: &mut (impl rand::RngCore + rand::CryptoRng)) -> crate::cesr::Nonce { crate::cesr::Nonce::generate(|dst| csprng.fill_bytes(dst)) } From 8e3cfd4a343f639a14215008f4785adf6d457493 Mon Sep 17 00:00:00 2001 From: Michiel Date: Wed, 4 Sep 2024 12:51:08 +0200 Subject: [PATCH 3/5] Fix typo Signed-off-by: Michiel --- examples/cli-test-cross-type.sh | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/examples/cli-test-cross-type.sh b/examples/cli-test-cross-type.sh index 0c6d778..c0ae5cb 100755 --- a/examples/cli-test-cross-type.sh +++ b/examples/cli-test-cross-type.sh @@ -2,8 +2,8 @@ HPKE="./build-hpke" NACL="./build-nacl" -HPKE_TPS="$HPKE/bin/tsp" -NACL_TPS="$NACL/bin/tsp" +HPKE_TSP="$HPKE/bin/tsp" +NACL_TSP="$NACL/bin/tsp" # install two different versions of the TSP command line example tool cargo install --path . --bin tsp --root "$HPKE" @@ -17,31 +17,31 @@ echo "---- cleanup the database" rm -f marlon.sqlite marc.sqlite echo "---- create a new sender identity" -$HPKE_TPS --database marlon create --alias marlon `randuser` +$HPKE_TSP --database marlon create --alias marlon `randuser` echo "---- create a new receiver identity" -$NACL_TPS --database marc create --alias marc `randuser` +$NACL_TSP --database marc create --alias marc `randuser` -DID_MARC=$($NACL_TPS --database marc print marc) -DID_MARLON=$($HPKE_TPS --database marlon print marlon) +DID_MARC=$($NACL_TSP --database marc print marc) +DID_MARLON=$($HPKE_TSP --database marlon print marlon) echo "---- verify the address of the receiver" -$HPKE_TPS --database marlon verify --alias marc "$DID_MARC" +$HPKE_TSP --database marlon verify --alias marc "$DID_MARC" echo "---- verify the address of the sender" -$NACL_TPS --database marc verify --alias marlon "$DID_MARLON" +$NACL_TSP --database marc verify --alias marlon "$DID_MARLON" echo "---- wait 2 seconds and then send a message to the receiver" -sleep 2 && echo "Oh hi Marc" | $HPKE_TPS --database marlon send -s marlon -r marc & +sleep 2 && echo "Oh hi Marc" | $HPKE_TSP --database marlon send -s marlon -r marc & echo "---- receive the message" -$NACL_TPS --database marc receive --one marc +$NACL_TSP --database marc receive --one marc echo "---- wait 1 seconds and then send a message back" -sleep 1 && echo "Oh hello Marlon" | $NACL_TPS --database marc send -s marc -r marlon & +sleep 1 && echo "Oh hello Marlon" | $NACL_TSP --database marc send -s marc -r marlon & echo "---- receive the message" -$HPKE_TPS --database marlon receive --one marlon +$HPKE_TSP --database marlon receive --one marlon echo "---- cleanup databases" rm -f marc.sqlite marlon.sqlite From a5fe5c7c7b04b6778ef052cc6b7d387a385c5828 Mon Sep 17 00:00:00 2001 From: Michiel Date: Wed, 4 Sep 2024 16:02:05 +0200 Subject: [PATCH 4/5] Use MessageType to bundle CryptoType and SignatureType together Signed-off-by: Michiel --- tsp/src/crypto/mod.rs | 10 ++-------- tsp/src/crypto/nonconfidential.rs | 19 +++++++++---------- tsp/src/store.rs | 8 ++------ 3 files changed, 13 insertions(+), 24 deletions(-) diff --git a/tsp/src/crypto/mod.rs b/tsp/src/crypto/mod.rs index a55625a..f92c2cb 100644 --- a/tsp/src/crypto/mod.rs +++ b/tsp/src/crypto/mod.rs @@ -1,3 +1,4 @@ +use crate::definitions::MessageType; use crate::definitions::{ Digest, NonConfidentialData, Payload, PrivateKeyData, PrivateSigningKeyData, PrivateVid, PublicKeyData, PublicVerificationKeyData, TSPMessage, VerifiedVid, @@ -132,14 +133,7 @@ pub fn sign( pub fn verify<'a>( sender: &dyn VerifiedVid, tsp_message: &'a mut [u8], -) -> Result< - ( - &'a [u8], - crate::cesr::CryptoType, - crate::cesr::SignatureType, - ), - CryptoError, -> { +) -> Result<(&'a [u8], MessageType), CryptoError> { nonconfidential::verify(sender, tsp_message) } diff --git a/tsp/src/crypto/nonconfidential.rs b/tsp/src/crypto/nonconfidential.rs index 99319dc..040b79f 100644 --- a/tsp/src/crypto/nonconfidential.rs +++ b/tsp/src/crypto/nonconfidential.rs @@ -1,6 +1,6 @@ use crate::{ cesr::{CryptoType, DecodedEnvelope, Envelope, SignatureType}, - definitions::{PrivateVid, TSPMessage, VerifiedVid}, + definitions::{MessageType, PrivateVid, TSPMessage, VerifiedVid}, }; use ed25519_dalek::ed25519::signature::Signer; @@ -37,14 +37,7 @@ pub fn sign( pub fn verify<'a>( sender: &dyn VerifiedVid, tsp_message: &'a mut [u8], -) -> Result< - ( - &'a [u8], - crate::cesr::CryptoType, - crate::cesr::SignatureType, - ), - CryptoError, -> { +) -> Result<(&'a [u8], MessageType), CryptoError> { let view = crate::cesr::decode_envelope(tsp_message)?; // verify outer signature @@ -72,5 +65,11 @@ pub fn verify<'a>( return Err(CryptoError::MissingCiphertext); }; - Ok((nonconfidential_data, crypto_type, signature_type)) + Ok(( + nonconfidential_data, + MessageType { + crypto_type, + signature_type, + }, + )) } diff --git a/tsp/src/store.rs b/tsp/src/store.rs index 0f43033..86b2e31 100644 --- a/tsp/src/store.rs +++ b/tsp/src/store.rs @@ -778,17 +778,13 @@ impl Store { return Err(Error::UnverifiedVid(sender.to_string())); }; - let (message, crypto_type, signature_type) = - crate::crypto::verify(&*sender_vid, message)?; + let (message, message_type) = crate::crypto::verify(&*sender_vid, message)?; Ok(ReceivedTspMessage::GenericMessage { sender, nonconfidential_data: None, message, - message_type: MessageType { - crypto_type, - signature_type, - }, + message_type, }) } } From 092767ddf60274b51ac47019af18a0d4df772a94 Mon Sep 17 00:00:00 2001 From: Michiel Date: Wed, 4 Sep 2024 16:10:35 +0200 Subject: [PATCH 5/5] Clean up comment Signed-off-by: Michiel --- tsp/src/crypto/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsp/src/crypto/mod.rs b/tsp/src/crypto/mod.rs index f92c2cb..e8e36d6 100644 --- a/tsp/src/crypto/mod.rs +++ b/tsp/src/crypto/mod.rs @@ -116,7 +116,7 @@ pub fn open<'a>( CryptoType::NaclAuth | CryptoType::NaclEssr => { tsp_nacl::open(receiver, sender, raw_header, envelope, ciphertext) } - CryptoType::Plaintext => Err(CryptoError::MissingCiphertext), // TODO: better error code? + CryptoType::Plaintext => Err(CryptoError::MissingCiphertext), } }