sha1.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  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 sha1 implements the SHA1 hash algorithm as defined in RFC 3174.
  5. package sha1
  6. import (
  7. "crypto"
  8. "hash"
  9. )
  10. func init() {
  11. crypto.RegisterHash(crypto.SHA1, New)
  12. }
  13. // The size of a SHA1 checksum in bytes.
  14. const Size = 20
  15. // The blocksize of SHA1 in bytes.
  16. const BlockSize = 64
  17. const (
  18. chunk = 64
  19. init0 = 0x67452301
  20. init1 = 0xEFCDAB89
  21. init2 = 0x98BADCFE
  22. init3 = 0x10325476
  23. init4 = 0xC3D2E1F0
  24. )
  25. // digest represents the partial evaluation of a checksum.
  26. type digest struct {
  27. h [5]uint32
  28. x [chunk]byte
  29. nx int
  30. len uint64
  31. }
  32. func (d *digest) Reset() {
  33. d.h[0] = init0
  34. d.h[1] = init1
  35. d.h[2] = init2
  36. d.h[3] = init3
  37. d.h[4] = init4
  38. d.nx = 0
  39. d.len = 0
  40. }
  41. // New returns a new hash.Hash computing the SHA1 checksum.
  42. func New() hash.Hash {
  43. d := new(digest)
  44. d.Reset()
  45. return d
  46. }
  47. func (d *digest) Size() int { return Size }
  48. func (d *digest) BlockSize() int { return BlockSize }
  49. func (d *digest) Write(p []byte) (nn int, err error) {
  50. nn = len(p)
  51. d.len += uint64(nn)
  52. if d.nx > 0 {
  53. n := copy(d.x[d.nx:], p)
  54. d.nx += n
  55. if d.nx == chunk {
  56. block(d, d.x[:])
  57. d.nx = 0
  58. }
  59. p = p[n:]
  60. }
  61. if len(p) >= chunk {
  62. n := len(p) &^ (chunk - 1)
  63. block(d, p[:n])
  64. p = p[n:]
  65. }
  66. if len(p) > 0 {
  67. d.nx = copy(d.x[:], p)
  68. }
  69. return
  70. }
  71. func (d0 *digest) Sum(in []byte) []byte {
  72. // Make a copy of d0 so that caller can keep writing and summing.
  73. d := *d0
  74. hash := d.checkSum()
  75. return append(in, hash[:]...)
  76. }
  77. func (d *digest) checkSum() [Size]byte {
  78. len := d.len
  79. // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64.
  80. var tmp [64]byte
  81. tmp[0] = 0x80
  82. if len%64 < 56 {
  83. d.Write(tmp[0 : 56-len%64])
  84. } else {
  85. d.Write(tmp[0 : 64+56-len%64])
  86. }
  87. // Length in bits.
  88. len <<= 3
  89. for i := uint(0); i < 8; i++ {
  90. tmp[i] = byte(len >> (56 - 8*i))
  91. }
  92. d.Write(tmp[0:8])
  93. if d.nx != 0 {
  94. panic("d.nx != 0")
  95. }
  96. var digest [Size]byte
  97. for i, s := range d.h {
  98. digest[i*4] = byte(s >> 24)
  99. digest[i*4+1] = byte(s >> 16)
  100. digest[i*4+2] = byte(s >> 8)
  101. digest[i*4+3] = byte(s)
  102. }
  103. return digest
  104. }
  105. // Sum returns the SHA1 checksum of the data.
  106. func Sum(data []byte) [Size]byte {
  107. var d digest
  108. d.Reset()
  109. d.Write(data)
  110. return d.checkSum()
  111. }