github.com/aliyun/aliyun-oss-go-sdk@v3.0.2+incompatible/oss/crc.go (about) 1 package oss 2 3 import ( 4 "hash" 5 "hash/crc64" 6 ) 7 8 // digest represents the partial evaluation of a checksum. 9 type digest struct { 10 crc uint64 11 tab *crc64.Table 12 } 13 14 // NewCRC creates a new hash.Hash64 computing the CRC64 checksum 15 // using the polynomial represented by the Table. 16 func NewCRC(tab *crc64.Table, init uint64) hash.Hash64 { return &digest{init, tab} } 17 18 // Size returns the number of bytes sum will return. 19 func (d *digest) Size() int { return crc64.Size } 20 21 // BlockSize returns the hash's underlying block size. 22 // The Write method must be able to accept any amount 23 // of data, but it may operate more efficiently if all writes 24 // are a multiple of the block size. 25 func (d *digest) BlockSize() int { return 1 } 26 27 // Reset resets the hash to its initial state. 28 func (d *digest) Reset() { d.crc = 0 } 29 30 // Write (via the embedded io.Writer interface) adds more data to the running hash. 31 // It never returns an error. 32 func (d *digest) Write(p []byte) (n int, err error) { 33 d.crc = crc64.Update(d.crc, d.tab, p) 34 return len(p), nil 35 } 36 37 // Sum64 returns CRC64 value. 38 func (d *digest) Sum64() uint64 { return d.crc } 39 40 // Sum returns hash value. 41 func (d *digest) Sum(in []byte) []byte { 42 s := d.Sum64() 43 return append(in, byte(s>>56), byte(s>>48), byte(s>>40), byte(s>>32), byte(s>>24), byte(s>>16), byte(s>>8), byte(s)) 44 } 45 46 // gf2Dim dimension of GF(2) vectors (length of CRC) 47 const gf2Dim int = 64 48 49 func gf2MatrixTimes(mat []uint64, vec uint64) uint64 { 50 var sum uint64 51 for i := 0; vec != 0; i++ { 52 if vec&1 != 0 { 53 sum ^= mat[i] 54 } 55 56 vec >>= 1 57 } 58 return sum 59 } 60 61 func gf2MatrixSquare(square []uint64, mat []uint64) { 62 for n := 0; n < gf2Dim; n++ { 63 square[n] = gf2MatrixTimes(mat, mat[n]) 64 } 65 } 66 67 // CRC64Combine combines CRC64 68 func CRC64Combine(crc1 uint64, crc2 uint64, len2 uint64) uint64 { 69 var even [gf2Dim]uint64 // Even-power-of-two zeros operator 70 var odd [gf2Dim]uint64 // Odd-power-of-two zeros operator 71 72 // Degenerate case 73 if len2 == 0 { 74 return crc1 75 } 76 77 // Put operator for one zero bit in odd 78 odd[0] = crc64.ECMA // CRC64 polynomial 79 var row uint64 = 1 80 for n := 1; n < gf2Dim; n++ { 81 odd[n] = row 82 row <<= 1 83 } 84 85 // Put operator for two zero bits in even 86 gf2MatrixSquare(even[:], odd[:]) 87 88 // Put operator for four zero bits in odd 89 gf2MatrixSquare(odd[:], even[:]) 90 91 // Apply len2 zeros to crc1, first square will put the operator for one zero byte, eight zero bits, in even 92 for { 93 // Apply zeros operator for this bit of len2 94 gf2MatrixSquare(even[:], odd[:]) 95 96 if len2&1 != 0 { 97 crc1 = gf2MatrixTimes(even[:], crc1) 98 } 99 100 len2 >>= 1 101 102 // If no more bits set, then done 103 if len2 == 0 { 104 break 105 } 106 107 // Another iteration of the loop with odd and even swapped 108 gf2MatrixSquare(odd[:], even[:]) 109 if len2&1 != 0 { 110 crc1 = gf2MatrixTimes(odd[:], crc1) 111 } 112 len2 >>= 1 113 114 // If no more bits set, then done 115 if len2 == 0 { 116 break 117 } 118 } 119 120 // Return combined CRC 121 crc1 ^= crc2 122 return crc1 123 }