| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | // Copyright 2010 The Go Authors. All rights reserved. | 
					
						
							|  |  |  | // Use of this source code is governed by a BSD-style | 
					
						
							|  |  |  | // license that can be found in the LICENSE file. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Package ripemd160 implements the RIPEMD-160 hash algorithm. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // Deprecated: RIPEMD-160 is a legacy hash and should not be used for new | 
					
						
							|  |  |  | // applications. Also, this package does not and will not provide an optimized | 
					
						
							|  |  |  | // implementation. Instead, use a modern hash like SHA-256 (from crypto/sha256). | 
					
						
							| 
									
										
										
										
											2024-07-08 07:33:11 +00:00
										 |  |  | package ripemd160 | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | // RIPEMD-160 is designed by Hans Dobbertin, Antoon Bosselaers, and Bart | 
					
						
							|  |  |  | // Preneel with specifications available at: | 
					
						
							|  |  |  | // http://homes.esat.kuleuven.be/~cosicart/pdf/AB-9601/AB-9601.pdf. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"crypto" | 
					
						
							|  |  |  | 	"hash" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func init() { | 
					
						
							|  |  |  | 	crypto.RegisterHash(crypto.RIPEMD160, New) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // The size of the checksum in bytes. | 
					
						
							|  |  |  | const Size = 20 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // The block size of the hash algorithm in bytes. | 
					
						
							|  |  |  | const BlockSize = 64 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const ( | 
					
						
							|  |  |  | 	_s0 = 0x67452301 | 
					
						
							|  |  |  | 	_s1 = 0xefcdab89 | 
					
						
							|  |  |  | 	_s2 = 0x98badcfe | 
					
						
							|  |  |  | 	_s3 = 0x10325476 | 
					
						
							|  |  |  | 	_s4 = 0xc3d2e1f0 | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // digest represents the partial evaluation of a checksum. | 
					
						
							|  |  |  | type digest struct { | 
					
						
							|  |  |  | 	s  [5]uint32       // running context | 
					
						
							|  |  |  | 	x  [BlockSize]byte // temporary buffer | 
					
						
							|  |  |  | 	nx int             // index into x | 
					
						
							|  |  |  | 	tc uint64          // total count of bytes processed | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (d *digest) Reset() { | 
					
						
							|  |  |  | 	d.s[0], d.s[1], d.s[2], d.s[3], d.s[4] = _s0, _s1, _s2, _s3, _s4 | 
					
						
							|  |  |  | 	d.nx = 0 | 
					
						
							|  |  |  | 	d.tc = 0 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // New returns a new hash.Hash computing the checksum. | 
					
						
							|  |  |  | func New() hash.Hash { | 
					
						
							|  |  |  | 	result := new(digest) | 
					
						
							|  |  |  | 	result.Reset() | 
					
						
							|  |  |  | 	return result | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (d *digest) Size() int { return Size } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (d *digest) BlockSize() int { return BlockSize } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (d *digest) Write(p []byte) (nn int, err error) { | 
					
						
							|  |  |  | 	nn = len(p) | 
					
						
							|  |  |  | 	d.tc += uint64(nn) | 
					
						
							|  |  |  | 	if d.nx > 0 { | 
					
						
							|  |  |  | 		n := len(p) | 
					
						
							|  |  |  | 		if n > BlockSize-d.nx { | 
					
						
							|  |  |  | 			n = BlockSize - d.nx | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		for i := 0; i < n; i++ { | 
					
						
							|  |  |  | 			d.x[d.nx+i] = p[i] | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		d.nx += n | 
					
						
							|  |  |  | 		if d.nx == BlockSize { | 
					
						
							|  |  |  | 			_Block(d, d.x[0:]) | 
					
						
							|  |  |  | 			d.nx = 0 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		p = p[n:] | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	n := _Block(d, p) | 
					
						
							|  |  |  | 	p = p[n:] | 
					
						
							|  |  |  | 	if len(p) > 0 { | 
					
						
							|  |  |  | 		d.nx = copy(d.x[:], p) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (d0 *digest) Sum(in []byte) []byte { | 
					
						
							|  |  |  | 	// Make a copy of d0 so that caller can keep writing and summing. | 
					
						
							|  |  |  | 	d := *d0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Padding.  Add a 1 bit and 0 bits until 56 bytes mod 64. | 
					
						
							|  |  |  | 	tc := d.tc | 
					
						
							|  |  |  | 	var tmp [64]byte | 
					
						
							|  |  |  | 	tmp[0] = 0x80 | 
					
						
							|  |  |  | 	if tc%64 < 56 { | 
					
						
							|  |  |  | 		d.Write(tmp[0 : 56-tc%64]) | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		d.Write(tmp[0 : 64+56-tc%64]) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Length in bits. | 
					
						
							|  |  |  | 	tc <<= 3 | 
					
						
							|  |  |  | 	for i := uint(0); i < 8; i++ { | 
					
						
							|  |  |  | 		tmp[i] = byte(tc >> (8 * i)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	d.Write(tmp[0:8]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if d.nx != 0 { | 
					
						
							|  |  |  | 		panic("d.nx != 0") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var digest [Size]byte | 
					
						
							|  |  |  | 	for i, s := range d.s { | 
					
						
							|  |  |  | 		digest[i*4] = byte(s) | 
					
						
							|  |  |  | 		digest[i*4+1] = byte(s >> 8) | 
					
						
							|  |  |  | 		digest[i*4+2] = byte(s >> 16) | 
					
						
							|  |  |  | 		digest[i*4+3] = byte(s >> 24) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return append(in, digest[:]...) | 
					
						
							|  |  |  | } |