OSDN Git Service

new repo
[bytom/vapor.git] / vendor / github.com / tendermint / go-crypto / keys / ecc.go
1 package keys
2
3 import (
4         "encoding/binary"
5         "errors"
6         "hash/crc32"
7         "hash/crc64"
8
9         "github.com/howeyc/crc16"
10 )
11
12 // ECC is used for anything that calculates an error-correcting code
13 type ECC interface {
14         // AddECC calculates an error-correcting code for the input
15         // returns an output with the code appended
16         AddECC([]byte) []byte
17
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)
21 }
22
23 var errInputTooShort = errors.New("input too short, no checksum present")
24 var errChecksumDoesntMatch = errors.New("checksum does not match")
25
26 // NoECC is a no-op placeholder, kind of useless... except for tests
27 type NoECC struct{}
28
29 var _ ECC = NoECC{}
30
31 func (_ NoECC) AddECC(input []byte) []byte            { return input }
32 func (_ NoECC) CheckECC(input []byte) ([]byte, error) { return input, nil }
33
34 // CRC16 does the ieee crc16 polynomial check
35 type CRC16 struct {
36         Poly  uint16
37         table *crc16.Table
38 }
39
40 var _ ECC = (*CRC16)(nil)
41
42 const crc16ByteCount = 2
43
44 func NewIBMCRC16() *CRC16 {
45         return &CRC16{Poly: crc16.IBM}
46 }
47
48 func NewSCSICRC16() *CRC16 {
49         return &CRC16{Poly: crc16.SCSI}
50 }
51
52 func NewCCITTCRC16() *CRC16 {
53         return &CRC16{Poly: crc16.CCITT}
54 }
55
56 func (c *CRC16) AddECC(input []byte) []byte {
57         table := c.getTable()
58
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)
63
64         // append it to the input
65         output := append(input, check...)
66         return output
67 }
68
69 func (c *CRC16) CheckECC(input []byte) ([]byte, error) {
70         table := c.getTable()
71
72         if len(input) <= crc16ByteCount {
73                 return nil, errInputTooShort
74         }
75         cut := len(input) - crc16ByteCount
76         data, check := input[:cut], input[cut:]
77         crc := binary.BigEndian.Uint16(check)
78         calc := crc16.Checksum(data, table)
79         if crc != calc {
80                 return nil, errChecksumDoesntMatch
81         }
82         return data, nil
83 }
84
85 func (c *CRC16) getTable() *crc16.Table {
86         if c.table != nil {
87                 return c.table
88         }
89         if c.Poly == 0 {
90                 c.Poly = crc16.IBM
91         }
92         c.table = crc16.MakeTable(c.Poly)
93         return c.table
94 }
95
96 // CRC32 does the ieee crc32 polynomial check
97 type CRC32 struct {
98         Poly  uint32
99         table *crc32.Table
100 }
101
102 var _ ECC = (*CRC32)(nil)
103
104 func NewIEEECRC32() *CRC32 {
105         return &CRC32{Poly: crc32.IEEE}
106 }
107
108 func NewCastagnoliCRC32() *CRC32 {
109         return &CRC32{Poly: crc32.Castagnoli}
110 }
111
112 func NewKoopmanCRC32() *CRC32 {
113         return &CRC32{Poly: crc32.Koopman}
114 }
115
116 func (c *CRC32) AddECC(input []byte) []byte {
117         table := c.getTable()
118
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)
123
124         // append it to the input
125         output := append(input, check...)
126         return output
127 }
128
129 func (c *CRC32) CheckECC(input []byte) ([]byte, error) {
130         table := c.getTable()
131
132         if len(input) <= crc32.Size {
133                 return nil, errInputTooShort
134         }
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)
139         if crc != calc {
140                 return nil, errChecksumDoesntMatch
141         }
142         return data, nil
143 }
144
145 func (c *CRC32) getTable() *crc32.Table {
146         if c.table == nil {
147                 if c.Poly == 0 {
148                         c.Poly = crc32.IEEE
149                 }
150                 c.table = crc32.MakeTable(c.Poly)
151         }
152         return c.table
153 }
154
155 // CRC64 does the ieee crc64 polynomial check
156 type CRC64 struct {
157         Poly  uint64
158         table *crc64.Table
159 }
160
161 var _ ECC = (*CRC64)(nil)
162
163 func NewISOCRC64() *CRC64 {
164         return &CRC64{Poly: crc64.ISO}
165 }
166
167 func NewECMACRC64() *CRC64 {
168         return &CRC64{Poly: crc64.ECMA}
169 }
170
171 func (c *CRC64) AddECC(input []byte) []byte {
172         table := c.getTable()
173
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)
178
179         // append it to the input
180         output := append(input, check...)
181         return output
182 }
183
184 func (c *CRC64) CheckECC(input []byte) ([]byte, error) {
185         table := c.getTable()
186
187         if len(input) <= crc64.Size {
188                 return nil, errInputTooShort
189         }
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)
194         if crc != calc {
195                 return nil, errChecksumDoesntMatch
196         }
197         return data, nil
198 }
199
200 func (c *CRC64) getTable() *crc64.Table {
201         if c.table == nil {
202                 if c.Poly == 0 {
203                         c.Poly = crc64.ISO
204                 }
205                 c.table = crc64.MakeTable(c.Poly)
206         }
207         return c.table
208 }