sha256.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /*
  2. * Minio Cloud Storage, (C) 2016 Minio, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package sha256
  17. import (
  18. "crypto/sha256"
  19. "hash"
  20. "runtime"
  21. )
  22. // Size - The size of a SHA256 checksum in bytes.
  23. const Size = 32
  24. // BlockSize - The blocksize of SHA256 in bytes.
  25. const BlockSize = 64
  26. const (
  27. chunk = 64
  28. init0 = 0x6A09E667
  29. init1 = 0xBB67AE85
  30. init2 = 0x3C6EF372
  31. init3 = 0xA54FF53A
  32. init4 = 0x510E527F
  33. init5 = 0x9B05688C
  34. init6 = 0x1F83D9AB
  35. init7 = 0x5BE0CD19
  36. )
  37. // digest represents the partial evaluation of a checksum.
  38. type digest struct {
  39. h [8]uint32
  40. x [chunk]byte
  41. nx int
  42. len uint64
  43. }
  44. // Reset digest back to default
  45. func (d *digest) Reset() {
  46. d.h[0] = init0
  47. d.h[1] = init1
  48. d.h[2] = init2
  49. d.h[3] = init3
  50. d.h[4] = init4
  51. d.h[5] = init5
  52. d.h[6] = init6
  53. d.h[7] = init7
  54. d.nx = 0
  55. d.len = 0
  56. }
  57. func block(dig *digest, p []byte) {
  58. is386bit := runtime.GOARCH == "386"
  59. isARM := runtime.GOARCH == "arm"
  60. if is386bit || isARM {
  61. blockGeneric(dig, p)
  62. }
  63. switch !is386bit && !isARM {
  64. case avx2:
  65. blockAvx2Go(dig, p)
  66. case avx:
  67. blockAvxGo(dig, p)
  68. case ssse3:
  69. blockSsseGo(dig, p)
  70. case armSha:
  71. blockArmGo(dig, p)
  72. default:
  73. blockGeneric(dig, p)
  74. }
  75. }
  76. // New returns a new hash.Hash computing the SHA256 checksum.
  77. func New() hash.Hash {
  78. if avx2 || avx || ssse3 || armSha {
  79. d := new(digest)
  80. d.Reset()
  81. return d
  82. }
  83. // default back to the standard golang implementation
  84. return sha256.New()
  85. }
  86. // Sum256 - single caller sha256 helper
  87. func Sum256(data []byte) [Size]byte {
  88. var d digest
  89. d.Reset()
  90. d.Write(data)
  91. return d.checkSum()
  92. }
  93. // Return size of checksum
  94. func (d *digest) Size() int { return Size }
  95. // Return blocksize of checksum
  96. func (d *digest) BlockSize() int { return BlockSize }
  97. // Write to digest
  98. func (d *digest) Write(p []byte) (nn int, err error) {
  99. nn = len(p)
  100. d.len += uint64(nn)
  101. if d.nx > 0 {
  102. n := copy(d.x[d.nx:], p)
  103. d.nx += n
  104. if d.nx == chunk {
  105. block(d, d.x[:])
  106. d.nx = 0
  107. }
  108. p = p[n:]
  109. }
  110. if len(p) >= chunk {
  111. n := len(p) &^ (chunk - 1)
  112. block(d, p[:n])
  113. p = p[n:]
  114. }
  115. if len(p) > 0 {
  116. d.nx = copy(d.x[:], p)
  117. }
  118. return
  119. }
  120. // Return sha256 sum in bytes
  121. func (d *digest) Sum(in []byte) []byte {
  122. // Make a copy of d0 so that caller can keep writing and summing.
  123. d0 := *d
  124. hash := d0.checkSum()
  125. return append(in, hash[:]...)
  126. }
  127. // Intermediate checksum function
  128. func (d *digest) checkSum() [Size]byte {
  129. len := d.len
  130. // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64.
  131. var tmp [64]byte
  132. tmp[0] = 0x80
  133. if len%64 < 56 {
  134. d.Write(tmp[0 : 56-len%64])
  135. } else {
  136. d.Write(tmp[0 : 64+56-len%64])
  137. }
  138. // Length in bits.
  139. len <<= 3
  140. for i := uint(0); i < 8; i++ {
  141. tmp[i] = byte(len >> (56 - 8*i))
  142. }
  143. d.Write(tmp[0:8])
  144. if d.nx != 0 {
  145. panic("d.nx != 0")
  146. }
  147. h := d.h[:]
  148. var digest [Size]byte
  149. for i, s := range h {
  150. digest[i*4] = byte(s >> 24)
  151. digest[i*4+1] = byte(s >> 16)
  152. digest[i*4+2] = byte(s >> 8)
  153. digest[i*4+3] = byte(s)
  154. }
  155. return digest
  156. }