md4.go 2.1 KB

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