github.com/GitbookIO/syncgroup@v0.0.0-20200915204659-4f0b2961ab10/quickhash/aeshash/aeshash.go (about) 1 package aeshash 2 3 import _ "unsafe" 4 5 // import "leb.io/hashland/nhash" 6 7 var masks [32]uint64 8 var shifts [32]uint64 9 10 // used in asm_{386,amd64}.s 11 const hashRandomBytes = 32 12 13 // this is really 2 x 128 bit round keys 14 var aeskeysched [hashRandomBytes]byte 15 16 var aesdebug [hashRandomBytes]byte 17 18 func aeshashbody() 19 20 //func Hash(p unsafe.Pointer, s, h uintptr) uintptr 21 //func HashStr(p string, s, h uintptr) uintptr 22 func Hash(b []byte, seed uint64) uint64 23 func HashStr(s string, seed uint64) uint64 24 func Hash64(v uint64, s uint64) uint64 25 func Hash32(v uint32, s uint64) uint64 26 27 //func aeshash(p unsafe.Pointer, s, h uintptr) uintptr 28 //func aeshash32(p unsafe.Pointer, s, h uintptr) uintptr 29 //func aeshash64(p unsafe.Pointer, s, h uintptr) uintptr 30 //func aeshashstr(p unsafe.Pointer, s, h uintptr) uintptr 31 32 func init() { 33 p := aeskeysched[:] 34 p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7] = 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8 35 p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15] = 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x10 36 p[16], p[17], p[18], p[19], p[20], p[21], p[22], p[23] = 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18 37 p[24], p[25], p[26], p[27], p[28], p[29], p[30], p[31] = 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0xFF 38 p = aesdebug[:] 39 p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7] = 0xFF, 0, 0, 0, 0, 0, 0, 0xFE 40 p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15] = 0xFD, 0, 0, 0, 0, 0, 0, 0xFC 41 } 42 43 // Make sure interfaces are correctly implemented. Stolen from another implementation. 44 // I did something similar in another package to verify the interface but didn't know you could elide the variable in a var. 45 // What a cute wart it is. 46 var ( 47 //_ hash.Hash = new(Digest) 48 // _ nhash.Hash64 = new(StateAES) 49 // _ nhash.HashStream = new(StateAES) 50 ) 51 52 type StateAES struct { 53 hash uint64 54 seed uint64 55 clen int 56 tail []byte 57 } 58 59 func NewAES(seed uint64) *StateAES { 60 s := new(StateAES) 61 s.seed = seed 62 s.Reset() 63 return s 64 } 65 66 // Return the size of the resulting hash. 67 func (d *StateAES) Size() int { return 8 } 68 69 // Return the blocksize of the hash which in this case is 1 byte. 70 func (d *StateAES) BlockSize() int { return 1 } 71 72 // Return the maximum number of seed bypes required. In this case 2 x 32 73 func (d *StateAES) NumSeedBytes() int { 74 return 8 75 } 76 77 // Return the number of bits the hash function outputs. 78 func (d *StateAES) HashSizeInBits() int { 79 return 64 80 } 81 82 // Reset the hash state. 83 func (d *StateAES) Reset() { 84 d.hash = 0 85 d.clen = 0 86 d.tail = nil 87 } 88 89 // Accept a byte stream p used for calculating the hash. For now this call is lazy and the actual hash calculations take place in Sum() and Sum32(). 90 func (d *StateAES) Write(p []byte) (nn int, err error) { 91 l := len(p) 92 d.clen += l 93 d.tail = append(d.tail, p...) 94 return l, nil 95 } 96 97 func (d *StateAES) Write64(h uint64) (err error) { 98 d.clen += 8 99 d.tail = append(d.tail, byte(h>>56), byte(h>>48), byte(h>>40), byte(h>>32), byte(h>>24), byte(h>>16), byte(h>>8), byte(h)) 100 return nil 101 } 102 103 // Return the current hash as a byte slice. 104 func (d *StateAES) Sum(b []byte) []byte { 105 d.hash = Hash(d.tail, d.seed) 106 h := d.hash 107 return append(b, byte(h>>56), byte(h>>48), byte(h>>40), byte(h>>32), byte(h>>24), byte(h>>16), byte(h>>8), byte(h)) 108 } 109 110 // Return the current hash as a 64 bit unsigned type. 111 func (d *StateAES) Sum64() uint64 { 112 d.hash = Hash(d.tail, d.seed) 113 return d.hash 114 } 115 116 func (d *StateAES) Hash64(b []byte, seeds ...uint64) uint64 { 117 switch len(seeds) { 118 case 1: 119 d.seed = seeds[0] 120 } 121 d.hash = Hash(b, d.seed) 122 //fmt.Printf("pc=0x%08x, pb=0x%08x\n", d.pc, d.pb) 123 return d.hash 124 }