<commit_before><?php namespace WRS;

/**
 * Calculates ChaCha20 blocks based on a given (key, nonce, ctr) set
 */
class ChaCha20Block {

    /**
     * ChaCha20 works on 32-bit integers
     */
    const INT_BIT_LENGTH = 32;
    const INT_BIT_MASK = 0xFFFFFFFF;

    /**
     * Define the ChaCha20 state format
     */
    const STATE_CONST_LENGTH = 4;
    const STATE_CONST_BASEINDEX = 0;
    const STATE_KEY_LENGTH = 8;
    const STATE_KEY_BASEINDEX = 4;
    const STATE_COUNTER_LENGTH = 1;
    const STATE_COUNTER_BASEINDEX = 12;
    const STATE_NONCE_LENGTH = 3;
    const STATE_NONCE_BASEINDEX = 13;

    const STATE_ARRAY_LENGTH = self::STATE_CONST_LENGTH
        + self::STATE_KEY_LENGTH
        + self::STATE_COUNTER_LENGTH
        + self::STATE_NONCE_LENGTH;

    /**
     * These are the ChaCha20 constants. They are not magical,
     * nor cryptographically designed : the represent an ascii-str
     * "expand 32-byte k" when written as 4 LITTLE-endian uint32
     */
    const CONSTANT_VALUE_0 = 0x61707865; // "expa"
    const CONSTANT_VALUE_1 = 0x3320646e; // "nd 3"
    const CONSTANT_VALUE_2 = 0x79622d32; // "2-by"
    const CONSTANT_VALUE_3 = 0x6b206574; // "te k"

    /**
     * Number of full (column + diagonal) iterations
     */
    const FULL_QUARTER_ROUND_ITERATIONS = 10;

    /**
     * internal state is what is built when key, nonce, ctr are modified
     */
    private $initial_state;

    /**
     * final state is the output of the calculation
     */
    private $final_state;

    /**
     * ensures that every manipulated value is truncated to integer length
     *
     * @return uint32    an integer capped at INT_BIT_MASK bits
     */
    protected function cap($value) {
        return $value & self::INT_BIT_MASK;
    }

    /**
     * rotate bits to the left by $n bits
     *
     * @param uint32    $value      value to rotate
     * @param int       $left       number of slots to rotate
     *
     * @return uint32   $value rotated $nbits to the left
     */
    protected function rot_left($value, $left) {
        if ($left < 0 or $left >= self::INT_BIT_LENGTH) {
            throw new Exception(sprintf("Left bitwise-rotation %d is outstide range [0..%d[", $left, self::INT_BIT_LENGTH));
        }
        $first = $value;
        $lp = $this->cap($value << $left);
        $rp = $this->cap($value >> (self::INT_BIT_LENGTH - $left));
        $value = $lp | $rp;
        return $value;
    }

    /**
     * does a bitwise XOR between the arguments
     *
     * @return uint32    an integer capped at INT_BIT_MASK bits
     */
    protected function xor($a, $b) {
        return $a ^ $b;
    }

    /**
     * add two integers and cap the sum to the required number of bits
     *
     * @return uint32    an integer capped at INT_BIT_MASK bits
     */
    protected function add_cap($a, $b) {
        return $this->cap($a + $b);
    }

    /**
     * initialize internal "const" values one by one
     *
     * @param int       $index      index in const range
     * @param uint32    $value      value to store
     */
    private function set_const($index, $value) {
        if ($index < 0 or $index >= self::STATE_CONST_LENGTH) {
            throw new Exception(sprintf("Const index %d is outstide range [0..%d[", $index, self::STATE_CONST_LENGTH.'['));
        }
        $this->initial_state[self::STATE_CONST_BASEINDEX + $index] = $this->cap($value);
    }

    /**
     * initialize internal "key" values one by one
     *
     * @param int       $index      index in key range
     * @param uint32    $value      value to store
     */
    public function set_key_index_uint32($index, $value) {
        if ($index < 0 or $index >= self::STATE_KEY_LENGTH) {
            throw new Exception(sprintf("Key index %d is outstide range [0..%d[", $index, self::STATE_KEY_LENGTH.'['));
        }
        $this->initial_state[self::STATE_KEY_BASEINDEX + $index] = $this->cap($value);
    }

