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

Support blind variant #37

Open
chris-wood opened this issue Mar 6, 2021 · 9 comments
Open

Support blind variant #37

chris-wood opened this issue Mar 6, 2021 · 9 comments

Comments

@chris-wood
Copy link

Blind BLS signatures have come up a number of times on the CFRG mailing list and in other places in the IETF. Adding this to the current document seems quite doable (it only changes the how the CoreSign operation is computed, I think).

@kwantam, would you be open to a PR that adds this feature?

@chris-wood
Copy link
Author

chris-wood commented Jul 30, 2021

Here's a first cut at a solution based on the current draft. (Bugs are obviously my fault!) First, move the private key operation in CoreSign out to a separate CoreEvalaute function, like so:

CoreEvaluate(SK, Q):
   return SK * Q

CoreSign:
   Q = hash_to_point(message)
   R = CoreEvaluate(SK, Q)
   signature = point_to_signature(R)
   return signature

Then, define Blind, BlindSign, and Finalize functions (similar to the blind RSA draft) that invoke CoreEvaluate like so:

CoreBlind(message):
   R = GG.RandomScalar()
   T = hash_to_point(message)
   blinded_message = point_to_pubkey(R * T)
   return R, blinded_message

CoreFinalize(message, PK, R, blinded_sig):
   Y = signature_to_point(blinded_sig)
   R_inv = R^-1
   signature = point_to_signature(R_inv * Y)
   if CoreVerify(PK, message, signature):
   return signature
   raise Error

CoreBlindSign(SK, blinded_message):
   Q = pubkey_to_point(blinded_message)
   Z = CoreEvaluate(SK, Q)
   return point_to_signature(Z)

It would also be interesting if we could support partially blind signatures, a la 2021/203.

cc @dot-asm, @veorq, @zhenfeizhang for thoughts

@dot-asm
Copy link

dot-asm commented Jul 30, 2021

CoreBlind(message):
R = GG.RandomScalar()
R = hash_to_point(message)
blinded_message = point_to_pubkey(T * Q)
return R, blinded_message

You surely meant T = hash_to_point(message) and then T * R. As for the latter, T * R, since R is supposed to be secret, one can make case that one should use accordingly "armored" scalar multiplication. I mean just T * R suggests "whatever multiplication," which allows "non-armored," which might be formally inadequate.

@chris-wood
Copy link
Author

(Fixed -- thanks!)

@dot-asm
Copy link

dot-asm commented Jul 30, 2021

T * R

Or rather R * T, right? I mean in all other cases scalar goes first, and it's only appropriate to be consistent. Well, one doesn't really have a choice [but to be consistent], right? Just like one has no choice of swapping base and exponent in exponentiation operation operator...

@chris-wood
Copy link
Author

Or rather R * T, right? I mean in all other cases scalar goes first, and it's only appropriate to be consistent. Well, one doesn't really have a choice, right? Just like one has no choice of swapping base and exponent in exponentiation operation operator...

I didn't realize that was the convention, so, yeah, fixed. :)

@dot-asm
Copy link

dot-asm commented Jul 31, 2021

blinded_message = point_to_pubkey(R * T)

point_to_pubkey is not right here, it should be point_to_signature. In the context of this draft pubkey and signature refer to the complementary curves. And blinding, signing and unblinding are all occurring on the "signature" curve. This applies even to CoreBlindSign. I mean it's not pubkey_to_point, but signature_to_point.

@dot-asm
Copy link

dot-asm commented Jul 31, 2021

CoreFinalize(message, PK, R, blinded_sig):
...
if CoreVerify(PK, message, signature):
return signature

I understand that it's much easier to simply call CoreVerify, but it's really a waste in the context. For example, would you engage with a signer without first validating its public key? Do you actually have to hash_to_point two times? I mean these are the things that CoreVerify is specified to do, while they can, have to really, be done in advance. The potential problem with specifying it this way is that there is tendency to take spec literally, which can effectively prevent perfectly legitimate optimizations.

CoreBlindSign(SK, blinded_message):
Q = pubkeysignature_to_point(blinded_message)
Z = CoreEvaluate(SK, Q)

I'd argue that a group-check should be performed prior to the secret key operation. Well, there is ongoing discussion about making group-check part of deserialization, but till it's settled, it's more than appropriate to be explicit that it should be performed.

@dot-asm
Copy link

dot-asm commented Jul 31, 2021

a group-check should be performed prior to the secret key operation.

As well as prior multiplication by R_inv in CoreFinalize.

@chris-wood
Copy link
Author

I understand that it's much easier to simply call CoreVerify, but it's really a waste in the context. For example, would you engage with a signer without first validating its public key? Do you actually have to hash_to_point two times? I mean these are the things that CoreVerify is specified to do, while they can, have to really, be done in advance. The potential problem with specifying it this way is that there is tendency to take spec literally, which can effectively prevent perfectly legitimate optimizations.

The intent is to ensure that no output from the protocol will ever fail verification. This just ensures that's the case.

I'd argue that a group-check should be performed prior to the secret key operation. Well, there is ongoing discussion about making group-check part of deserialization, but till it's settled, it's more than appropriate to be explicit that it should be performed.

That's a good idea, in both places. :-)

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

No branches or pull requests

2 participants