...

Source file src/golang.org/x/crypto/sha3/sha3.go

Documentation: golang.org/x/crypto/sha3

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

View as plain text