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 5// Package ripemd160 implements the RIPEMD-160 hash algorithm. 6package ripemd160 // import "golang.org/x/crypto/ripemd160" 7 8// RIPEMD-160 is designed by by Hans Dobbertin, Antoon Bosselaers, and Bart 9// Preneel with specifications available at: 10// http://homes.esat.kuleuven.be/~cosicart/pdf/AB-9601/AB-9601.pdf. 11 12import ( 13 "crypto" 14 "hash" 15) 16 17func init() { 18 crypto.RegisterHash(crypto.RIPEMD160, New) 19} 20 21// The size of the checksum in bytes. 22const Size = 20 23 24// The block size of the hash algorithm in bytes. 25const BlockSize = 64 26 27const ( 28 _s0 = 0x67452301 29 _s1 = 0xefcdab89 30 _s2 = 0x98badcfe 31 _s3 = 0x10325476 32 _s4 = 0xc3d2e1f0 33) 34 35// digest represents the partial evaluation of a checksum. 36type digest struct { 37 s [5]uint32 // running context 38 x [BlockSize]byte // temporary buffer 39 nx int // index into x 40 tc uint64 // total count of bytes processed 41} 42 43func (d *digest) Reset() { 44 d.s[0], d.s[1], d.s[2], d.s[3], d.s[4] = _s0, _s1, _s2, _s3, _s4 45 d.nx = 0 46 d.tc = 0 47} 48 49// New returns a new hash.Hash computing the checksum. 50func New() hash.Hash { 51 result := new(digest) 52 result.Reset() 53 return result 54} 55 56func (d *digest) Size() int { return Size } 57 58func (d *digest) BlockSize() int { return BlockSize } 59 60func (d *digest) Write(p []byte) (nn int, err error) { 61 nn = len(p) 62 d.tc += uint64(nn) 63 if d.nx > 0 { 64 n := len(p) 65 if n > BlockSize-d.nx { 66 n = BlockSize - d.nx 67 } 68 for i := 0; i < n; i++ { 69 d.x[d.nx+i] = p[i] 70 } 71 d.nx += n 72 if d.nx == BlockSize { 73 _Block(d, d.x[0:]) 74 d.nx = 0 75 } 76 p = p[n:] 77 } 78 n := _Block(d, p) 79 p = p[n:] 80 if len(p) > 0 { 81 d.nx = copy(d.x[:], p) 82 } 83 return 84} 85 86func (d0 *digest) Sum(in []byte) []byte { 87 // Make a copy of d0 so that caller can keep writing and summing. 88 d := *d0 89 90 // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. 91 tc := d.tc 92 var tmp [64]byte 93 tmp[0] = 0x80 94 if tc%64 < 56 { 95 d.Write(tmp[0 : 56-tc%64]) 96 } else { 97 d.Write(tmp[0 : 64+56-tc%64]) 98 } 99 100 // Length in bits. 101 tc <<= 3 102 for i := uint(0); i < 8; i++ { 103 tmp[i] = byte(tc >> (8 * i)) 104 } 105 d.Write(tmp[0:8]) 106 107 if d.nx != 0 { 108 panic("d.nx != 0") 109 } 110 111 var digest [Size]byte 112 for i, s := range d.s { 113 digest[i*4] = byte(s) 114 digest[i*4+1] = byte(s >> 8) 115 digest[i*4+2] = byte(s >> 16) 116 digest[i*4+3] = byte(s >> 24) 117 } 118 119 return append(in, digest[:]...) 120} 121