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

[crypto & al] Direct signing/verification for values #4846

Closed
wants to merge 8 commits into from

Conversation

huitseeker
Copy link
Contributor

@huitseeker huitseeker commented Jun 30, 2020

What this does

We used to do:

let hash = msg.hash()
private_key.sign_message(hash)
signature.verify_msg(hash, public_key)
public_key.verify_msg(hash, signature)

Now we do:

private_key.sign(&message)
signature.verify(&message, public_key)
public_key.verify(&message, signature)

Throughout the code base.

Why was it this way?

Long story short: domain separation & weaknesses in serialization engine. We bypassed serialization (which was ambiguous, as of a while ago) and had a very specific way of constructing a hash value, which was sha3(sha3(domain_separation_bytes) || serialized_object_bytes), and then you signed that HashValue. See libra_crypto::hash::CryptoHasher for the domain separation details.

What are the signed bytes now?

We automatically derive them for you, but they're sha3(domain_separation_bytes) || serialized_object_bytes.

So signing is handled for existing structs. What do I do if I want to define MyFancyStruct ?

use libra_crypto_derive::{CryptoHasher, LCSCryptoHash}

#[derive(Serialize, Deserialize, CryptoHasher, LCSCryptoHash)]
pub struct MyCryptoSignableCustomThingy {
...
}

priv_key.sign(my_crypto_signable_custom_thingy)

Is this in specs?

It's upcoming. The older signing/verification isn't there yet.

Why is this better?

It's simpler and more secure (you might pass the wrong hash in code, it's even a crypto gotcha).

Why is this worse?

Serialization is now on the critical path for signing / verification operations, which are exposed as infallible. Serialization can fail in some edge cases, so now they can panic. There's no clean way of recovering from this sort situation, but we are committed to and have a plan to push serialization failures into a never-visited corner (see e.g. #4928).

What's left?

See above re:spec. It's my very next item.

@bors-libra
Copy link
Contributor

☔ The latest upstream changes (presumably 7aa3450) made this pull request unmergeable. Please resolve the merge conflicts.

@huitseeker huitseeker force-pushed the sign_stuff branch 2 times, most recently from 274cf65 to 2d47094 Compare July 2, 2020 16:48
Copy link
Contributor

@ma2bd ma2bd left a comment

Choose a reason for hiding this comment

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

Just random questions for my own understanding and a few minor comments.

testsuite/generate-format/src/consensus.rs Show resolved Hide resolved
testsuite/generate-format/src/libra.rs Outdated Show resolved Hide resolved
crypto/crypto/src/unit_tests/ed25519_test.rs Show resolved Hide resolved
secure/storage/src/vault.rs Outdated Show resolved Hide resolved
The strategy that underpins this is:
- armoring serialization, as in diem#4250
- acknowledging signing is a bad place to recover from a serialization error.
@huitseeker huitseeker changed the title [WIP][crypto] Towards generic signing/verification APIs [crypto & al] Direct signing/verification for values Jul 7, 2020
@huitseeker huitseeker marked this pull request as ready for review July 7, 2020 00:48
Copy link
Contributor

@ma2bd ma2bd left a comment

Choose a reason for hiding this comment

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

The new API is very nice. Thanks for the changes!

) -> Result<Self::SignatureMaterial, CryptoMaterialError>;
/// Note: this assumes serialization is unfaillible. See libra_common::lcs::ser
/// for a discussion of this assumption.
fn sign<T: CryptoHash + Serialize>(&self, message: &T) -> Self::SignatureMaterial;
Copy link
Contributor

Choose a reason for hiding this comment

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

Yay!

@ankushagarwal
Copy link
Contributor

@huitseeker Can you update the swiss-knife README.md before you land?

This uses the new functionality to sign/verify any struct that implements libra_crypto::hash::CryptoHash + serde::ser::Serialize directly.

Note that it makes the semantics of e.g. client/swiss-knife ambiguous, as the deserialization of a payload into an unknown type offered by this API is impossible: the new APis need to know (and use) the type to figure out the prefix that should be applied in signing that struct.

`#[allow(deprecated)]` has been introduced in every place the old functionality needed to be maintained.
We want to reduce the uncertainty on how to sign/verify in Libra=> let's not leave those around.
- verify_struct_msg -> verify
- batch_verify_struct_signatures -> batch_verify
- batch_verify_aggregated_struct_signature -> batch_verify_aggregated_signatures
@huitseeker
Copy link
Contributor Author

@bors-libra r=ankushagarwal

@bors-libra
Copy link
Contributor

📌 Commit bd6c45d has been approved by ankushagarwal

@bors-libra
Copy link
Contributor

⌛ Testing commit bd6c45d with merge 13290df...

bors-libra pushed a commit that referenced this pull request Jul 7, 2020
bors-libra pushed a commit that referenced this pull request Jul 7, 2020
This uses the new functionality to sign/verify any struct that implements libra_crypto::hash::CryptoHash + serde::ser::Serialize directly.

Note that it makes the semantics of e.g. client/swiss-knife ambiguous, as the deserialization of a payload into an unknown type offered by this API is impossible: the new APis need to know (and use) the type to figure out the prefix that should be applied in signing that struct.

`#[allow(deprecated)]` has been introduced in every place the old functionality needed to be maintained.

Closes: #4846
Approved by: ankushagarwal
bors-libra pushed a commit that referenced this pull request Jul 7, 2020
We want to reduce the uncertainty on how to sign/verify in Libra=> let's not leave those around.

Closes: #4846
Approved by: ankushagarwal
bors-libra pushed a commit that referenced this pull request Jul 7, 2020
bors-libra pushed a commit that referenced this pull request Jul 7, 2020
Closes: #4846
Approved by: ankushagarwal
bors-libra pushed a commit that referenced this pull request Jul 7, 2020
- verify_struct_msg -> verify
- batch_verify_struct_signatures -> batch_verify
- batch_verify_aggregated_struct_signature -> batch_verify_aggregated_signatures

Closes: #4846
Approved by: ankushagarwal
bors-libra pushed a commit that referenced this pull request Jul 7, 2020
Closes: #4846
Approved by: ankushagarwal
@github-actions
Copy link

github-actions bot commented Jul 7, 2020

Cluster Test Result

all up : 1073 TPS, 4215 ms latency, 5100 ms p99 latency, no expired txns

Repro cmd:

./scripts/cti --tag land_13290dfe --run bench

@bors-libra
Copy link
Contributor

☀️ Test successful - checks-actions_land_blocking_test, checks-circle_commit_workflow
Approved by: ankushagarwal
Pushing 13290df to master...

@bors-libra bors-libra closed this in bbdad54 Jul 7, 2020
@huitseeker huitseeker added the breaking Any changes that will require restarting the testnet label Jul 7, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking Any changes that will require restarting the testnet cla-signed
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants