<?php 
declare(strict_types=1); 
 
/** 
 * Class ParagonIE_Sodium_Core_SecretStream_State 
 */ 
class ParagonIE_Sodium_Core_SecretStream_State 
{ 
    protected string $key; 
    protected int $counter; 
    protected string $nonce; 
    protected string $_pad; 
 
    /** 
     * ParagonIE_Sodium_Core_SecretStream_State constructor. 
     * @param string $key 
     * @param string|null $nonce 
     */ 
    public function __construct( 
        #[SensitiveParameter] 
        string $key, 
        ?string $nonce = null 
    ) { 
        $this->key = $key; 
        $this->counter = 1; 
        if (is_null($nonce)) { 
            $nonce = str_repeat("\0", 12); 
        } 
        $this->nonce = str_pad($nonce, 12, "\0"); 
        $this->_pad = str_repeat("\0", 4); 
    } 
 
    /** 
     * @return self 
     */ 
    public function counterReset(): self 
    { 
        $this->counter = 1; 
        $this->_pad = str_repeat("\0", 4); 
        return $this; 
    } 
 
    /** 
     * @return string 
     */ 
    public function getKey(): string 
    { 
        return $this->key; 
    } 
 
    /** 
     * @return string 
     */ 
    public function getCounter(): string 
    { 
        return ParagonIE_Sodium_Core_Util::store32_le($this->counter); 
    } 
 
    /** 
     * @return string 
     */ 
    public function getNonce(): string 
    { 
        if (ParagonIE_Sodium_Core_Util::strlen($this->nonce) !== 12) { 
            $this->nonce = str_pad($this->nonce, 12, "\0"); 
        } 
        return $this->nonce; 
    } 
 
    /** 
     * @return string 
     */ 
    public function getCombinedNonce(): string 
    { 
        return $this->getCounter() . 
            ParagonIE_Sodium_Core_Util::substr($this->getNonce(), 0, 8); 
    } 
 
    /** 
     * @return self 
     */ 
    public function incrementCounter(): self 
    { 
        ++$this->counter; 
        return $this; 
    } 
 
    /** 
     * @return bool 
     */ 
    public function needsRekey(): bool 
    { 
        return ($this->counter & 0xffff) === 0; 
    } 
 
    /** 
     * @param string $newKeyAndNonce 
     * @return self 
     */ 
    public function rekey( 
        #[SensitiveParameter] 
        string $newKeyAndNonce 
    ): self { 
        $this->key = ParagonIE_Sodium_Core_Util::substr($newKeyAndNonce, 0, 32); 
        $this->nonce = str_pad( 
            ParagonIE_Sodium_Core_Util::substr($newKeyAndNonce, 32), 
            12, 
            "\0" 
        ); 
        return $this; 
    } 
 
    /** 
     * @param string $str 
     * @return self 
     */ 
    public function xorNonce( 
        #[SensitiveParameter] 
        string $str 
    ): self { 
        $this->nonce = ParagonIE_Sodium_Core_Util::xorStrings( 
            $this->getNonce(), 
            str_pad( 
                ParagonIE_Sodium_Core_Util::substr($str, 0, 8), 
                12, 
                "\0" 
            ) 
        ); 
        return $this; 
    } 
 
    /** 
     * @param string $string 
     * @return self 
     */ 
    public static function fromString( 
        #[SensitiveParameter] 
        string $string 
    ): self { 
        $state = new ParagonIE_Sodium_Core_SecretStream_State( 
            ParagonIE_Sodium_Core_Util::substr($string, 0, 32) 
        ); 
        $state->counter = ParagonIE_Sodium_Core_Util::load_4( 
            ParagonIE_Sodium_Core_Util::substr($string, 32, 4) 
        ); 
        $state->nonce = ParagonIE_Sodium_Core_Util::substr($string, 36, 12); 
        $state->_pad = ParagonIE_Sodium_Core_Util::substr($string, 48, 8); 
        return $state; 
    } 
 
    /** 
     * @return string 
     */ 
    public function toString(): string 
    { 
        return $this->key . 
            $this->getCounter() . 
            $this->nonce . 
            $this->_pad; 
    } 
} 
 
 |