Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[tor] Add ability to encrypt the Tor private key on disk #6500

Merged
merged 5 commits into from
Sep 30, 2022

Conversation

orbitalturtle
Copy link
Contributor

@orbitalturtle orbitalturtle commented May 5, 2022

This PR replaces #4458. Since I've been making some of the changes for @gkrizek and it's been a bit tricky to manage making PRs into his PRs... we thought it would be nice to have a fresh start. :)

Depends on #6526

Graham's original PR description:

It's possible that a user might not want the Tor private key to sit on the disk in plaintext (it is a private key after all). So this commit adds a new flag to encrypt the Tor private key on disk using the wallet's seed. When the --tor.encryptkey flag is used, LND will still write the Tor key to the same file, however it will now be encrypted instead of plaintext. This essentially uses the same method to encrypt the Tor private key as is used to encrypt the Static Channel Backup file.

Summary of Changes:

  • Moves the crypto.go file from chanbackup into its own package called lnencrypt. This was needed because we can't directly reference the encryptPayloadToWriter and decryptPayloadFromReader functions from the chanbackup package due to circular dependency issues. Also, I think it's very likely that future enhancements will also want to use these same functions. Thus I've moved them to their own package.

  • Creates a flag called --tor.encryptkey which encrypts the Tor private key.

When this is set it encrypts the private key and writes the encrypted blob to the same file on disk. This allows users to still keep the same functionality and flows as before (like refreshing a hidden service), but adds protection when running in untrusted environments.

  • Add necessary tests and documentation

@guggero guggero self-requested a review May 5, 2022 09:28
@guggero guggero added this to the v0.16.0 milestone May 5, 2022
@guggero guggero added enhancement Improvements to existing features / behaviour security General label for issues/PRs related to the security of the software P2 should be fixed if one has time tor labels May 5, 2022
@orbitalturtle
Copy link
Contributor Author

@guggero Oops, sorry, looks like I broke something when trying to fix the onion file stuff, as discussed here: #4458 (comment) But I'm having trouble fixing the issue...

First question, if you get a chance: Does moving the onion file stuff to a new package within Tor make sense? Re: this convo #4458 (comment)?

If it does make sense to move it... I'm getting the following error that I am struggling to fix

no required module provides package github.com/lightningnetwork/lnd/tor/onionfile; to add it: go get github.com/lightningnetwork/lnd/tor/onionfile

and if I try to do that...

go get: module github.com/lightningnetwork/lnd/tor@upgrade found (v1.0.0), but does not contain package github.com/lightningnetwork/lnd/tor/onionfile

@guggero
Copy link
Collaborator

guggero commented May 6, 2022

Since you last rebased we made the tor package its own submodule.
That fixed a dependency issue but makes it a bit harder to create PRs that change the functionality, unfortunately.

You need to do the following now (that goes for any change to a package that is a submodule, meaning it has its own go.mod file):

  • create PR 1 with the changes to the submodule only (in this case al the changes in tor).
  • after PR 1 is merged, a new tag for the affected submodule is pushed
  • create PR 2 that uses the updated submodule in the rest of the code base

Of course for development it makes sense to create PR 1 and PR2 at the same time and just stack the commits of both in the second PR and use a replace directive until PR 1 is merged and tagged.

@orbitalturtle
Copy link
Contributor Author

@guggero Ah got it, thank you for the explanation!

@orbitalturtle
Copy link
Contributor Author

Hey @guggero one more question for you!

Now I've split the Tor code out into a separate PR. But the Tor changes depend on changes in the keychain and lnencrypt packages. So now I'm getting this response when I try to run "go test" in the Tor module

onionfile/onion_file.go:10:2: no required module provides package github.com/lightningnetwork/lnd/keychain; to add it:
	go get github.com/lightningnetwork/lnd/keychain
onionfile/onion_file.go:11:2: no required module provides package github.com/lightningnetwork/lnd/lnencrypt; to add it:
	go get github.com/lightningnetwork/lnd/lnencrypt

And when I do go get github.com/lightningnetwork/lnd/keychain I get:

go get: module github.com/lightningnetwork/lnd@upgrade found (v0.0.2), but does not contain package github.com/lightningnetwork/lnd/keychain

Wondering if I need to split out the keychain & lnencrypt changes into a third PR? Or if something else is going on

@guggero
Copy link
Collaborator

guggero commented May 9, 2022

Hmm, this is a tough one. I guess what I forgot to mention is that the tor submodule, to be independent and to work standalone and to avoid circular dependencies, shouldn't have any references to the parent lnd packages.

So this requires some additional refactoring...

