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

Deposit Signature Subgroup Check #1333

Closed
kirk-baird opened this issue Jul 6, 2020 · 8 comments
Closed

Deposit Signature Subgroup Check #1333

kirk-baird opened this issue Jul 6, 2020 · 8 comments
Assignees
Labels
A0 bug Something isn't working consensus An issue/PR that touches consensus code, such as state_processing or block verification. security

Comments

@kirk-baird
Copy link
Member

Description

The deposit signature needs to be verified individually and check both the signature subgroup and the public key subgroup.

Version

master

Present Behaviour

PublicKey subgroups are not checked in the function fast_aggregate_verify_pre_aggregated() which is the function currently called by verify_deposit_signature().

Expected Behaviour

PublicKey subgroups should be checked, this is done in Signature::Verify().

Steps to resolve

Update the function verify_deposit_signature() in consensus/state_processing/src/per_block_processing/verify_deposit.rs such that it calls
Signature::verify() in crypto/bls/src/signature.rs.

@kirk-baird kirk-baird added bug Something isn't working security labels Jul 6, 2020
@ghost ghost added A0 labels Sep 9, 2020
@paulhauner
Copy link
Member

Hey @kirk-baird is this still relevant? :)

@kirk-baird
Copy link
Member Author

Hey @kirk-baird is this still relevant? :)

Yep this is still relevant, instead of using a signature set for the deposit it would be safer to verify the signature directly.

i.e. We currently have

    let deposit_signature_message = deposit_pubkey_signature_message(&deposit_data, spec)
        .ok_or_else(|| error(DepositInvalid::BadBlsBytes))?;

    verify!(
        deposit_signature_set(&deposit_signature_message).verify(),
        DepositInvalid::BadSignature
    );

Where deposit_signature_message is (PublicKey, SIgnature, Message)
The simplest solution is

    let (pubkey, signature, message) = deposit_pubkey_signature_message(&deposit_data, spec)
        .ok_or_else(|| error(DepositInvalid::BadBlsBytes))?;

    verify!(
        signature.verify(&pubkey, message).verify(),
        DepositInvalid::BadSignature
    );

This will mean we are no longer parallelising deposit signatures though which would be a little slower.

The other option is what is being discussed with the blst guys and I'll ping Andy about our current status. It is to do the subgroup checks when we first deserialise a point then we don't need to worry cause all public keys and signatures will have their subgroup checked by this point.

@paulhauner
Copy link
Member

I believe @blacktemplar is working on this now :)

@blacktemplar
Copy link
Contributor

I started looking into this and I am not sure why @kirk-baird's proposed simple solution should solve the problem.

I am currently looking into the BLST implementations and there we have the following call stack:
signature.verify(&pubkey, message)
-> signature.point.unwrap().verify(pubkey.point(), message)
-> signature.point.unwrap().verify(message.as_bytes(), DST, &[], pubkey.point())
-> signature.point.unwrap().aggregate_verify(&[message.as_bytes().as_slice()], DST, &[pubkey.point()])

Besides some infinity checks nothing else happens in those calls.

Following the call stack on the currently used method deposit_signature_set(&deposit_signature_message).verify() shows that it will also use the aggregate_verify function, so without going into detail of that function, either both approaches do subgroup checks or none of them do it. Maybe also relevant this comment: https://github.com/supranational/blst/blob/ce25c7202dacab8fa64a939f05f6efa232b25ea8/bindings/rust/src/lib.rs#L601.

@kirk-baird do you have any updates about the second solution that checks subgroups on serialization?

@kirk-baird
Copy link
Member Author

Yep this is an open issue on BLST. It depends where we end up doing the subgroup check.

That solution will CURRENTLY works for milagro_bls but I will update milagro_bls to match blst after they've decided where subgroup checks will be done!

Basically it comes down to a potential optimisation in the BLS libraries using Proof Of Possession that after we've verified ownership of the public key we do not need to check the subgroup again (as we've already done it).

Deposit (signature, public key) pairs are where we verify a user has knowledge of the secret key for that public key so we need to enforce public key subgroups are checked.

On the other hand these public keys subgroups do not need to be checked for fast_aggregate_verify() or batch_fast_aggregate_verify() as we assume that the public key is already verified and so the implementation may optimise them out, we just need to confirm whether BLST will optimise these out or not.

@paulhauner paulhauner added A1 and removed A0 labels Oct 2, 2020
@paulhauner
Copy link
Member

Pushing this back to A1 since we're blocked on BLST and it's not going to happen before the audit.

@paulhauner paulhauner removed the A1 label Nov 8, 2020
@paulhauner
Copy link
Member

Hey @kirk-baird wondering if this is still relevant 😆

@paulhauner paulhauner added the A0 label Nov 8, 2020
@kirk-baird
Copy link
Member Author

kirk-baird commented Nov 10, 2020

Yep although we technically now do a subgroup check, we are using an aggregate verify function which we aren't allowed to use on unverified PublicKeys. It would be better practice and safer to avoid SignatureSets i.e.

pub fn verify_deposit_signature(deposit_data: &DepositData, spec: &ChainSpec) -> Result<()> {
    let (public_key, signature, msg) = deposit_pubkey_signature_message(&deposit_data, spec)
        .ok_or_else(|| error(DepositInvalid::BadBlsBytes))?;

    verify!(
        signature.verify(&public_key, msg)
        DepositInvalid::BadSignature
    );

    Ok(())
}

@bors bors bot closed this as completed in 3b405f1 Nov 20, 2020
@michaelsproul michaelsproul added the consensus An issue/PR that touches consensus code, such as state_processing or block verification. label Nov 9, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A0 bug Something isn't working consensus An issue/PR that touches consensus code, such as state_processing or block verification. security
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants