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

Display and Debug for secret keys prints a hash #312

Merged
merged 2 commits into from Nov 2, 2021

Conversation

dr-orlovsky
Copy link
Contributor

Extract of concept ACK part of #311 related to changing the way secret keys are displayed/printed out

@dr-orlovsky dr-orlovsky changed the title Display and Debug foe secret keys prints a hash Display and Debug for secret keys prints a hash Jun 27, 2021
@dr-orlovsky dr-orlovsky force-pushed the extrakeys/display branch 6 times, most recently from adfda2e to 739d36f Compare June 27, 2021 18:47
Copy link
Collaborator

@real-or-random real-or-random left a comment

Choose a reason for hiding this comment

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

Concept ACK

src/key.rs Outdated
Comment on lines 206 to 211
#[cfg(any(feature = "std", feature = "alloc"))] {
#[allow(deprecated)]
s.serialize_str(&self.format_secret())
}
#[cfg(not(any(feature = "std", feature = "alloc")))]
s.serialize_bytes(&self[..])
Copy link
Member

Choose a reason for hiding this comment

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

idk if we really want that.
serializing differently depending on features can cause serious breakage.
we can also easily implement stack based str here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hm, can you elaborate how to do that?

Copy link
Member

Choose a reason for hiding this comment

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

See the last 2 commits here: https://github.com/elichai/rust-secp256k1/tree/pr-312 (feel free to cherry-pick them)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@elichai cherry-picked, thanks!

@elichai
Copy link
Member

elichai commented Jun 28, 2021

Is there an actual need to print a hash of the private key instead of just <redacted private key>?

@dr-orlovsky
Copy link
Contributor Author

@elichai I think since we need to distinguish two different keys it's good to print their hashes

@elichai
Copy link
Member

elichai commented Jun 29, 2021

@elichai I think since we need to distinguish two different keys it's good to print their hashes

idk, I'm not a big fun of actual logic inside of Debug prints, and also not sure assuming that it's safe to print a hash of a private key is such a great assumption, @real-or-random @apoelstra what do you think?

@real-or-random
Copy link
Collaborator

idk, I'm not a big fun of actual logic inside of Debug prints

No strong opinions here. I think it's acceptable for Debug.

and also not sure assuming that it's safe to print a hash of a private key is such a great assumption

I think it's fine. I think even printing the keys out is fine, even though it's better to avoid that footgun. (But if you have Debug prints in your code, it's your fault in the end...)

Hashing is for sure a better idea, and secret keys should have enough entropy. But we should nevertheless tag the tash, i.e., add a prefix like "rust-secp256k1DEBUG" to make sure we don't collide with other Maybe even BIP340-style tagging if bitcoinhashes supports this.

@dr-orlovsky
Copy link
Contributor Author

@devrandom I did tagged hashing. Doing it with bitcoin_hashes::sha256t will require introduction of two new types (for hash tag and for tagged hash) which is an overkill, so I just reproduced the logic right in the code without optimization of tagged hash midstate generation.

@devrandom
Copy link
Contributor

Ironically enough, the wrong random person was tagged in the previous message. ;-)

@dr-orlovsky
Copy link
Contributor Author

Ha! That's funny! Sorry :)

@real-or-random, I meant you

src/macros.rs Outdated
/// This is the only method that outputs the actual secret key value, and, thus,
/// should be used with extreme precaution.
#[deprecated(
note = "Caution: you are explicitly outputting secret key value! This can be done
Copy link
Member

Choose a reason for hiding this comment

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

If a user says they want to do something, let them do it. Forcing a warning print or an allow statement after they explicitly stated they want it (via an aptly named method call) is just making the library harder to use for no obvious gain. The goal here should be to make sure that the users' code is readable - if they're writing out the secret key it should be really painfully obvious that they are - not to make it actively hard for the user to write out secret key material.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I assume the point of the warning is that users don't forget to remove debug prints from their code after debugging. And this seems indeed helpful.

Copy link
Member

Choose a reason for hiding this comment

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

And if a user actually wants to print a secret for some reason? eg in lightning you might imagine a secret which just represents the payment claim, and which the sender should not consider materially "secret"? Not all cryptographic protocols require that secrets stay out of debug logs, nor should we be the ones to decide that even if the secrets control lots of bitcoin! It's not our job to "fix" client applications, only remove foot guns; if they don't do code review or catch bugs that our well-named functions make obvious, there isn't anything we can do about it, and we shouldn't make the lives of our users harder.

Copy link
Collaborator

Choose a reason for hiding this comment

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

And if a user actually wants to print a secret for some reason? eg in lightning you might imagine a secret which just represents the payment claim, and which the sender should not consider materially "secret"?

Yeah, and you may want to build protocols where public keys are secret. secp256k1 is supposed to be high-level library hard to misuse. As a wrapper we should follow the same philosophy. And this means we need to make an educated guess which values are supposed to be secret, and I think then a secret key is a good candidate. ;)

Not all cryptographic protocols require that secrets stay out of debug logs, nor should we be the ones to decide that even if the secrets control lots of bitcoin! It's not our job to "fix" client applications, only remove foot guns; if they don't do code review or catch bugs that our well-named functions make obvious, there isn't anything we can do about it, and we shouldn't make the lives of our users harder.

I think in this case is foot-gunny. You introduce some Debug prints for debugging, then fix your bug and forget to remove the Debug prints. If you want to print secrets in production, even for logging, there are other ways to do. It's not impossible to do it, we're just forcing the users to think about their intentions.

But of course, the distinction between avoiding foot guns and imposing our will on users is fuzzy, and it's no surprise that different people draw the line in different places. So in the end, I don't care too much.

Copy link
Member

Choose a reason for hiding this comment

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

Look at it another way, what if a user, for whatever reason, legitimately wants to print a secret key? Adding a giant warning every time they compile is just being obnoxious. We can be anti-footgun by making the warning something clearer (I dunno, fmt_secret_key_printing_secret), forcing users to see a scary compile warning is going beyond anti-footgun and assuming users are using the library in exactly the way we intend (which I guess is just on-chain bitcoin, cause this doesn't make sense for lighting).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

And if a user actually wants to print a secret for some reason?

Then you should mark such calls with #[allow(deprecated)] as like here: b284e44#diff-0988d5d2259e1a401001675578c38d09c46290b877b66b07fb96a7e034ccdf70R674

Copy link
Member

Choose a reason for hiding this comment

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

Frankly, I find that kind of thing obnoxious to our users. It is not our job to tell users exactly how they must use this library, and we shouldn't force our users to add stupid hacks and workarounds just to use the library. We can help them avoid bugs by making sure their code is clear in their calls to clearly-named functions, but that's about it. Also, this method is not deprecated, it's intended to be in the API, so it's just completely a misnomer and confusing to users on top.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed that depreciation part

src/macros.rs Outdated Show resolved Hide resolved
src/macros.rs Outdated Show resolved Hide resolved
src/macros.rs Outdated Show resolved Hide resolved
src/macros.rs Outdated Show resolved Hide resolved
@tcharding tcharding mentioned this pull request Jul 29, 2021
@dr-orlovsky dr-orlovsky force-pushed the extrakeys/display branch 4 times, most recently from 0858c9f to a828af6 Compare August 9, 2021 15:40
@dr-orlovsky
Copy link
Contributor Author

@TheBlueMatt @thomaseizinger @elichai Tried to fulfill all suggestions, completelly refactored PR history. Now there is no depricated thing, and everything done in the same manner with display_secret() alike it is done for std::Path

thomaseizinger
thomaseizinger previously approved these changes Aug 10, 2021
Copy link
Contributor

@thomaseizinger thomaseizinger left a comment

Choose a reason for hiding this comment

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

Thanks!

A few nits, but generally ACK a828af6

src/secret.rs Outdated Show resolved Hide resolved
src/secret.rs Outdated Show resolved Hide resolved
src/key.rs Outdated Show resolved Hide resolved
src/key.rs Outdated Show resolved Hide resolved
@dr-orlovsky
Copy link
Contributor Author

dr-orlovsky commented Aug 21, 2021

@thomaseizinger covered your review comments with the last commit

UPDT: @thomaseizinger actually had to revert that change: its impossible to use to_string() as you suggested without relying on the alloc feature, which is not always present for this crate.

@dr-orlovsky dr-orlovsky force-pushed the extrakeys/display branch 2 times, most recently from e209663 to 73c0779 Compare August 22, 2021 08:53
@apoelstra
Copy link
Member

Should remove the commit from #314 and I'm not sure why hashes::hex or formatting with {:x} is insufficient and we need to implement manual hex encoding.

@dr-orlovsky
Copy link
Contributor Author

@thomaseizinger all all suggestions are implemented

@apoelstra commit removed. As for manual hex, we need this function b/c of no-std

@dr-orlovsky dr-orlovsky force-pushed the extrakeys/display branch 2 times, most recently from 1f5d6da to 60f7e58 Compare September 27, 2021 11:52
Debug-print secrets as tagged hashes

Refactoring Display/Debug for secret values with display_secret
Copy link
Member

@apoelstra apoelstra left a comment

Choose a reason for hiding this comment

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

ACK 6810c2b

Copy link
Contributor

@thomaseizinger thomaseizinger left a comment

Choose a reason for hiding this comment

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

ACK 6810c2b

@dr-orlovsky
Copy link
Contributor Author

I assume this can be merged now? At least github says all criteria are fulfilled.

@apoelstra apoelstra merged commit 88196bd into rust-bitcoin:master Nov 2, 2021
@apoelstra
Copy link
Member

Yep, thanks

apoelstra added a commit that referenced this pull request Dec 20, 2021
de77518 Serde serialization for KeyPair (Dr Maxim Orlovsky)

Pull request description:

  Serde implementation for `KeyPair` type (which hadn't it before).

  Based on #312 (includes all commits from that PR, will be rebased upon merge)

ACKs for top commit:
  apoelstra:
    ACK de77518

Tree-SHA512: 1e75c4fc772dcba5ce7edb30235a58550342cf986c6a77b4affd81defeba456c9655e28b081e0040c1f8440da3f7ad2224485d35222c1921099567b4d1533794
mariocynicys added a commit to mariocynicys/rust-teos that referenced this pull request Jun 26, 2022
Needed to pump the lightning version used and had to pump bitcoin, bitcoincore-rpc aswell to match dep verions in lightining
merkle root computation changed in `bitcoin`, thus some methods in the test_utils needed to adapt (basically by adding a tx if there is none in a block). See: rust-bitcoin/rust-bitcoin@b454cf8
Also SecretKey had it's `to_string` method removed, so TEOS now encodes its tower key using `secret_bytes()` and `from_slice()`. See: rust-bitcoin/rust-secp256k1#312
mariocynicys added a commit to mariocynicys/rust-teos that referenced this pull request Jul 20, 2022
Needed to pump the lightning version used and had to pump bitcoin, bitcoincore-rpc aswell to match dep verions in lightining
merkle root computation changed in `bitcoin`, thus some methods in the test_utils needed to adapt (basically by adding a tx if there is none in a block). See: rust-bitcoin/rust-bitcoin@b454cf8
Also SecretKey had it's `to_string` method removed, so TEOS now encodes its tower key using `secret_bytes()` and `from_slice()`. See: rust-bitcoin/rust-secp256k1#312
mariocynicys added a commit to mariocynicys/rust-teos that referenced this pull request Jul 20, 2022
Needed to pump the lightning version used and had to pump bitcoin, bitcoincore-rpc aswell to match dep verions in lightining
merkle root computation changed in `bitcoin`, thus some methods in the test_utils needed to adapt (basically by adding a tx if there is none in a block). See: rust-bitcoin/rust-bitcoin@b454cf8
Also SecretKey had it's `to_string` method removed, so TEOS now encodes its tower key using `secret_bytes()` and `from_slice()`. See: rust-bitcoin/rust-secp256k1#312
mariocynicys added a commit to mariocynicys/rust-teos that referenced this pull request Jul 28, 2022
Needed to pump the lightning version used and had to pump bitcoin, bitcoincore-rpc aswell to match dep verions in lightining
merkle root computation changed in `bitcoin`, thus some methods in the test_utils needed to adapt (basically by adding a tx if there is none in a block). See: rust-bitcoin/rust-bitcoin@b454cf8
Also SecretKey had it's `to_string` method removed, so TEOS now encodes its tower key using `secret_bytes()` and `from_slice()`. See: rust-bitcoin/rust-secp256k1#312
mariocynicys added a commit to mariocynicys/rust-teos that referenced this pull request Jul 28, 2022
Needed to pump the lightning version used and had to pump bitcoin, bitcoincore-rpc aswell to match dep verions in lightining
merkle root computation changed in `bitcoin`, thus some methods in the test_utils needed to adapt (basically by adding a tx if there is none in a block). See: rust-bitcoin/rust-bitcoin@b454cf8
Also SecretKey had it's `to_string` method removed, so TEOS now encodes its tower key using `secret_bytes()` and `from_slice()`. See: rust-bitcoin/rust-secp256k1#312
mariocynicys added a commit to mariocynicys/rust-teos that referenced this pull request Jul 29, 2022
Needed to bump the lightning version used and had to bump bitcoin, bitcoincore-rpc aswell to match dep verions in lightining
merkle root computation changed in `bitcoin`, thus some methods in the test_utils needed to adapt (basically by adding a tx if there is none in a block). See: rust-bitcoin/rust-bitcoin@b454cf8
Also SecretKey had it's `to_string` method removed, so TEOS now encodes its tower key using `secret_bytes()` and `from_slice()`. See: rust-bitcoin/rust-secp256k1#312
mariocynicys added a commit to mariocynicys/rust-teos that referenced this pull request Jul 29, 2022
Needed to bump the lightning version used and had to bump bitcoin, bitcoincore-rpc aswell to match dep verions in lightining
merkle root computation changed in `bitcoin`, thus some methods in the test_utils needed to adapt (basically by adding a tx if there is none in a block). See: rust-bitcoin/rust-bitcoin@b454cf8
Also SecretKey had it's `to_string` method removed, so TEOS now encodes its tower key using `display_secret().to_string()`. See: rust-bitcoin/rust-secp256k1#312
mariocynicys added a commit to mariocynicys/rust-teos that referenced this pull request Jul 31, 2022
Needed to bump the lightning version used and had to bump bitcoin, bitcoincore-rpc aswell to match dep verions in lightining
merkle root computation changed in `bitcoin`, thus some methods in the test_utils needed to adapt (basically by adding a tx if there is none in a block). See: rust-bitcoin/rust-bitcoin@b454cf8
Also SecretKey had it's `to_string` method removed, so TEOS now encodes its tower key using `display_secret().to_string()`. See: rust-bitcoin/rust-secp256k1#312
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.

None yet

7 participants