My suggestion:

  • refactor the EncryptPayloadtoWriter and DecryptPayloadFromReader to be an interface that is independent of the keychain package (requires the genEncryptionKey part to be pulled out and the encryption key be a []byte directly).
  • copy that new interface to the tor package and accept it as the input for the NewOnionFile instead of the keyRing (that's the way to decouple packages: if an interface has exactly the same methods with the same signatures they are compatible, even if the interface is declared under different names in different packages)
  • Create a simple mock for that new interface instead of using the lntest/mock mock one

@guggero guggero removed their request for review May 10, 2022 16:55
@orbitalturtle
Copy link
Contributor Author

Got it, thank you @guggero . Will let you know when I have the latest PRs up.

@guggero
Copy link
Collaborator

guggero commented May 10, 2022

Sounds good! Will review once you give me the heads up.

@orbitalturtle
Copy link
Contributor Author

@guggero One more question... so because we're getting rid of all the lnd dependencies in the Tor module, we don't need to split the onionfile code into a new subpackage of Tor, correct? Just want to make sure I before I move that back

@guggero
Copy link
Collaborator

guggero commented May 11, 2022

I think the OnionFile struct (and its file) can be moved directly to the main tor package/submodule. Or it can stay in the tor/onionfile package (but shouldn't be a submodule, so shouldn't have its own go.mod file) and be renamed to just File (since it will be used as onionfile.File externally, with the current name onionfile.OnionFile it's a bit too verbose IMO).

@orbitalturtle orbitalturtle force-pushed the encrypt-tor-privkey branch 6 times, most recently from 76289a9 to 2de8691 Compare May 11, 2022 22:51
@orbitalturtle orbitalturtle force-pushed the encrypt-tor-privkey branch 3 times, most recently from 5d25e25 to b689dfc Compare May 24, 2022 00:30
@orbitalturtle
Copy link
Contributor Author

Rebased this just fyi. It's ready for a look!

@Roasbeef Roasbeef requested a review from Crypt-iQ August 24, 2022 20:17
lnencrypt/crypto.go Outdated Show resolved Hide resolved
chanbackup/multi.go Outdated Show resolved Hide resolved
chanbackup/multi.go Outdated Show resolved Hide resolved
rpcserver.go Outdated Show resolved Hide resolved
Copy link
Collaborator

@guggero guggero left a comment

Choose a reason for hiding this comment

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

Thanks for the latest updates!
I think we're getting closer here. The diff can be quite a bit smaller though if we follow @Crypt-iQ's suggestion.

chanbackup/multi.go Outdated Show resolved Hide resolved
tor/onionfile/onion_file.go Outdated Show resolved Hide resolved
sample-lnd.conf Outdated Show resolved Hide resolved
@orbitalturtle orbitalturtle force-pushed the encrypt-tor-privkey branch 5 times, most recently from 14eb5c9 to 8b0f904 Compare August 31, 2022 19:35
@orbitalturtle
Copy link
Contributor Author

@Crypt-iQ and @guggero, thanks again for the reviews! I made those updates.

@guggero guggero self-requested a review September 1, 2022 09:13
@guggero
Copy link
Collaborator

guggero commented Sep 9, 2022

Can be rebased now and use the tor/v1.1.0 dependency in go.mod.

@orbitalturtle orbitalturtle force-pushed the encrypt-tor-privkey branch 2 times, most recently from f7e883b to 5807076 Compare September 12, 2022 00:37
Copy link
Collaborator

@guggero guggero left a comment

Choose a reason for hiding this comment

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

Thanks for the rebase and update. Tested the latest version, all seems to work as advertised 🎉

There are still quite a few nits in there. I'd appreciate a scan of all commits before requesting review (in future PRs) to avoid too many rounds of review.

chanbackup/multi.go Show resolved Hide resolved
chanbackup/multi.go Show resolved Hide resolved
chanbackup/multi_test.go Outdated Show resolved Hide resolved
chanbackup/single.go Outdated Show resolved Hide resolved
chanbackup/single_test.go Show resolved Hide resolved
lnencrypt/crypto_test.go Outdated Show resolved Hide resolved
lnencrypt/crypto_test.go Outdated Show resolved Hide resolved
lnencrypt/test_utils.go Outdated Show resolved Hide resolved
go.sum Show resolved Hide resolved
watchtower/config.go Outdated Show resolved Hide resolved
Copy link
Collaborator

@guggero guggero left a comment

Choose a reason for hiding this comment

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

Very nice, LGTM 🎉

lnencrypt/crypto.go Show resolved Hide resolved
lnencrypt/crypto.go Outdated Show resolved Hide resolved
lnencrypt/crypto.go Show resolved Hide resolved
@orbitalturtle
Copy link
Contributor Author

Thanks @guggero! I made those changes. And sure, I'll definitely keep a closer eye out for those nits & code style guidelines in the future!

@lightninglabs-deploy
Copy link

@Crypt-iQ: review reminder

@guggero
Copy link
Collaborator

guggero commented Sep 29, 2022

Needs a rebase.

orbitalturtle and others added 5 commits September 30, 2022 01:53
…its own package called lnencrypt

The functions inside of the crypto.go file in chanbackup (like EncryptPayloadToWriter and DecryptPayloadFromReader) can be used by a lot of things outside of just the chanbackup package. We can't just reference them directly from the chanbackup package because it's likely that it would generate circular dependencies. Therefore we need to move these functions into their own package to be referenced by chanbackup and whatever new functionality that needs them
…vate key on disk

It's possible that a user might not want the Tor private key to sit on the disk in plaintext (it is a private key after all). So this commit adds a new flag to encrypt the Tor private key on disk using the wallet's seed. When the --tor.encryptkey flag is used, LND will still write the Tor key to the same file, however it will now be encrypted intead of plaintext. This essentially uses the same method to encrypt the Tor private key as is used to encrypt the Static Channel Backup file.
@orbitalturtle
Copy link
Contributor Author

@guggero rebased

@guggero guggero merged commit 35c5964 into lightningnetwork:master Sep 30, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Improvements to existing features / behaviour P2 should be fixed if one has time security General label for issues/PRs related to the security of the software tor
Projects
No open projects
Status: Done
Development

Successfully merging this pull request may close these issues.

5 participants