package hasher import ( "hash" "unsafe" ) type accurateRipDigestV1 struct { crc uint32 pos uint32 offset uint32 } func NewAccurateRipV1(offset uint32) hash.Hash32 { return &accurateRipDigestV1{0, offset + 1, offset} } func (d *accurateRipDigestV1) Size() int { return 4 } func (d *accurateRipDigestV1) BlockSize() int { return 1 } func (d *accurateRipDigestV1) Reset() { d.crc = 0; d.pos = d.offset + 1 } func (d *accurateRipDigestV1) Sum32() uint32 { return d.crc } func (d *accurateRipDigestV1) Sum(in []byte) []byte { s := d.Sum32() return append(in, byte(s>>24), byte(s>>16), byte(s>>8), byte(s)) } func (d *accurateRipDigestV1) Write(p []byte) (n int, err error) { numWords := uintptr(len(p)) * unsafe.Sizeof(p[0]) / unsafe.Sizeof(uint32(0)) words := unsafe.Slice((*uint32)(unsafe.Pointer(unsafe.SliceData(p))), numWords) for _, w := range words { //this can wrap d.crc += d.pos * w d.pos++ } return len(p), nil } type accurateRipDigestV2 struct { crc uint32 multiplier uint32 offset uint32 } func NewAccurateRipV2(offset uint32) hash.Hash32 { return &accurateRipDigestV2{0, offset + 1, offset} } func (d *accurateRipDigestV2) Size() int { return 4 } func (d *accurateRipDigestV2) BlockSize() int { return 1 } func (d *accurateRipDigestV2) Reset() { d.crc = 0; d.multiplier = d.offset + 1 } func (d *accurateRipDigestV2) Sum32() uint32 { return d.crc } func (d *accurateRipDigestV2) Sum(in []byte) []byte { s := d.Sum32() return append(in, byte(s>>24), byte(s>>16), byte(s>>8), byte(s)) } func (d *accurateRipDigestV2) Write(p []byte) (n int, err error) { numWords := uintptr(len(p)) * unsafe.Sizeof(p[0]) / unsafe.Sizeof(uint32(0)) words := unsafe.Slice((*uint32)(unsafe.Pointer(unsafe.SliceData(p))), numWords) for _, w := range words { crcNew := uint64(w) * uint64(d.multiplier) LO := crcNew & 0xFFFFFFFF HI := crcNew / 0x100000000 //this can wrap d.crc += uint32(HI) d.crc += uint32(LO) d.multiplier++ } return len(p), nil }