You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

120 lines
2.4 KiB

  1. // Copyright 2010 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 ripemd160 implements the RIPEMD-160 hash algorithm.
  5. package ripemd160 // import "golang.org/x/crypto/ripemd160"
  6. // RIPEMD-160 is designed by by Hans Dobbertin, Antoon Bosselaers, and Bart
  7. // Preneel with specifications available at:
  8. // http://homes.esat.kuleuven.be/~cosicart/pdf/AB-9601/AB-9601.pdf.
  9. import (
  10. "crypto"
  11. "hash"
  12. )
  13. func init() {
  14. crypto.RegisterHash(crypto.RIPEMD160, New)
  15. }
  16. // The size of the checksum in bytes.
  17. const Size = 20
  18. // The block size of the hash algorithm in bytes.
  19. const BlockSize = 64
  20. const (
  21. _s0 = 0x67452301
  22. _s1 = 0xefcdab89
  23. _s2 = 0x98badcfe
  24. _s3 = 0x10325476
  25. _s4 = 0xc3d2e1f0
  26. )
  27. // digest represents the partial evaluation of a checksum.
  28. type digest struct {
  29. s [5]uint32 // running context
  30. x [BlockSize]byte // temporary buffer
  31. nx int // index into x
  32. tc uint64 // total count of bytes processed
  33. }
  34. func (d *digest) Reset() {
  35. d.s[0], d.s[1], d.s[2], d.s[3], d.s[4] = _s0, _s1, _s2, _s3, _s4
  36. d.nx = 0
  37. d.tc = 0
  38. }
  39. // New returns a new hash.Hash computing the checksum.
  40. func New() hash.Hash {
  41. result := new(digest)
  42. result.Reset()
  43. return result
  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.tc += uint64(nn)
  50. if d.nx > 0 {
  51. n := len(p)
  52. if n > BlockSize-d.nx {
  53. n = BlockSize - 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 == BlockSize {
  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 := *d0
  75. // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64.
  76. tc := d.tc
  77. var tmp [64]byte
  78. tmp[0] = 0x80
  79. if tc%64 < 56 {
  80. d.Write(tmp[0 : 56-tc%64])
  81. } else {
  82. d.Write(tmp[0 : 64+56-tc%64])
  83. }
  84. // Length in bits.
  85. tc <<= 3
  86. for i := uint(0); i < 8; i++ {
  87. tmp[i] = byte(tc >> (8 * i))
  88. }
  89. d.Write(tmp[0:8])
  90. if d.nx != 0 {
  91. panic("d.nx != 0")
  92. }
  93. var digest [Size]byte
  94. for i, s := range d.s {
  95. digest[i*4] = byte(s)
  96. digest[i*4+1] = byte(s >> 8)
  97. digest[i*4+2] = byte(s >> 16)
  98. digest[i*4+3] = byte(s >> 24)
  99. }
  100. return append(in, digest[:]...)
  101. }