-
Notifications
You must be signed in to change notification settings - Fork 17.8k
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
x/crypto/scrypt: implementation not compliant with RFC 7914? #33703
Comments
Amusingly, if the Go implementation isn't RFC compliant, then the reference implementation itself may not be either. It does not seem to check For context[1]: The Go implementation also looks a lot like the reference implementation, and performs similar checks. Here are the sanity checks done with http://www.tarsnap.com/scrypt/scrypt-1.3.0.tgz
*The original scrypt paper[1] does not explicit give the inequality |
|
This seems like a valid analysis, but I have little bandwidth to verify its soundness at this time. I suggest compiling the reference implementation and verifying that it accepts the non-compliant parameters. Depending on the results, it could lead to a more-actionable outcome: if there is a bug in the reference implementation, and that implementation changes as a result of that bug, there is more reason to fix that bug in Go. However, all of these parameters are controlled by the caller outside the package and the "fix" involves reducing the robustness. A simple workaround would be to wrap the function or validate the arguments prior to the function call. It would be very useful to understand the practical impact of violating the inequality |
A significant practical impact is that if other implementations follow the spec while Go doesn't that can lead to non-portability between implementations, i.e with respect to parameters passed to scrypt. In fact, it's already happened: the go-ethereum project includes test data that relies on Go's scrypt's non-RFC-compliant behavior, though that wasn't a deliberate choice by go-ethereum's maintainers at the time the test data was generated (several years ago). When that test data is used with an RFC-compliant implementation there will be an error/exception, e.g. with Node.js' built-in scrypt, introduced in Node v10.5.0.
Yes, that's possible, and I've taken that approach. It's rather awkward, though, to explain to users why libraries I'm working on complain about parameters that go-ethereum / Go handles just fine: "sorry, those scrypt parameters are not RFC compliant and won't work with Node's compliant implementation." I agree that:
Maybe we can loop-in Colin Percival? I could @ mention him (cperciva) but will leave that to your discretion. |
We should first ascertain whether the reference implementation has the same bug, and then loop in Colin if so. In that case what we do would depend on whether the reference implementation fixes it, and on the impact of violating the bounds. If the reference implementation is unaffected, we should just fix our implementation to be RFC compliant. |
Sounds good. I don't have a lot of experience with C and am fumbling around a bit trying to "ascertain whether the reference implementation has the same bug". I'll report back with steps/results if I can confirm one way or another. However, please let me know whether you'll be waiting on me or plan to conduct a test yourselves, as I'll probably need to get some help from a coworker to avoid spending too much time figuring out the tooling. I think it's just a matter of changing some values in |
@michaelsbradleyjr I can do this part, stand by for results. |
To save time, compiling the sample test was achieved by simply running the following commands in the
When executed, the binary
We edit the source file and add a print statement:
We now compile and re-run the program to output whether the
Conclusion: The /cc @FiloSottile |
Thank you @as, much appreciated. So, the questions seem to boil down to:
Noting again that at present re: (2) and (4) there are already real-world implications, e.g. Node.js |
That slipped into the RFC by accident. I think it may have originally been intended to say We haven't gotten around to submitting an Errata Report for the RFC yet... |
My original analysis that @michaelsbradleyjr referred to in #33703 (comment) was wrong. I actually found the mistake (incorrect conversion between bits/bytes) in the RFC and filed errata a few months ago. See 5971, 5972, and 5973. |
Following confirmation by |
See: https://tools.ietf.org/html/rfc7914. In particular, Section 2: scrypt Parameters:
Compare with: https://github.com/golang/crypto/blob/master/scrypt/scrypt.go#L200.
That is, it doesn't enforce
N < 2^(128 * r / 8)
as far as I can tell (I'm not fluent in Go). In the Go playground I find thatN
's upper limit whenr
is1
is16777215
such thatN=262144
,r=1
,p=8
won't cause scrypt to choke even though it should per the RFC.Context: ethereum/go-ethereum#19977.
The text was updated successfully, but these errors were encountered: