You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

141 lines
3.0 KiB

8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
  1. package keys
  2. import (
  3. "encoding/binary"
  4. "errors"
  5. "hash/crc32"
  6. "hash/crc64"
  7. )
  8. // ECC is used for anything that calculates an error-correcting code
  9. type ECC interface {
  10. // AddECC calculates an error-correcting code for the input
  11. // returns an output with the code appended
  12. AddECC([]byte) []byte
  13. // CheckECC verifies if the ECC is proper on the input and returns
  14. // the data with the code removed, or an error
  15. CheckECC([]byte) ([]byte, error)
  16. }
  17. // NoECC is a no-op placeholder, kind of useless... except for tests
  18. type NoECC struct{}
  19. var _ ECC = NoECC{}
  20. func (_ NoECC) AddECC(input []byte) []byte { return input }
  21. func (_ NoECC) CheckECC(input []byte) ([]byte, error) { return input, nil }
  22. // CRC32 does the ieee crc32 polynomial check
  23. type CRC32 struct {
  24. Poly uint32
  25. table *crc32.Table
  26. }
  27. var _ ECC = &CRC32{}
  28. func NewIEEECRC32() *CRC32 {
  29. return &CRC32{Poly: crc32.IEEE}
  30. }
  31. func NewCastagnoliCRC32() *CRC32 {
  32. return &CRC32{Poly: crc32.Castagnoli}
  33. }
  34. func NewKoopmanCRC32() *CRC32 {
  35. return &CRC32{Poly: crc32.Koopman}
  36. }
  37. func (c *CRC32) AddECC(input []byte) []byte {
  38. table := c.getTable()
  39. // get crc and convert to some bytes...
  40. crc := crc32.Checksum(input, table)
  41. check := make([]byte, crc32.Size)
  42. binary.BigEndian.PutUint32(check, crc)
  43. // append it to the input
  44. output := append(input, check...)
  45. return output
  46. }
  47. func (c *CRC32) CheckECC(input []byte) ([]byte, error) {
  48. table := c.getTable()
  49. if len(input) <= crc32.Size {
  50. return nil, errors.New("input too short, no checksum present")
  51. }
  52. cut := len(input) - crc32.Size
  53. data, check := input[:cut], input[cut:]
  54. crc := binary.BigEndian.Uint32(check)
  55. calc := crc32.Checksum(data, table)
  56. if crc != calc {
  57. return nil, errors.New("Checksum does not match")
  58. }
  59. return data, nil
  60. }
  61. func (c *CRC32) getTable() *crc32.Table {
  62. if c.table == nil {
  63. if c.Poly == 0 {
  64. c.Poly = crc32.IEEE
  65. }
  66. c.table = crc32.MakeTable(c.Poly)
  67. }
  68. return c.table
  69. }
  70. // CRC64 does the ieee crc64 polynomial check
  71. type CRC64 struct {
  72. Poly uint64
  73. table *crc64.Table
  74. }
  75. var _ ECC = &CRC64{}
  76. func NewISOCRC64() *CRC64 {
  77. return &CRC64{Poly: crc64.ISO}
  78. }
  79. func NewECMACRC64() *CRC64 {
  80. return &CRC64{Poly: crc64.ECMA}
  81. }
  82. func (c *CRC64) AddECC(input []byte) []byte {
  83. table := c.getTable()
  84. // get crc and convert to some bytes...
  85. crc := crc64.Checksum(input, table)
  86. check := make([]byte, crc64.Size)
  87. binary.BigEndian.PutUint64(check, crc)
  88. // append it to the input
  89. output := append(input, check...)
  90. return output
  91. }
  92. func (c *CRC64) CheckECC(input []byte) ([]byte, error) {
  93. table := c.getTable()
  94. if len(input) <= crc64.Size {
  95. return nil, errors.New("input too short, no checksum present")
  96. }
  97. cut := len(input) - crc64.Size
  98. data, check := input[:cut], input[cut:]
  99. crc := binary.BigEndian.Uint64(check)
  100. calc := crc64.Checksum(data, table)
  101. if crc != calc {
  102. return nil, errors.New("Checksum does not match")
  103. }
  104. return data, nil
  105. }
  106. func (c *CRC64) getTable() *crc64.Table {
  107. if c.table == nil {
  108. if c.Poly == 0 {
  109. c.Poly = crc64.ISO
  110. }
  111. c.table = crc64.MakeTable(c.Poly)
  112. }
  113. return c.table
  114. }