pax_global_header00006660000000000000000000000064122225224440014511gustar00rootroot0000000000000052 comment=721792ff9bf301f480d4e3dae83153ac4d7e2b1c golang-nzaat-1.0/000077500000000000000000000000001222252244400137335ustar00rootroot00000000000000golang-nzaat-1.0/LICENSE000066400000000000000000000030111222252244400147330ustar00rootroot00000000000000(c) 2013, Tonnerre Lombard , Ancient Solutions. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Ancient Solutions nor the name of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. golang-nzaat-1.0/nzaat.go000066400000000000000000000104641222252244400154040ustar00rootroot00000000000000// Copyright 2013 Tonnerre Lombard // All rights reserved. // Use of this source code is governed by a BSD-style license that can // be found in the LICENSE file. // NZAAT originates from Thorsten “mirabilos” Glaser . // This file defines the NZAAT hash which is derived from Bob Jenkins’ // one at a time hash with the goals to ① not have 00000000 as result // (for speed optimisations with hash table lookups) and ② change for // every input octet, even NUL bytes – no matter what state. For con‐ // venience, NZAAT, which can have an all-zero result, for outside of // hash table lookup dereference deferral, is also provided. // // We define the following primitives (all modulo 2³²): // // OUP(s,b) → { OAV(s,b); MIX(s); } // This is the Update function of Jenkins’ one-at-a-time hash // NUP(s,b) → { NAV(s,b); MIX(s); } // This shall be the body of the for loop in the Write method // OAV(s,b) → { ADD(s,b); } // This is how the Add part of Jenkins’ one-at-a-time hash works // NAV(s,b) → { ADD(s,b+c); } – c const // This is how the Add part of Write differs – by a const // ADD(x,y) → { x += y; } // Generic addition function // MIX(s) → { s += s << 10; s ^= s >> 6; } // This is the Mix part of both Update functions (common) // FIN(s) → { s += s << 3; s ^= s >> 11; s += s << 15; result ← s; } // This is the Postprocess function for the one-at-a-time hash // NZF(s) → { MIX(s); if(!s){++s;} FIN(s); } // NZF(s) ≘ { if (!s) { s = 1; } else { NAF(s); } } // This is the Postprocess function for the new NZAT hash // NAF(s) → { MIX(s); FIN(s); } // This shall become the Postprocess function for the NZAAT hash // // This means that the difference between OAAT and NZAT is ① a factor // c (constant) that is added to the state in addition to every input // octet, ② preventing the hash result from becoming 0, by a volunta‐ // ry collision on exactly(!) one value, and ③ mixing in another zero // data octet to improve avalanche behaviour; OAAT’s avalanche bitmap // is all green except for the last (OAAT) data octet; we avoid a few // yellow-bit patterns, nothing really bad, by making that last octet // be not really the last. The impact of these changes doesn’t worsen // the hash’s properties, except for NZAT’s new collision. NZAAT does // not collide more than OAAT, so it’s better in all respects. // // First some observations on some of the above primitives, proven by // me empirically (can be proven algebraically as well): // // FIN(s) = 0 ⇐ s = 0 // Only a state of 0 yields a hash result of 0 // MIX(s) = 0 ⇐ s = 0 // When updating only the Add part (not the Mix part) determines // whether the next state is 0 // ADD(s,v) = 0 ⇐ s = 100000000h - v (mod 2³²) // For each input byte value there is exactly one previous-state // producing a 0 next-state (that being -s mod 2³² for dword in‐ // put values and, for bytes, simpler -s mod 2⁸) // ADD(s,b+c) ≠ s ⇐ b is byte, c is 1, works // Choose c arbitrarily, 1 is economical, even on e.g. ARM // // All this means we can use an IV of 0, add arbitrary octet data and // have a good result (for NZAAT) while having to provide for exactly // one 2-in-1 collision for NZAT manually. This implementation mainly // aims for economic code (small, fast, RISC CPUs notwithstanding). package nzaat import "hash" type digest uint32 // New returns a new hash.Hash32 computing the NZAAT checksum. func New() hash.Hash32 { d := new(digest) d.Reset() return d } func (d *digest) Reset() { *d = 0 } func (d *digest) Size() int { return 4 } func (d *digest) BlockSize() int { return 1 } func (d *digest) Write(p []byte) (nn int, err error) { for _, x := range p { *d += digest(x) + 1 *d += *d << 10 *d ^= *d >> 6 } return len(p), nil } // Count NILs in all parts func (d *digest) Sum32() uint32 { var sum uint32 = uint32(*d) sum += sum << 10 sum ^= sum >> 6 sum += sum << 3 sum ^= sum >> 11 sum += sum << 15 return sum } func (d *digest) Sum(in []byte) []byte { var s uint32 = d.Sum32() return append(in, byte(s>>24), byte(s>>16), byte(s>>8), byte(s)) } // Checksum returns the NZAAT checksum of data. func Checksum(data []byte) uint32 { var h hash.Hash32 = New() h.Write(data) return h.Sum32() } golang-nzaat-1.0/nzaat_test.go000066400000000000000000000023041222252244400164350ustar00rootroot00000000000000// Copyright 2013 Tonnerre Lombard // All rights reserved. // Use of this source code is governed by a BSD-style license that can // be found in the LICENSE file. package nzaat import ( "hash" "testing" ) // Test the hash of an empty string. func TestEmpty(t *testing.T) { var h hash.Hash32 = New() var res uint32 = h.Sum32() t.Logf("NZAAT(\"\") = %x\n", res) if res != 0 { t.Fail() } } // Test the hash of a string with just "a" in it. func TestStringA(t *testing.T) { var h hash.Hash32 = New() var res uint32 h.Write([]byte("a")) res = h.Sum32() t.Logf("NZAAT(\"a\") = %x\n", res) if res != 0xc31517c4 { t.Fail() } } // Test the hash of a string with "abc" in it. func TestStringABC(t *testing.T) { var h hash.Hash32 = New() var res uint32 h.Write([]byte("abc")) res = h.Sum32() t.Logf("NZAAT(\"abc\") = %x\n", res) if res != 0xC3E39E2D { t.Fail() } } // Test the hash of a string with "message digest" in it. func TestStringMessageDigest(t *testing.T) { var h hash.Hash32 = New() var res uint32 h.Write([]byte("message digest")) res = h.Sum32() t.Logf("NZAAT(\"message digest\") = %x\n", res) if res != 0x434B78B4 { t.Fail() } }