This repository houses the Rainbow and Rainstorm hash functions, developed by Cris at DOSYAGO and licensed under Apache-2.0. The 64-bit variants have passed all tests in the SMHasher3 suite. Results can be found in the results/
subdirectory.
The code contains a reference implementation in C++, a port to WASM, and a Makefile for building everything.
Algorithm | Speed | Hash Size | Purpose | Core Mixing Function | Security |
---|---|---|---|---|---|
Rainbow | 5.79 GiB/sec | 64 to 256 bits | General-purpose non-cryptographic hashing | Multiplication, subtraction/addition, rotation, XOR | Not designed for cryptographic security |
Rainstorm | 1.91 GiB/sec (at 4 rounds, tuneable) | 64 to 512 bits | Potential cryptographic hashing | Addition/subtraction, rotation, XOR | No formal security analysis yet |
JavaScript channel:
- As a Node.JS library, via:
npm i @dosyago/rainsum@latest
Then you can use as:
import {rainbowHash, rainstormHash} from '@dosyago/rainsum';
const seed = 0x0;
const hash = await rainbowHash(256, seed, 'Hello there!');
const intendedCryptoHash = await rainstormHash(512, seed, Buffer.from('Hello there!'));
- As a NPM global binary, via:
npm i -g @dosyago/rainsum@latest
jsrsum --help
Native channel:
First, make everything:
make clean && make
sudo make install # if you wish
Then you can use either:
-
As object code, or a C library or by using the C++ files in
./src/
, specifically importing "tool.h" and using "rainsum.cpp" -
As a command line tool:
rainsum file.txt
# will output a hash using the default values: Algorithm: rainbow, Hash size in bits: 256
# see --help for other arguments
rainsum --help
Usage: rainsum [OPTIONS] [INFILE]
Calculate a Rainbow or Rainstorm hash.
Options:
-m, --mode [digest|stream] Specifies the mode, where:
digest mode (the default) gives a fixed length hash in hex, or
stream mode gives a variable length binary feedback output
-a, --algorithm [bow|storm] Specify the hash algorithm to use. Default: storm
-s, --size [64-256|64-512] Specify the bit size of the hash. Default: 256
-o, --output-file FILE Output file for the hash or stream
-t, --test-vectors Calculate the hash of the standard test vectors
-l, --output-length HASHES Set the output length in hash iterations (stream only)
-v, --version Print out the version
--seed Seed value (64-bit number or string). If string is used,
it is hashed with Rainstorm to a 64-bit number
Note: The jsrsum
NPM binary (which uses wasm, and is installable via npm i -g @dosyago/rainsum
) offers the same API and command-line options as the native C++ binary, but is slower.
This repository produces:
- rainsum CLI tool and rainstorm.o and rainbow.o object files
- wasm binary
- JavaScript CLI tool (API compat with C++ binary, but slower)
- NPM package with
jsrsum
global (the JavaScript CLI tool), plus an importable ES Module library exportingasync rainbowHash(hashSize, seed, input)
andasync rainstormHash(hashSize, seed, input)
functions taking inputs asstring
orBuffer
, backed by the wasm binary. - A collection of scripts:
./scripts/bench.mjs
: benchmark the speed between the JS WASM and C++ implementations./scripts/verify.mjs
: verify the correctness of the implementations- And other scripts.
Build with make:
make clean && make
Optionall to install rainsum into an executable path location, run:
make install
which may require sudo
privileges.
Rain hash functions C++ vs Node/WASM benchmark:
Test Input & Size (bytes) Run C++ Version WASM Version Fastest
input1 (10 bytes) 1 7,310,292 ns 122,337,000 ns 16.00x (C++ wins!)
input2 (100 bytes) 1 5,250,875 ns 113,674,500 ns 21.00x (C++ wins!)
input3 (1,000 bytes) 1 5,341,625 ns 112,402,958 ns 21.00x (C++ wins!)
input4 (10,000 bytes) 1 4,912,209 ns 113,795,750 ns 23.00x (C++ wins!)
input5 (100,000 bytes) 1 5,247,208 ns 112,086,708 ns 21.00x (C++ wins!)
input6 (1,000,000 bytes) 1 5,717,125 ns 112,697,792 ns 19.00x (C++ wins!)
input7 (10,000,000 bytes) 1 10,700,834 ns 119,352,417 ns 11.00x (C++ wins!)
input8 (100,000,000 bytes) 1 52,803,417 ns 191,939,500 ns 3.00x (C++ wins!)
input1 (10 bytes) 2 3,671,250 ns 107,211,375 ns 29.00x (C++ wins!)
input2 (100 bytes) 2 5,072,792 ns 112,407,625 ns 22.00x (C++ wins!)
input3 (1,000 bytes) 2 4,668,833 ns 111,602,583 ns 23.00x (C++ wins!)
input4 (10,000 bytes) 2 4,660,792 ns 112,008,292 ns 24.00x (C++ wins!)
input5 (100,000 bytes) 2 4,675,875 ns 112,914,708 ns 24.00x (C++ wins!)
input6 (1,000,000 bytes) 2 5,334,500 ns 114,160,917 ns 21.00x (C++ wins!)
input7 (10,000,000 bytes) 2 11,232,792 ns 119,210,000 ns 10.00x (C++ wins!)
input8 (100,000,000 bytes) 2 52,097,042 ns 181,990,375 ns 3.00x (C++ wins!)
input1 (10 bytes) 3 3,726,791 ns 106,394,125 ns 28.00x (C++ wins!)
input2 (100 bytes) 3 4,990,500 ns 113,719,291 ns 22.00x (C++ wins!)
input3 (1,000 bytes) 3 4,882,792 ns 113,991,917 ns 23.00x (C++ wins!)
input4 (10,000 bytes) 3 5,054,458 ns 112,881,500 ns 22.00x (C++ wins!)
input5 (100,000 bytes) 3 5,180,958 ns 112,406,250 ns 21.00x (C++ wins!)
input6 (1,000,000 bytes) 3 5,779,833 ns 113,486,834 ns 19.00x (C++ wins!)
input7 (10,000,000 bytes) 3 10,747,875 ns 119,093,209 ns 11.00x (C++ wins!)
input8 (100,000,000 bytes) 3 52,637,666 ns 170,915,917 ns 3.00x (C++ wins!)
.
|-- LICENSE.txt
|-- Makefile
|-- PAPER.md
|-- README.md
|-- docs
| |-- app.js
| |-- index.html
| |-- rain.cjs
| `-- rain.wasm
|-- js
| |-- lib
| | `-- api.mjs
| |-- package-lock.json
| |-- package.json
| |-- rainsum.mjs
| |-- test.mjs
| `-- wasm
| |-- rain.cjs
| `-- rain.wasm
|-- rain
| |-- bin
| | `-- rainsum
| `-- obj
| |-- rainbow.d
| |-- rainbow.o
| |-- rainstorm.d
| |-- rainstorm.o
| |-- rainsum.d
| `-- rainsum.o
|-- rainsum -> rain/bin/rainsum
|-- results
| |-- dieharder
| | |-- README.md
| | |-- rainbow-256.txt
| | |-- rainbow-64-infinite.txt
| | |-- rainstorm-256.txt
| | `-- rainstorm-64-infinite.txt
| `-- smhasher3
| |-- rainbow-128.txt
| |-- rainbow-256.txt
| |-- rainbow.txt
| |-- rainstorm-128.txt
| |-- rainstorm-256.txt
| `-- rainstorm.txt
|-- scripts
| |-- 1srain.sh
| |-- bench.mjs
| |-- blockchain.sh
| |-- build.sh
| |-- chain.mjs
| |-- debug.sh
| |-- package-lock.json
| |-- package.json
| |-- testjs.sh
| |-- vectors.sh
| `-- verify.sh
|-- src
| |-- common.h
| |-- cxxopts.hpp
| |-- rainbow.cpp
| |-- rainstorm.cpp
| |-- rainsum.cpp
| `-- tool.h
`-- verification
`-- vectors.txt
14 directories, 52 files
Rainbow is a fast hash function. It's intended for general-purpose, non-cryptographic hashing. The core mixing function utilizes multiplication, subtraction/addition, rotation, and XOR.
Rainstorm is a slower hash function with a tunable-round feature. It's designed with cryptographic hashing in mind, but it hasn't been formally analyzed for security, so we provide no guarantees. The core mixing function uses addition/subtraction, rotation, and XOR.
Rainstorm's round number is adjustable, potentially offering additional security. However, please note that this is hypothetical until rigorous security analysis is completed.
While Rainstorm's design reflects cryptographic hashing principles, it has not been formally analyzed and thus, cannot be considered 'secure.' We strongly encourage those interested to conduct an analysis and offer feedback.
Great! I see that the program rainsum.cpp
is for calculating a Rainbow or Rainstorm hash. The software can operate in two modes, "digest" or "stream", which affects how it outputs the hash. It also allows the user to select different hash algorithms and sizes, specify the input and output files, use predefined test vectors, and set the output length in hashes.
The fundamental concept for the mixing functions derived from Discohash, but has been significantly developed and extended. The overall architecture and processing flow of the hash were inspired by existing hash functions.
This repository and content is licensed under Apache-2.0 unless otherwise noted. It's copyright © Cris and The Dosyago Corporation 2023. All rights reserved.
Rainsum is a powerful command-line utility for calculating Rainbow or Rainstorm hashes of input data. This tool can operate in two modes: "digest" or "stream". In "digest" mode, Rainsum outputs a fixed-length hash in hex, while in "stream" mode it produces variable-length binary output.
Rainsum also offers multiple hashing algorithms, sizes, and various configurable options to cater to a wide range of use cases.
There is also a JavaScript WASM version, consistent with the C++ version, and 8 - 16 times slower on small and medium inputs (100 bytes to 10MiB), and 2 - 3 times slower on large inputs (100MiB and up), at js/rainsum.mjs
. This JavaScript version of rainsum can be used mostly like the C++ version, so the below guide and instrutions suffice essentially for both.
The basic command structure of Rainsum is as follows:
rainsum [OPTIONS] [INFILE]
Here, [OPTIONS]
is a list of options that modify the behavior of Rainsum and [INFILE]
is the input file to hash. If no file is specified, Rainsum reads from standard input.
Here are the options that you can use with Rainsum:
-m, --mode [digest|stream]
: Specifies the mode. Default isdigest
.-a, --algorithm [bow|storm]
: Specify the hash algorithm to use. Default isstorm
.-s, --size [64-256|64-512]
: Specify the bit size of the hash. Default is256
.-o, --output-file FILE
: Specifies the output file for the hash or stream.-t, --test-vectors
: Calculates the hash of the standard test vectors.-l, --output-length HASHES
: Sets the output length in hash iterations (stream only).--seed
: Seed value (64-bit number or string). If a string is used, it is hashed with Rainstorm to a 64-bit number.-h, --help
: Prints usage information.-v, --version
: Prints out the version of the software.
In digest mode, Rainsum calculates a fixed-length hash of the input data and outputs the result in hexadecimal form.
For example, to calculate a 256-bit Rainstorm hash of input.txt
and output it to output.txt
, you would use:
rainsum -m digest -a storm -s 256 -o output.txt input.txt
In stream mode, Rainsum calculates a hash of the input data and then uses that hash as input to the next iteration of the hash function, repeating this process for a specified number of iterations. The result is a stream of binary data.
For example, to generate a 512-bit Rainstorm hash stream of input.txt
for 1000000 iterations and output it to output.txt
, you would use:
rainsum -m stream -a storm -s 512 -l 1000000 -o output.txt input.txt
Rainsum supports the following hash algorithms:
bow
: Rainbow hashstorm
: Rainstorm hash
And these sizes (in bits):
- Rainbow:
64
,128
,256
- Rainstorm:
64
,128
,256
,512
Rainsum includes a set of predefined test vectors that you can use to verify the correct operation of the hash functions. To use these test vectors, include the -t
or --test-vectors
option in your command.
You can provide a seed value for the hash function using the --seed
option followed by a 64-bit number or a string. If a string is used, Rainsum will hash it with Rainstorm to generate a 64-bit number.
Use -h
or --help
to print usage information. Use -v
or --version
to print the version of the software.
Rainsum is written in C++. Make sure to have a modern C++ compiler and appropriate libraries (like filesystem, iostream, etc.) installed to compile the code. A makefile or build system setup might be required depending on your specific project configuration.
Rainsum provides a powerful and flexible command-line interface for calculating Rainbow and Rainstorm hashes. Whether you're working on a small project or a large-scale system, Rainsum offers the features and options you need to get the job done.
The hashes' stability may change over time, as we might modify constants, mixing specifics, and more as we gather insights. Should such changes alter the hashes' output, we will denote the changes with new version numbers.
The current test vectors for Rainstorm and Rainbow are:
Rainbow v1.0.4 Test Vectors
./rainsum -a bow --test-vectors
:
b735f3165b474cf1a824a63ba18c7d087353e778b6d38bd1c26f7b027c6980d9 ""
c7343ac7ee1e4990b55227b0182c41e9a6bbc295a17e2194d4e0081124657c3c "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
53efdb8f046dba30523e9004fce7d194fdf6c79a59d6e3687907652e38e53123 "The quick brown fox jumps over the lazy dog"
95a3515641473aa3726bcc5f454c658bfc9b714736f3ffa8b347807775c2078e "The quick brown fox jumps over the lazy cog"
f27c10f32ae243afea08dfb15e0c86c0b601792d1cd195ca651fe5394c56f200 "The quick brown fox jumps over the lazy dog."
e21780122142956ff99d560069a123b75d014f0b110d307d9b23d79f58ebeb29 "After the rainstorm comes the rainbow."
a46a9e5cba400ed3e1deec852fb0667e8acbbcfeb71cf0f3a1901396aaae6e19 "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
Rainstorm v0.0.5 Test Vectors
./rainsum --test-vectors
:
e3ea5f8885f7bb16468d08c578f0e7cc15febd31c27e323a79ef87c35756ce1e ""
9e07ce365903116b62ac3ac0a033167853853074313f443d5b372f0225eede50 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
f88600f4b65211a95c6817d0840e0fc2d422883ddf310f29fa8d4cbfda962626 "The quick brown fox jumps over the lazy dog"
ec05208dd1fbf47b9539a761af723612eaa810762ab7a77b715fcfb3bf44f04a "The quick brown fox jumps over the lazy cog"
822578f80d46184a674a6069486b4594053490de8ddf343cc1706418e527bec8 "The quick brown fox jumps over the lazy dog."
410427b981efa6ef884cd1f3d812c880bc7a37abc7450dd62803a4098f28d0f1 "After the rainstorm comes the rainbow."
47b5d8cb1df8d81ed23689936d2edaa7bd5c48f5bc463600a4d7a56342ac80b9 "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
You can build and install the rainsum
utility using the provided Makefile. First, clone the repository and change into the root directory of the project:
git clone https://github.com/dosyago/rain
cd rain
Then, build the utility with make:
make
If you want to install rainsum
globally, so it can be run from any directory, use the make install
command:
make install
This command might require administrator privileges, depending on your system's configuration. If you encounter a permission error, try using sudo
:
sudo make install
After installation, you can run rainsum
from any directory:
rainsum --help
See the Field Manual for more information on usage.
We warmly welcome any analysis, along with faster implementations or suggested modifications. Collaboration is highly encouraged!