libp2p / rust-libp2p

The Rust Implementation of the libp2p networking stack.
https://libp2p.io
MIT License
4.62k stars 961 forks source link

transports: Deterministic certificate generation #3049

Open melekes opened 2 years ago

melekes commented 2 years ago

Presently (https://github.com/libp2p/rust-libp2p/pull/2622), the certificate is supposed to be generated and stored somewhere along the node's key. This could be improved. As it was pointed out in the spec, we should be able to derive a TLS certificate from node's key. This will improve dev experience.

melekes commented 2 years ago

I've spent today looking into ways of doing it. One way is

        // Convert `identity::KeyPair` into `rcgen::KeyPair`.
        let der = id_keys.serialize_der();
        let key_pair = rcgen::KeyPair::from_der(der).map_err(ConfigError::CertificateGenError)?;
        params.key_pair = Some(key_pair);

convert identity::KeyPair to DER and create rcgen::KeyPair from it.

@thomaseizinger pointed out that it might be simpler to use HKDF that will act as the seed for randomness (at what point? during certificate creation https://docs.rs/rcgen/0.10.0/rcgen/struct.CertificateParams.html#structfield.serial_number?).

thomaseizinger commented 2 years ago

@thomaseizinger pointed out that it might be simpler to use HKDF that will act as the seed for randomness (at what point? during certificate creation https://docs.rs/rcgen/0.10.0/rcgen/struct.CertificateParams.html#structfield.serial_number?).

I think we need to patch rcgen to allow for configuration of the randomness source to put in a deterministic one based off a seed. You can then use a HKDF to generate the seed.

There is also randomness in the ECDSA signature on the certificate itself so if you want truly deterministic certificates, that needs to be fixed too. Just the same Keypair doesn't cut it.

For the HKDF, it is probably better to generate the certificate seed and the keypair from different derivations from a common secret and not the certificate from the keypair.

mxinden commented 2 years ago

I would guess @MarcoPolo has opinions here given his related work on https://github.com/libp2p/go-libp2p/pull/1833.

thomaseizinger commented 2 years ago

If patching rcgen is too hard, we might also just inline the certificate generation. ring does all the heavy lifting of the crypto anyway and we don't need much configuration for our usecase so this could turn out quite clean actually.

thomaseizinger commented 2 years ago

As mentioned in https://github.com/melekes/rust-libp2p/pull/12, this is blocked on https://github.com/briansmith/ring/commit/fe9e4d08c1727bea42d31e0d31ee58c4e8e4dc4e getting released and webrtc updating to that new ring release.

thomaseizinger commented 1 year ago

I think this would also be easier to resolve with #3659 because str0m depends on openssl and to parse the cerificate, meaning we don't necessarily need to use ring to generate it.

thomaseizinger commented 11 months ago

This now also affects WebTransport: https://github.com/libp2p/rust-libp2p/pull/4874

dariusc93 commented 6 months ago

While its possible to get around this by generating the cert outside of the behaviour, i think until ring does ever support RFC6979, we should probably do a workaround, though might be considered hacky, but would get the job done to make the cert deterministic out of the box for webrtc (and webtransport when the server side is implemented in libp2p) vs outside workarounds.

thomaseizinger commented 1 month ago

This crate might help: https://docs.rs/x509-cert.

Credits to @pinkforest for pointing me to it.

thomaseizinger commented 1 month ago

Draft for generating deterministic(?) certificates: https://gist.github.com/nnathan/73ccb767ba706ccd07686066e0fde0f5

Also cc @dgarus

dariusc93 commented 1 month ago

Draft for generating deterministic(?) certificates: https://gist.github.com/nnathan/73ccb767ba706ccd07686066e0fde0f5

Also cc @dgarus

Forgotten all about x509-cert crate honestly. Hopefully we can use this in a meaningful way in rust-libp2p