-
Notifications
You must be signed in to change notification settings - Fork 169
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
EdDSA Verification Checks #430
Conversation
… and integrating it in Point / Scalar structure
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would replace all assert
with require
, as most of the time it doesn't make sense to continue the test, e.g., if the msg := random.Bits...
fails, no reason to continue the test.
Also, there are some assert.Nil
which should be require.NoError
.
I thought that HasSmallOrder
is defined on the point and doesn't need to take a slice of bytes, no?
Also, IsCanonical
could be defined only in the eddsa package, as it doesn't make sense in the edwards25519
package, given that Point
s and Scalar
s always are canonical.
sign/eddsa/eddsa_test.go
Outdated
// Test the property of a EdDSA signature | ||
func TestEdDSASigningRandom(t *testing.T) { | ||
suite := edwards25519.NewBlakeSHA256Ed25519() | ||
//suite := edwards25519.NewBlakeSHA256Ed25519() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
//suite := edwards25519.NewBlakeSHA256Ed25519() |
sign/eddsa/eddsa_test.go
Outdated
msg := make([]byte, 32) | ||
_, err := rand.Read(msg) | ||
assert.NoError(t, err) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
msg := make([]byte, 32) | |
_, err := rand.Read(msg) | |
assert.NoError(t, err) | |
msg := random.Bits(256, true, random.New()) |
sign/eddsa/eddsa_test.go
Outdated
msg := make([]byte, 32) | ||
_, err := rand.Read(msg) | ||
assert.NoError(t, err) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
msg := make([]byte, 32) | |
_, err := rand.Read(msg) | |
assert.NoError(t, err) | |
msg := random.Bits(256, true, random.New()) |
sign/eddsa/eddsa_test.go
Outdated
} | ||
|
||
// Test non-canonical keys | ||
// TODO check with p+2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this check be easily added?
sign/eddsa/eddsa_test.go
Outdated
err = ed.Public.UnmarshalBinary(publicKey) | ||
assert.Nil(t, err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
err = ed.Public.UnmarshalBinary(publicKey) | |
assert.Nil(t, err) | |
require.NoError(ed.Public.UnmarshalBinary(publicKey)) |
sign/eddsa/eddsa_test.go
Outdated
assert.Nil(t, err) | ||
|
||
err = Verify(ed.Public, msg2, sig2) | ||
assert.Equal(t, fmt.Errorf("signature is not canonical"), err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
assert.Equal(t, fmt.Errorf("signature is not canonical"), err) | |
require.Equal(t, fmt.Errorf("signature is not canonical"), err) |
sign/eddsa/eddsa_test.go
Outdated
msg := make([]byte, 32) | ||
_, err := rand.Read(msg) | ||
assert.NoError(t, err) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
msg := make([]byte, 32) | |
_, err := rand.Read(msg) | |
assert.NoError(t, err) | |
msg := random.Bits(256, true, random.New()) |
sign/eddsa/eddsa_test.go
Outdated
assert.NoError(t, err) | ||
|
||
sig, err := ed.Sign(msg) | ||
assert.Nil(t, err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
assert.Nil(t, err) | |
require.NoError(t, err) |
sign/eddsa/eddsa_test.go
Outdated
|
||
sig, err := ed.Sign(msg) | ||
assert.Nil(t, err) | ||
assert.Nil(t, Verify(ed.Public, msg, sig)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
assert.Nil(t, Verify(ed.Public, msg, sig)) | |
require.NoError(t, Verify(ed.Public, msg, sig)) |
sign/eddsa/eddsa_test.go
Outdated
} | ||
|
||
err = Verify(ed.Public, msg, sig) | ||
assert.Equal(t, fmt.Errorf("signature is not canonical"), err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
assert.Equal(t, fmt.Errorf("signature is not canonical"), err) | |
require.Equal(t, fmt.Errorf("signature is not canonical"), err) |
Yeah, I'm yet to work my way through
I used the byte slice because
👍 |
Yes - I still don't really understand what this check does with all the XORs :( This is where I would've liked to have an input from Simone, to know what makes most sense. From an engineering point of view Is it correct to replace |
If I understand it correctly, the XORing ensures that
We might run into that at https://github.com/dedis/kyber/pull/430/files#diff-bd9209ce75feb92351db6c68bd8010d7R154 |
sign/eddsa/eddsa.go
Outdated
if len(sig) != 64 { | ||
return fmt.Errorf("signature length invalid, expect 64 but got %v", len(sig)) | ||
} | ||
if (sig[63]&240) > 0 && !group.Scalar().(edDSAScalar).IsCanonical(sig[32:]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The (sig[63]&240) > 0
should also go in IsCanonical
.
This doesn't make sense: if the keys are supposed to be OK, crypto.stackexchange to the rescue: https://crypto.stackexchange.com/questions/55632/libsodium-x25519-and-ed25519-small-order-check So, if I get that right, the second-last paragraph has a nice summary:
So if we test for
But I don't see yet where we should/could check for the correct subgroup with That's probably for another PR. |
Aha, I was under the impression that |
Added `edda.VerifyWithChecks` which checks if the scalars and points are canonical and ensures the points do not have a small order. Refer: RFC8032§5.1.7 and https://eprint.iacr.org/2020/823.pdf Builds on top of dedis#427 and closes dedis#426 and dedis#311. Co-authored-by: David Cerezo <david@calctopia.com> Co-authored-by: Linus Gasser <linus.gasser@epfl.ch>
Added `edda.VerifyWithChecks` which checks if the scalars and points are canonical and ensures the points do not have a small order. Refer: RFC8032§5.1.7 and https://eprint.iacr.org/2020/823.pdf Builds on top of #427 and closes #426 and #311. Co-authored-by: David Cerezo <david@calctopia.com> Co-authored-by: Linus Gasser <linus.gasser@epfl.ch>
This PR builds on #427 with the following modifications:
IsCanonical
andHasSmallOrder
checks are moved toPoint
andScalar
implementations ofedwards25519
edwards25519
eddsa.VerifyWithChecks(pub, msg, sig []byte)
which checks constraints as imposed by RFC8032 and group order checks as suggested in https://eprint.iacr.org/2020/823.pdf and implemented in libsodium