Crypto v0.0.4 - #799
Conversation
…and per msg wrapped symmetric keys (random)
c01a23c to
1bdfb5d
Compare
janiejestemja
left a comment
There was a problem hiding this comment.
if you're ok with the changes in general, i'll go ahead and replace all the .unwrap()'s with more proper error handling. @benStre @jonasstrehle
sadly i failed at my first attempt to implement pqc across the board, i'll try more thoroughly for crypto v0.0.5 i suppose. luckily this means, i didn't had to introduce the HalloBack block type for now.
in general next things i'd approach are these two
- wire up rng behind nonce for aes, and salt for hkdf (current version leaks a little 🥹)
- add ephemeral x25519 keys (current implementation is not forward secure 😭 )
what i can't wrap my mind around is
- add static keys via config file and implement some sort of whitelisting within the interface-section as well? is there really a need for this?
| } | ||
| } | ||
|
|
||
| pub trait CryptoSync: Send + Sync { |
There was a problem hiding this comment.
the idea here is to circumvent the async restrictions given by web crypto api, for now...
since only web crypto is async, i copied the crypto implementation from embedded there. it's kind of a cheat, and i feel like this can be done differently by doing some refactoring around it.
There was a problem hiding this comment.
I think it's a good solution to separate the async and sync implementations - we did something similar for the ComInterfaceFactories. But since crypto is just included via the facade, we need a uniform interface for every implementation. So I think you could implement CryptoSync e.g. for native like it is right now, and then auto derive the Crypto trait for every T that implements CryptoSync.
We could then later actually support sync execution with crypto, but for now, only the async Crypto trait will actually be used.
| /// * the block signature is validated because the block is for own endpoint and signature is set | ||
| /// * the block needs to be relayed to other endpoints or is a trace block, which requires async handling for the relay/trace logic | ||
| /// The MaybeAsync returns the own received block if the block is for own endpoint and signature is valid, otherwise None | ||
| // FIXME #732: this seams to generate a very big future which causes heap allocation to fail on embedded targets (!?) |
There was a problem hiding this comment.
not entirely certain if i fixed this, by fixing a FIXME no-clone, reordering the code, and using pinned boxes for trace blocks.
| if is_for_own && block_type != BlockType::Hello { | ||
| info!("Block is for this endpoint ({})", self.endpoint); | ||
|
|
||
| Some(block) // FIXME #733: no clone |
There was a problem hiding this comment.
fixme comment can be removed, left it there as a reference for review....
| } | ||
|
|
||
| /// Updates the sender and timestamp of the block | ||
| fn update_sender_and_timestamp( |
There was a problem hiding this comment.
i'm uncertain why this method was nested into the one beneath (prapare_own_block()), as far as i understand nested function in general lead to issues, although i don't know if this would be here the case.
There was a problem hiding this comment.
I think it was just an arbitrary decision because this function was only used inside prepare_own_block, and is also just a standalone utitlity function, not a method that needs self. I don't think theres really a downside in this case, but I also think its cleaner to have it as a separate method.
| .flags_and_timestamp | ||
| .set_block_type(BlockType::Hello); | ||
| // TODO #182 include fingerprint of the own public key into body | ||
| // -> done in prepare_own_block (for now?) |
There was a problem hiding this comment.
actually the prepare body function currently clones own public keys into the body of hello-blocks, not just a fingerprint. without a working certificate authority, where the fingerprint can be used to retrieve a verified key a fingerprint seems rather useless for now.
although if the long term plan is to setup a server acting as certificate authority in this context, it would be unnecessary to implement per-interface-whitelisting of any sorts.
benStre
left a comment
There was a problem hiding this comment.
Thank you - looks good.
I added a view comments - overall, I think you can continue with this approach.
Loading the endpoint keys from the config would be very cool to have, but you can also add this at the end once everything else works.
| } | ||
| } | ||
|
|
||
| pub trait CryptoSync: Send + Sync { |
There was a problem hiding this comment.
I think it's a good solution to separate the async and sync implementations - we did something similar for the ComInterfaceFactories. But since crypto is just included via the facade, we need a uniform interface for every implementation. So I think you could implement CryptoSync e.g. for native like it is right now, and then auto derive the Crypto trait for every T that implements CryptoSync.
We could then later actually support sync execution with crypto, but for now, only the async Crypto trait will actually be used.
|
|
||
| fn gen_ed25519<'a>() | ||
| -> AsyncCryptoResult<'a, (Vec<u8>, Vec<u8>), Self::Ed25519GenError> | ||
| -> AsyncCryptoResult<'a, ([u8; 32], [u8; 32]), Self::Ed25519GenError> |
There was a problem hiding this comment.
I would recommend to define a type alias for the [u8; 32] and others that are used in multiple locations, e.g.
type PrivKey = [u8; 32]It might even be better to put them into actual newtype wrapper structs, to ensure a private and public key or whatever don't get accidently mixed up.
| } | ||
|
|
||
| /// Updates the sender and timestamp of the block | ||
| fn update_sender_and_timestamp( |
There was a problem hiding this comment.
I think it was just an arbitrary decision because this function was only used inside prepare_own_block, and is also just a standalone utitlity function, not a method that needs self. I don't think theres really a downside in this case, but I also think its cleaner to have it as a separate method.
| pub direct_endpoint: Option<Endpoint>, | ||
| pub connection_timestamp: u64, | ||
| uuid: ComInterfaceSocketUUID, | ||
| pub pub_sig_key: Option<[u8; 32]>, |
There was a problem hiding this comment.
keys should always be associated directly with an Endpoint, not with a socket. An endpoint might be connected via multiple sockets, and multiple endpoints might be connected via a single socket. It's also necessary to keep the keys in memory when a socket disconnects.
The most simple solution would be something like a HashMap<Endpointt,Keys> stored in the ComHub.
This draft contains:
Additional changes: