libp2p / rust-libp2p

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

transports: Deterministic certificate generation #3049

Open melekes opened 1 year ago

melekes commented 1 year 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 1 year 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 1 year 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 1 year ago

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

thomaseizinger commented 1 year 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 1 year 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 7 months ago

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

dariusc93 commented 2 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.