Skip to content

Conversation

@benthecarman
Copy link
Collaborator

Implement self-signed certificate generation using ring directly, removing the rcgen dependency along with its transitive dependencies (yasna, time). ring was already in our dependency tree via tokio-rustls.

@ldk-reviews-bot
Copy link

ldk-reviews-bot commented Jan 20, 2026

👋 Thanks for assigning @TheBlueMatt as a reviewer!
I'll wait for their review and will help manage the review process.
Once they submit their review, I'll check if a second reviewer would be helpful.

Copy link

@TheBlueMatt TheBlueMatt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not actually clear on why we want support for building a self-signed cert? In such cases shouldn't we just not use TLS?

tokio = { version = "1.38.0", default-features = false, features = ["time", "signal", "rt-multi-thread"] }
tokio-rustls = { version = "0.26", default-features = false, features = ["ring"] }
rcgen = { version = "0.13", default-features = false, features = ["ring"] }
ring = { version = "0.17", default-features = false }

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given we're gonna ship a binary, I do very much wonder whether we shouldn't use native-tls across the stack in ldk-server. That would avoid us being responsible for shipping updates to ring and rustls in case of a security issue (though honestly I'm not entirely clear on why we want TLS for the RPC to begin with)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that if we did so we could retain the cert-building logic here by switching to secp256k1 rather than secp256r1-via-ring.

Ok(der_sequence(&san_ext))
}

fn build_san_extension(hosts: &[String]) -> Result<Vec<u8>, String> {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

given its self-signed anyway why are we building a SAN? Can't we just have a fixed CN of localhost and call it a day?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's been many times where I need to do this with lnd. A lot with docker containers where we need to add the container's name to the cert so other containers can call on the rpc

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right but its a self-signed cert so the hostname is usually not validated? Or are there things that validate the hostname even for a self-signed cert?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am pretty sure the hostname is validated because I normally am not able to get anything to work unless I add it to the cert

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean that's up to the client. In browsers its definitely not. Given we're likely to mis-auto-detect the hostname (or eg someone might have an alias we're not aware of, eg via tailscale), we should probably prime the ecosystem to not validate for self-signed certs so that. IMO hostname validation on self-signed certs is marginally dangerous as people might treat it as gospel.

let mut rng = rand::thread_rng();
let mut key_bytes = [0u8; 32];
rng.fill(&mut key_bytes);
getrandom::getrandom(&mut key_bytes)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rand as a dep isn't actually removed?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah its still a transitive dep but if our underlying crates stop using it, we will be fine now

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its in Cargo.toml still?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it never was in there

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uh huhhhhhhhhhhhhhhhh :)

diff --git a/ldk-server/Cargo.toml b/ldk-server/Cargo.toml
index 965c960..54f4626 100644
--- a/ldk-server/Cargo.toml
+++ b/ldk-server/Cargo.toml
@@ -1,40 +1,40 @@
 [package]
 name = "ldk-server"
 version = "0.1.0"
 edition = "2021"

 [dependencies]
 ldk-node = { git = "https://github.com/lightningdevkit/ldk-node", rev = "d1bbf978c8b7abe87ae2e40793556c1fe4e7ea49" }
 serde = { version = "1.0.203", default-features = false, features = ["derive"] }
 hyper = { version = "1", default-features = false, features = ["server", "http1"] }
 http-body-util = { version = "0.1", default-features = false }
 hyper-util = { version = "0.1", default-features = false, features = ["server-graceful"] }
 tokio = { version = "1.38.0", default-features = false, features = ["time", "signal", "rt-multi-thread"] }
 tokio-rustls = { version = "0.26", default-features = false, features = ["ring"] }
-rcgen = { version = "0.13", default-features = false, features = ["ring"] }
+ring = { version = "0.17", default-features = false }
+getrandom = { version = "0.2", default-features = false }
 prost = { version = "0.11.6", default-features = false, features = ["std"] }
 ldk-server-protos = { path = "../ldk-server-protos" }
 bytes = { version = "1.4.0", default-features = false }
 hex = { package = "hex-conservative", version = "0.2.1", default-features = false }
 rusqlite = { version = "0.31.0", features = ["bundled"] }
-rand = { version = "0.8.5", default-features = false }

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i am blind

benthecarman and others added 2 commits January 20, 2026 13:54
Implement self-signed certificate generation using ring directly,
removing the rcgen dependency along with its transitive dependencies
(yasna, time). ring was already in our dependency tree via tokio-rustls.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@benthecarman
Copy link
Collaborator Author

I'm not actually clear on why we want support for building a self-signed cert? In such cases shouldn't we just not use TLS?

there are definitely cases where you want encryption but dont want to go through the hassle of the CA and can just share the certificate directly

Copy link

@TheBlueMatt TheBlueMatt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't test this, but I blindly trust Claude to do things right the first time with no mistakes.

@benthecarman benthecarman merged commit 73e6a0b into lightningdevkit:main Jan 30, 2026
7 checks passed
@benthecarman benthecarman deleted the rm-rcgen branch January 30, 2026 17:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants