Current File : /home/k/a/r/karenpetzb/www/items/category/Core.tar
XSalsa20.php000064400000002533150712117330006615 0ustar00<?php

if (class_exists('ParagonIE_Sodium_Core_XSalsa20', false)) {
    return;
}

/**
 * Class ParagonIE_Sodium_Core_XSalsa20
 */
abstract class ParagonIE_Sodium_Core_XSalsa20 extends ParagonIE_Sodium_Core_HSalsa20
{
    /**
     * Expand a key and nonce into an xsalsa20 keystream.
     *
     * @internal You should not use this directly from another application
     *
     * @param int $len
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function xsalsa20($len, $nonce, $key)
    {
        $ret = self::salsa20(
            $len,
            self::substr($nonce, 16, 8),
            self::hsalsa20($nonce, $key)
        );
        return $ret;
    }

    /**
     * Encrypt a string with XSalsa20. Doesn't provide integrity.
     *
     * @internal You should not use this directly from another application
     *
     * @param string $message
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function xsalsa20_xor($message, $nonce, $key)
    {
        return self::xorStrings(
            $message,
            self::xsalsa20(
                self::strlen($message),
                $nonce,
                $key
            )
        );
    }
}
SecretStream/State.php000064400000007050150712117330010740 0ustar00<?php

/**
 * Class ParagonIE_Sodium_Core_SecretStream_State
 */
class ParagonIE_Sodium_Core_SecretStream_State
{
    /** @var string $key */
    protected $key;

    /** @var int $counter */
    protected $counter;

    /** @var string $nonce */
    protected $nonce;

    /** @var string $_pad */
    protected $_pad;

    /**
     * ParagonIE_Sodium_Core_SecretStream_State constructor.
     * @param string $key
     * @param string|null $nonce
     */
    public function __construct($key, $nonce = null)
    {
        $this->key = $key;
        $this->counter = 1;
        if (is_null($nonce)) {
            $nonce = str_repeat("\0", 12);
        }
        $this->nonce = str_pad($nonce, 12, "\0", STR_PAD_RIGHT);;
        $this->_pad = str_repeat("\0", 4);
    }

    /**
     * @return self
     */
    public function counterReset()
    {
        $this->counter = 1;
        $this->_pad = str_repeat("\0", 4);
        return $this;
    }

    /**
     * @return string
     */
    public function getKey()
    {
        return $this->key;
    }

    /**
     * @return string
     */
    public function getCounter()
    {
        return ParagonIE_Sodium_Core_Util::store32_le($this->counter);
    }

    /**
     * @return string
     */
    public function getNonce()
    {
        if (!is_string($this->nonce)) {
            $this->nonce = str_repeat("\0", 12);
        }
        if (ParagonIE_Sodium_Core_Util::strlen($this->nonce) !== 12) {
            $this->nonce = str_pad($this->nonce, 12, "\0", STR_PAD_RIGHT);
        }
        return $this->nonce;
    }

    /**
     * @return string
     */
    public function getCombinedNonce()
    {
        return $this->getCounter() .
            ParagonIE_Sodium_Core_Util::substr($this->getNonce(), 0, 8);
    }

    /**
     * @return self
     */
    public function incrementCounter()
    {
        ++$this->counter;
        return $this;
    }

    /**
     * @return bool
     */
    public function needsRekey()
    {
        return ($this->counter & 0xffff) === 0;
    }

    /**
     * @param string $newKeyAndNonce
     * @return self
     */
    public function rekey($newKeyAndNonce)
    {
        $this->key = ParagonIE_Sodium_Core_Util::substr($newKeyAndNonce, 0, 32);
        $this->nonce = str_pad(
            ParagonIE_Sodium_Core_Util::substr($newKeyAndNonce, 32),
            12,
            "\0",
            STR_PAD_RIGHT
        );
        return $this;
    }

    /**
     * @param string $str
     * @return self
     */
    public function xorNonce($str)
    {
        $this->nonce = ParagonIE_Sodium_Core_Util::xorStrings(
            $this->getNonce(),
            str_pad(
                ParagonIE_Sodium_Core_Util::substr($str, 0, 8),
                12,
                "\0",
                STR_PAD_RIGHT
            )
        );
        return $this;
    }

    /**
     * @param string $string
     * @return self
     */
    public static function fromString($string)
    {
        $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()
    {
        return $this->key .
            $this->getCounter() .
            $this->nonce .
            $this->_pad;
    }
}
Util.php000064400000000134150712117330006170 0ustar00<?php
namespace ParagonIE\Sodium\Core;

class Util extends \ParagonIE_Sodium_Core_Util
{

}
AES/KeySchedule.php000064400000003531150712117330010074 0ustar00<?php

if (class_exists('ParagonIE_Sodium_Core_AES_KeySchedule', false)) {
    return;
}

/**
 * @internal This should only be used by sodium_compat
 */
class ParagonIE_Sodium_Core_AES_KeySchedule
{
    /** @var array<int, int> $skey -- has size 120 */
    protected $skey;

    /** @var bool $expanded */
    protected $expanded = false;

    /** @var int $numRounds */
    private $numRounds;

    /**
     * @param array $skey
     * @param int $numRounds
     */
    public function __construct(array $skey, $numRounds = 10)
    {
        $this->skey = $skey;
        $this->numRounds = $numRounds;
    }

    /**
     * Get a value at an arbitrary index. Mostly used for unit testing.
     *
     * @param int $i
     * @return int
     */
    public function get($i)
    {
        return $this->skey[$i];
    }

    /**
     * @return int
     */
    public function getNumRounds()
    {
        return $this->numRounds;
    }

    /**
     * @param int $offset
     * @return ParagonIE_Sodium_Core_AES_Block
     */
    public function getRoundKey($offset)
    {
        return ParagonIE_Sodium_Core_AES_Block::fromArray(
            array_slice($this->skey, $offset, 8)
        );
    }

    /**
     * Return an expanded key schedule
     *
     * @return ParagonIE_Sodium_Core_AES_Expanded
     */
    public function expand()
    {
        $exp = new ParagonIE_Sodium_Core_AES_Expanded(
            array_fill(0, 120, 0),
            $this->numRounds
        );
        $n = ($exp->numRounds + 1) << 2;
        for ($u = 0, $v = 0; $u < $n; ++$u, $v += 2) {
            $x = $y = $this->skey[$u];
            $x &= 0x55555555;
            $exp->skey[$v] = ($x | ($x << 1)) & ParagonIE_Sodium_Core_Util::U32_MAX;
            $y &= 0xAAAAAAAA;
            $exp->skey[$v + 1] = ($y | ($y >> 1)) & ParagonIE_Sodium_Core_Util::U32_MAX;
        }
        return $exp;
    }
}
AES/Block.php000064400000024342150712117330006724 0ustar00<?php

if (class_exists('ParagonIE_Sodium_Core_AES_Block', false)) {
    return;
}

/**
 * @internal This should only be used by sodium_compat
 */
class ParagonIE_Sodium_Core_AES_Block extends SplFixedArray
{
    /**
     * @var array<int, int>
     */
    protected $values = array();

    /**
     * @var int
     */
    protected $size;

    /**
     * @param int $size
     */
    public function __construct($size = 8)
    {
        parent::__construct($size);
        $this->size = $size;
        $this->values = array_fill(0, $size, 0);
    }

    /**
     * @return self
     */
    public static function init()
    {
        return new self(8);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param array<int, int> $array
     * @param bool $save_indexes
     * @return self
     *
     * @psalm-suppress MethodSignatureMismatch
     */
    #[ReturnTypeWillChange]
    public static function fromArray($array, $save_indexes = null)
    {
        $count = count($array);
        if ($save_indexes) {
            $keys = array_keys($array);
        } else {
            $keys = range(0, $count - 1);
        }
        $array = array_values($array);
        /** @var array<int, int> $keys */

        $obj = new ParagonIE_Sodium_Core_AES_Block();
        if ($save_indexes) {
            for ($i = 0; $i < $count; ++$i) {
                $obj->offsetSet($keys[$i], $array[$i]);
            }
        } else {
            for ($i = 0; $i < $count; ++$i) {
                $obj->offsetSet($i, $array[$i]);
            }
        }
        return $obj;
    }


    /**
     * @internal You should not use this directly from another application
     *
     * @param int|null $offset
     * @param int $value
     * @return void
     *
     * @psalm-suppress MethodSignatureMismatch
     * @psalm-suppress MixedArrayOffset
     */
    #[ReturnTypeWillChange]
    public function offsetSet($offset, $value)
    {
        if (!is_int($value)) {
            throw new InvalidArgumentException('Expected an integer');
        }
        if (is_null($offset)) {
            $this->values[] = $value;
        } else {
            $this->values[$offset] = $value;
        }
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param int $offset
     * @return bool
     *
     * @psalm-suppress MethodSignatureMismatch
     * @psalm-suppress MixedArrayOffset
     */
    #[ReturnTypeWillChange]
    public function offsetExists($offset)
    {
        return isset($this->values[$offset]);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param int $offset
     * @return void
     *
     * @psalm-suppress MethodSignatureMismatch
     * @psalm-suppress MixedArrayOffset
     */
    #[ReturnTypeWillChange]
    public function offsetUnset($offset)
    {
        unset($this->values[$offset]);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param int $offset
     * @return int
     *
     * @psalm-suppress MethodSignatureMismatch
     * @psalm-suppress MixedArrayOffset
     */
    #[ReturnTypeWillChange]
    public function offsetGet($offset)
    {
        if (!isset($this->values[$offset])) {
            $this->values[$offset] = 0;
        }
        return (int) ($this->values[$offset]);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @return array
     */
    public function __debugInfo()
    {
        $out = array();
        foreach ($this->values as $v) {
            $out[] = str_pad(dechex($v), 8, '0', STR_PAD_LEFT);
        }
        return array(implode(', ', $out));
        /*
         return array(implode(', ', $this->values));
         */
    }

    /**
     * @param int $cl low bit mask
     * @param int $ch high bit mask
     * @param int $s shift
     * @param int $x index 1
     * @param int $y index 2
     * @return self
     */
    public function swapN($cl, $ch, $s, $x, $y)
    {
        static $u32mask = ParagonIE_Sodium_Core_Util::U32_MAX;
        $a = $this->values[$x] & $u32mask;
        $b = $this->values[$y] & $u32mask;
        // (x) = (a & cl) | ((b & cl) << (s));
        $this->values[$x] = ($a & $cl) | ((($b & $cl) << $s) & $u32mask);
        // (y) = ((a & ch) >> (s)) | (b & ch);
        $this->values[$y] = ((($a & $ch) & $u32mask) >> $s) | ($b & $ch);
        return $this;
    }

    /**
     * @param int $x index 1
     * @param int $y index 2
     * @return self
     */
    public function swap2($x, $y)
    {
        return $this->swapN(0x55555555, 0xAAAAAAAA, 1, $x, $y);
    }

    /**
     * @param int $x index 1
     * @param int $y index 2
     * @return self
     */
    public function swap4($x, $y)
    {
        return $this->swapN(0x33333333, 0xCCCCCCCC, 2, $x, $y);
    }

    /**
     * @param int $x index 1
     * @param int $y index 2
     * @return self
     */
    public function swap8($x, $y)
    {
        return $this->swapN(0x0F0F0F0F, 0xF0F0F0F0, 4, $x, $y);
    }

    /**
     * @return self
     */
    public function orthogonalize()
    {
        return $this
            ->swap2(0, 1)
            ->swap2(2, 3)
            ->swap2(4, 5)
            ->swap2(6, 7)

            ->swap4(0, 2)
            ->swap4(1, 3)
            ->swap4(4, 6)
            ->swap4(5, 7)

            ->swap8(0, 4)
            ->swap8(1, 5)
            ->swap8(2, 6)
            ->swap8(3, 7);
    }

    /**
     * @return self
     */
    public function shiftRows()
    {
        for ($i = 0; $i < 8; ++$i) {
            $x = $this->values[$i] & ParagonIE_Sodium_Core_Util::U32_MAX;
            $this->values[$i] = (
                ($x & 0x000000FF)
                    | (($x & 0x0000FC00) >> 2) | (($x & 0x00000300) << 6)
                    | (($x & 0x00F00000) >> 4) | (($x & 0x000F0000) << 4)
                    | (($x & 0xC0000000) >> 6) | (($x & 0x3F000000) << 2)
            ) & ParagonIE_Sodium_Core_Util::U32_MAX;
        }
        return $this;
    }

    /**
     * @param int $x
     * @return int
     */
    public static function rotr16($x)
    {
        return (($x << 16) & ParagonIE_Sodium_Core_Util::U32_MAX) | ($x >> 16);
    }

    /**
     * @return self
     */
    public function mixColumns()
    {
        $q0 = $this->values[0];
        $q1 = $this->values[1];
        $q2 = $this->values[2];
        $q3 = $this->values[3];
        $q4 = $this->values[4];
        $q5 = $this->values[5];
        $q6 = $this->values[6];
        $q7 = $this->values[7];
        $r0 = (($q0 >> 8) | ($q0 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX;
        $r1 = (($q1 >> 8) | ($q1 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX;
        $r2 = (($q2 >> 8) | ($q2 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX;
        $r3 = (($q3 >> 8) | ($q3 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX;
        $r4 = (($q4 >> 8) | ($q4 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX;
        $r5 = (($q5 >> 8) | ($q5 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX;
        $r6 = (($q6 >> 8) | ($q6 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX;
        $r7 = (($q7 >> 8) | ($q7 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX;

        $this->values[0] = $q7 ^ $r7 ^ $r0 ^ self::rotr16($q0 ^ $r0);
        $this->values[1] = $q0 ^ $r0 ^ $q7 ^ $r7 ^ $r1 ^ self::rotr16($q1 ^ $r1);
        $this->values[2] = $q1 ^ $r1 ^ $r2 ^ self::rotr16($q2 ^ $r2);
        $this->values[3] = $q2 ^ $r2 ^ $q7 ^ $r7 ^ $r3 ^ self::rotr16($q3 ^ $r3);
        $this->values[4] = $q3 ^ $r3 ^ $q7 ^ $r7 ^ $r4 ^ self::rotr16($q4 ^ $r4);
        $this->values[5] = $q4 ^ $r4 ^ $r5 ^ self::rotr16($q5 ^ $r5);
        $this->values[6] = $q5 ^ $r5 ^ $r6 ^ self::rotr16($q6 ^ $r6);
        $this->values[7] = $q6 ^ $r6 ^ $r7 ^ self::rotr16($q7 ^ $r7);
        return $this;
    }

    /**
     * @return self
     */
    public function inverseMixColumns()
    {
        $q0 = $this->values[0];
        $q1 = $this->values[1];
        $q2 = $this->values[2];
        $q3 = $this->values[3];
        $q4 = $this->values[4];
        $q5 = $this->values[5];
        $q6 = $this->values[6];
        $q7 = $this->values[7];
        $r0 = (($q0 >> 8) | ($q0 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX;
        $r1 = (($q1 >> 8) | ($q1 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX;
        $r2 = (($q2 >> 8) | ($q2 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX;
        $r3 = (($q3 >> 8) | ($q3 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX;
        $r4 = (($q4 >> 8) | ($q4 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX;
        $r5 = (($q5 >> 8) | ($q5 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX;
        $r6 = (($q6 >> 8) | ($q6 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX;
        $r7 = (($q7 >> 8) | ($q7 << 24)) & ParagonIE_Sodium_Core_Util::U32_MAX;

        $this->values[0] = $q5 ^ $q6 ^ $q7 ^ $r0 ^ $r5 ^ $r7 ^ self::rotr16($q0 ^ $q5 ^ $q6 ^ $r0 ^ $r5);
        $this->values[1] = $q0 ^ $q5 ^ $r0 ^ $r1 ^ $r5 ^ $r6 ^ $r7 ^ self::rotr16($q1 ^ $q5 ^ $q7 ^ $r1 ^ $r5 ^ $r6);
        $this->values[2] = $q0 ^ $q1 ^ $q6 ^ $r1 ^ $r2 ^ $r6 ^ $r7 ^ self::rotr16($q0 ^ $q2 ^ $q6 ^ $r2 ^ $r6 ^ $r7);
        $this->values[3] = $q0 ^ $q1 ^ $q2 ^ $q5 ^ $q6 ^ $r0 ^ $r2 ^ $r3 ^ $r5 ^ self::rotr16($q0 ^ $q1 ^ $q3 ^ $q5 ^ $q6 ^ $q7 ^ $r0 ^ $r3 ^ $r5 ^ $r7);
        $this->values[4] = $q1 ^ $q2 ^ $q3 ^ $q5 ^ $r1 ^ $r3 ^ $r4 ^ $r5 ^ $r6 ^ $r7 ^ self::rotr16($q1 ^ $q2 ^ $q4 ^ $q5 ^ $q7 ^ $r1 ^ $r4 ^ $r5 ^ $r6);
        $this->values[5] = $q2 ^ $q3 ^ $q4 ^ $q6 ^ $r2 ^ $r4 ^ $r5 ^ $r6 ^ $r7 ^ self::rotr16($q2 ^ $q3 ^ $q5 ^ $q6 ^ $r2 ^ $r5 ^ $r6 ^ $r7);
        $this->values[6] = $q3 ^ $q4 ^ $q5 ^ $q7 ^ $r3 ^ $r5 ^ $r6 ^ $r7 ^ self::rotr16($q3 ^ $q4 ^ $q6 ^ $q7 ^ $r3 ^ $r6 ^ $r7);
        $this->values[7] = $q4 ^ $q5 ^ $q6 ^ $r4 ^ $r6 ^ $r7 ^ self::rotr16($q4 ^ $q5 ^ $q7 ^ $r4 ^ $r7);
        return $this;
    }

    /**
     * @return self
     */
    public function inverseShiftRows()
    {
        for ($i = 0; $i < 8; ++$i) {
            $x = $this->values[$i];
            $this->values[$i] = ParagonIE_Sodium_Core_Util::U32_MAX & (
                ($x & 0x000000FF)
                    | (($x & 0x00003F00) << 2) | (($x & 0x0000C000) >> 6)
                    | (($x & 0x000F0000) << 4) | (($x & 0x00F00000) >> 4)
                    | (($x & 0x03000000) << 6) | (($x & 0xFC000000) >> 2)
            );
        }
        return $this;
    }
}
AES/Expanded.php000064400000000460150712117330007415 0ustar00<?php

if (class_exists('ParagonIE_Sodium_Core_AES_Expanded', false)) {
    return;
}

/**
 * @internal This should only be used by sodium_compat
 */
class ParagonIE_Sodium_Core_AES_Expanded extends ParagonIE_Sodium_Core_AES_KeySchedule
{
    /** @var bool $expanded */
    protected $expanded = true;
}
Poly1305/State.php000064400000000160150712117330007566 0ustar00<?php
namespace ParagonIE\Sodium\Core\Poly1305;

class State extends \ParagonIE_Sodium_Core_Poly1305_State
{

}
Ed25519.php000064400000000142150712117330006210 0ustar00<?php
namespace ParagonIE\Sodium\Core;

class Ed25519 extends \ParagonIE_Sodium_Core_Ed25519
{

}
XChaCha20.php000064400000000146150712117330006657 0ustar00<?php
namespace ParagonIE\Sodium\Core;

class XChaCha20 extends \ParagonIE_Sodium_Core_XChaCha20
{

}
Base64/UrlSafe.php000064400000017063150712117330007651 0ustar00<?php

/**
 * Class ParagonIE_Sodium_Core_Base64UrlSafe
 *
 *  Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
 *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
 */
class ParagonIE_Sodium_Core_Base64_UrlSafe
{
    // COPY ParagonIE_Sodium_Core_Base64_Common STARTING HERE
    /**
     * Encode into Base64
     *
     * Base64 character set "[A-Z][a-z][0-9]+/"
     *
     * @param string $src
     * @return string
     * @throws TypeError
     */
    public static function encode($src)
    {
        return self::doEncode($src, true);
    }

    /**
     * Encode into Base64, no = padding
     *
     * Base64 character set "[A-Z][a-z][0-9]+/"
     *
     * @param string $src
     * @return string
     * @throws TypeError
     */
    public static function encodeUnpadded($src)
    {
        return self::doEncode($src, false);
    }

    /**
     * @param string $src
     * @param bool $pad   Include = padding?
     * @return string
     * @throws TypeError
     */
    protected static function doEncode($src, $pad = true)
    {
        $dest = '';
        $srcLen = ParagonIE_Sodium_Core_Util::strlen($src);
        // Main loop (no padding):
        for ($i = 0; $i + 3 <= $srcLen; $i += 3) {
            /** @var array<int, int> $chunk */
            $chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, 3));
            $b0 = $chunk[1];
            $b1 = $chunk[2];
            $b2 = $chunk[3];

            $dest .=
                self::encode6Bits(               $b0 >> 2       ) .
                self::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) .
                self::encode6Bits((($b1 << 2) | ($b2 >> 6)) & 63) .
                self::encode6Bits(  $b2                     & 63);
        }
        // The last chunk, which may have padding:
        if ($i < $srcLen) {
            /** @var array<int, int> $chunk */
            $chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, $srcLen - $i));
            $b0 = $chunk[1];
            if ($i + 1 < $srcLen) {
                $b1 = $chunk[2];
                $dest .=
                    self::encode6Bits($b0 >> 2) .
                    self::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) .
                    self::encode6Bits(($b1 << 2) & 63);
                if ($pad) {
                    $dest .= '=';
                }
            } else {
                $dest .=
                    self::encode6Bits( $b0 >> 2) .
                    self::encode6Bits(($b0 << 4) & 63);
                if ($pad) {
                    $dest .= '==';
                }
            }
        }
        return $dest;
    }

    /**
     * decode from base64 into binary
     *
     * Base64 character set "./[A-Z][a-z][0-9]"
     *
     * @param string $src
     * @param bool $strictPadding
     * @return string
     * @throws RangeException
     * @throws TypeError
     * @psalm-suppress RedundantCondition
     */
    public static function decode($src, $strictPadding = false)
    {
        // Remove padding
        $srcLen = ParagonIE_Sodium_Core_Util::strlen($src);
        if ($srcLen === 0) {
            return '';
        }

        if ($strictPadding) {
            if (($srcLen & 3) === 0) {
                if ($src[$srcLen - 1] === '=') {
                    $srcLen--;
                    if ($src[$srcLen - 1] === '=') {
                        $srcLen--;
                    }
                }
            }
            if (($srcLen & 3) === 1) {
                throw new RangeException(
                    'Incorrect padding'
                );
            }
            if ($src[$srcLen - 1] === '=') {
                throw new RangeException(
                    'Incorrect padding'
                );
            }
        } else {
            $src = rtrim($src, '=');
            $srcLen =  ParagonIE_Sodium_Core_Util::strlen($src);
        }

        $err = 0;
        $dest = '';
        // Main loop (no padding):
        for ($i = 0; $i + 4 <= $srcLen; $i += 4) {
            /** @var array<int, int> $chunk */
            $chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, 4));
            $c0 = self::decode6Bits($chunk[1]);
            $c1 = self::decode6Bits($chunk[2]);
            $c2 = self::decode6Bits($chunk[3]);
            $c3 = self::decode6Bits($chunk[4]);

            $dest .= pack(
                'CCC',
                ((($c0 << 2) | ($c1 >> 4)) & 0xff),
                ((($c1 << 4) | ($c2 >> 2)) & 0xff),
                ((($c2 << 6) | $c3) & 0xff)
            );
            $err |= ($c0 | $c1 | $c2 | $c3) >> 8;
        }
        // The last chunk, which may have padding:
        if ($i < $srcLen) {
            /** @var array<int, int> $chunk */
            $chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, $srcLen - $i));
            $c0 = self::decode6Bits($chunk[1]);

            if ($i + 2 < $srcLen) {
                $c1 = self::decode6Bits($chunk[2]);
                $c2 = self::decode6Bits($chunk[3]);
                $dest .= pack(
                    'CC',
                    ((($c0 << 2) | ($c1 >> 4)) & 0xff),
                    ((($c1 << 4) | ($c2 >> 2)) & 0xff)
                );
                $err |= ($c0 | $c1 | $c2) >> 8;
            } elseif ($i + 1 < $srcLen) {
                $c1 = self::decode6Bits($chunk[2]);
                $dest .= pack(
                    'C',
                    ((($c0 << 2) | ($c1 >> 4)) & 0xff)
                );
                $err |= ($c0 | $c1) >> 8;
            } elseif ($i < $srcLen && $strictPadding) {
                $err |= 1;
            }
        }
        /** @var bool $check */
        $check = ($err === 0);
        if (!$check) {
            throw new RangeException(
                'Base64::decode() only expects characters in the correct base64 alphabet'
            );
        }
        return $dest;
    }
    // COPY ParagonIE_Sodium_Core_Base64_Common ENDING HERE
    /**
     * Uses bitwise operators instead of table-lookups to turn 6-bit integers
     * into 8-bit integers.
     *
     * Base64 character set:
     * [A-Z]      [a-z]      [0-9]      +     /
     * 0x41-0x5a, 0x61-0x7a, 0x30-0x39, 0x2b, 0x2f
     *
     * @param int $src
     * @return int
     */
    protected static function decode6Bits($src)
    {
        $ret = -1;

        // if ($src > 0x40 && $src < 0x5b) $ret += $src - 0x41 + 1; // -64
        $ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 64);

        // if ($src > 0x60 && $src < 0x7b) $ret += $src - 0x61 + 26 + 1; // -70
        $ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 70);

        // if ($src > 0x2f && $src < 0x3a) $ret += $src - 0x30 + 52 + 1; // 5
        $ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src + 5);

        // if ($src == 0x2c) $ret += 62 + 1;
        $ret += (((0x2c - $src) & ($src - 0x2e)) >> 8) & 63;

        // if ($src == 0x5f) ret += 63 + 1;
        $ret += (((0x5e - $src) & ($src - 0x60)) >> 8) & 64;

        return $ret;
    }

    /**
     * Uses bitwise operators instead of table-lookups to turn 8-bit integers
     * into 6-bit integers.
     *
     * @param int $src
     * @return string
     */
    protected static function encode6Bits($src)
    {
        $diff = 0x41;

        // if ($src > 25) $diff += 0x61 - 0x41 - 26; // 6
        $diff += ((25 - $src) >> 8) & 6;

        // if ($src > 51) $diff += 0x30 - 0x61 - 26; // -75
        $diff -= ((51 - $src) >> 8) & 75;

        // if ($src > 61) $diff += 0x2d - 0x30 - 10; // -13
        $diff -= ((61 - $src) >> 8) & 13;

        // if ($src > 62) $diff += 0x5f - 0x2b - 1; // 3
        $diff += ((62 - $src) >> 8) & 49;

        return pack('C', $src + $diff);
    }
}
Base64/Original.php000064400000017055150712117330010055 0ustar00<?php

/**
 * Class ParagonIE_Sodium_Core_Base64
 *
 *  Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
 *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
 */
class ParagonIE_Sodium_Core_Base64_Original
{
    // COPY ParagonIE_Sodium_Core_Base64_Common STARTING HERE
    /**
     * Encode into Base64
     *
     * Base64 character set "[A-Z][a-z][0-9]+/"
     *
     * @param string $src
     * @return string
     * @throws TypeError
     */
    public static function encode($src)
    {
        return self::doEncode($src, true);
    }

    /**
     * Encode into Base64, no = padding
     *
     * Base64 character set "[A-Z][a-z][0-9]+/"
     *
     * @param string $src
     * @return string
     * @throws TypeError
     */
    public static function encodeUnpadded($src)
    {
        return self::doEncode($src, false);
    }

    /**
     * @param string $src
     * @param bool $pad   Include = padding?
     * @return string
     * @throws TypeError
     */
    protected static function doEncode($src, $pad = true)
    {
        $dest = '';
        $srcLen = ParagonIE_Sodium_Core_Util::strlen($src);
        // Main loop (no padding):
        for ($i = 0; $i + 3 <= $srcLen; $i += 3) {
            /** @var array<int, int> $chunk */
            $chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, 3));
            $b0 = $chunk[1];
            $b1 = $chunk[2];
            $b2 = $chunk[3];

            $dest .=
                self::encode6Bits(               $b0 >> 2       ) .
                self::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) .
                self::encode6Bits((($b1 << 2) | ($b2 >> 6)) & 63) .
                self::encode6Bits(  $b2                     & 63);
        }
        // The last chunk, which may have padding:
        if ($i < $srcLen) {
            /** @var array<int, int> $chunk */
            $chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, $srcLen - $i));
            $b0 = $chunk[1];
            if ($i + 1 < $srcLen) {
                $b1 = $chunk[2];
                $dest .=
                    self::encode6Bits($b0 >> 2) .
                    self::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) .
                    self::encode6Bits(($b1 << 2) & 63);
                if ($pad) {
                    $dest .= '=';
                }
            } else {
                $dest .=
                    self::encode6Bits( $b0 >> 2) .
                    self::encode6Bits(($b0 << 4) & 63);
                if ($pad) {
                    $dest .= '==';
                }
            }
        }
        return $dest;
    }

    /**
     * decode from base64 into binary
     *
     * Base64 character set "./[A-Z][a-z][0-9]"
     *
     * @param string $src
     * @param bool $strictPadding
     * @return string
     * @throws RangeException
     * @throws TypeError
     * @psalm-suppress RedundantCondition
     */
    public static function decode($src, $strictPadding = false)
    {
        // Remove padding
        $srcLen = ParagonIE_Sodium_Core_Util::strlen($src);
        if ($srcLen === 0) {
            return '';
        }

        if ($strictPadding) {
            if (($srcLen & 3) === 0) {
                if ($src[$srcLen - 1] === '=') {
                    $srcLen--;
                    if ($src[$srcLen - 1] === '=') {
                        $srcLen--;
                    }
                }
            }
            if (($srcLen & 3) === 1) {
                throw new RangeException(
                    'Incorrect padding'
                );
            }
            if ($src[$srcLen - 1] === '=') {
                throw new RangeException(
                    'Incorrect padding'
                );
            }
        } else {
            $src = rtrim($src, '=');
            $srcLen =  ParagonIE_Sodium_Core_Util::strlen($src);
        }

        $err = 0;
        $dest = '';
        // Main loop (no padding):
        for ($i = 0; $i + 4 <= $srcLen; $i += 4) {
            /** @var array<int, int> $chunk */
            $chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, 4));
            $c0 = self::decode6Bits($chunk[1]);
            $c1 = self::decode6Bits($chunk[2]);
            $c2 = self::decode6Bits($chunk[3]);
            $c3 = self::decode6Bits($chunk[4]);

            $dest .= pack(
                'CCC',
                ((($c0 << 2) | ($c1 >> 4)) & 0xff),
                ((($c1 << 4) | ($c2 >> 2)) & 0xff),
                ((($c2 << 6) | $c3) & 0xff)
            );
            $err |= ($c0 | $c1 | $c2 | $c3) >> 8;
        }
        // The last chunk, which may have padding:
        if ($i < $srcLen) {
            /** @var array<int, int> $chunk */
            $chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, $srcLen - $i));
            $c0 = self::decode6Bits($chunk[1]);

            if ($i + 2 < $srcLen) {
                $c1 = self::decode6Bits($chunk[2]);
                $c2 = self::decode6Bits($chunk[3]);
                $dest .= pack(
                    'CC',
                    ((($c0 << 2) | ($c1 >> 4)) & 0xff),
                    ((($c1 << 4) | ($c2 >> 2)) & 0xff)
                );
                $err |= ($c0 | $c1 | $c2) >> 8;
            } elseif ($i + 1 < $srcLen) {
                $c1 = self::decode6Bits($chunk[2]);
                $dest .= pack(
                    'C',
                    ((($c0 << 2) | ($c1 >> 4)) & 0xff)
                );
                $err |= ($c0 | $c1) >> 8;
            } elseif ($i < $srcLen && $strictPadding) {
                $err |= 1;
            }
        }
        /** @var bool $check */
        $check = ($err === 0);
        if (!$check) {
            throw new RangeException(
                'Base64::decode() only expects characters in the correct base64 alphabet'
            );
        }
        return $dest;
    }
    // COPY ParagonIE_Sodium_Core_Base64_Common ENDING HERE

    /**
     * Uses bitwise operators instead of table-lookups to turn 6-bit integers
     * into 8-bit integers.
     *
     * Base64 character set:
     * [A-Z]      [a-z]      [0-9]      +     /
     * 0x41-0x5a, 0x61-0x7a, 0x30-0x39, 0x2b, 0x2f
     *
     * @param int $src
     * @return int
     */
    protected static function decode6Bits($src)
    {
        $ret = -1;

        // if ($src > 0x40 && $src < 0x5b) $ret += $src - 0x41 + 1; // -64
        $ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 64);

        // if ($src > 0x60 && $src < 0x7b) $ret += $src - 0x61 + 26 + 1; // -70
        $ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 70);

        // if ($src > 0x2f && $src < 0x3a) $ret += $src - 0x30 + 52 + 1; // 5
        $ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src + 5);

        // if ($src == 0x2b) $ret += 62 + 1;
        $ret += (((0x2a - $src) & ($src - 0x2c)) >> 8) & 63;

        // if ($src == 0x2f) ret += 63 + 1;
        $ret += (((0x2e - $src) & ($src - 0x30)) >> 8) & 64;

        return $ret;
    }

    /**
     * Uses bitwise operators instead of table-lookups to turn 8-bit integers
     * into 6-bit integers.
     *
     * @param int $src
     * @return string
     */
    protected static function encode6Bits($src)
    {
        $diff = 0x41;

        // if ($src > 25) $diff += 0x61 - 0x41 - 26; // 6
        $diff += ((25 - $src) >> 8) & 6;

        // if ($src > 51) $diff += 0x30 - 0x61 - 26; // -75
        $diff -= ((51 - $src) >> 8) & 75;

        // if ($src > 61) $diff += 0x2b - 0x30 - 10; // -15
        $diff -= ((61 - $src) >> 8) & 15;

        // if ($src > 62) $diff += 0x2f - 0x2b - 1; // 3
        $diff += ((62 - $src) >> 8) & 3;

        return pack('C', $src + $diff);
    }
}
X25519.php000064400000000140150712117330006065 0ustar00<?php
namespace ParagonIE\Sodium\Core;

class X25519 extends \ParagonIE_Sodium_Core_X25519
{

}
Poly1305.php000064400000000144150712117330006510 0ustar00<?php
namespace ParagonIE\Sodium\Core;

class Poly1305 extends \ParagonIE_Sodium_Core_Poly1305
{

}
ChaCha20/Ctx.php000064400000000154150712117330007264 0ustar00<?php
namespace ParagonIE\Sodium\Core\ChaCha20;

class Ctx extends \ParagonIE_Sodium_Core_ChaCha20_Ctx
{

}
ChaCha20/IetfCtx.php000064400000000164150712117330010075 0ustar00<?php
namespace ParagonIE\Sodium\Core\ChaCha20;

class IetfCtx extends \ParagonIE_Sodium_Core_ChaCha20_IetfCtx
{

}
AEGIS128L.php000064400000007124150712117330006460 0ustar00<?php

if (!defined('SODIUM_COMPAT_AEGIS_C0')) {
    define('SODIUM_COMPAT_AEGIS_C0', "\x00\x01\x01\x02\x03\x05\x08\x0d\x15\x22\x37\x59\x90\xe9\x79\x62");
}
if (!defined('SODIUM_COMPAT_AEGIS_C1')) {
    define('SODIUM_COMPAT_AEGIS_C1', "\xdb\x3d\x18\x55\x6d\xc2\x2f\xf1\x20\x11\x31\x42\x73\xb5\x28\xdd");
}

class ParagonIE_Sodium_Core_AEGIS128L extends ParagonIE_Sodium_Core_AES
{
    /**
     * @param string $ct
     * @param string $tag
     * @param string $ad
     * @param string $key
     * @param string $nonce
     * @return string
     * @throws SodiumException
     */
    public static function decrypt($ct, $tag, $ad, $key, $nonce)
    {
        $state = self::init($key, $nonce);
        $ad_blocks = (self::strlen($ad) + 31) >> 5;
        for ($i = 0; $i < $ad_blocks; ++$i) {
            $ai = self::substr($ad, $i << 5, 32);
            if (self::strlen($ai) < 32) {
                $ai = str_pad($ai, 32, "\0", STR_PAD_RIGHT);
            }
            $state->absorb($ai);
        }

        $msg = '';
        $cn = self::strlen($ct) & 31;
        $ct_blocks = self::strlen($ct) >> 5;
        for ($i = 0; $i < $ct_blocks; ++$i) {
            $msg .= $state->dec(self::substr($ct, $i << 5, 32));
        }
        if ($cn) {
            $start = $ct_blocks << 5;
            $msg .= $state->decPartial(self::substr($ct, $start, $cn));
        }
        $expected_tag = $state->finalize(
            self::strlen($ad) << 3,
            self::strlen($msg) << 3
        );
        if (!self::hashEquals($expected_tag, $tag)) {
            try {
                // The RFC says to erase msg, so we shall try:
                ParagonIE_Sodium_Compat::memzero($msg);
            } catch (SodiumException $ex) {
                // Do nothing if we cannot memzero
            }
            throw new SodiumException('verification failed');
        }
        return $msg;
    }

    /**
     * @param string $msg
     * @param string $ad
     * @param string $key
     * @param string $nonce
     * @return array
     *
     * @throws SodiumException
     */
    public static function encrypt($msg, $ad, $key, $nonce)
    {
        $state = self::init($key, $nonce);
        // ad_blocks = Split(ZeroPad(ad, 256), 256)
        // for ai in ad_blocks:
        //     Absorb(ai)
        $ad_len = self::strlen($ad);
        $msg_len = self::strlen($msg);
        $ad_blocks = ($ad_len + 31) >> 5;
        for ($i = 0; $i < $ad_blocks; ++$i) {
            $ai = self::substr($ad, $i << 5, 32);
            if (self::strlen($ai) < 32) {
                $ai = str_pad($ai, 32, "\0", STR_PAD_RIGHT);
            }
            $state->absorb($ai);
        }

        // msg_blocks = Split(ZeroPad(msg, 256), 256)
        // for xi in msg_blocks:
        //     ct = ct || Enc(xi)
        $ct = '';
        $msg_blocks = ($msg_len + 31) >> 5;
        for ($i = 0; $i < $msg_blocks; ++$i) {
            $xi = self::substr($msg, $i << 5, 32);
            if (self::strlen($xi) < 32) {
                $xi = str_pad($xi, 32, "\0", STR_PAD_RIGHT);
            }
            $ct .= $state->enc($xi);
        }
        // tag = Finalize(|ad|, |msg|)
        // ct = Truncate(ct, |msg|)
        $tag = $state->finalize(
            $ad_len << 3,
            $msg_len << 3
        );
        // return ct and tag
        return array(
            self::substr($ct, 0, $msg_len),
            $tag
        );
    }

    /**
     * @param string $key
     * @param string $nonce
     * @return ParagonIE_Sodium_Core_AEGIS_State128L
     */
    public static function init($key, $nonce)
    {
        return ParagonIE_Sodium_Core_AEGIS_State128L::init($key, $nonce);
    }
}
HChaCha20.php000064400000000146150712117330006637 0ustar00<?php
namespace ParagonIE\Sodium\Core;

class HChaCha20 extends \ParagonIE_Sodium_Core_HChaCha20
{

}
Salsa20.php000064400000000142150712117330006457 0ustar00<?php
namespace ParagonIE\Sodium\Core;

class Salsa20 extends \ParagonIE_Sodium_Core_Salsa20
{

}
Curve25519/Ge/Precomp.php000064400000000176150712117330010713 0ustar00<?php
namespace ParagonIE\Sodium\Core\Curve25519\Ge;

class Precomp extends \ParagonIE_Sodium_Core_Curve25519_Ge_Precomp
{

}
Curve25519/Ge/P2.php000064400000000164150712117330007564 0ustar00<?php
namespace ParagonIE\Sodium\Core\Curve25519\Ge;

class P2 extends \ParagonIE_Sodium_Core_Curve25519_Ge_P2
{

}
Curve25519/Ge/P3.php000064400000000164150712117330007565 0ustar00<?php
namespace ParagonIE\Sodium\Core\Curve25519\Ge;

class P3 extends \ParagonIE_Sodium_Core_Curve25519_Ge_P3
{

}
Curve25519/Ge/P1p1.php000064400000000170150712117330010021 0ustar00<?php
namespace ParagonIE\Sodium\Core\Curve25519\Ge;

class P1p1 extends \ParagonIE_Sodium_Core_Curve25519_Ge_P1p1
{

}
Curve25519/Ge/Cached.php000064400000000174150712117330010453 0ustar00<?php
namespace ParagonIE\Sodium\Core\Curve25519\Ge;

class Cached extends \ParagonIE_Sodium_Core_Curve25519_Ge_Cached
{

}
Curve25519/Fe.php000064400000000156150712117330007303 0ustar00<?php
namespace ParagonIE\Sodium\Core\Curve25519;

class Fe extends \ParagonIE_Sodium_Core_Curve25519_Fe
{

}
Curve25519/H.php000064400000000154150712117330007136 0ustar00<?php
namespace ParagonIE\Sodium\Core\Curve25519;

class H extends \ParagonIE_Sodium_Core_Curve25519_H
{

}
Curve25519/README.md000064400000000332150712117330007513 0ustar00# Curve25519 Data Structures

These are PHP implementation of the [structs used in the ref10 curve25519 code](https://github.com/jedisct1/libsodium/blob/master/src/libsodium/include/sodium/private/curve25519_ref10.h).
AES.php000064400000037015150712117330005673 0ustar00<?php

if (class_exists('ParagonIE_Sodium_Core_AES', false)) {
    return;
}

/**
 * Bitsliced implementation of the AES block cipher.
 *
 * Based on the implementation provided by BearSSL.
 *
 * @internal This should only be used by sodium_compat
 */
class ParagonIE_Sodium_Core_AES extends ParagonIE_Sodium_Core_Util
{
    /**
     * @var int[] AES round constants
     */
    private static $Rcon = array(
        0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36
    );

    /**
     * Mutates the values of $q!
     *
     * @param ParagonIE_Sodium_Core_AES_Block $q
     * @return void
     */
    public static function sbox(ParagonIE_Sodium_Core_AES_Block $q)
    {
        /**
         * @var int $x0
         * @var int $x1
         * @var int $x2
         * @var int $x3
         * @var int $x4
         * @var int $x5
         * @var int $x6
         * @var int $x7
         */
        $x0 = $q[7] & self::U32_MAX;
        $x1 = $q[6] & self::U32_MAX;
        $x2 = $q[5] & self::U32_MAX;
        $x3 = $q[4] & self::U32_MAX;
        $x4 = $q[3] & self::U32_MAX;
        $x5 = $q[2] & self::U32_MAX;
        $x6 = $q[1] & self::U32_MAX;
        $x7 = $q[0] & self::U32_MAX;

        $y14 = $x3 ^ $x5;
        $y13 = $x0 ^ $x6;
        $y9 = $x0 ^ $x3;
        $y8 = $x0 ^ $x5;
        $t0 = $x1 ^ $x2;
        $y1 = $t0 ^ $x7;
        $y4 = $y1 ^ $x3;
        $y12 = $y13 ^ $y14;
        $y2 = $y1 ^ $x0;
        $y5 = $y1 ^ $x6;
        $y3 = $y5 ^ $y8;
        $t1 = $x4 ^ $y12;
        $y15 = $t1 ^ $x5;
        $y20 = $t1 ^ $x1;
        $y6 = $y15 ^ $x7;
        $y10 = $y15 ^ $t0;
        $y11 = $y20 ^ $y9;
        $y7 = $x7 ^ $y11;
        $y17 = $y10 ^ $y11;
        $y19 = $y10 ^ $y8;
        $y16 = $t0 ^ $y11;
        $y21 = $y13 ^ $y16;
        $y18 = $x0 ^ $y16;

        /*
         * Non-linear section.
         */
        $t2 = $y12 & $y15;
        $t3 = $y3 & $y6;
        $t4 = $t3 ^ $t2;
        $t5 = $y4 & $x7;
        $t6 = $t5 ^ $t2;
        $t7 = $y13 & $y16;
        $t8 = $y5 & $y1;
        $t9 = $t8 ^ $t7;
        $t10 = $y2 & $y7;
        $t11 = $t10 ^ $t7;
        $t12 = $y9 & $y11;
        $t13 = $y14 & $y17;
        $t14 = $t13 ^ $t12;
        $t15 = $y8 & $y10;
        $t16 = $t15 ^ $t12;
        $t17 = $t4 ^ $t14;
        $t18 = $t6 ^ $t16;
        $t19 = $t9 ^ $t14;
        $t20 = $t11 ^ $t16;
        $t21 = $t17 ^ $y20;
        $t22 = $t18 ^ $y19;
        $t23 = $t19 ^ $y21;
        $t24 = $t20 ^ $y18;

        $t25 = $t21 ^ $t22;
        $t26 = $t21 & $t23;
        $t27 = $t24 ^ $t26;
        $t28 = $t25 & $t27;
        $t29 = $t28 ^ $t22;
        $t30 = $t23 ^ $t24;
        $t31 = $t22 ^ $t26;
        $t32 = $t31 & $t30;
        $t33 = $t32 ^ $t24;
        $t34 = $t23 ^ $t33;
        $t35 = $t27 ^ $t33;
        $t36 = $t24 & $t35;
        $t37 = $t36 ^ $t34;
        $t38 = $t27 ^ $t36;
        $t39 = $t29 & $t38;
        $t40 = $t25 ^ $t39;

        $t41 = $t40 ^ $t37;
        $t42 = $t29 ^ $t33;
        $t43 = $t29 ^ $t40;
        $t44 = $t33 ^ $t37;
        $t45 = $t42 ^ $t41;
        $z0 = $t44 & $y15;
        $z1 = $t37 & $y6;
        $z2 = $t33 & $x7;
        $z3 = $t43 & $y16;
        $z4 = $t40 & $y1;
        $z5 = $t29 & $y7;
        $z6 = $t42 & $y11;
        $z7 = $t45 & $y17;
        $z8 = $t41 & $y10;
        $z9 = $t44 & $y12;
        $z10 = $t37 & $y3;
        $z11 = $t33 & $y4;
        $z12 = $t43 & $y13;
        $z13 = $t40 & $y5;
        $z14 = $t29 & $y2;
        $z15 = $t42 & $y9;
        $z16 = $t45 & $y14;
        $z17 = $t41 & $y8;

        /*
         * Bottom linear transformation.
         */
        $t46 = $z15 ^ $z16;
        $t47 = $z10 ^ $z11;
        $t48 = $z5 ^ $z13;
        $t49 = $z9 ^ $z10;
        $t50 = $z2 ^ $z12;
        $t51 = $z2 ^ $z5;
        $t52 = $z7 ^ $z8;
        $t53 = $z0 ^ $z3;
        $t54 = $z6 ^ $z7;
        $t55 = $z16 ^ $z17;
        $t56 = $z12 ^ $t48;
        $t57 = $t50 ^ $t53;
        $t58 = $z4 ^ $t46;
        $t59 = $z3 ^ $t54;
        $t60 = $t46 ^ $t57;
        $t61 = $z14 ^ $t57;
        $t62 = $t52 ^ $t58;
        $t63 = $t49 ^ $t58;
        $t64 = $z4 ^ $t59;
        $t65 = $t61 ^ $t62;
        $t66 = $z1 ^ $t63;
        $s0 = $t59 ^ $t63;
        $s6 = $t56 ^ ~$t62;
        $s7 = $t48 ^ ~$t60;
        $t67 = $t64 ^ $t65;
        $s3 = $t53 ^ $t66;
        $s4 = $t51 ^ $t66;
        $s5 = $t47 ^ $t65;
        $s1 = $t64 ^ ~$s3;
        $s2 = $t55 ^ ~$t67;

        $q[7] = $s0 & self::U32_MAX;
        $q[6] = $s1 & self::U32_MAX;
        $q[5] = $s2 & self::U32_MAX;
        $q[4] = $s3 & self::U32_MAX;
        $q[3] = $s4 & self::U32_MAX;
        $q[2] = $s5 & self::U32_MAX;
        $q[1] = $s6 & self::U32_MAX;
        $q[0] = $s7 & self::U32_MAX;
    }

    /**
     * Mutates the values of $q!
     *
     * @param ParagonIE_Sodium_Core_AES_Block $q
     * @return void
     */
    public static function invSbox(ParagonIE_Sodium_Core_AES_Block $q)
    {
        self::processInversion($q);
        self::sbox($q);
        self::processInversion($q);
    }

    /**
     * This is some boilerplate code needed to invert an S-box. Rather than repeat the code
     * twice, I moved it to a protected method.
     *
     * Mutates $q
     *
     * @param ParagonIE_Sodium_Core_AES_Block $q
     * @return void
     */
    protected static function processInversion(ParagonIE_Sodium_Core_AES_Block $q)
    {
        $q0 = (~$q[0]) & self::U32_MAX;
        $q1 = (~$q[1]) & self::U32_MAX;
        $q2 = $q[2] & self::U32_MAX;
        $q3 = $q[3] & self::U32_MAX;
        $q4 = $q[4] & self::U32_MAX;
        $q5 = (~$q[5])  & self::U32_MAX;
        $q6 = (~$q[6])  & self::U32_MAX;
        $q7 = $q[7] & self::U32_MAX;
        $q[7] = ($q1 ^ $q4 ^ $q6) & self::U32_MAX;
        $q[6] = ($q0 ^ $q3 ^ $q5) & self::U32_MAX;
        $q[5] = ($q7 ^ $q2 ^ $q4) & self::U32_MAX;
        $q[4] = ($q6 ^ $q1 ^ $q3) & self::U32_MAX;
        $q[3] = ($q5 ^ $q0 ^ $q2) & self::U32_MAX;
        $q[2] = ($q4 ^ $q7 ^ $q1) & self::U32_MAX;
        $q[1] = ($q3 ^ $q6 ^ $q0) & self::U32_MAX;
        $q[0] = ($q2 ^ $q5 ^ $q7) & self::U32_MAX;
    }

    /**
     * @param int $x
     * @return int
     */
    public static function subWord($x)
    {
        $q = ParagonIE_Sodium_Core_AES_Block::fromArray(
            array($x, $x, $x, $x, $x, $x, $x, $x)
        );
        $q->orthogonalize();
        self::sbox($q);
        $q->orthogonalize();
        return $q[0] & self::U32_MAX;
    }

    /**
     * Calculate the key schedule from a given random key
     *
     * @param string $key
     * @return ParagonIE_Sodium_Core_AES_KeySchedule
     * @throws SodiumException
     */
    public static function keySchedule($key)
    {
        $key_len = self::strlen($key);
        switch ($key_len) {
            case 16:
                $num_rounds = 10;
                break;
            case 24:
                $num_rounds = 12;
                break;
            case 32:
                $num_rounds = 14;
                break;
            default:
                throw new SodiumException('Invalid key length: ' . $key_len);
        }
        $skey = array();
        $comp_skey = array();
        $nk = $key_len >> 2;
        $nkf = ($num_rounds + 1) << 2;
        $tmp = 0;

        for ($i = 0; $i < $nk; ++$i) {
            $tmp = self::load_4(self::substr($key, $i << 2, 4));
            $skey[($i << 1)] = $tmp;
            $skey[($i << 1) + 1] = $tmp;
        }

        for ($i = $nk, $j = 0, $k = 0; $i < $nkf; ++$i) {
            if ($j === 0) {
                $tmp = (($tmp & 0xff) << 24) | ($tmp >> 8);
                $tmp = (self::subWord($tmp) ^ self::$Rcon[$k]) & self::U32_MAX;
            } elseif ($nk > 6 && $j === 4) {
                $tmp = self::subWord($tmp);
            }
            $tmp ^= $skey[($i - $nk) << 1];
            $skey[($i << 1)] = $tmp & self::U32_MAX;
            $skey[($i << 1) + 1] = $tmp & self::U32_MAX;
            if (++$j === $nk) {
                /** @psalm-suppress LoopInvalidation */
                $j = 0;
                ++$k;
            }
        }
        for ($i = 0; $i < $nkf; $i += 4) {
            $q = ParagonIE_Sodium_Core_AES_Block::fromArray(
                array_slice($skey, $i << 1, 8)
            );
            $q->orthogonalize();
            // We have to overwrite $skey since we're not using C pointers like BearSSL did
            for ($j = 0; $j < 8; ++$j) {
                $skey[($i << 1) + $j] = $q[$j];
            }
        }
        for ($i = 0, $j = 0; $i < $nkf; ++$i, $j += 2) {
            $comp_skey[$i] = ($skey[$j] & 0x55555555)
                | ($skey[$j + 1] & 0xAAAAAAAA);
        }
        return new ParagonIE_Sodium_Core_AES_KeySchedule($comp_skey, $num_rounds);
    }

    /**
     * Mutates $q
     *
     * @param ParagonIE_Sodium_Core_AES_KeySchedule $skey
     * @param ParagonIE_Sodium_Core_AES_Block $q
     * @param int $offset
     * @return void
     */
    public static function addRoundKey(
        ParagonIE_Sodium_Core_AES_Block $q,
        ParagonIE_Sodium_Core_AES_KeySchedule $skey,
        $offset = 0
    ) {
        $block = $skey->getRoundKey($offset);
        for ($j = 0; $j < 8; ++$j) {
            $q[$j] = ($q[$j] ^ $block[$j]) & ParagonIE_Sodium_Core_Util::U32_MAX;
        }
    }

    /**
     * This mainly exists for testing, as we need the round key features for AEGIS.
     *
     * @param string $message
     * @param string $key
     * @return string
     * @throws SodiumException
     */
    public static function decryptBlockECB($message, $key)
    {
        if (self::strlen($message) !== 16) {
            throw new SodiumException('decryptBlockECB() expects a 16 byte message');
        }
        $skey = self::keySchedule($key)->expand();
        $q = ParagonIE_Sodium_Core_AES_Block::init();
        $q[0] = self::load_4(self::substr($message, 0, 4));
        $q[2] = self::load_4(self::substr($message, 4, 4));
        $q[4] = self::load_4(self::substr($message, 8, 4));
        $q[6] = self::load_4(self::substr($message, 12, 4));

        $q->orthogonalize();
        self::bitsliceDecryptBlock($skey, $q);
        $q->orthogonalize();

        return self::store32_le($q[0]) .
            self::store32_le($q[2]) .
            self::store32_le($q[4]) .
            self::store32_le($q[6]);
    }

    /**
     * This mainly exists for testing, as we need the round key features for AEGIS.
     *
     * @param string $message
     * @param string $key
     * @return string
     * @throws SodiumException
     */
    public static function encryptBlockECB($message, $key)
    {
        if (self::strlen($message) !== 16) {
            throw new SodiumException('encryptBlockECB() expects a 16 byte message');
        }
        $comp_skey = self::keySchedule($key);
        $skey = $comp_skey->expand();
        $q = ParagonIE_Sodium_Core_AES_Block::init();
        $q[0] = self::load_4(self::substr($message, 0, 4));
        $q[2] = self::load_4(self::substr($message, 4, 4));
        $q[4] = self::load_4(self::substr($message, 8, 4));
        $q[6] = self::load_4(self::substr($message, 12, 4));

        $q->orthogonalize();
        self::bitsliceEncryptBlock($skey, $q);
        $q->orthogonalize();

        return self::store32_le($q[0]) .
            self::store32_le($q[2]) .
            self::store32_le($q[4]) .
            self::store32_le($q[6]);
    }

    /**
     * Mutates $q
     *
     * @param ParagonIE_Sodium_Core_AES_Expanded $skey
     * @param ParagonIE_Sodium_Core_AES_Block $q
     * @return void
     */
    public static function bitsliceEncryptBlock(
        ParagonIE_Sodium_Core_AES_Expanded $skey,
        ParagonIE_Sodium_Core_AES_Block $q
    ) {
        self::addRoundKey($q, $skey);
        for ($u = 1; $u < $skey->getNumRounds(); ++$u) {
            self::sbox($q);
            $q->shiftRows();
            $q->mixColumns();
            self::addRoundKey($q, $skey, ($u << 3));
        }
        self::sbox($q);
        $q->shiftRows();
        self::addRoundKey($q, $skey, ($skey->getNumRounds() << 3));
    }

    /**
     * @param string $x
     * @param string $y
     * @return string
     */
    public static function aesRound($x, $y)
    {
        $q = ParagonIE_Sodium_Core_AES_Block::init();
        $q[0] = self::load_4(self::substr($x, 0, 4));
        $q[2] = self::load_4(self::substr($x, 4, 4));
        $q[4] = self::load_4(self::substr($x, 8, 4));
        $q[6] = self::load_4(self::substr($x, 12, 4));

        $rk = ParagonIE_Sodium_Core_AES_Block::init();
        $rk[0] = $rk[1] = self::load_4(self::substr($y, 0, 4));
        $rk[2] = $rk[3] = self::load_4(self::substr($y, 4, 4));
        $rk[4] = $rk[5] = self::load_4(self::substr($y, 8, 4));
        $rk[6] = $rk[7] = self::load_4(self::substr($y, 12, 4));

        $q->orthogonalize();
        self::sbox($q);
        $q->shiftRows();
        $q->mixColumns();
        $q->orthogonalize();
        // add round key without key schedule:
        for ($i = 0; $i < 8; ++$i) {
            $q[$i] ^= $rk[$i];
        }
        return self::store32_le($q[0]) .
            self::store32_le($q[2]) .
            self::store32_le($q[4]) .
            self::store32_le($q[6]);
    }

    /**
     * Process two AES blocks in one shot.
     *
     * @param string $b0  First AES block
     * @param string $rk0 First round key
     * @param string $b1  Second AES block
     * @param string $rk1 Second round key
     * @return string[]
     */
    public static function doubleRound($b0, $rk0, $b1, $rk1)
    {
        $q = ParagonIE_Sodium_Core_AES_Block::init();
        // First block
        $q[0] = self::load_4(self::substr($b0, 0, 4));
        $q[2] = self::load_4(self::substr($b0, 4, 4));
        $q[4] = self::load_4(self::substr($b0, 8, 4));
        $q[6] = self::load_4(self::substr($b0, 12, 4));
        // Second block
        $q[1] = self::load_4(self::substr($b1, 0, 4));
        $q[3] = self::load_4(self::substr($b1, 4, 4));
        $q[5] = self::load_4(self::substr($b1, 8, 4));
        $q[7] = self::load_4(self::substr($b1, 12, 4));;

        $rk = ParagonIE_Sodium_Core_AES_Block::init();
        // First round key
        $rk[0] = self::load_4(self::substr($rk0, 0, 4));
        $rk[2] = self::load_4(self::substr($rk0, 4, 4));
        $rk[4] = self::load_4(self::substr($rk0, 8, 4));
        $rk[6] = self::load_4(self::substr($rk0, 12, 4));
        // Second round key
        $rk[1] = self::load_4(self::substr($rk1, 0, 4));
        $rk[3] = self::load_4(self::substr($rk1, 4, 4));
        $rk[5] = self::load_4(self::substr($rk1, 8, 4));
        $rk[7] = self::load_4(self::substr($rk1, 12, 4));

        $q->orthogonalize();
        self::sbox($q);
        $q->shiftRows();
        $q->mixColumns();
        $q->orthogonalize();
        // add round key without key schedule:
        for ($i = 0; $i < 8; ++$i) {
            $q[$i] ^= $rk[$i];
        }
        return array(
            self::store32_le($q[0]) . self::store32_le($q[2]) . self::store32_le($q[4]) . self::store32_le($q[6]),
            self::store32_le($q[1]) . self::store32_le($q[3]) . self::store32_le($q[5]) . self::store32_le($q[7]),
        );
    }

    /**
     * @param ParagonIE_Sodium_Core_AES_Expanded $skey
     * @param ParagonIE_Sodium_Core_AES_Block $q
     * @return void
     */
    public static function bitsliceDecryptBlock(
        ParagonIE_Sodium_Core_AES_Expanded $skey,
        ParagonIE_Sodium_Core_AES_Block $q
    ) {
        self::addRoundKey($q, $skey, ($skey->getNumRounds() << 3));
        for ($u = $skey->getNumRounds() - 1; $u > 0; --$u) {
            $q->inverseShiftRows();
            self::invSbox($q);
            self::addRoundKey($q, $skey, ($u << 3));
            $q->inverseMixColumns();
        }
        $q->inverseShiftRows();
        self::invSbox($q);
        self::addRoundKey($q, $skey, ($u << 3));
    }
}
Curve25519.php000064400000000150150712117330006743 0ustar00<?php
namespace ParagonIE\Sodium\Core;

class Curve25519 extends \ParagonIE_Sodium_Core_Curve25519
{

}
AEGIS/State128L.php000064400000020052150712117330007533 0ustar00<?php

if (class_exists('ParagonIE_Sodium_Core_AEGIS_State128L', false)) {
    return;
}

if (!defined('SODIUM_COMPAT_AEGIS_C0')) {
    define('SODIUM_COMPAT_AEGIS_C0', "\x00\x01\x01\x02\x03\x05\x08\x0d\x15\x22\x37\x59\x90\xe9\x79\x62");
}
if (!defined('SODIUM_COMPAT_AEGIS_C1')) {
    define('SODIUM_COMPAT_AEGIS_C1', "\xdb\x3d\x18\x55\x6d\xc2\x2f\xf1\x20\x11\x31\x42\x73\xb5\x28\xdd");
}

class ParagonIE_Sodium_Core_AEGIS_State128L
{
    /** @var array<int, string> $state */
    protected $state;
    public function __construct()
    {
        $this->state = array_fill(0, 8, '');
    }

    /**
     * @internal Only use this for unit tests!
     * @return string[]
     */
    public function getState()
    {
        return array_values($this->state);
    }

    /**
     * @param array $input
     * @return self
     * @throws SodiumException
     *
     * @internal Only for unit tests
     */
    public static function initForUnitTests(array $input)
    {
        if (count($input) < 8) {
            throw new SodiumException('invalid input');
        }
        $state = new self();
        for ($i = 0; $i < 8; ++$i) {
            $state->state[$i] = $input[$i];
        }
        return $state;
    }

    /**
     * @param string $key
     * @param string $nonce
     * @return self
     */
    public static function init($key, $nonce)
    {
        $state = new self();

        // S0 = key ^ nonce
        $state->state[0] = $key ^ $nonce;
        // S1 = C1
        $state->state[1] = SODIUM_COMPAT_AEGIS_C1;
        // S2 = C0
        $state->state[2] = SODIUM_COMPAT_AEGIS_C0;
        // S3 = C1
        $state->state[3] = SODIUM_COMPAT_AEGIS_C1;
        // S4 = key ^ nonce
        $state->state[4] = $key ^ $nonce;
        // S5 = key ^ C0
        $state->state[5] = $key ^ SODIUM_COMPAT_AEGIS_C0;
        // S6 = key ^ C1
        $state->state[6] = $key ^ SODIUM_COMPAT_AEGIS_C1;
        // S7 = key ^ C0
        $state->state[7] = $key ^ SODIUM_COMPAT_AEGIS_C0;

        // Repeat(10, Update(nonce, key))
        for ($i = 0; $i < 10; ++$i) {
            $state->update($nonce, $key);
        }
        return $state;
    }

    /**
     * @param string $ai
     * @return self
     */
    public function absorb($ai)
    {
        if (ParagonIE_Sodium_Core_Util::strlen($ai) !== 32) {
            throw new SodiumException('Input must be two AES blocks in size');
        }
        $t0 = ParagonIE_Sodium_Core_Util::substr($ai, 0, 16);
        $t1 = ParagonIE_Sodium_Core_Util::substr($ai, 16, 16);
        return $this->update($t0, $t1);
    }


    /**
     * @param string $ci
     * @return string
     * @throws SodiumException
     */
    public function dec($ci)
    {
        if (ParagonIE_Sodium_Core_Util::strlen($ci) !== 32) {
            throw new SodiumException('Input must be two AES blocks in size');
        }

        // z0 = S6 ^ S1 ^ (S2 & S3)
        $z0 = $this->state[6]
            ^ $this->state[1]
            ^ ParagonIE_Sodium_Core_Util::andStrings($this->state[2], $this->state[3]);
        // z1 = S2 ^ S5 ^ (S6 & S7)
        $z1 = $this->state[2]
            ^ $this->state[5]
            ^ ParagonIE_Sodium_Core_Util::andStrings($this->state[6], $this->state[7]);

        // t0, t1 = Split(xi, 128)
        $t0 = ParagonIE_Sodium_Core_Util::substr($ci, 0, 16);
        $t1 = ParagonIE_Sodium_Core_Util::substr($ci, 16, 16);

        // out0 = t0 ^ z0
        // out1 = t1 ^ z1
        $out0 = $t0 ^ $z0;
        $out1 = $t1 ^ $z1;

        // Update(out0, out1)
        // xi = out0 || out1
        $this->update($out0, $out1);
        return $out0 . $out1;
    }

    /**
     * @param string $cn
     * @return string
     */
    public function decPartial($cn)
    {
        $len = ParagonIE_Sodium_Core_Util::strlen($cn);

        // z0 = S6 ^ S1 ^ (S2 & S3)
        $z0 = $this->state[6]
            ^ $this->state[1]
            ^ ParagonIE_Sodium_Core_Util::andStrings($this->state[2], $this->state[3]);
        // z1 = S2 ^ S5 ^ (S6 & S7)
        $z1 = $this->state[2]
            ^ $this->state[5]
            ^ ParagonIE_Sodium_Core_Util::andStrings($this->state[6], $this->state[7]);

        // t0, t1 = Split(ZeroPad(cn, 256), 128)
        $cn = str_pad($cn, 32, "\0", STR_PAD_RIGHT);
        $t0 = ParagonIE_Sodium_Core_Util::substr($cn, 0, 16);
        $t1 = ParagonIE_Sodium_Core_Util::substr($cn, 16, 16);
        // out0 = t0 ^ z0
        // out1 = t1 ^ z1
        $out0 = $t0 ^ $z0;
        $out1 = $t1 ^ $z1;

        // xn = Truncate(out0 || out1, |cn|)
        $xn = ParagonIE_Sodium_Core_Util::substr($out0 . $out1, 0, $len);

        // v0, v1 = Split(ZeroPad(xn, 256), 128)
        $padded = str_pad($xn, 32, "\0", STR_PAD_RIGHT);
        $v0 = ParagonIE_Sodium_Core_Util::substr($padded, 0, 16);
        $v1 = ParagonIE_Sodium_Core_Util::substr($padded, 16, 16);
        // Update(v0, v1)
        $this->update($v0, $v1);

        // return xn
        return $xn;
    }

    /**
     * @param string $xi
     * @return string
     * @throws SodiumException
     */
    public function enc($xi)
    {
        if (ParagonIE_Sodium_Core_Util::strlen($xi) !== 32) {
            throw new SodiumException('Input must be two AES blocks in size');
        }

        // z0 = S6 ^ S1 ^ (S2 & S3)
        $z0 = $this->state[6]
            ^ $this->state[1]
            ^ ParagonIE_Sodium_Core_Util::andStrings($this->state[2], $this->state[3]);
        // z1 = S2 ^ S5 ^ (S6 & S7)
        $z1 = $this->state[2]
            ^ $this->state[5]
            ^ ParagonIE_Sodium_Core_Util::andStrings($this->state[6], $this->state[7]);

        // t0, t1 = Split(xi, 128)
        $t0 = ParagonIE_Sodium_Core_Util::substr($xi, 0, 16);
        $t1 = ParagonIE_Sodium_Core_Util::substr($xi, 16, 16);

        // out0 = t0 ^ z0
        // out1 = t1 ^ z1
        $out0 = $t0 ^ $z0;
        $out1 = $t1 ^ $z1;

        // Update(t0, t1)
        // ci = out0 || out1
        $this->update($t0, $t1);

        // return ci
        return $out0 . $out1;
    }

    /**
     * @param int $ad_len_bits
     * @param int $msg_len_bits
     * @return string
     */
    public function finalize($ad_len_bits, $msg_len_bits)
    {
        $encoded = ParagonIE_Sodium_Core_Util::store64_le($ad_len_bits) .
            ParagonIE_Sodium_Core_Util::store64_le($msg_len_bits);
        $t = $this->state[2] ^ $encoded;
        for ($i = 0; $i < 7; ++$i) {
            $this->update($t, $t);
        }
        return ($this->state[0] ^ $this->state[1] ^ $this->state[2] ^ $this->state[3]) .
            ($this->state[4] ^ $this->state[5] ^ $this->state[6] ^ $this->state[7]);
    }

    /**
     * @param string $m0
     * @param string $m1
     * @return self
     */
    public function update($m0, $m1)
    {
        /*
           S'0 = AESRound(S7, S0 ^ M0)
           S'1 = AESRound(S0, S1)
           S'2 = AESRound(S1, S2)
           S'3 = AESRound(S2, S3)
           S'4 = AESRound(S3, S4 ^ M1)
           S'5 = AESRound(S4, S5)
           S'6 = AESRound(S5, S6)
           S'7 = AESRound(S6, S7)
         */
        list($s_0, $s_1) = ParagonIE_Sodium_Core_AES::doubleRound(
            $this->state[7], $this->state[0] ^ $m0,
            $this->state[0], $this->state[1]
        );

        list($s_2, $s_3) = ParagonIE_Sodium_Core_AES::doubleRound(
            $this->state[1], $this->state[2],
            $this->state[2], $this->state[3]
        );

        list($s_4, $s_5) = ParagonIE_Sodium_Core_AES::doubleRound(
            $this->state[3], $this->state[4] ^ $m1,
            $this->state[4], $this->state[5]
        );
        list($s_6, $s_7) = ParagonIE_Sodium_Core_AES::doubleRound(
            $this->state[5], $this->state[6],
            $this->state[6], $this->state[7]
        );

        /*
           S0  = S'0
           S1  = S'1
           S2  = S'2
           S3  = S'3
           S4  = S'4
           S5  = S'5
           S6  = S'6
           S7  = S'7
         */
        $this->state[0] = $s_0;
        $this->state[1] = $s_1;
        $this->state[2] = $s_2;
        $this->state[3] = $s_3;
        $this->state[4] = $s_4;
        $this->state[5] = $s_5;
        $this->state[6] = $s_6;
        $this->state[7] = $s_7;
        return $this;
    }
}AEGIS/State256.php000064400000014575150712117330007436 0ustar00<?php

if (class_exists('ParagonIE_Sodium_Core_AEGIS_State256', false)) {
    return;
}

if (!defined('SODIUM_COMPAT_AEGIS_C0')) {
    define('SODIUM_COMPAT_AEGIS_C0', "\x00\x01\x01\x02\x03\x05\x08\x0d\x15\x22\x37\x59\x90\xe9\x79\x62");
}
if (!defined('SODIUM_COMPAT_AEGIS_C1')) {
    define('SODIUM_COMPAT_AEGIS_C1', "\xdb\x3d\x18\x55\x6d\xc2\x2f\xf1\x20\x11\x31\x42\x73\xb5\x28\xdd");
}

class ParagonIE_Sodium_Core_AEGIS_State256
{
    /** @var array<int, string> $state */
    protected $state;
    public function __construct()
    {
        $this->state = array_fill(0, 6, '');
    }

    /**
     * @internal Only use this for unit tests!
     * @return string[]
     */
    public function getState()
    {
        return array_values($this->state);
    }

    /**
     * @param array $input
     * @return self
     * @throws SodiumException
     *
     * @internal Only for unit tests
     */
    public static function initForUnitTests(array $input)
    {
        if (count($input) < 6) {
            throw new SodiumException('invalid input');
        }
        $state = new self();
        for ($i = 0; $i < 6; ++$i) {
            $state->state[$i] = $input[$i];
        }
        return $state;
    }

    /**
     * @param string $key
     * @param string $nonce
     * @return self
     */
    public static function init($key, $nonce)
    {
        $state = new self();
        $k0 = ParagonIE_Sodium_Core_Util::substr($key, 0, 16);
        $k1 = ParagonIE_Sodium_Core_Util::substr($key, 16, 16);
        $n0 = ParagonIE_Sodium_Core_Util::substr($nonce, 0, 16);
        $n1 = ParagonIE_Sodium_Core_Util::substr($nonce, 16, 16);

        // S0 = k0 ^ n0
        // S1 = k1 ^ n1
        // S2 = C1
        // S3 = C0
        // S4 = k0 ^ C0
        // S5 = k1 ^ C1
        $k0_n0 = $k0 ^ $n0;
        $k1_n1 = $k1 ^ $n1;
        $state->state[0] = $k0_n0;
        $state->state[1] = $k1_n1;
        $state->state[2] = SODIUM_COMPAT_AEGIS_C1;
        $state->state[3] = SODIUM_COMPAT_AEGIS_C0;
        $state->state[4] = $k0 ^ SODIUM_COMPAT_AEGIS_C0;
        $state->state[5] = $k1 ^ SODIUM_COMPAT_AEGIS_C1;

        // Repeat(4,
        //   Update(k0)
        //   Update(k1)
        //   Update(k0 ^ n0)
        //   Update(k1 ^ n1)
        // )
        for ($i = 0; $i < 4; ++$i) {
            $state->update($k0);
            $state->update($k1);
            $state->update($k0 ^ $n0);
            $state->update($k1 ^ $n1);
        }
        return $state;
    }

    /**
     * @param string $ai
     * @return self
     * @throws SodiumException
     */
    public function absorb($ai)
    {
        if (ParagonIE_Sodium_Core_Util::strlen($ai) !== 16) {
            throw new SodiumException('Input must be an AES block in size');
        }
        return $this->update($ai);
    }

    /**
     * @param string $ci
     * @return string
     * @throws SodiumException
     */
    public function dec($ci)
    {
        if (ParagonIE_Sodium_Core_Util::strlen($ci) !== 16) {
            throw new SodiumException('Input must be an AES block in size');
        }
        // z = S1 ^ S4 ^ S5 ^ (S2 & S3)
        $z = $this->state[1]
            ^ $this->state[4]
            ^ $this->state[5]
            ^ ParagonIE_Sodium_Core_Util::andStrings($this->state[2], $this->state[3]);
        $xi = $ci ^ $z;
        $this->update($xi);
        return $xi;
    }

    /**
     * @param string $cn
     * @return string
     */
    public function decPartial($cn)
    {
        $len = ParagonIE_Sodium_Core_Util::strlen($cn);
        // z = S1 ^ S4 ^ S5 ^ (S2 & S3)
        $z = $this->state[1]
            ^ $this->state[4]
            ^ $this->state[5]
            ^ ParagonIE_Sodium_Core_Util::andStrings($this->state[2], $this->state[3]);

        // t = ZeroPad(cn, 128)
        $t = str_pad($cn, 16, "\0", STR_PAD_RIGHT);

        // out = t ^ z
        $out = $t ^ $z;

        // xn = Truncate(out, |cn|)
        $xn = ParagonIE_Sodium_Core_Util::substr($out, 0, $len);

        // v = ZeroPad(xn, 128)
        $v = str_pad($xn, 16, "\0", STR_PAD_RIGHT);
        // Update(v)
        $this->update($v);

        // return xn
        return $xn;
    }

    /**
     * @param string $xi
     * @return string
     * @throws SodiumException
     */
    public function enc($xi)
    {
        if (ParagonIE_Sodium_Core_Util::strlen($xi) !== 16) {
            throw new SodiumException('Input must be an AES block in size');
        }
        // z = S1 ^ S4 ^ S5 ^ (S2 & S3)
        $z = $this->state[1]
            ^ $this->state[4]
            ^ $this->state[5]
            ^ ParagonIE_Sodium_Core_Util::andStrings($this->state[2], $this->state[3]);
        $this->update($xi);
        return $xi ^ $z;
    }

    /**
     * @param int $ad_len_bits
     * @param int $msg_len_bits
     * @return string
     */
    public function finalize($ad_len_bits, $msg_len_bits)
    {
        $encoded = ParagonIE_Sodium_Core_Util::store64_le($ad_len_bits) .
            ParagonIE_Sodium_Core_Util::store64_le($msg_len_bits);
        $t = $this->state[3] ^ $encoded;

        for ($i = 0; $i < 7; ++$i) {
            $this->update($t);
        }

        return ($this->state[0] ^ $this->state[1] ^ $this->state[2]) .
            ($this->state[3] ^ $this->state[4] ^ $this->state[5]);
    }

    /**
     * @param string $m
     * @return self
     */
    public function update($m)
    {
        /*
            S'0 = AESRound(S5, S0 ^ M)
            S'1 = AESRound(S0, S1)
            S'2 = AESRound(S1, S2)
            S'3 = AESRound(S2, S3)
            S'4 = AESRound(S3, S4)
            S'5 = AESRound(S4, S5)
         */
        list($s_0, $s_1) = ParagonIE_Sodium_Core_AES::doubleRound(
            $this->state[5],$this->state[0] ^ $m,
            $this->state[0], $this->state[1]
        );

        list($s_2, $s_3) = ParagonIE_Sodium_Core_AES::doubleRound(
            $this->state[1], $this->state[2],
            $this->state[2], $this->state[3]
        );
        list($s_4, $s_5) = ParagonIE_Sodium_Core_AES::doubleRound(
            $this->state[3], $this->state[4],
            $this->state[4], $this->state[5]
        );

        /*
            S0  = S'0
            S1  = S'1
            S2  = S'2
            S3  = S'3
            S4  = S'4
            S5  = S'5
         */
        $this->state[0] = $s_0;
        $this->state[1] = $s_1;
        $this->state[2] = $s_2;
        $this->state[3] = $s_3;
        $this->state[4] = $s_4;
        $this->state[5] = $s_5;
        return $this;
    }
}
BLAKE2b.php000064400000000142150712117330006314 0ustar00<?php
namespace ParagonIE\Sodium\Core;

class BLAKE2b extends \ParagonIE_Sodium_Core_BLAKE2b
{

}
AEGIS256.php000064400000007016150712117330006346 0ustar00<?php

if (!defined('SODIUM_COMPAT_AEGIS_C0')) {
    define('SODIUM_COMPAT_AEGIS_C0', "\x00\x01\x01\x02\x03\x05\x08\x0d\x15\x22\x37\x59\x90\xe9\x79\x62");
}
if (!defined('SODIUM_COMPAT_AEGIS_C1')) {
    define('SODIUM_COMPAT_AEGIS_C1', "\xdb\x3d\x18\x55\x6d\xc2\x2f\xf1\x20\x11\x31\x42\x73\xb5\x28\xdd");
}

class ParagonIE_Sodium_Core_AEGIS256 extends ParagonIE_Sodium_Core_AES
{
    /**
     * @param string $ct
     * @param string $tag
     * @param string $ad
     * @param string $key
     * @param string $nonce
     * @return string
     * @throws SodiumException
     */
    public static function decrypt($ct, $tag, $ad, $key, $nonce)
    {
        $state = self::init($key, $nonce);

        // ad_blocks = Split(ZeroPad(ad, 128), 128)
        $ad_blocks = (self::strlen($ad) + 15) >> 4;
        // for ai in ad_blocks:
        //     Absorb(ai)
        for ($i = 0; $i < $ad_blocks; ++$i) {
            $ai = self::substr($ad, $i << 4, 16);
            if (self::strlen($ai) < 16) {
                $ai = str_pad($ai, 16, "\0", STR_PAD_RIGHT);
            }
            $state->absorb($ai);
        }

        $msg = '';
        $cn = self::strlen($ct) & 15;
        $ct_blocks = self::strlen($ct) >> 4;
        // ct_blocks = Split(ZeroPad(ct, 128), 128)
        // cn = Tail(ct, |ct| mod 128)
        for ($i = 0; $i < $ct_blocks; ++$i) {
            $msg .= $state->dec(self::substr($ct, $i << 4, 16));
        }
        // if cn is not empty:
        //   msg = msg || DecPartial(cn)
        if ($cn) {
            $start = $ct_blocks << 4;
            $msg .= $state->decPartial(self::substr($ct, $start, $cn));
        }
        $expected_tag = $state->finalize(
            self::strlen($ad) << 3,
            self::strlen($msg) << 3
        );
        if (!self::hashEquals($expected_tag, $tag)) {
            try {
                // The RFC says to erase msg, so we shall try:
                ParagonIE_Sodium_Compat::memzero($msg);
            } catch (SodiumException $ex) {
                // Do nothing if we cannot memzero
            }
            throw new SodiumException('verification failed');
        }
        return $msg;
    }

    /**
     * @param string $msg
     * @param string $ad
     * @param string $key
     * @param string $nonce
     * @return array
     * @throws SodiumException
     */
    public static function encrypt($msg, $ad, $key, $nonce)
    {
        $state = self::init($key, $nonce);
        $ad_len = self::strlen($ad);
        $msg_len = self::strlen($msg);
        $ad_blocks = ($ad_len + 15) >> 4;
        for ($i = 0; $i < $ad_blocks; ++$i) {
            $ai = self::substr($ad, $i << 4, 16);
            if (self::strlen($ai) < 16) {
                $ai = str_pad($ai, 16, "\0", STR_PAD_RIGHT);
            }
            $state->absorb($ai);
        }

        $ct = '';
        $msg_blocks = ($msg_len + 15) >> 4;
        for ($i = 0; $i < $msg_blocks; ++$i) {
            $xi = self::substr($msg, $i << 4, 16);
            if (self::strlen($xi) < 16) {
                $xi = str_pad($xi, 16, "\0", STR_PAD_RIGHT);
            }
            $ct .= $state->enc($xi);
        }
        $tag = $state->finalize(
            $ad_len << 3,
            $msg_len << 3
        );
        return array(
            self::substr($ct, 0, $msg_len),
            $tag
        );

    }

    /**
     * @param string $key
     * @param string $nonce
     * @return ParagonIE_Sodium_Core_AEGIS_State256
     */
    public static function init($key, $nonce)
    {
        return ParagonIE_Sodium_Core_AEGIS_State256::init($key, $nonce);
    }
}
Ristretto255.php000064400000052574150712117330007525 0ustar00<?php

/**
 * Class ParagonIE_Sodium_Core_Ristretto255
 */
class ParagonIE_Sodium_Core_Ristretto255 extends ParagonIE_Sodium_Core_Ed25519
{
    const crypto_core_ristretto255_HASHBYTES = 64;
    const HASH_SC_L = 48;
    const CORE_H2C_SHA256 = 1;
    const CORE_H2C_SHA512 = 2;

    /**
     * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
     * @param int $b
     * @return ParagonIE_Sodium_Core_Curve25519_Fe
     */
    public static function fe_cneg(ParagonIE_Sodium_Core_Curve25519_Fe $f, $b)
    {
        $negf = self::fe_neg($f);
        return self::fe_cmov($f, $negf, $b);
    }

    /**
     * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
     * @return ParagonIE_Sodium_Core_Curve25519_Fe
     * @throws SodiumException
     */
    public static function fe_abs(ParagonIE_Sodium_Core_Curve25519_Fe $f)
    {
        return self::fe_cneg($f, self::fe_isnegative($f));
    }

    /**
     * Returns 0 if this field element results in all NUL bytes.
     *
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
     * @return int
     * @throws SodiumException
     */
    public static function fe_iszero(ParagonIE_Sodium_Core_Curve25519_Fe $f)
    {
        static $zero;
        if ($zero === null) {
            $zero = str_repeat("\x00", 32);
        }
        /** @var string $zero */
        $str = self::fe_tobytes($f);

        $d = 0;
        for ($i = 0; $i < 32; ++$i) {
            $d |= self::chrToInt($str[$i]);
        }
        return (($d - 1) >> 31) & 1;
    }


    /**
     * @param ParagonIE_Sodium_Core_Curve25519_Fe $u
     * @param ParagonIE_Sodium_Core_Curve25519_Fe $v
     * @return array{x: ParagonIE_Sodium_Core_Curve25519_Fe, nonsquare: int}
     *
     * @throws SodiumException
     */
    public static function ristretto255_sqrt_ratio_m1(
        ParagonIE_Sodium_Core_Curve25519_Fe $u,
        ParagonIE_Sodium_Core_Curve25519_Fe $v
    ) {
        $sqrtm1 = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqrtm1);

        $v3 = self::fe_mul(
            self::fe_sq($v),
            $v
        ); /* v3 = v^3 */
        $x = self::fe_mul(
            self::fe_mul(
                self::fe_sq($v3),
                $u
            ),
            $v
        ); /* x = uv^7 */

        $x = self::fe_mul(
            self::fe_mul(
                self::fe_pow22523($x), /* x = (uv^7)^((q-5)/8) */
                $v3
            ),
            $u
        ); /* x = uv^3(uv^7)^((q-5)/8) */

        $vxx = self::fe_mul(
            self::fe_sq($x),
            $v
        ); /* vx^2 */

        $m_root_check = self::fe_sub($vxx, $u); /* vx^2-u */
        $p_root_check = self::fe_add($vxx, $u); /* vx^2+u */
        $f_root_check = self::fe_mul($u, $sqrtm1); /* u*sqrt(-1) */
        $f_root_check = self::fe_add($vxx, $f_root_check); /* vx^2+u*sqrt(-1) */

        $has_m_root = self::fe_iszero($m_root_check);
        $has_p_root = self::fe_iszero($p_root_check);
        $has_f_root = self::fe_iszero($f_root_check);

        $x_sqrtm1 = self::fe_mul($x, $sqrtm1); /* x*sqrt(-1) */

        $x = self::fe_abs(
            self::fe_cmov($x, $x_sqrtm1, $has_p_root | $has_f_root)
        );
        return array(
            'x' => $x,
            'nonsquare' => $has_m_root | $has_p_root
        );
    }

    /**
     * @param string $s
     * @return int
     * @throws SodiumException
     */
    public static function ristretto255_point_is_canonical($s)
    {
        $c = (self::chrToInt($s[31]) & 0x7f) ^ 0x7f;
        for ($i = 30; $i > 0; --$i) {
            $c |= self::chrToInt($s[$i]) ^ 0xff;
        }
        $c = ($c - 1) >> 8;
        $d = (0xed - 1 - self::chrToInt($s[0])) >> 8;
        $e = self::chrToInt($s[31]) >> 7;

        return 1 - ((($c & $d) | $e | self::chrToInt($s[0])) & 1);
    }

    /**
     * @param string $s
     * @param bool $skipCanonicalCheck
     * @return array{h: ParagonIE_Sodium_Core_Curve25519_Ge_P3, res: int}
     * @throws SodiumException
     */
    public static function ristretto255_frombytes($s, $skipCanonicalCheck = false)
    {
        if (!$skipCanonicalCheck) {
            if (!self::ristretto255_point_is_canonical($s)) {
                throw new SodiumException('S is not canonical');
            }
        }

        $s_ = self::fe_frombytes($s);
        $ss = self::fe_sq($s_); /* ss = s^2 */

        $u1 = self::fe_sub(self::fe_1(), $ss); /* u1 = 1-ss */
        $u1u1 = self::fe_sq($u1); /* u1u1 = u1^2 */

        $u2 = self::fe_add(self::fe_1(), $ss); /* u2 = 1+ss */
        $u2u2 = self::fe_sq($u2); /* u2u2 = u2^2 */

        $v = self::fe_mul(
            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$d),
            $u1u1
        ); /* v = d*u1^2 */
        $v = self::fe_neg($v); /* v = -d*u1^2 */
        $v = self::fe_sub($v, $u2u2); /* v = -(d*u1^2)-u2^2 */
        $v_u2u2 = self::fe_mul($v, $u2u2); /* v_u2u2 = v*u2^2 */

        // fe25519_1(one);
        // notsquare = ristretto255_sqrt_ratio_m1(inv_sqrt, one, v_u2u2);
        $one = self::fe_1();
        $result = self::ristretto255_sqrt_ratio_m1($one, $v_u2u2);
        $inv_sqrt = $result['x'];
        $notsquare = $result['nonsquare'];

        $h = new ParagonIE_Sodium_Core_Curve25519_Ge_P3();

        $h->X = self::fe_mul($inv_sqrt, $u2);
        $h->Y = self::fe_mul(self::fe_mul($inv_sqrt, $h->X), $v);

        $h->X = self::fe_mul($h->X, $s_);
        $h->X = self::fe_abs(
            self::fe_add($h->X, $h->X)
        );
        $h->Y = self::fe_mul($u1, $h->Y);
        $h->Z = self::fe_1();
        $h->T = self::fe_mul($h->X, $h->Y);

        $res = - ((1 - $notsquare) | self::fe_isnegative($h->T) | self::fe_iszero($h->Y));
        return array('h' => $h, 'res' => $res);
    }

    /**
     * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $h
     * @return string
     * @throws SodiumException
     */
    public static function ristretto255_p3_tobytes(ParagonIE_Sodium_Core_Curve25519_Ge_P3 $h)
    {
        $sqrtm1 = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqrtm1);
        $invsqrtamd = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$invsqrtamd);

        $u1 = self::fe_add($h->Z, $h->Y); /* u1 = Z+Y */
        $zmy = self::fe_sub($h->Z, $h->Y); /* zmy = Z-Y */
        $u1 = self::fe_mul($u1, $zmy); /* u1 = (Z+Y)*(Z-Y) */
        $u2 = self::fe_mul($h->X, $h->Y); /* u2 = X*Y */

        $u1_u2u2 = self::fe_mul(self::fe_sq($u2), $u1); /* u1_u2u2 = u1*u2^2 */
        $one = self::fe_1();

        // fe25519_1(one);
        // (void) ristretto255_sqrt_ratio_m1(inv_sqrt, one, u1_u2u2);
        $result = self::ristretto255_sqrt_ratio_m1($one, $u1_u2u2);
        $inv_sqrt = $result['x'];

        $den1 = self::fe_mul($inv_sqrt, $u1); /* den1 = inv_sqrt*u1 */
        $den2 = self::fe_mul($inv_sqrt, $u2); /* den2 = inv_sqrt*u2 */
        $z_inv = self::fe_mul($h->T, self::fe_mul($den1, $den2)); /* z_inv = den1*den2*T */

        $ix = self::fe_mul($h->X, $sqrtm1); /* ix = X*sqrt(-1) */
        $iy = self::fe_mul($h->Y, $sqrtm1); /* iy = Y*sqrt(-1) */
        $eden = self::fe_mul($den1, $invsqrtamd);

        $t_z_inv =  self::fe_mul($h->T, $z_inv); /* t_z_inv = T*z_inv */
        $rotate = self::fe_isnegative($t_z_inv);

        $x_ = self::fe_copy($h->X);
        $y_ = self::fe_copy($h->Y);
        $den_inv = self::fe_copy($den2);

        $x_ = self::fe_cmov($x_, $iy, $rotate);
        $y_ = self::fe_cmov($y_, $ix, $rotate);
        $den_inv = self::fe_cmov($den_inv, $eden, $rotate);

        $x_z_inv = self::fe_mul($x_, $z_inv);
        $y_ = self::fe_cneg($y_, self::fe_isnegative($x_z_inv));


        // fe25519_sub(s_, h->Z, y_);
        // fe25519_mul(s_, den_inv, s_);
        // fe25519_abs(s_, s_);
        // fe25519_tobytes(s, s_);
        return self::fe_tobytes(
            self::fe_abs(
                self::fe_mul(
                    $den_inv,
                    self::fe_sub($h->Z, $y_)
                )
            )
        );
    }

    /**
     * @param ParagonIE_Sodium_Core_Curve25519_Fe $t
     * @return ParagonIE_Sodium_Core_Curve25519_Ge_P3
     *
     * @throws SodiumException
     */
    public static function ristretto255_elligator(ParagonIE_Sodium_Core_Curve25519_Fe $t)
    {
        $sqrtm1   = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqrtm1);
        $onemsqd  = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$onemsqd);
        $d        = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$d);
        $sqdmone  = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqdmone);
        $sqrtadm1 = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqrtadm1);

        $one = self::fe_1();
        $r   = self::fe_mul($sqrtm1, self::fe_sq($t));         /* r = sqrt(-1)*t^2 */
        $u   = self::fe_mul(self::fe_add($r, $one), $onemsqd); /* u = (r+1)*(1-d^2) */
        $c   = self::fe_neg(self::fe_1());                     /* c = -1 */
        $rpd = self::fe_add($r, $d);                           /* rpd = r+d */

        $v = self::fe_mul(
            self::fe_sub(
                $c,
                self::fe_mul($r, $d)
            ),
            $rpd
        ); /* v = (c-r*d)*(r+d) */

        $result = self::ristretto255_sqrt_ratio_m1($u, $v);
        $s = $result['x'];
        $wasnt_square = 1 - $result['nonsquare'];

        $s_prime = self::fe_neg(
            self::fe_abs(
                self::fe_mul($s, $t)
            )
        ); /* s_prime = -|s*t| */
        $s = self::fe_cmov($s, $s_prime, $wasnt_square);
        $c = self::fe_cmov($c, $r, $wasnt_square);

        // fe25519_sub(n, r, one);            /* n = r-1 */
        // fe25519_mul(n, n, c);              /* n = c*(r-1) */
        // fe25519_mul(n, n, ed25519_sqdmone); /* n = c*(r-1)*(d-1)^2 */
        // fe25519_sub(n, n, v);              /* n =  c*(r-1)*(d-1)^2-v */
        $n = self::fe_sub(
            self::fe_mul(
                self::fe_mul(
                    self::fe_sub($r, $one),
                    $c
                ),
                $sqdmone
            ),
            $v
        ); /* n =  c*(r-1)*(d-1)^2-v */

        $w0 = self::fe_mul(
            self::fe_add($s, $s),
            $v
        ); /* w0 = 2s*v */

        $w1 = self::fe_mul($n, $sqrtadm1); /* w1 = n*sqrt(ad-1) */
        $ss = self::fe_sq($s); /* ss = s^2 */
        $w2 = self::fe_sub($one, $ss); /* w2 = 1-s^2 */
        $w3 = self::fe_add($one, $ss); /* w3 = 1+s^2 */

        return new ParagonIE_Sodium_Core_Curve25519_Ge_P3(
            self::fe_mul($w0, $w3),
            self::fe_mul($w2, $w1),
            self::fe_mul($w1, $w3),
            self::fe_mul($w0, $w2)
        );
    }

    /**
     * @param string $h
     * @return string
     * @throws SodiumException
     */
    public static function ristretto255_from_hash($h)
    {
        if (self::strlen($h) !== 64) {
            throw new SodiumException('Hash must be 64 bytes');
        }
        //fe25519_frombytes(r0, h);
        //fe25519_frombytes(r1, h + 32);
        $r0 = self::fe_frombytes(self::substr($h, 0, 32));
        $r1 = self::fe_frombytes(self::substr($h, 32, 32));

        //ristretto255_elligator(&p0, r0);
        //ristretto255_elligator(&p1, r1);
        $p0 = self::ristretto255_elligator($r0);
        $p1 = self::ristretto255_elligator($r1);

        //ge25519_p3_to_cached(&p1_cached, &p1);
        //ge25519_add_cached(&p_p1p1, &p0, &p1_cached);
        $p_p1p1 = self::ge_add(
            $p0,
            self::ge_p3_to_cached($p1)
        );

        //ge25519_p1p1_to_p3(&p, &p_p1p1);
        //ristretto255_p3_tobytes(s, &p);
        return self::ristretto255_p3_tobytes(
            self::ge_p1p1_to_p3($p_p1p1)
        );
    }

    /**
     * @param string $p
     * @return int
     * @throws SodiumException
     */
    public static function is_valid_point($p)
    {
        $result = self::ristretto255_frombytes($p);
        if ($result['res'] !== 0) {
            return 0;
        }
        return 1;
    }

    /**
     * @param string $p
     * @param string $q
     * @return string
     * @throws SodiumException
     */
    public static function ristretto255_add($p, $q)
    {
        $p_res = self::ristretto255_frombytes($p);
        $q_res = self::ristretto255_frombytes($q);
        if ($p_res['res'] !== 0 || $q_res['res'] !== 0) {
            throw new SodiumException('Could not add points');
        }
        $p_p3 = $p_res['h'];
        $q_p3 = $q_res['h'];
        $q_cached = self::ge_p3_to_cached($q_p3);
        $r_p1p1 = self::ge_add($p_p3, $q_cached);
        $r_p3 = self::ge_p1p1_to_p3($r_p1p1);
        return self::ristretto255_p3_tobytes($r_p3);
    }

    /**
     * @param string $p
     * @param string $q
     * @return string
     * @throws SodiumException
     */
    public static function ristretto255_sub($p, $q)
    {
        $p_res = self::ristretto255_frombytes($p);
        $q_res = self::ristretto255_frombytes($q);
        if ($p_res['res'] !== 0 || $q_res['res'] !== 0) {
            throw new SodiumException('Could not add points');
        }
        $p_p3 = $p_res['h'];
        $q_p3 = $q_res['h'];
        $q_cached = self::ge_p3_to_cached($q_p3);
        $r_p1p1 = self::ge_sub($p_p3, $q_cached);
        $r_p3 = self::ge_p1p1_to_p3($r_p1p1);
        return self::ristretto255_p3_tobytes($r_p3);
    }


    /**
     * @param int $hLen
     * @param ?string $ctx
     * @param string $msg
     * @return string
     * @throws SodiumException
     * @psalm-suppress PossiblyInvalidArgument hash API
     */
    protected static function h2c_string_to_hash_sha256($hLen, $ctx, $msg)
    {
        $h = array_fill(0, $hLen, 0);
        $ctx_len = !is_null($ctx) ? self::strlen($ctx) : 0;
        if ($hLen > 0xff) {
            throw new SodiumException('Hash must be less than 256 bytes');
        }

        if ($ctx_len > 0xff) {
            $st = hash_init('sha256');
            self::hash_update($st, "H2C-OVERSIZE-DST-");
            self::hash_update($st, $ctx);
            $ctx = hash_final($st, true);
            $ctx_len = 32;
        }
        $t = array(0, $hLen, 0);
        $ux = str_repeat("\0", 64);
        $st = hash_init('sha256');
        self::hash_update($st, $ux);
        self::hash_update($st, $msg);
        self::hash_update($st, self::intArrayToString($t));
        self::hash_update($st, $ctx);
        self::hash_update($st, self::intToChr($ctx_len));
        $u0 = hash_final($st, true);

        for ($i = 0; $i < $hLen; $i += 64) {
            $ux = self::xorStrings($ux, $u0);
            ++$t[2];
            $st = hash_init('sha256');
            self::hash_update($st, $ux);
            self::hash_update($st, self::intToChr($t[2]));
            self::hash_update($st, $ctx);
            self::hash_update($st, self::intToChr($ctx_len));
            $ux = hash_final($st, true);
            $amount = min($hLen - $i, 64);
            for ($j = 0; $j < $amount; ++$j) {
                $h[$i + $j] = self::chrToInt($ux[$i]);
            }
        }
        return self::intArrayToString(array_slice($h, 0, $hLen));
    }

    /**
     * @param int $hLen
     * @param ?string $ctx
     * @param string $msg
     * @return string
     * @throws SodiumException
     * @psalm-suppress PossiblyInvalidArgument hash API
     */
    protected static function h2c_string_to_hash_sha512($hLen, $ctx, $msg)
    {
        $h = array_fill(0, $hLen, 0);
        $ctx_len = !is_null($ctx) ? self::strlen($ctx) : 0;
        if ($hLen > 0xff) {
            throw new SodiumException('Hash must be less than 256 bytes');
        }

        if ($ctx_len > 0xff) {
            $st = hash_init('sha256');
            self::hash_update($st, "H2C-OVERSIZE-DST-");
            self::hash_update($st, $ctx);
            $ctx = hash_final($st, true);
            $ctx_len = 32;
        }
        $t = array(0, $hLen, 0);
        $ux = str_repeat("\0", 128);
        $st = hash_init('sha512');
        self::hash_update($st, $ux);
        self::hash_update($st, $msg);
        self::hash_update($st, self::intArrayToString($t));
        self::hash_update($st, $ctx);
        self::hash_update($st, self::intToChr($ctx_len));
        $u0 = hash_final($st, true);

        for ($i = 0; $i < $hLen; $i += 128) {
            $ux = self::xorStrings($ux, $u0);
            ++$t[2];
            $st = hash_init('sha512');
            self::hash_update($st, $ux);
            self::hash_update($st, self::intToChr($t[2]));
            self::hash_update($st, $ctx);
            self::hash_update($st, self::intToChr($ctx_len));
            $ux = hash_final($st, true);
            $amount = min($hLen - $i, 128);
            for ($j = 0; $j < $amount; ++$j) {
                $h[$i + $j] = self::chrToInt($ux[$i]);
            }
        }
        return self::intArrayToString(array_slice($h, 0, $hLen));
    }

    /**
     * @param int $hLen
     * @param ?string $ctx
     * @param string $msg
     * @param int $hash_alg
     * @return string
     * @throws SodiumException
     */
    public static function h2c_string_to_hash($hLen, $ctx, $msg, $hash_alg)
    {
        switch ($hash_alg) {
            case self::CORE_H2C_SHA256:
                return self::h2c_string_to_hash_sha256($hLen, $ctx, $msg);
            case self::CORE_H2C_SHA512:
                return self::h2c_string_to_hash_sha512($hLen, $ctx, $msg);
            default:
                throw new SodiumException('Invalid H2C hash algorithm');
        }
    }

    /**
     * @param ?string $ctx
     * @param string $msg
     * @param int $hash_alg
     * @return string
     * @throws SodiumException
     */
    protected static function _string_to_element($ctx, $msg, $hash_alg)
    {
        return self::ristretto255_from_hash(
            self::h2c_string_to_hash(self::crypto_core_ristretto255_HASHBYTES, $ctx, $msg, $hash_alg)
        );
    }

    /**
     * @return string
     * @throws SodiumException
     * @throws Exception
     */
    public static function ristretto255_random()
    {
        return self::ristretto255_from_hash(
            ParagonIE_Sodium_Compat::randombytes_buf(self::crypto_core_ristretto255_HASHBYTES)
        );
    }

    /**
     * @return string
     * @throws SodiumException
     */
    public static function ristretto255_scalar_random()
    {
        return self::scalar_random();
    }

    /**
     * @param string $s
     * @return string
     * @throws SodiumException
     */
    public static function ristretto255_scalar_complement($s)
    {
        return self::scalar_complement($s);
    }


    /**
     * @param string $s
     * @return string
     */
    public static function ristretto255_scalar_invert($s)
    {
        return self::sc25519_invert($s);
    }

    /**
     * @param string $s
     * @return string
     * @throws SodiumException
     */
    public static function ristretto255_scalar_negate($s)
    {
        return self::scalar_negate($s);
    }

    /**
     * @param string $x
     * @param string $y
     * @return string
     */
    public static function ristretto255_scalar_add($x, $y)
    {
        return self::scalar_add($x, $y);
    }

    /**
     * @param string $x
     * @param string $y
     * @return string
     */
    public static function ristretto255_scalar_sub($x, $y)
    {
        return self::scalar_sub($x, $y);
    }

    /**
     * @param string $x
     * @param string $y
     * @return string
     */
    public static function ristretto255_scalar_mul($x, $y)
    {
        return self::sc25519_mul($x, $y);
    }

    /**
     * @param string $ctx
     * @param string $msg
     * @param int $hash_alg
     * @return string
     * @throws SodiumException
     */
    public static function ristretto255_scalar_from_string($ctx, $msg, $hash_alg)
    {
        $h = array_fill(0, 64, 0);
        $h_be = self::stringToIntArray(
            self::h2c_string_to_hash(
                self::HASH_SC_L, $ctx, $msg, $hash_alg
            )
        );

        for ($i = 0; $i < self::HASH_SC_L; ++$i) {
            $h[$i] = $h_be[self::HASH_SC_L - 1 - $i];
        }
        return self::ristretto255_scalar_reduce(self::intArrayToString($h));
    }

    /**
     * @param string $s
     * @return string
     */
    public static function ristretto255_scalar_reduce($s)
    {
        return self::sc_reduce($s);
    }

    /**
     * @param string $n
     * @param string $p
     * @return string
     * @throws SodiumException
     */
    public static function scalarmult_ristretto255($n, $p)
    {
        if (self::strlen($n) !== 32) {
            throw new SodiumException('Scalar must be 32 bytes, ' . self::strlen($p) . ' given.');
        }
        if (self::strlen($p) !== 32) {
            throw new SodiumException('Point must be 32 bytes, ' . self::strlen($p) . ' given.');
        }
        $result = self::ristretto255_frombytes($p);
        if ($result['res'] !== 0) {
            throw new SodiumException('Could not multiply points');
        }
        $P = $result['h'];

        $t = self::stringToIntArray($n);
        $t[31] &= 0x7f;
        $Q = self::ge_scalarmult(self::intArrayToString($t), $P);
        $q = self::ristretto255_p3_tobytes($Q);
        if (ParagonIE_Sodium_Compat::is_zero($q)) {
            throw new SodiumException('An unknown error has occurred');
        }
        return $q;
    }

    /**
     * @param string $n
     * @return string
     * @throws SodiumException
     */
    public static function scalarmult_ristretto255_base($n)
    {
        $t = self::stringToIntArray($n);
        $t[31] &= 0x7f;
        $Q = self::ge_scalarmult_base(self::intArrayToString($t));
        $q = self::ristretto255_p3_tobytes($Q);
        if (ParagonIE_Sodium_Compat::is_zero($q)) {
            throw new SodiumException('An unknown error has occurred');
        }
        return $q;
    }
}
ChaCha20.php000064400000000144150712117330006525 0ustar00<?php
namespace ParagonIE\Sodium\Core;

class ChaCha20 extends \ParagonIE_Sodium_Core_ChaCha20
{

}
HSalsa20.php000064400000000144150712117330006571 0ustar00<?php
namespace ParagonIE\Sodium\Core;

class HSalsa20 extends \ParagonIE_Sodium_Core_HSalsa20
{

}
SipHash.php000064400000000142150712117330006611 0ustar00<?php
namespace ParagonIE\Sodium\Core;

class SipHash extends \ParagonIE_Sodium_Core_SipHash
{

}
Xsalsa20.php000064400000000144150714105000006642 0ustar00<?php
namespace ParagonIE\Sodium\Core;

class Xsalsa20 extends \ParagonIE_Sodium_Core_XSalsa20
{

}