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
redo fuzz target #264
redo fuzz target #264
Conversation
68755f3
to
904ddad
Compare
One of the doc tests is failing with the fuzzing enabled
|
Also, just making sure I understand correctly, this only overrides sign/verify for fuzzing, it doesn't override context creation and relevant code, right? |
@elichai correct. To override context creation would require I override As for the failing doctest, there seems to be a Cargo bug where I can't propagate |
Got it! There is a second variable You should be able to run |
4eaf672
to
335687a
Compare
BTW, in getting this to work, I notice that we broke the old fuzz implemntation with #233. So this PR is release-blocking. |
We can now run unit tests with the fuzz feature on, and they'll pass, which is some assurance that fuzzing with the feature on won't lead to spurious failures due to the fuzz harness inadequately simulating message signing.
335687a
to
b1916a7
Compare
I believe rust-lightning's fuzz stuff needs both? Maybe only the tweak stuff, though, I'd have to check. |
It would surprise me if you were using One interesting thing we could try would be to compile libsecp with an order-13 group (rather than the ~2^256-order group that we normally use). And then not mock any functions. |
I'd buy that it meant our fuzzers have been bad, but still need to be able to call it.
Hmm, this may make sense - forcing the fuzzer to guess two bytes instead of one kinda sucks, but if it means we get exact behavior maybe its still worth it. |
You can call everything in the library now with this PR. Before you couldn't because many functions were |
Oh, oops, I misread that as order-2^13, not order-13, maybe lets just do that? |
Will need a couple hours to play with this -- our order-13 implementation apparently rejects secret keys outside of the range [1, 12] so I'm seeing if I can work around that or if I should just patch the vendored copy of rust-secp to be more forgiving :P. |
Hmmm. So, I can definitely do the order-13 thing but it breaks a lot of our unit tests because half the valid pubkeys on secp are invalid on secp-13, and vice-versa. I can change the overflow logic to check against the secp curve order,, or I can be more clever (and say, reject half of all keys). The former would mean fewer unit tests break, but the latter would give us better fuzz-test coverage. No matter what, fuzz test failures are going to be weird and confusing since all of the public curvepoints will live on a different curve from secp. |
But even with all these considerations, I think we should do it. What do you think @elichai @TheBlueMatt? To be clear, my proposal is:
By using a group of order 13 but allowing secret keys > 13, we break some invariants ... such as there being only one secret key corresponding to each public key and the I think we should try it, and if shit hits the fan we'll just return to the proposal from this PR (where almost all unit tests pass so we know it's being sane) in a patch release. |
I don't think this is a good idea. Its generally not unreasonable to panic if a hash function generates an invalid secp private key, whereas suddenly it will be commonplace. Otherwise I tend to agree. |
Yeah, that's reasonable. I'll change it to check against the actual secp order (or at least, something so big that it's cryptographically inaccessible). |
Added a commit which demonstrates what this'd look like. Currently the tests fail because schnorr signing fails a high proportion of the time when you run it on a compromised group (since BIP340 was defined assuming that out-of-range nonces are cryptographically inaccessible). Also I directly edited the vendored copy of libsecp rather than adding a patch to the vendor script, which I need to fix before this is mergeable. |
Hmm, CI should not have passed there. Looks like it's not actually running the test matrix. Sigh. |
c919480
to
b1916a7
Compare
Removed the order-13 commit. We should revisit this in the future but it'll take a fair bit more work than just enabling the order-13 group. Let's try to get this in now so we can have a release. |
secp256k1-sys/src/recovery.rs
Outdated
) -> c_int { | ||
let sig_sl = slice::from_raw_parts(sig as *const u8, 65); | ||
let msg_sl = slice::from_raw_parts(msg32 as *const u8, 32); | ||
println!("HMM0"); |
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.
You forgot this print here
sig_sl.swap(32, 64); | ||
sig_sl[64] -= 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.
Oh you're using the pubkey parity(0x02/0x03) for a Recover parity, clever :)
secp256k1-sys/src/recovery.rs
Outdated
let msg_sl = slice::from_raw_parts(msg32 as *const u8, 32); | ||
println!("HMM0"); | ||
|
||
if sig_sl[64] > 4 { |
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 think that should be >= 4
, because the VERIFY_CHECK makes sure that recid < 4
, so it should return 0 on 4.
fff07a6
to
238328d
Compare
238328d
to
75d7177
Compare
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.
utACK
The existing fuzz target code had a number of problems
This PR reimplements signing/verification for both Schnorr and ECDSA, such that a fuzzer should be able to forge "valid" signatures.
It does not implement ECDH, since I couldn't find a reasonable way to get a commutative function of (secret key, public key) that the fuzzer could plausibly fake, nor did I implement the tweak_add and tweak_add_check API for the same reason. I think the ECDH case is probably okay because you never "verify" an ECDH secret without recomputing it, so the fuzzer will know what value to target.