News for hackers. Stuff that matters.
Re:SipHash and HalfSipHash Added to Linux Kernel by mrigor on Tuesday January 10, 2017 @01:46AM (#13363163)
Re:SipHash and HalfSipHash Added to Linux Kernel by zer0t3ch on Tuesday January 10, 2017 @02:45AM (#13363361)
As someone who's not at all versed in cryptography, (yet) anyone want to put this in more laymen terms? Maybe compare it to an existing cryptographical-method I might understand or at least know of?
Re:SipHash and HalfSipHash Added to Linux Kernel by majke on Tuesday January 10, 2017 @04:19AM (#13363646)
Hash tables are very important data structures in the computer science world. Hash tables allow you to have amortized O(1) access cost to arbitrary elements - like key/value (often called: map, dict).

In order to implement hash table one need to map key onto an index in the table - this is done with a hash function: hash(string) ---> number.

Here's a problem. If an attacker knows the hash function, she can produce many strings that will give the same number in return. This usually wasn't a problem, but in the web world it is. It is possible to flood the server (usually in python, ruby, perl) with such crafted requests that, for example, all headers will end up with precisely the same hash value: hash(any_given_header_in_request) ---> fixed value.

This is will result in hash table collision and is generally bad. Normal hash functions can't solve this. This problem of maliciously creating hash collisions is called "hash flooding".

Siphash is an attempt to solve the problem. It is more than a hash function - it's a crypto PRF function and that gives you more guarantees than dumb hash function. Most importantly it takes two values: a "string to hash" and a "crypto key": siphash(string, crypto_key) --> number.

The idea is to generate this "crypto_key" randomly on each program execution, to make sure the attacker can't predict it.

Crypto speaking hash functions may be reversible. There is nothing guaranteeing that they are not. But Siphash is a PRF, and in crypto-speach this means it's not reversible. If you can produce an efficient algorithm to reverse Siphash - ie: given crypto key and hash value predict input string - you can write a good paper and be famous.

Re:SipHash and HalfSipHash Added to Linux Kernel by anilgulecha on Tuesday January 10, 2017 @08:27AM (#13364585)
> Here's a problem. If an attacker knows the hash function, she can produce many strings that will give the same number in return.

I may be misunderstanding you, but isn't the point of a (good) cryptographic hash function that you cannot produce the multiple plaintext which will give the same value, despite knowing the hash function?

Re:SipHash and HalfSipHash Added to Linux Kernel by majke on Tuesday January 10, 2017 @08:34AM (#13364618)
In practice you take X lower bits of the hash value. For example 10 bits if the hash table size is 1024. It's trivial to find many input stings which hash(string) % 1024 == fixed value, for any, even best cryptographic hash function.
Re:SipHash and HalfSipHash Added to Linux Kernel by koolba on Tuesday January 10, 2017 @08:59AM (#13364723)
> Siphash is an attempt to solve the problem. It is more than a hash function - it's a crypto PRF function and that gives you more guarantees than dumb hash function. Most importantly it takes two values: a "string to hash" and a "crypto key": siphash(string, crypto_key) --> number.

That sounds suspiciously like an HMAC.

Re:SipHash and HalfSipHash Added to Linux Kernel by Arnt on Tuesday January 10, 2017 @09:23AM (#13364901)
The difference is in the detail.

An HMAC gives you something very nice, but it's of its choosing. If you want a 256-entry cache, the security properties of a 256-bit HMAC result is not a good fit for the needs of a cache key.

If you want an infinitely big cache, an HMAC gives you zero collisions, but in this case what you want is an 8-bit result that spreads nicely over the 256 values, doesn't let an attacker fill one bucket, and doesn't let an attacker learn anything about the other users and their cache entries.

Re:SipHash and HalfSipHash Added to Linux Kernel by koolba on Tuesday January 10, 2017 @09:36AM (#13365025)
It still sounds like an HMAC albeit with a 64-bit output rather than a larger (say 256-bit) output.

From reading up on it a bit more, it is an MAC[1]. The difference between it and a generic HMAC construction (say with HMAC-SHA256) is that it's intended to specifically be an MAC which leads to more efficiency.

> An HMAC gives you something very nice, but it's of its choosing. If you want a 256-entry cache, the security properties of a 256-bit HMAC result is not a good fit for the needs of a cache key.

It'd be a fine fit from a cryptographic perspective. It's just slow relative to something like this which more catered to the specific problem.

> If you want an infinitely big cache, an HMAC gives you zero collisions, but in this case what you want is an 8-bit result that spreads nicely over the 256 values, doesn't let an attacker fill one bucket, and doesn't let an attacker learn anything about the other users and their cache entries.

The result of SipHash is 8-bytes (not bits). You'd still have to truncate or consolidate the bits to reduce it to 1-byte (8-bits).

[1]: https://en.wikipedia.org/wiki/SipHash

Re:SipHash and HalfSipHash Added to Linux Kernel by eternalban on Tuesday January 10, 2017 @09:34AM (#13365009)
> 8-bit result that spreads nicely over the 256 values, doesn't let an attacker fill one bucket, and doesn't let an attacker learn anything about the other users and their cache entries.

Willing to be educated, but won't I get that by just masking off 8 bits off of say SHA-x?

[edit: h(s + secret-bits) & 0xff ]

Re:SipHash and HalfSipHash Added to Linux Kernel by dchest on Tuesday January 10, 2017 @04:57PM (#13369499)
Chopped HMAC-SHA will have similar properties to SipHash, however it is a lot slower.
Re:SipHash and HalfSipHash Added to Linux Kernel by eternalban on Tuesday January 10, 2017 @06:19PM (#13370200)
Good to know. Is that a general statement or only true for specific subset of languages? Blake2B, for example, is demonstrably faster than MD5 in C, etc., but just barely faster than SHA-1 on the JVM.
Re:SipHash and HalfSipHash Added to Linux Kernel by dchest on Tuesday January 10, 2017 @06:27PM (#13370272)
All collision-resistant secure cryptographic hash functions (whew) should have this property (BLAKE2, SHA-3, Skein, etc.) (Note: those vulnerable to length extension — e.g. SHA-1, SHA-2 — should be used in HMAC construction for keying.)

BLAKE2 is fast for many use cases, but its block size is 64 (for BLAKE2s) and 128 (for BLAKEb) bytes, so hashing anything shorter than the block size will take the same time as hashing the full block. SipHash was designed for fast hashing of short inputs (its block size is 8 bytes), which is why it's good for hash tables and similar uses.

As for performance in different languages: SipHash is pretty fast in any language that has native 64-bit integers, but is not so fast in those which don't (JavaScript). The same applies to BLAKE2b (but not BLAKE2s).

BLAKE2 is slower in Java than MD5 probably because it doesn't use SIMD instructions there, which give a good boost for it (as designed).

Re:SipHash and HalfSipHash Added to Linux Kernel by eternalban on Tuesday January 10, 2017 @06:39PM (#13370349)
Great stuff, thanks. (Just realized who you are! Like your Go work.)

Not sure about the SIMD angle & Java. Ref. impl. of Blake2B [in C] doesn't use it [last I looked at it]. I ~think it has to do with the endian bias of the algo.

Re:SipHash and HalfSipHash Added to Linux Kernel by dchest on Tuesday January 10, 2017 @07:30PM (#13370695)
(Thanks!:)

There are a few optimized implementation in the BLAKE2 code package — https://github.com/BLAKE2/BLAKE2. "Ref" indeed doesn't use SIMD, but other implementations do use them. I think the claim that it's faster than MD5 is based on benchmarking SIMD implementations, and if I remember correctly, the reference one is a bit slower.

Yes, endianness conversion — that is, just reading uint64 or uint32 from byte arrays — if done in the most simple way by bit shifting can be a factor. Another factor that influenced performance of pure Go implementation (should be similar to Java) is bounds checking.

Re:SipHash and HalfSipHash Added to Linux Kernel by eternalban on Tuesday January 10, 2017 @08:07PM (#13370897)
"BLAKE2 comes in two main flavors: BLAKE2b is optimized for 64-bit platforms, and BLAKE2s for smaller architectures. On 64-bit platforms, BLAKE2 is often faster than MD5, yet provides security similar to that of SHA-3. We specify parallel versions BLAKE2bp and BLAKE2sp that are up to 4 and 8 times faster, by taking advantage of SIMD and/or multiple cores."

Well, it's supposed to beat MD5 straight up. Granted the claim is a bit hedged.

> if done in the most simple way by bit shifting can be a factor

Do you mean using byte swap instructions or is there an algorithm that I should know about? :)

Re:SipHash and HalfSipHash Added to Linux Kernel by dchest on Tuesday January 10, 2017 @09:21PM (#13371235)
Parallel versions of BLAKE2 are indeed even faster, but optimized implementations of non-parallel BLAKE2s and BLAKE2b also use SIMD instructions in compression function (e.g. https://github.com/BLAKE2/BLAKE2/blob/master/sse/blake2b-rou...).

* * *

Not byte swapping, just simple reading bytes and shifting them into the correct position in uint32 like this:

   uint32 result = (b[3] << 24) | (b[2] << 16)  | (b[1] <<  8) | b[0];
Which is slower than

   uint32 result = *b;
or if LE is not native:

   uint32 result = swap(*b);
Re:SipHash and HalfSipHash Added to Linux Kernel by eternalban on Wednesday January 11, 2017 @09:06AM (#13373910)
> optimized implementations of non-parallel BLAKE2s and BLAKE2b also use SIMD

Sure, have seen those. No biggie, but my point was that vanila B2b (on C) is already neck and neck with MD5.

> uint32 result = (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | b[0];

Yep, akaik that's all you can do on the JVM & of course for 64bit it's even more work. I thought you meant some sort of magic number bit wizzardry :)

Re:SipHash and HalfSipHash Added to Linux Kernel by Arnt on Tuesday January 10, 2017 @12:55PM (#13367034)
People do that. I've done it myself. But all the math about SHA's security properties is about absence of collisions in the full result, not about relative frequency in a small part of the result.

Maybe SHA-8 works fine. I don't know. I've never seen any real mathematical investigation of that, and that's the point.

Re:SipHash and HalfSipHash Added to Linux Kernel by dchest on Tuesday January 10, 2017 @04:59PM (#13369527)
A secure cryptographic hash function's collision resistance should be MIN(output_length/2, claimed_security). For example, SHA-256 collision security is 128 bits with 256-bit output, but if you truncate output to 128 bits, collision resistance will be 64 bits.
Re:SipHash and HalfSipHash Added to Linux Kernel by eternalban on Tuesday January 10, 2017 @01:02PM (#13367131)
Isn't a secure hash supposed to have bit independence?
Re:SipHash and HalfSipHash Added to Linux Kernel by nialo on Tuesday January 10, 2017 @11:20AM (#13365954)
it is a lot like an HMAC. The advantage of something like SipHash is just that it's faster for the same security, not that it's fundamentally different from HMAC.
Re:SipHash and HalfSipHash Added to Linux Kernel by grey-area on Tuesday January 10, 2017 @06:10AM (#13364050)
I've been looking at using this recently, and had a stupid question about using it -

Is it ok to use the same random key with siphash for lots of different hashes as long as the key is secret and mutates once per launch (i.e. generating once on app startup and use it for all hashes)?

Re:SipHash and HalfSipHash Added to Linux Kernel by wolf550e on Tuesday January 10, 2017 @06:52AM (#13364195)
The danger in your scheme is that an attacker who finds a way to see lots of keyed hash values in one hash table can flood a different hash table. You should keep a 16 byte key per hash table.
Re:SipHash and HalfSipHash Added to Linux Kernel by grey-area on Tuesday January 10, 2017 @07:31AM (#13364343)
Thanks, I'll only have one set of hashes. My question was really is it ok to use one key per table of hashes, or does it have to be one key per hash. I think you're saying one per table is fine, but wanted to be sure I wasn't doing it wrong. I'll have another look for examples.
Re:SipHash and HalfSipHash Added to Linux Kernel by wolf550e on Tuesday January 10, 2017 @09:15AM (#13364847)
It's one key per table.
Re:SipHash and HalfSipHash Added to Linux Kernel by grey-area on Tuesday January 10, 2017 @05:01PM (#13369543)
Thanks
Re:SipHash and HalfSipHash Added to Linux Kernel by semi-extrinsic on Tuesday January 10, 2017 @03:01AM (#13363425)
ELI5 (distilled from wikipedia page linked by GP, forgive me any errors):

Web servers use hash tables for storing per-request data. If an attacker knows the hash function (say, SHA1), they can create a few hundred requests that yield the same hash, giving hundreds of hash collisions and creating a Denial-of-Service attack with the same effect as millions of ordinary requests. It's a form of DoS amplification.

A keyed hash function fixes this by keeping part of the hash algorithm (the key) secret. You can turn e.g. SHA1 into a keyed hash function by e.g. HMAC, but that's computationally expensive. SipHash, being a "natively keyed" hash function, is much faster.

Re:SipHash and HalfSipHash Added to Linux Kernel by daveguy on Tuesday January 10, 2017 @09:26AM (#13364934)
Except if the hash is SHA1 (or any other non-compromised cryptographic hash) they would have a very difficult time creating requests that yield the same hash, that aren't the same request, right?
Re:SipHash and HalfSipHash Added to Linux Kernel by semi-extrinsic on Tuesday January 10, 2017 @10:38AM (#13365558)
I'm not sure, but I think if you're just interested in creating N collisions, as opposed to finding something that collides with given plaintext X, that the birthday paradox gives you a huge performance increase and makes it feasible. Also, I think many still use MD5 in applications where SipHash is intended (at least the Linux kernel does).