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.

194 lines
4.3 KiB

  1. // Written in 2011-2012 by Dmitry Chestnykh.
  2. //
  3. // To the extent possible under law, the author have dedicated all copyright
  4. // and related and neighboring rights to this software to the public domain
  5. // worldwide. This software is distributed without any warranty.
  6. // http://creativecommons.org/publicdomain/zero/1.0/
  7. // Package blake256 implements BLAKE-256 and BLAKE-224 hash functions (SHA-3
  8. // candidate).
  9. package blake256
  10. import "hash"
  11. // The block size of the hash algorithm in bytes.
  12. const BlockSize = 64
  13. // The size of BLAKE-256 hash in bytes.
  14. const Size = 32
  15. // The size of BLAKE-224 hash in bytes.
  16. const Size224 = 28
  17. type digest struct {
  18. hashSize int // hash output size in bits (224 or 256)
  19. h [8]uint32 // current chain value
  20. s [4]uint32 // salt (zero by default)
  21. t uint64 // message bits counter
  22. nullt bool // special case for finalization: skip counter
  23. x [BlockSize]byte // buffer for data not yet compressed
  24. nx int // number of bytes in buffer
  25. }
  26. var (
  27. // Initialization values.
  28. iv256 = [8]uint32{
  29. 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
  30. 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19}
  31. iv224 = [8]uint32{
  32. 0xC1059ED8, 0x367CD507, 0x3070DD17, 0xF70E5939,
  33. 0xFFC00B31, 0x68581511, 0x64F98FA7, 0xBEFA4FA4}
  34. pad = [64]byte{0x80}
  35. )
  36. // Reset resets the state of digest. It leaves salt intact.
  37. func (d *digest) Reset() {
  38. if d.hashSize == 224 {
  39. d.h = iv224
  40. } else {
  41. d.h = iv256
  42. }
  43. d.t = 0
  44. d.nx = 0
  45. d.nullt = false
  46. }
  47. func (d *digest) Size() int { return d.hashSize >> 3 }
  48. func (d *digest) BlockSize() int { return BlockSize }
  49. func (d *digest) Write(p []byte) (nn int, err error) {
  50. nn = len(p)
  51. if d.nx > 0 {
  52. n := len(p)
  53. if n > BlockSize-d.nx {
  54. n = BlockSize - d.nx
  55. }
  56. d.nx += copy(d.x[d.nx:], p)
  57. if d.nx == BlockSize {
  58. block(d, d.x[:])
  59. d.nx = 0
  60. }
  61. p = p[n:]
  62. }
  63. if len(p) >= BlockSize {
  64. n := len(p) &^ (BlockSize - 1)
  65. block(d, p[:n])
  66. p = p[n:]
  67. }
  68. if len(p) > 0 {
  69. d.nx = copy(d.x[:], p)
  70. }
  71. return
  72. }
  73. // Sum returns the calculated checksum.
  74. func (d0 *digest) Sum(in []byte) []byte {
  75. // Make a copy of d0 so that caller can keep writing and summing.
  76. d := *d0
  77. nx := uint64(d.nx)
  78. l := d.t + nx<<3
  79. len := make([]byte, 8)
  80. len[0] = byte(l >> 56)
  81. len[1] = byte(l >> 48)
  82. len[2] = byte(l >> 40)
  83. len[3] = byte(l >> 32)
  84. len[4] = byte(l >> 24)
  85. len[5] = byte(l >> 16)
  86. len[6] = byte(l >> 8)
  87. len[7] = byte(l)
  88. if nx == 55 {
  89. // One padding byte.
  90. d.t -= 8
  91. if d.hashSize == 224 {
  92. d.Write([]byte{0x80})
  93. } else {
  94. d.Write([]byte{0x81})
  95. }
  96. } else {
  97. if nx < 55 {
  98. // Enough space to fill the block.
  99. if nx == 0 {
  100. d.nullt = true
  101. }
  102. d.t -= 440 - nx<<3
  103. d.Write(pad[0 : 55-nx])
  104. } else {
  105. // Need 2 compressions.
  106. d.t -= 512 - nx<<3
  107. d.Write(pad[0 : 64-nx])
  108. d.t -= 440
  109. d.Write(pad[1:56])
  110. d.nullt = true
  111. }
  112. if d.hashSize == 224 {
  113. d.Write([]byte{0x00})
  114. } else {
  115. d.Write([]byte{0x01})
  116. }
  117. d.t -= 8
  118. }
  119. d.t -= 64
  120. d.Write(len)
  121. out := make([]byte, d.Size())
  122. j := 0
  123. for _, s := range d.h[:d.hashSize>>5] {
  124. out[j+0] = byte(s >> 24)
  125. out[j+1] = byte(s >> 16)
  126. out[j+2] = byte(s >> 8)
  127. out[j+3] = byte(s >> 0)
  128. j += 4
  129. }
  130. return append(in, out...)
  131. }
  132. func (d *digest) setSalt(s []byte) {
  133. if len(s) != 16 {
  134. panic("salt length must be 16 bytes")
  135. }
  136. d.s[0] = uint32(s[0])<<24 | uint32(s[1])<<16 | uint32(s[2])<<8 | uint32(s[3])
  137. d.s[1] = uint32(s[4])<<24 | uint32(s[5])<<16 | uint32(s[6])<<8 | uint32(s[7])
  138. d.s[2] = uint32(s[8])<<24 | uint32(s[9])<<16 | uint32(s[10])<<8 | uint32(s[11])
  139. d.s[3] = uint32(s[12])<<24 | uint32(s[13])<<16 | uint32(s[14])<<8 | uint32(s[15])
  140. }
  141. // New returns a new hash.Hash computing the BLAKE-256 checksum.
  142. func New() hash.Hash {
  143. return &digest{
  144. hashSize: 256,
  145. h: iv256,
  146. }
  147. }
  148. // NewSalt is like New but initializes salt with the given 16-byte slice.
  149. func NewSalt(salt []byte) hash.Hash {
  150. d := &digest{
  151. hashSize: 256,
  152. h: iv256,
  153. }
  154. d.setSalt(salt)
  155. return d
  156. }
  157. // New224 returns a new hash.Hash computing the BLAKE-224 checksum.
  158. func New224() hash.Hash {
  159. return &digest{
  160. hashSize: 224,
  161. h: iv224,
  162. }
  163. }
  164. // New224Salt is like New224 but initializes salt with the given 16-byte slice.
  165. func New224Salt(salt []byte) hash.Hash {
  166. d := &digest{
  167. hashSize: 224,
  168. h: iv224,
  169. }
  170. d.setSalt(salt)
  171. return d
  172. }