github.com/piotrnar/gocoin@v0.0.0-20240512203912-faa0448c5e96/lib/others/siphash/hash.go (about)

     1  // +build !arm,!amd64 appengine gccgo
     2  
     3  // Written in 2012 by Dmitry Chestnykh.
     4  //
     5  // To the extent possible under law, the author have dedicated all copyright
     6  // and related and neighboring rights to this software to the public domain
     7  // worldwide. This software is distributed without any warranty.
     8  // http://creativecommons.org/publicdomain/zero/1.0/
     9  
    10  package siphash
    11  
    12  // Hash returns the 64-bit SipHash-2-4 of the given byte slice with two 64-bit
    13  // parts of 128-bit key: k0 and k1.
    14  func Hash(k0, k1 uint64, p []byte) uint64 {
    15  	// Initialization.
    16  	v0 := k0 ^ 0x736f6d6570736575
    17  	v1 := k1 ^ 0x646f72616e646f6d
    18  	v2 := k0 ^ 0x6c7967656e657261
    19  	v3 := k1 ^ 0x7465646279746573
    20  	t := uint64(len(p)) << 56
    21  
    22  	// Compression.
    23  	for len(p) >= BlockSize {
    24  		m := uint64(p[0]) | uint64(p[1])<<8 | uint64(p[2])<<16 | uint64(p[3])<<24 |
    25  			uint64(p[4])<<32 | uint64(p[5])<<40 | uint64(p[6])<<48 | uint64(p[7])<<56
    26  		v3 ^= m
    27  
    28  		// Round 1.
    29  		v0 += v1
    30  		v1 = v1<<13 | v1>>(64-13)
    31  		v1 ^= v0
    32  		v0 = v0<<32 | v0>>(64-32)
    33  
    34  		v2 += v3
    35  		v3 = v3<<16 | v3>>(64-16)
    36  		v3 ^= v2
    37  
    38  		v0 += v3
    39  		v3 = v3<<21 | v3>>(64-21)
    40  		v3 ^= v0
    41  
    42  		v2 += v1
    43  		v1 = v1<<17 | v1>>(64-17)
    44  		v1 ^= v2
    45  		v2 = v2<<32 | v2>>(64-32)
    46  
    47  		// Round 2.
    48  		v0 += v1
    49  		v1 = v1<<13 | v1>>(64-13)
    50  		v1 ^= v0
    51  		v0 = v0<<32 | v0>>(64-32)
    52  
    53  		v2 += v3
    54  		v3 = v3<<16 | v3>>(64-16)
    55  		v3 ^= v2
    56  
    57  		v0 += v3
    58  		v3 = v3<<21 | v3>>(64-21)
    59  		v3 ^= v0
    60  
    61  		v2 += v1
    62  		v1 = v1<<17 | v1>>(64-17)
    63  		v1 ^= v2
    64  		v2 = v2<<32 | v2>>(64-32)
    65  
    66  		v0 ^= m
    67  		p = p[BlockSize:]
    68  	}
    69  
    70  	// Compress last block.
    71  	switch len(p) {
    72  	case 7:
    73  		t |= uint64(p[6]) << 48
    74  		fallthrough
    75  	case 6:
    76  		t |= uint64(p[5]) << 40
    77  		fallthrough
    78  	case 5:
    79  		t |= uint64(p[4]) << 32
    80  		fallthrough
    81  	case 4:
    82  		t |= uint64(p[3]) << 24
    83  		fallthrough
    84  	case 3:
    85  		t |= uint64(p[2]) << 16
    86  		fallthrough
    87  	case 2:
    88  		t |= uint64(p[1]) << 8
    89  		fallthrough
    90  	case 1:
    91  		t |= uint64(p[0])
    92  	}
    93  
    94  	v3 ^= t
    95  
    96  	// Round 1.
    97  	v0 += v1
    98  	v1 = v1<<13 | v1>>(64-13)
    99  	v1 ^= v0
   100  	v0 = v0<<32 | v0>>(64-32)
   101  
   102  	v2 += v3
   103  	v3 = v3<<16 | v3>>(64-16)
   104  	v3 ^= v2
   105  
   106  	v0 += v3
   107  	v3 = v3<<21 | v3>>(64-21)
   108  	v3 ^= v0
   109  
   110  	v2 += v1
   111  	v1 = v1<<17 | v1>>(64-17)
   112  	v1 ^= v2
   113  	v2 = v2<<32 | v2>>(64-32)
   114  
   115  	// Round 2.
   116  	v0 += v1
   117  	v1 = v1<<13 | v1>>(64-13)
   118  	v1 ^= v0
   119  	v0 = v0<<32 | v0>>(64-32)
   120  
   121  	v2 += v3
   122  	v3 = v3<<16 | v3>>(64-16)
   123  	v3 ^= v2
   124  
   125  	v0 += v3
   126  	v3 = v3<<21 | v3>>(64-21)
   127  	v3 ^= v0
   128  
   129  	v2 += v1
   130  	v1 = v1<<17 | v1>>(64-17)
   131  	v1 ^= v2
   132  	v2 = v2<<32 | v2>>(64-32)
   133  
   134  	v0 ^= t
   135  
   136  	// Finalization.
   137  	v2 ^= 0xff
   138  
   139  	// Round 1.
   140  	v0 += v1
   141  	v1 = v1<<13 | v1>>(64-13)
   142  	v1 ^= v0
   143  	v0 = v0<<32 | v0>>(64-32)
   144  
   145  	v2 += v3
   146  	v3 = v3<<16 | v3>>(64-16)
   147  	v3 ^= v2
   148  
   149  	v0 += v3
   150  	v3 = v3<<21 | v3>>(64-21)
   151  	v3 ^= v0
   152  
   153  	v2 += v1
   154  	v1 = v1<<17 | v1>>(64-17)
   155  	v1 ^= v2
   156  	v2 = v2<<32 | v2>>(64-32)
   157  
   158  	// Round 2.
   159  	v0 += v1
   160  	v1 = v1<<13 | v1>>(64-13)
   161  	v1 ^= v0
   162  	v0 = v0<<32 | v0>>(64-32)
   163  
   164  	v2 += v3
   165  	v3 = v3<<16 | v3>>(64-16)
   166  	v3 ^= v2
   167  
   168  	v0 += v3
   169  	v3 = v3<<21 | v3>>(64-21)
   170  	v3 ^= v0
   171  
   172  	v2 += v1
   173  	v1 = v1<<17 | v1>>(64-17)
   174  	v1 ^= v2
   175  	v2 = v2<<32 | v2>>(64-32)
   176  
   177  	// Round 3.
   178  	v0 += v1
   179  	v1 = v1<<13 | v1>>(64-13)
   180  	v1 ^= v0
   181  	v0 = v0<<32 | v0>>(64-32)
   182  
   183  	v2 += v3
   184  	v3 = v3<<16 | v3>>(64-16)
   185  	v3 ^= v2
   186  
   187  	v0 += v3
   188  	v3 = v3<<21 | v3>>(64-21)
   189  	v3 ^= v0
   190  
   191  	v2 += v1
   192  	v1 = v1<<17 | v1>>(64-17)
   193  	v1 ^= v2
   194  	v2 = v2<<32 | v2>>(64-32)
   195  
   196  	// Round 4.
   197  	v0 += v1
   198  	v1 = v1<<13 | v1>>(64-13)
   199  	v1 ^= v0
   200  	v0 = v0<<32 | v0>>(64-32)
   201  
   202  	v2 += v3
   203  	v3 = v3<<16 | v3>>(64-16)
   204  	v3 ^= v2
   205  
   206  	v0 += v3
   207  	v3 = v3<<21 | v3>>(64-21)
   208  	v3 ^= v0
   209  
   210  	v2 += v1
   211  	v1 = v1<<17 | v1>>(64-17)
   212  	v1 ^= v2
   213  	v2 = v2<<32 | v2>>(64-32)
   214  
   215  	return v0 ^ v1 ^ v2 ^ v3
   216  }