md4.go 2.3 KB

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