legacy_hash.go raw

   1  // Copyright 2014 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 sha3
   6  
   7  // This implementation is only used for NewLegacyKeccak256 and
   8  // NewLegacyKeccak512, which are not implemented by crypto/sha3.
   9  // All other functions in this package are wrappers around crypto/sha3.
  10  
  11  import (
  12  	"crypto/subtle"
  13  	"encoding/binary"
  14  	"errors"
  15  	"hash"
  16  	"unsafe"
  17  
  18  	"golang.org/x/sys/cpu"
  19  )
  20  
  21  const (
  22  	dsbyteKeccak = 0b00000001
  23  
  24  	// rateK[c] is the rate in bytes for Keccak[c] where c is the capacity in
  25  	// bits. Given the sponge size is 1600 bits, the rate is 1600 - c bits.
  26  	rateK256  = (1600 - 256) / 8
  27  	rateK512  = (1600 - 512) / 8
  28  	rateK1024 = (1600 - 1024) / 8
  29  )
  30  
  31  // NewLegacyKeccak256 creates a new Keccak-256 hash.
  32  //
  33  // Only use this function if you require compatibility with an existing cryptosystem
  34  // that uses non-standard padding. All other users should use New256 instead.
  35  func NewLegacyKeccak256() hash.Hash {
  36  	return &state{rate: rateK512, outputLen: 32, dsbyte: dsbyteKeccak}
  37  }
  38  
  39  // NewLegacyKeccak512 creates a new Keccak-512 hash.
  40  //
  41  // Only use this function if you require compatibility with an existing cryptosystem
  42  // that uses non-standard padding. All other users should use New512 instead.
  43  func NewLegacyKeccak512() hash.Hash {
  44  	return &state{rate: rateK1024, outputLen: 64, dsbyte: dsbyteKeccak}
  45  }
  46  
  47  // spongeDirection indicates the direction bytes are flowing through the sponge.
  48  type spongeDirection int
  49  
  50  const (
  51  	// spongeAbsorbing indicates that the sponge is absorbing input.
  52  	spongeAbsorbing spongeDirection = iota
  53  	// spongeSqueezing indicates that the sponge is being squeezed.
  54  	spongeSqueezing
  55  )
  56  
  57  type state struct {
  58  	a [1600 / 8]byte // main state of the hash
  59  
  60  	// a[n:rate] is the buffer. If absorbing, it's the remaining space to XOR
  61  	// into before running the permutation. If squeezing, it's the remaining
  62  	// output to produce before running the permutation.
  63  	n, rate int
  64  
  65  	// dsbyte contains the "domain separation" bits and the first bit of
  66  	// the padding. Sections 6.1 and 6.2 of [1] separate the outputs of the
  67  	// SHA-3 and SHAKE functions by appending bitstrings to the message.
  68  	// Using a little-endian bit-ordering convention, these are "01" for SHA-3
  69  	// and "1111" for SHAKE, or 00000010b and 00001111b, respectively. Then the
  70  	// padding rule from section 5.1 is applied to pad the message to a multiple
  71  	// of the rate, which involves adding a "1" bit, zero or more "0" bits, and
  72  	// a final "1" bit. We merge the first "1" bit from the padding into dsbyte,
  73  	// giving 00000110b (0x06) and 00011111b (0x1f).
  74  	// [1] http://csrc.nist.gov/publications/drafts/fips-202/fips_202_draft.pdf
  75  	//     "Draft FIPS 202: SHA-3 Standard: Permutation-Based Hash and
  76  	//      Extendable-Output Functions (May 2014)"
  77  	dsbyte byte
  78  
  79  	outputLen int             // the default output size in bytes
  80  	state     spongeDirection // whether the sponge is absorbing or squeezing
  81  }
  82  
  83  // BlockSize returns the rate of sponge underlying this hash function.
  84  func (d *state) BlockSize() int { return d.rate }
  85  
  86  // Size returns the output size of the hash function in bytes.
  87  func (d *state) Size() int { return d.outputLen }
  88  
  89  // Reset clears the internal state by zeroing the sponge state and
  90  // the buffer indexes, and setting Sponge.state to absorbing.
  91  func (d *state) Reset() {
  92  	// Zero the permutation's state.
  93  	for i := range d.a {
  94  		d.a[i] = 0
  95  	}
  96  	d.state = spongeAbsorbing
  97  	d.n = 0
  98  }
  99  
 100  func (d *state) clone() *state {
 101  	ret := *d
 102  	return &ret
 103  }
 104  
 105  // permute applies the KeccakF-1600 permutation.
 106  func (d *state) permute() {
 107  	var a *[25]uint64
 108  	if cpu.IsBigEndian {
 109  		a = new([25]uint64)
 110  		for i := range a {
 111  			a[i] = binary.LittleEndian.Uint64(d.a[i*8:])
 112  		}
 113  	} else {
 114  		a = (*[25]uint64)(unsafe.Pointer(&d.a))
 115  	}
 116  
 117  	keccakF1600(a)
 118  	d.n = 0
 119  
 120  	if cpu.IsBigEndian {
 121  		for i := range a {
 122  			binary.LittleEndian.PutUint64(d.a[i*8:], a[i])
 123  		}
 124  	}
 125  }
 126  
 127  // pads appends the domain separation bits in dsbyte, applies
 128  // the multi-bitrate 10..1 padding rule, and permutes the state.
 129  func (d *state) padAndPermute() {
 130  	// Pad with this instance's domain-separator bits. We know that there's
 131  	// at least one byte of space in the sponge because, if it were full,
 132  	// permute would have been called to empty it. dsbyte also contains the
 133  	// first one bit for the padding. See the comment in the state struct.
 134  	d.a[d.n] ^= d.dsbyte
 135  	// This adds the final one bit for the padding. Because of the way that
 136  	// bits are numbered from the LSB upwards, the final bit is the MSB of
 137  	// the last byte.
 138  	d.a[d.rate-1] ^= 0x80
 139  	// Apply the permutation
 140  	d.permute()
 141  	d.state = spongeSqueezing
 142  }
 143  
 144  // Write absorbs more data into the hash's state. It panics if any
 145  // output has already been read.
 146  func (d *state) Write(p []byte) (n int, err error) {
 147  	if d.state != spongeAbsorbing {
 148  		panic("sha3: Write after Read")
 149  	}
 150  
 151  	n = len(p)
 152  
 153  	for len(p) > 0 {
 154  		x := subtle.XORBytes(d.a[d.n:d.rate], d.a[d.n:d.rate], p)
 155  		d.n += x
 156  		p = p[x:]
 157  
 158  		// If the sponge is full, apply the permutation.
 159  		if d.n == d.rate {
 160  			d.permute()
 161  		}
 162  	}
 163  
 164  	return
 165  }
 166  
 167  // Read squeezes an arbitrary number of bytes from the sponge.
 168  func (d *state) Read(out []byte) (n int, err error) {
 169  	// If we're still absorbing, pad and apply the permutation.
 170  	if d.state == spongeAbsorbing {
 171  		d.padAndPermute()
 172  	}
 173  
 174  	n = len(out)
 175  
 176  	// Now, do the squeezing.
 177  	for len(out) > 0 {
 178  		// Apply the permutation if we've squeezed the sponge dry.
 179  		if d.n == d.rate {
 180  			d.permute()
 181  		}
 182  
 183  		x := copy(out, d.a[d.n:d.rate])
 184  		d.n += x
 185  		out = out[x:]
 186  	}
 187  
 188  	return
 189  }
 190  
 191  // Sum applies padding to the hash state and then squeezes out the desired
 192  // number of output bytes. It panics if any output has already been read.
 193  func (d *state) Sum(in []byte) []byte {
 194  	if d.state != spongeAbsorbing {
 195  		panic("sha3: Sum after Read")
 196  	}
 197  
 198  	// Make a copy of the original hash so that caller can keep writing
 199  	// and summing.
 200  	dup := d.clone()
 201  	hash := make([]byte, dup.outputLen, 64) // explicit cap to allow stack allocation
 202  	dup.Read(hash)
 203  	return append(in, hash...)
 204  }
 205  
 206  const (
 207  	magicKeccak = "sha\x0b"
 208  	// magic || rate || main state || n || sponge direction
 209  	marshaledSize = len(magicKeccak) + 1 + 200 + 1 + 1
 210  )
 211  
 212  func (d *state) MarshalBinary() ([]byte, error) {
 213  	return d.AppendBinary(make([]byte, 0, marshaledSize))
 214  }
 215  
 216  func (d *state) AppendBinary(b []byte) ([]byte, error) {
 217  	switch d.dsbyte {
 218  	case dsbyteKeccak:
 219  		b = append(b, magicKeccak...)
 220  	default:
 221  		panic("unknown dsbyte")
 222  	}
 223  	// rate is at most 168, and n is at most rate.
 224  	b = append(b, byte(d.rate))
 225  	b = append(b, d.a[:]...)
 226  	b = append(b, byte(d.n), byte(d.state))
 227  	return b, nil
 228  }
 229  
 230  func (d *state) UnmarshalBinary(b []byte) error {
 231  	if len(b) != marshaledSize {
 232  		return errors.New("sha3: invalid hash state")
 233  	}
 234  
 235  	magic := string(b[:len(magicKeccak)])
 236  	b = b[len(magicKeccak):]
 237  	switch {
 238  	case magic == magicKeccak && d.dsbyte == dsbyteKeccak:
 239  	default:
 240  		return errors.New("sha3: invalid hash state identifier")
 241  	}
 242  
 243  	rate := int(b[0])
 244  	b = b[1:]
 245  	if rate != d.rate {
 246  		return errors.New("sha3: invalid hash state function")
 247  	}
 248  
 249  	copy(d.a[:], b)
 250  	b = b[len(d.a):]
 251  
 252  	n, state := int(b[0]), spongeDirection(b[1])
 253  	if n > d.rate {
 254  		return errors.New("sha3: invalid hash state")
 255  	}
 256  	d.n = n
 257  	if state != spongeAbsorbing && state != spongeSqueezing {
 258  		return errors.New("sha3: invalid hash state")
 259  	}
 260  	d.state = state
 261  
 262  	return nil
 263  }
 264