crc32.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. // Copyright 2009 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // Package crc32 implements the 32-bit cyclic redundancy check, or CRC-32,
  5. // checksum. See http://en.wikipedia.org/wiki/Cyclic_redundancy_check for
  6. // information.
  7. package crc32
  8. import (
  9. "hash"
  10. "sync"
  11. )
  12. // The size of a CRC-32 checksum in bytes.
  13. const Size = 4
  14. // Predefined polynomials.
  15. const (
  16. // IEEE is by far and away the most common CRC-32 polynomial.
  17. // Used by ethernet (IEEE 802.3), v.42, fddi, gzip, zip, png, ...
  18. IEEE = 0xedb88320
  19. // Castagnoli's polynomial, used in iSCSI.
  20. // Has better error detection characteristics than IEEE.
  21. // http://dx.doi.org/10.1109/26.231911
  22. Castagnoli = 0x82f63b78
  23. // Koopman's polynomial.
  24. // Also has better error detection characteristics than IEEE.
  25. // http://dx.doi.org/10.1109/DSN.2002.1028931
  26. Koopman = 0xeb31d82e
  27. )
  28. // Table is a 256-word table representing the polynomial for efficient processing.
  29. type Table [256]uint32
  30. // castagnoliTable points to a lazily initialized Table for the Castagnoli
  31. // polynomial. MakeTable will always return this value when asked to make a
  32. // Castagnoli table so we can compare against it to find when the caller is
  33. // using this polynomial.
  34. var castagnoliTable *Table
  35. var castagnoliOnce sync.Once
  36. func castagnoliInit() {
  37. castagnoliTable = makeTable(Castagnoli)
  38. }
  39. // IEEETable is the table for the IEEE polynomial.
  40. var IEEETable = makeTable(IEEE)
  41. // MakeTable returns the Table constructed from the specified polynomial.
  42. func MakeTable(poly uint32) *Table {
  43. switch poly {
  44. case IEEE:
  45. return IEEETable
  46. case Castagnoli:
  47. castagnoliOnce.Do(castagnoliInit)
  48. return castagnoliTable
  49. }
  50. return makeTable(poly)
  51. }
  52. // makeTable returns the Table constructed from the specified polynomial.
  53. func makeTable(poly uint32) *Table {
  54. t := new(Table)
  55. for i := 0; i < 256; i++ {
  56. crc := uint32(i)
  57. for j := 0; j < 8; j++ {
  58. if crc&1 == 1 {
  59. crc = (crc >> 1) ^ poly
  60. } else {
  61. crc >>= 1
  62. }
  63. }
  64. t[i] = crc
  65. }
  66. return t
  67. }
  68. // digest represents the partial evaluation of a checksum.
  69. type digest struct {
  70. crc uint32
  71. tab *Table
  72. }
  73. // New creates a new hash.Hash32 computing the CRC-32 checksum
  74. // using the polynomial represented by the Table.
  75. func New(tab *Table) hash.Hash32 { return &digest{0, tab} }
  76. // NewIEEE creates a new hash.Hash32 computing the CRC-32 checksum
  77. // using the IEEE polynomial.
  78. func NewIEEE() hash.Hash32 { return New(IEEETable) }
  79. func (d *digest) Size() int { return Size }
  80. func (d *digest) BlockSize() int { return 1 }
  81. func (d *digest) Reset() { d.crc = 0 }
  82. func update(crc uint32, tab *Table, p []byte) uint32 {
  83. crc = ^crc
  84. for _, v := range p {
  85. crc = tab[byte(crc)^v] ^ (crc >> 8)
  86. }
  87. return ^crc
  88. }
  89. // Update returns the result of adding the bytes in p to the crc.
  90. func Update(crc uint32, tab *Table, p []byte) uint32 {
  91. if tab == castagnoliTable {
  92. return updateCastagnoli(crc, p)
  93. }
  94. return update(crc, tab, p)
  95. }
  96. func (d *digest) Write(p []byte) (n int, err error) {
  97. d.crc = Update(d.crc, d.tab, p)
  98. return len(p), nil
  99. }
  100. func (d *digest) Sum32() uint32 { return d.crc }
  101. func (d *digest) Sum(in []byte) []byte {
  102. s := d.Sum32()
  103. return append(in, byte(s>>24), byte(s>>16), byte(s>>8), byte(s))
  104. }
  105. // Checksum returns the CRC-32 checksum of data
  106. // using the polynomial represented by the Table.
  107. func Checksum(data []byte, tab *Table) uint32 { return Update(0, tab, data) }
  108. // ChecksumIEEE returns the CRC-32 checksum of data
  109. // using the IEEE polynomial.
  110. func ChecksumIEEE(data []byte) uint32 { return update(0, IEEETable, data) }