The point of NIST standardizing on SHA-3 is to gradually replace SHA-2 due to the rise of computing power and the likelihood it will become as weak as SHA-1 is now in the near future. Unfortunately, like American credit cards vs. European chip & pin, it's going to take forever to adopt.
So we need to be careful not to use it in setting where that would be problematic. Or we can use it with workarounds, like double hashing (SHA-256d) or truncating its output.
SHA-3 is sponge based, so its output is always truncated, preventing length-extension attacks. So I think SHA-3 is a better default, though it's fine to use SHA-2 if you know what you're doing.
In a similar manner, apps that verify signatures/certificates often let the certificate specify which algorithm is used, so again effectively an attacker may be able to force the app to use SHA3 as long as it uses a library that has some support for it.
This is a common problem, and massively increases attack surface, since if a vulnerability can be found in any algorithm, it can be exploited. Downgrade attacks are a varient of the same.
Let me present an alternative:
Each protocol has one specific encryption algorithm and set of parameters. However, that set isn't fixed, but defined based on the current date and time.
For example, HTTPS could be defined as "SHA1 from 1996 till 2006", "SHA256 from 2005 till 2018", "SHA3 from 2017 till 2032", etc.
The dates can be written 10+ years into the future, so that software deployed today is still usable that many years into the future. As soon as the last date period expires, the software is not usable until it has been upgraded (unless both ends of the communication link choose to fake the date).
There is precedent for software 'expiring' - that happens whenever the root certificate of a trust store reaches an expiry date.
The downside is sometimes an algorithm might be broken before its date comes, and other times an algorithm may still be secure at that date. But that still seems better than our current mess of downgrade attacks.
Then the release of a new configuration can be done slowly with reasonable caution to get back to the desired redundancy level.
Not necessarily. If the client contacts the server using version X, the server will reply with version X.
Who says that? Either it is specified in the protocol, and then you're right that this is still a negotiation, or it is not specified in the protocol, so if the client does that is implementing some out of spec behavior. Which is true that already happened on the Internet for compatibility's sake, but keep in mind that there is still an advantage, as an adversary can't easily mess in the connection setup phase in a way that protocol version X looks like protocol version Y.
* you expect all servers to upgrade immediately, or at least faster than clients, or
* you delay upgrading clients you know to be insecure until servers had time to upgrade, or
* you are ok with breaking a significant portion of the network for every protocol update.
Either way, your proposal makes no sense for the internet.
Additionally, this is already possible with the current negotiation scheme. You can have clients refuse old algorithms (and they do). Your proposal doesn't improve anything there or anywhere else.
Slightly concerning news for the (mostly-Golang-based) Ethereum ecosystem, which relies on SHA3-256 for pretty much everything...
func main() {
h := sha3.New224()
buf := make([]byte, 4294967295)
h.Write(buf)
sum := h.Sum(nil)
fmt.Printf("%x\n", sum)
}
Doesn't crash on my amd64 dev machine.Later
I could have just looked at the code, too: the assembly you've linked to is just the Keccak permutation, not the entire Go hash; the buffer management is done in Go, not in assembly.
Presumably this isn't not-crashing just because the developers of the Golang stdlib somehow found+fixed this bug back in 2015 when this assembler file was baked. The error is in that assembler code, I'm sure. It's presumably getting masked by something. (Something that may be benign, or might be subtly corrupting the runtime.)
For a benign case: maybe the Golang runtime isn't allocating you precisely as many bytes as you're asking for, but rather a little bit more? Perhaps rounding up to a multiple of a page for more-than-page-sized allocations?
Not having access to an amd64 machine at the moment, I'll have to ask you: does increasing the size by one, as in the article, cause an infinite loop?
c5bcc3bc73b5ef45e91d2d7c70b64f196fac08eee4e4acf6e6571ebe
No matter what Go is allocating under the hood, it has to be feeding exactly that many bytes to the SHA3 algorithm.Well, yes, but this is supposed to be a buffer overflow — the algorithm itself is reading and/or writing past the end of the buffer it's been handed. My hypothesis was that Golang is allocating in such a way that reading/writing a single byte past the received slice bounds won't result in a protection fault in the way you'd expect if the allocation were exact.
https://github.com/golang/crypto/blob/642fcc37f5043eadb2509c...
Possibly not as fast as C, but easier to reason about, I'd say.
A second later
Oh, wait, yeah, this is just the Keccak permutation in assembly, not the entire hash. That was dumb of me. Yeah, this code looks ok?
The outer loop of the Write method (function?) is the same for all architectures.
One sec and I'll get you an answer to your thing about the extra write.
c5bcc3bc73b5ef45e91d2d7c70b64f196fac08eee4e4acf6e6571ebe
With the extra write and an extra byte on the big write (to try to trigger the loop condition): ec66be1ebccf055f839fccf2d12e641dcbbda4f5c71a3bdee6509495Read it yourself here:
https://cs.opensource.google/go/x/crypto/+/refs/tags/v0.1.0:...
There's obviously no problem.