    /**
     * initialize internal "nonce" values one by one
     *
     * @param int       $index      index in nonce range
     * @param uint32    $value      value to store
     */
    public function set_nonce_index_uint32($index, $value) {
        if ($index < 0 or $index >= self::STATE_NONCE_LENGTH) {
            throw new Exception(sprintf("Nonce index %d is outstide range [0..%d[", $index, self::STATE_NONCE_LENGTH.'['));
        }
        $this->initial_state[self::STATE_NONCE_BASEINDEX + $index] = $this->cap($value);
    }

    /**
     * initialize internal "block-counter" index
     *
     * @param uint32    $position   new block-counter index
     */
    public function set_counter($position) {
        $this->initial_state[self::STATE_COUNTER_BASEINDEX] = $this->cap($position);
    }

    /**
     * increment internal "block-counter" value by $step
     *
     * @param uint32    $step       step added to current block-counter value
     */
    public function inc_counter($step = 1) {
        $curval = $this->initial_state[self::STATE_COUNTER_BASEINDEX];
        $newval = $this->cap($curval + $step);
        $this->set_counter($newval);
    }

    /**
     * puts binary data to internal state
     *
     * extract $num little-endian uint32 from a least-significant-bit-starting
     * BINARY str named $name, and places these uint32's into internal-state
     * starting at $index
     *
     * @param   binary_string     $str    binary string holding little-endian uint32's
     */
    private function bin_to_internal($str, $name, $index, $num) {
        assert ($index > 0);
        assert ($num > 0);
        assert ($index + $num <= self::STATE_ARRAY_LENGTH);
        // check for input length
        $req_len = $num * self::INT_BIT_LENGTH >> 3;
        if (strlen($str) !== $req_len) {
            throw new Exception($name.' "'.bin2hex($str).'" is not a '.$req_len.'-bits long hex string');<commit_msg>switch util methods to static<commit_after><?php namespace WRS;

/**
 * Calculates ChaCha20 blocks based on a given (key, nonce, ctr) set
 */
class ChaCha20Block {

    /**
     * ChaCha20 works on 32-bit integers
     */
    const INT_BIT_LENGTH = 32;
    const INT_BIT_MASK = 0xFFFFFFFF;

    /**
     * Define the ChaCha20 state format
     */
    const STATE_CONST_LENGTH = 4;
    const STATE_CONST_BASEINDEX = 0;
    const STATE_KEY_LENGTH = 8;
    const STATE_KEY_BASEINDEX = 4;
    const STATE_COUNTER_LENGTH = 1;
    const STATE_COUNTER_BASEINDEX = 12;
    const STATE_NONCE_LENGTH = 3;
    const STATE_NONCE_BASEINDEX = 13;

    const STATE_ARRAY_LENGTH = self::STATE_CONST_LENGTH
        + self::STATE_KEY_LENGTH
        + self::STATE_COUNTER_LENGTH
        + self::STATE_NONCE_LENGTH;

    /**
     * These are the ChaCha20 constants. They are not magical,
     * nor cryptographically designed : the represent an ascii-str
     * "expand 32-byte k" when written as 4 LITTLE-endian uint32
     */
    const CONSTANT_VALUE_0 = 0x61707865; // "expa"
    const CONSTANT_VALUE_1 = 0x3320646e; // "nd 3"
    const CONSTANT_VALUE_2 = 0x79622d32; // "2-by"
    const CONSTANT_VALUE_3 = 0x6b206574; // "te k"

    /**
     * Number of full (column + diagonal) iterations
     */
    const FULL_QUARTER_ROUND_ITERATIONS = 10;

    /**
     * internal state is what is built when key, nonce, ctr are modified
     */
    private $initial_state;

    /**
     * final state is the output of the calculation
     */
    private $final_state;

    /**
     * ensures that every manipulated value is truncated to integer length
     *
     * @return uint32    an integer capped at INT_BIT_MASK bits
     */
    public static function cap($value) {
        return $value & self::INT_BIT_MASK;
    }

    /**
     * rotate bits to the left by $n bits
     *
     * @param uint32    $value      value to rotate
     * @param int       $left       number of slots to rotate
     *
     * @return uint32   $value rotated $nbits to the left
     */
    public static function rot_left($value, $left) {
        if ($left < 0 or $left >= self::INT_BIT_LENGTH) {
            throw new ChaCha20Exception(sprintf("Left bitwise-rotation %d is outstide range [0..%d[", $left, self::INT_BIT_LENGTH));
        }
        $first = $value;
        $lp = self::cap($value << $left);
        $rp = self::cap($value >> (self::INT_BIT_LENGTH - $left));
        $value = $lp | $rp;
        return $value;
    }

    /**
     * does a bitwise XOR between the arguments
     *
     * @return uint32    an integer capped at INT_BIT_MASK bits
     */
    public static function xor($a, $b) {
        return $a ^ $b;
    }

    /**
     * add two integers and cap the sum to the required number of bits
     *
     * @return uint32    an integer capped at INT_BIT_MASK bits
     */
    public static function add_cap($a, $b) {
        return self::cap($a + $b);
    }

    /**
     * initialize initial state's "const" values one by one
     *
     * @param int       $index      index in const range
     * @param uint32    $value      value to store
     */
    public function set_const($index, $value) {
        if ($index < 0 or $index >= self::STATE_CONST_LENGTH) {
            throw new ChaCha20Exception(sprintf("Const index %d is outstide range [0..%d[", $index, self::STATE_CONST_LENGTH.'['));
        }
        $this->initial_state[self::STATE_CONST_BASEINDEX + $index] = $this->cap($value);
    }

    /**
     * initialize initial state's "key" values one by one
     *
     * @param int       $index      index in key range
     * @param uint32    $value      value to store
     */
    public function set_key_index_uint32($index, $value) {
        if ($index < 0 or $index >= self::STATE_KEY_LENGTH) {
            throw new ChaCha20Exception(sprintf("Key index %d is outstide range [0..%d[", $index, self::STATE_KEY_LENGTH.'['));
        }
        $this->initial_state[self::STATE_KEY_BASEINDEX + $index] = $this->cap($value);
    }

    /**
     * initialize initial state's "nonce" values one by one
     *
     * @param int       $index      index in nonce range
     * @param uint32    $value      value to store
     */
    public function set_nonce_index_uint32($index, $value) {
        if ($index < 0 or $index >= self::STATE_NONCE_LENGTH) {
            throw new ChaCha20Exception(sprintf("Nonce index %d is outstide range [0..%d[", $index, self::STATE_NONCE_LENGTH.'['));
        }
        $this->initial_state[self::STATE_NONCE_BASEINDEX + $index] = $this->cap($value);
    }

    /**
     * initialize initial state's "block-counter" index
     *
     * @param uint32    $position   new block-counter index
     */
    public function set_counter($position) {
        $this->initial_state[self::STATE_COUNTER_BASEINDEX] = $this->cap($position);
    }

    /**
     * increment initial state's "block-counter" value by $step
     *
     * @param uint32    $step       step added to current block-counter value
     */
    public function inc_counter($step = 1) {
        $curval = $this->initial_state[self::STATE_COUNTER_BASEINDEX];
        $newval = $this->cap($curval + $step);
        $this->set_counter($newval);
    }

    /**
     * puts binary data to internal state
     *
     * extract $num little-endian uint32 from a least-significant-bit-starting
     * BINARY str named $name, and places these uint32's into internal-state
     * starting at $index
     *
     * @param   binary_string     $str    binary string holding little-endian uint32's
     */
    public function bin_to_internal($str, $name, $index, $num) {
        if ($index < 0) {
            throw new ChaCha20Exception(sprintf("Index %d cannot be negative", $index));
        }
        if ($num < 0) {
            throw new ChaCha20Exception(sprintf("Amount %d cannot be negative", $num));
        }
        if ($index + $num > self::STATE_ARRAY_LENGTH) {
            throw new ChaCha20Exception(sprintf("Cannot copy %d numbers starting at index %d as it would exceed target size of %d", $num, $index, self::STATE_ARRAY_LENGTH));
        }
        // check for input length
        $req_len = $num * self::INT_BIT_LENGTH >> 3;
        if (strlen($str) !== $req_len) {
            throw new ChaCha20Exception(sprintf('%s "%s" is not a %d-bits long hex string', $name, bin2hex($str), $req_len));
{'fraction_non_alphanumeric': 0.11625438811331537, 'fraction_numerical': 0.0199199934688546, 'mean_word_length': 2.3580043859649122, 'pattern_counts': {'":': 0, '<': 20, '<?xml version=': 0, '>': 47, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4401482', 'n_tokens_mistral': 4019, 'n_tokens_neox': 3767, 'n_words': 1096}