1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980 |
- package internal
- //go:generate go run chacha_core_gen.go
- import (
- "encoding/binary"
- )
- const (
- wordSize = 4 // the size of ChaCha20's words
- stateSize = 16 // the size of ChaCha20's state, in words
- blockSize = stateSize * wordSize // the size of ChaCha20's block, in bytes
- )
- type ChaCha20Stream struct {
- state [stateSize]uint32 // the state as an array of 16 32-bit words
- block [blockSize]byte // the keystream as an array of 64 bytes
- offset int // the offset of used bytes in block
- rounds int
- }
- func NewChaCha20Stream(key []byte, nonce []byte, rounds int) *ChaCha20Stream {
- s := new(ChaCha20Stream)
- // the magic constants for 256-bit keys
- s.state[0] = 0x61707865
- s.state[1] = 0x3320646e
- s.state[2] = 0x79622d32
- s.state[3] = 0x6b206574
- for i := 0; i < 8; i++ {
- s.state[i+4] = binary.LittleEndian.Uint32(key[i*4 : i*4+4])
- }
- switch len(nonce) {
- case 8:
- s.state[14] = binary.LittleEndian.Uint32(nonce[0:])
- s.state[15] = binary.LittleEndian.Uint32(nonce[4:])
- case 12:
- s.state[13] = binary.LittleEndian.Uint32(nonce[0:4])
- s.state[14] = binary.LittleEndian.Uint32(nonce[4:8])
- s.state[15] = binary.LittleEndian.Uint32(nonce[8:12])
- default:
- panic("bad nonce length")
- }
- s.rounds = rounds
- ChaCha20Block(&s.state, s.block[:], s.rounds)
- return s
- }
- func (s *ChaCha20Stream) XORKeyStream(dst, src []byte) {
- // Stride over the input in 64-byte blocks, minus the amount of keystream
- // previously used. This will produce best results when processing blocks
- // of a size evenly divisible by 64.
- i := 0
- max := len(src)
- for i < max {
- gap := blockSize - s.offset
- limit := i + gap
- if limit > max {
- limit = max
- }
- o := s.offset
- for j := i; j < limit; j++ {
- dst[j] = src[j] ^ s.block[o]
- o++
- }
- i += gap
- s.offset = o
- if o == blockSize {
- s.offset = 0
- s.state[12]++
- ChaCha20Block(&s.state, s.block[:], s.rounds)
- }
- }
- }
|