Skip to content

Commit

Permalink
add rainbow/rainstorm hashes
Browse files Browse the repository at this point in the history
  • Loading branch information
rurban committed Dec 14, 2024
1 parent 908b94f commit ac02c8a
Show file tree
Hide file tree
Showing 9 changed files with 549 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -744,6 +744,8 @@ add_library(
crc64.c
crcspeed.c
crccombine.c
rainbow_test.cpp
rainstorm_test.cpp
)

add_executable(SMHasher main.cpp)
Expand Down
6 changes: 6 additions & 0 deletions Hashes.h
Original file line number Diff line number Diff line change
Expand Up @@ -1424,3 +1424,9 @@ extern "C" void crc64_jones_test2(const void *input, int len, uint32_t seed, voi
extern "C" void crc64_jones_test3(const void *input, int len, uint32_t seed, void *out);
extern "C" void crc64_jones_default(const void *input, int len, uint32_t seed, void *out);

void rainbow64_test (const void *key, int len, uint32_t seed, void *out);
void rainbow128_test (const void *key, int len, uint32_t seed, void *out);
void rainbow256_test (const void *key, int len, uint32_t seed, void *out);
void rainstorm64_test (const void *key, int len, uint32_t seed, void *out);
void rainstorm128_test (const void *key, int len, uint32_t seed, void *out);
void rainstorm256_test (const void *key, int len, uint32_t seed, void *out);
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,12 @@ SMhasher
| [komihash](doc/komihash.txt) | 12179.74 | 33.23 | 224.80 (2) |1323 | |
| [polymur](doc/polymur.txt) | 9913.53 | 41.68 | 232.56 (3) |1128 | |
| [gxhash64](doc/gxhash64.txt) | 48919.73 | 36.61 | 236.98 (3) | | AES only |
w| [rainbow](doc/rainbow.txt) | 48919.73 | 36.61 | 236.98 (3) | | |
| [rainbow128](doc/rainbow128.txt) | 48919.73 | 36.61 | 236.98 (3) | | |
| [rainbow256](doc/rainbow256.txt) | 48919.73 | 36.61 | 236.98 (3) | | |
| [rainstorm](doc/rainstorm.txt) | 48919.73 | 36.61 | 236.98 (3) | | |
| [rainstorm128](doc/rainstorm128.txt) | 48919.73 | 36.61 | 236.98 (3) | | |
| [rainstorm256](doc/rainstorm256.txt) | 48919.73 | 36.61 | 236.98 (3) | | |

The sortable table variants:

Expand All @@ -236,6 +242,7 @@ The sortable table variants:
* [fast AMD EPYC 9554P 64-Core Processor (Server from 2024)](https://rurban.github.io/smhasher/doc/epyc.html)
* [Intel i5-2300 2.8GHz](https://rurban.github.io/smhasher/doc/intel.html)
* [AMD Ryzen 5 PRO 3350G 3.6GHz 32bit 32bit](https://rurban.github.io/smhasher/doc/i686.html)
* [AMD Ryzen 3 3200U 3.5GHz](https://rurban.github.io/smhasher/doc/ryzen3.html)
* [Mac Air i7-4650](https://rurban.github.io/smhasher/doc/air.html)
* [Cortex-A53 2GHz (Sony XPeria L4)](https://rurban.github.io/smhasher/doc/phone.html)

Expand Down
24 changes: 24 additions & 0 deletions doc/ryzen3.html
Original file line number Diff line number Diff line change
Expand Up @@ -1823,6 +1823,30 @@ <h1 id="smhasher">SMhasher</h1>
<td align="right"></td>
<td align="left"></td>
</tr>
<tr class="good">
<td align="left"><a href="rainbow.txt">rainbow</a></td>
<td align="right">1017.15</td>
<td align="right">178.25</td>
<td align="right">313.64 (9)</td>
<td align="right"></td>
<td align="left"></td>
</tr>
<tr class="good">
<td align="left"><a href="rainbow128.txt">rainbow128</a></td>
<td align="right">1017.15</td>
<td align="right">178.25</td>
<td align="right">313.64 (9)</td>
<td align="right"></td>
<td align="left"></td>
</tr>
<tr class="good">
<td align="left"><a href="rainbow256.txt">rainbow256</a></td>
<td align="right">1017.15</td>
<td align="right">178.25</td>
<td align="right">313.64 (9)</td>
<td align="right"></td>
<td align="left"></td>
</tr>
</tbody>
</table>

Expand Down
6 changes: 6 additions & 0 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -779,6 +779,12 @@ HashInfo g_hashes[] =
#endif
{ komihash_test, 64, 0x8157FF6D, "komihash", "komihash 5.10", GOOD, {} },
{ polymur_test, 64, 0x4F894810, "polymur", "github.com/orlp/polymur-hash v1, __SIZEOF_INT128__:" MACRO_ITOA(__SIZEOF_INT128__), GOOD, {} },
{ rainbow64_test, 64, 0x2972C52E, "rainbow", "Rainbow 64-bit v1.0.6 (aka Newhash 128-bit)", GOOD, {} },
{ rainbow128_test, 128, 0xFD9BCADD, "rainbow-128", "Rainbow 128-bit v1.0.6 (aka Newhash 128-bit)", GOOD, {} },
{ rainbow256_test, 256, 0xB327563D, "rainbow-256", "Rainbow 256-bit v1.0.6 (aka Newhash 256-bit)", GOOD, {} },
{ rainstorm64_test, 64, 0xC8DB71D5, "rainstorm", "Rainstorm 64-bit v0.0.6", GOOD, {} },
{ rainstorm128_test, 128, 0x17E0FC1B, "rainstorm-128", "Rainstorm 128-bit v0.0.6", GOOD, {} },
{ rainstorm256_test, 256, 0x8BDBF180, "rainstorm-256", "Rainstorm 256-bit v0.0.6", GOOD, {} },
};

HashInfo * findHash ( const char * name )
Expand Down
214 changes: 214 additions & 0 deletions rainbow.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
/*
* Rainbow hash function - 256-bit internal state, 128-bit input chunks, up to 256-bit output
* Stream based
* Can also be utilized as an eXtensible Output Function (XOF).
*
* Copyright (C) 2023 Cris Stringfellow (and DOSYAGO)
*
* Rainstorm hash is licensed under Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "Platform.h"
#ifdef smhasher3
#include "Hashlib.h"
#endif

// P to W are primes chosen for their excellent avalanche properties
static const uint64_t P = UINT64_C( 0xFFFFFFFFFFFFFFFF) - 58;
static const uint64_t Q = UINT64_C(13166748625691186689);
static const uint64_t R = UINT64_C( 1573836600196043749);
static const uint64_t S = UINT64_C( 1478582680485693857);
static const uint64_t T = UINT64_C( 1584163446043636637);
static const uint64_t U = UINT64_C( 1358537349836140151);
static const uint64_t V = UINT64_C( 2849285319520710901);
static const uint64_t W = UINT64_C( 2366157163652459183);

static inline void mixA( uint64_t * s ) {
uint64_t a = s[0], b = s[1], c = s[2], d = s[3];

a *= P;
a = ROTR64(a, 23);
a *= Q;

b ^= a;

b *= R;
b = ROTR64(b, 29);
b *= S;

c *= T;
c = ROTR64(c, 31);
c *= U;

d ^= c;

d *= V;
d = ROTR64(d, 37);
d *= W;

s[0] = a; s[1] = b; s[2] = c; s[3] = d;
}

static inline void mixB( uint64_t * s, uint64_t iv ) {
uint64_t a = s[1], b = s[2];

a *= V;
a = ROTR64(a, 23);
a *= W;

b ^= a + iv;

b *= R;
b = ROTR64(b, 23);
b *= S;

s[1] = a; s[2] = b;
}

template <uint32_t hashsize>
static void rainbow( const void * in, const size_t olen, const seed_t seed, void * out ) {
const uint8_t * data = (const uint8_t *)in;
uint64_t h[4] = { seed + olen + 1, seed + olen + 3, seed + olen + 5, seed + olen + 7 };
size_t len = olen;
uint64_t g = 0;
bool inner = 0;

while (len >= 16) {
g = GET_U64(data, 0);

h[0] -= g;
h[1] += g;

data += 8;

g = GET_U64(data, 0);

h[2] += g;
h[3] -= g;

if (inner) {
mixB(h, seed);
} else {
mixA(h);
}
inner ^= 1;

data += 8;
len -= 16;
}

mixB(h, seed);

switch (len) {
case 15: h[0] += (uint64_t)data[14] << 56; // FALLTHROUGH
case 14: h[1] += (uint64_t)data[13] << 48; // FALLTHROUGH
case 13: h[2] += (uint64_t)data[12] << 40; // FALLTHROUGH
case 12: h[3] += (uint64_t)data[11] << 32; // FALLTHROUGH
case 11: h[0] += (uint64_t)data[10] << 24; // FALLTHROUGH
case 10: h[1] += (uint64_t)data[ 9] << 16; // FALLTHROUGH
case 9: h[2] += (uint64_t)data[ 8] << 8; // FALLTHROUGH
case 8: h[3] += data[ 7]; // FALLTHROUGH
case 7: h[0] += (uint64_t)data[ 6] << 48; // FALLTHROUGH
case 6: h[1] += (uint64_t)data[ 5] << 40; // FALLTHROUGH
case 5: h[2] += (uint64_t)data[ 4] << 32; // FALLTHROUGH
case 4: h[3] += (uint64_t)data[ 3] << 24; // FALLTHROUGH
case 3: h[0] += (uint64_t)data[ 2] << 16; // FALLTHROUGH
case 2: h[1] += (uint64_t)data[ 1] << 8; // FALLTHROUGH
case 1: h[2] += (uint64_t)data[ 0];
}

mixA(h);
mixB(h, seed);
mixA(h);

g = 0;
g -= h[2];
g -= h[3];

PUT_U64(g, (uint8_t *)out, 0);
if (hashsize == 128) {
mixA(h);
g = 0;
g -= h[3];
g -= h[2];
PUT_U64(g, (uint8_t *)out, 8);
} else if (hashsize == 256) {
mixA(h);
g = 0;
g -= h[3];
g -= h[2];
PUT_U64(g, (uint8_t *)out, 8);
mixA(h);
mixB(h, seed);
mixA(h);
g = 0;
g -= h[3];
g -= h[2];
PUT_U64(g, (uint8_t *)out, 16);
mixA(h);
g = 0;
g -= h[3];
g -= h[2];
PUT_U64(g, (uint8_t *)out, 24);
}
}

#ifdef smhasher3
REGISTER_FAMILY(rainbow,
$.src_url = "https://github.com/dosyago/rain",
$.src_status = HashFamilyInfo::SRC_STABLEISH
);

REGISTER_HASH(rainbow,
$.desc = "Rainbow v1.0.6 (aka Newhash)",
$.hash_flags = 0,
$.impl_flags =
FLAG_IMPL_MULTIPLY_64_64 |
FLAG_IMPL_ROTATE |
FLAG_IMPL_LICENSE_APACHE2,
$.bits = 64,
$.verification_LE = 0x2972C52E,
$.verification_BE = 0x217A79E2,
$.hashfn_native = rainbow<64, false>,
$.hashfn_bswap = rainbow<64, true>
);

REGISTER_HASH(rainbow_128,
$.desc = "Rainbow 128-bit v1.0.6 (aka Newhash 128-bit)",
$.hash_flags = 0,
$.impl_flags =
FLAG_IMPL_MULTIPLY_64_64 |
FLAG_IMPL_ROTATE |
FLAG_IMPL_LICENSE_APACHE2,
$.bits = 128,
$.verification_LE = 0xFD9BCADD,
$.verification_BE = 0xAF215EDF,
$.hashfn_native = rainbow<128, false>,
$.hashfn_bswap = rainbow<128, true>
);

REGISTER_HASH(rainbow_256,
$.desc = "Rainbow 256-bit v1.0.6 (aka Newhash 256-bit)",
$.hash_flags = 0,
$.impl_flags =
FLAG_IMPL_MULTIPLY_64_64 |
FLAG_IMPL_ROTATE |
FLAG_IMPL_LICENSE_APACHE2,
$.bits = 256,
$.verification_LE = 0xB327563D,
$.verification_BE = 0x10C46364,
$.hashfn_native = rainbow<256, false>,
$.hashfn_bswap = rainbow<256, true>
);
#endif
46 changes: 46 additions & 0 deletions rainbow_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#include <string.h>
#include <stdint.h>
typedef uint32_t seed_t;

static inline uint64_t GET_U64(const uint8_t* data, size_t index) {
uint64_t result;
memcpy(&result, data + index, sizeof(result));
#ifdef BIG_ENDIAN
result = ((result & 0x00000000000000FF) << 56) |
((result & 0x000000000000FF00) << 40) |
((result & 0x0000000000FF0000) << 24) |
((result & 0x00000000FF000000) << 8) |
((result & 0x000000FF00000000) >> 8) |
((result & 0x0000FF0000000000) >> 24) |
((result & 0x00FF000000000000) >> 40) |
((result & 0xFF00000000000000) >> 56);
#endif
return result;
}

static inline void PUT_U64(uint64_t value, uint8_t* data, size_t index) {
#ifdef BIG_ENDIAN
value = ((value & 0x00000000000000FF) << 56) |
((value & 0x000000000000FF00) << 40) |
((value & 0x0000000000FF0000) << 24) |
((value & 0x00000000FF000000) << 8) |
((value & 0x000000FF00000000) >> 8) |
((value & 0x0000FF0000000000) >> 24) |
((value & 0x00FF000000000000) >> 40) |
((value & 0xFF00000000000000) >> 56);
#endif
memcpy(data + index, &value, sizeof(value));
}

#include "rainbow.hpp"

//objsize:
void rainbow64_test ( const void *key, int len, uint32_t seed, void *out) {
rainbow<64>;
}
void rainbow128_test ( const void *key, int len, uint32_t seed, void *out) {
rainbow<128>;
}
void rainbow256_test ( const void *key, int len, uint32_t seed, void *out) {
rainbow<256>;
}
Loading

0 comments on commit ac02c8a

Please sign in to comment.