pool.go 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. package hmac
  2. import (
  3. "crypto/sha1"
  4. "crypto/sha256"
  5. "hash"
  6. "sync"
  7. )
  8. // setZeroes sets all bytes from b to zeroes.
  9. //
  10. // See https://github.com/golang/go/issues/5373
  11. func setZeroes(b []byte) {
  12. for i := range b {
  13. b[i] = 0
  14. }
  15. }
  16. func (h *hmac) resetTo(key []byte) {
  17. h.outer.Reset()
  18. h.inner.Reset()
  19. setZeroes(h.ipad)
  20. setZeroes(h.opad)
  21. if len(key) > h.blocksize {
  22. // If key is too big, hash it.
  23. h.outer.Write(key)
  24. key = h.outer.Sum(nil)
  25. }
  26. copy(h.ipad, key)
  27. copy(h.opad, key)
  28. for i := range h.ipad {
  29. h.ipad[i] ^= 0x36
  30. }
  31. for i := range h.opad {
  32. h.opad[i] ^= 0x5c
  33. }
  34. h.inner.Write(h.ipad)
  35. }
  36. var hmacSHA1Pool = &sync.Pool{
  37. New: func() interface{} {
  38. h := New(sha1.New, make([]byte, sha1.BlockSize))
  39. return h
  40. },
  41. }
  42. // AcquireSHA1 returns new HMAC from pool.
  43. func AcquireSHA1(key []byte) hash.Hash {
  44. h := hmacSHA1Pool.Get().(*hmac)
  45. assertHMACSize(h, sha1.Size, sha1.BlockSize)
  46. h.resetTo(key)
  47. return h
  48. }
  49. // PutSHA1 puts h to pool.
  50. func PutSHA1(h hash.Hash) {
  51. hm := h.(*hmac)
  52. assertHMACSize(hm, sha1.Size, sha1.BlockSize)
  53. hmacSHA1Pool.Put(hm)
  54. }
  55. var hmacSHA256Pool = &sync.Pool{
  56. New: func() interface{} {
  57. h := New(sha256.New, make([]byte, sha256.BlockSize))
  58. return h
  59. },
  60. }
  61. // AcquireSHA256 returns new HMAC from SHA256 pool.
  62. func AcquireSHA256(key []byte) hash.Hash {
  63. h := hmacSHA256Pool.Get().(*hmac)
  64. assertHMACSize(h, sha256.Size, sha256.BlockSize)
  65. h.resetTo(key)
  66. return h
  67. }
  68. // PutSHA256 puts h to SHA256 pool.
  69. func PutSHA256(h hash.Hash) {
  70. hm := h.(*hmac)
  71. assertHMACSize(hm, sha256.Size, sha256.BlockSize)
  72. hmacSHA256Pool.Put(hm)
  73. }
  74. // assertHMACSize panics if h.size != size or h.blocksize != blocksize.
  75. //
  76. // Put and Acquire functions are internal functions to project, so
  77. // checking it via such assert is optimal.
  78. func assertHMACSize(h *hmac, size, blocksize int) {
  79. if h.size != size || h.blocksize != blocksize {
  80. panic("BUG: hmac size invalid") // nolint
  81. }
  82. }