9 "github.com/howeyc/crc16"
12 // ECC is used for anything that calculates an error-correcting code
14 // AddECC calculates an error-correcting code for the input
15 // returns an output with the code appended
18 // CheckECC verifies if the ECC is proper on the input and returns
19 // the data with the code removed, or an error
20 CheckECC([]byte) ([]byte, error)
23 var errInputTooShort = errors.New("input too short, no checksum present")
24 var errChecksumDoesntMatch = errors.New("checksum does not match")
26 // NoECC is a no-op placeholder, kind of useless... except for tests
31 func (_ NoECC) AddECC(input []byte) []byte { return input }
32 func (_ NoECC) CheckECC(input []byte) ([]byte, error) { return input, nil }
34 // CRC16 does the ieee crc16 polynomial check
40 var _ ECC = (*CRC16)(nil)
42 const crc16ByteCount = 2
44 func NewIBMCRC16() *CRC16 {
45 return &CRC16{Poly: crc16.IBM}
48 func NewSCSICRC16() *CRC16 {
49 return &CRC16{Poly: crc16.SCSI}
52 func NewCCITTCRC16() *CRC16 {
53 return &CRC16{Poly: crc16.CCITT}
56 func (c *CRC16) AddECC(input []byte) []byte {
59 // get crc and convert to some bytes...
60 crc := crc16.Checksum(input, table)
61 check := make([]byte, crc16ByteCount)
62 binary.BigEndian.PutUint16(check, crc)
64 // append it to the input
65 output := append(input, check...)
69 func (c *CRC16) CheckECC(input []byte) ([]byte, error) {
72 if len(input) <= crc16ByteCount {
73 return nil, errInputTooShort
75 cut := len(input) - crc16ByteCount
76 data, check := input[:cut], input[cut:]
77 crc := binary.BigEndian.Uint16(check)
78 calc := crc16.Checksum(data, table)
80 return nil, errChecksumDoesntMatch
85 func (c *CRC16) getTable() *crc16.Table {
92 c.table = crc16.MakeTable(c.Poly)
96 // CRC32 does the ieee crc32 polynomial check
102 var _ ECC = (*CRC32)(nil)
104 func NewIEEECRC32() *CRC32 {
105 return &CRC32{Poly: crc32.IEEE}
108 func NewCastagnoliCRC32() *CRC32 {
109 return &CRC32{Poly: crc32.Castagnoli}
112 func NewKoopmanCRC32() *CRC32 {
113 return &CRC32{Poly: crc32.Koopman}
116 func (c *CRC32) AddECC(input []byte) []byte {
117 table := c.getTable()
119 // get crc and convert to some bytes...
120 crc := crc32.Checksum(input, table)
121 check := make([]byte, crc32.Size)
122 binary.BigEndian.PutUint32(check, crc)
124 // append it to the input
125 output := append(input, check...)
129 func (c *CRC32) CheckECC(input []byte) ([]byte, error) {
130 table := c.getTable()
132 if len(input) <= crc32.Size {
133 return nil, errInputTooShort
135 cut := len(input) - crc32.Size
136 data, check := input[:cut], input[cut:]
137 crc := binary.BigEndian.Uint32(check)
138 calc := crc32.Checksum(data, table)
140 return nil, errChecksumDoesntMatch
145 func (c *CRC32) getTable() *crc32.Table {
150 c.table = crc32.MakeTable(c.Poly)
155 // CRC64 does the ieee crc64 polynomial check
161 var _ ECC = (*CRC64)(nil)
163 func NewISOCRC64() *CRC64 {
164 return &CRC64{Poly: crc64.ISO}
167 func NewECMACRC64() *CRC64 {
168 return &CRC64{Poly: crc64.ECMA}
171 func (c *CRC64) AddECC(input []byte) []byte {
172 table := c.getTable()
174 // get crc and convert to some bytes...
175 crc := crc64.Checksum(input, table)
176 check := make([]byte, crc64.Size)
177 binary.BigEndian.PutUint64(check, crc)
179 // append it to the input
180 output := append(input, check...)
184 func (c *CRC64) CheckECC(input []byte) ([]byte, error) {
185 table := c.getTable()
187 if len(input) <= crc64.Size {
188 return nil, errInputTooShort
190 cut := len(input) - crc64.Size
191 data, check := input[:cut], input[cut:]
192 crc := binary.BigEndian.Uint64(check)
193 calc := crc64.Checksum(data, table)
195 return nil, errChecksumDoesntMatch
200 func (c *CRC64) getTable() *crc64.Table {
205 c.table = crc64.MakeTable(c.Poly)