sha256.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  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. // Fallback to the standard golang implementation
  84. // if no features were found.
  85. return sha256.New()
  86. }
  87. // Sum256 - single caller sha256 helper
  88. func Sum256(data []byte) [Size]byte {
  89. var d digest
  90. d.Reset()
  91. d.Write(data)
  92. return d.checkSum()
  93. }
  94. // Return size of checksum
  95. func (d *digest) Size() int { return Size }
  96. // Return blocksize of checksum
  97. func (d *digest) BlockSize() int { return BlockSize }
  98. // Write to digest
  99. func (d *digest) Write(p []byte) (nn int, err error) {
  100. nn = len(p)
  101. d.len += uint64(nn)
  102. if d.nx > 0 {
  103. n := copy(d.x[d.nx:], p)
  104. d.nx += n
  105. if d.nx == chunk {
  106. block(d, d.x[:])
  107. d.nx = 0
  108. }
  109. p = p[n:]
  110. }
  111. if len(p) >= chunk {
  112. n := len(p) &^ (chunk - 1)
  113. block(d, p[:n])
  114. p = p[n:]
  115. }
  116. if len(p) > 0 {
  117. d.nx = copy(d.x[:], p)
  118. }
  119. return
  120. }
  121. // Return sha256 sum in bytes
  122. func (d *digest) Sum(in []byte) []byte {
  123. // Make a copy of d0 so that caller can keep writing and summing.
  124. d0 := *d
  125. hash := d0.checkSum()
  126. return append(in, hash[:]...)
  127. }
  128. // Intermediate checksum function
  129. func (d *digest) checkSum() [Size]byte {
  130. len := d.len
  131. // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64.
  132. var tmp [64]byte
  133. tmp[0] = 0x80
  134. if len%64 < 56 {
  135. d.Write(tmp[0 : 56-len%64])
  136. } else {
  137. d.Write(tmp[0 : 64+56-len%64])
  138. }
  139. // Length in bits.
  140. len <<= 3
  141. for i := uint(0); i < 8; i++ {
  142. tmp[i] = byte(len >> (56 - 8*i))
  143. }
  144. d.Write(tmp[0:8])
  145. if d.nx != 0 {
  146. panic("d.nx != 0")
  147. }
  148. h := d.h[:]
  149. var digest [Size]byte
  150. for i, s := range h {
  151. digest[i*4] = byte(s >> 24)
  152. digest[i*4+1] = byte(s >> 16)
  153. digest[i*4+2] = byte(s >> 8)
  154. digest[i*4+3] = byte(s)
  155. }
  156. return digest
  157. }