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