ru-se.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

State.php (15980B)


      1 <?php
      2 
      3 if (class_exists('ParagonIE_Sodium_Core32_Poly1305_State', false)) {
      4     return;
      5 }
      6 
      7 /**
      8  * Class ParagonIE_Sodium_Core32_Poly1305_State
      9  */
     10 class ParagonIE_Sodium_Core32_Poly1305_State extends ParagonIE_Sodium_Core32_Util
     11 {
     12     /**
     13      * @var array<int, int>
     14      */
     15     protected $buffer = array();
     16 
     17     /**
     18      * @var bool
     19      */
     20     protected $final = false;
     21 
     22     /**
     23      * @var array<int, ParagonIE_Sodium_Core32_Int32>
     24      */
     25     public $h;
     26 
     27     /**
     28      * @var int
     29      */
     30     protected $leftover = 0;
     31 
     32     /**
     33      * @var array<int, ParagonIE_Sodium_Core32_Int32>
     34      */
     35     public $r;
     36 
     37     /**
     38      * @var array<int, ParagonIE_Sodium_Core32_Int64>
     39      */
     40     public $pad;
     41 
     42     /**
     43      * ParagonIE_Sodium_Core32_Poly1305_State constructor.
     44      *
     45      * @internal You should not use this directly from another application
     46      *
     47      * @param string $key
     48      * @throws InvalidArgumentException
     49      * @throws SodiumException
     50      * @throws TypeError
     51      */
     52     public function __construct($key = '')
     53     {
     54         if (self::strlen($key) < 32) {
     55             throw new InvalidArgumentException(
     56                 'Poly1305 requires a 32-byte key'
     57             );
     58         }
     59         /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
     60         $this->r = array(
     61             // st->r[0] = ...
     62             ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 0, 4))
     63                 ->setUnsignedInt(true)
     64                 ->mask(0x3ffffff),
     65             // st->r[1] = ...
     66             ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 3, 4))
     67                 ->setUnsignedInt(true)
     68                 ->shiftRight(2)
     69                 ->mask(0x3ffff03),
     70             // st->r[2] = ...
     71             ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 6, 4))
     72                 ->setUnsignedInt(true)
     73                 ->shiftRight(4)
     74                 ->mask(0x3ffc0ff),
     75             // st->r[3] = ...
     76             ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 9, 4))
     77                 ->setUnsignedInt(true)
     78                 ->shiftRight(6)
     79                 ->mask(0x3f03fff),
     80             // st->r[4] = ...
     81             ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 12, 4))
     82                 ->setUnsignedInt(true)
     83                 ->shiftRight(8)
     84                 ->mask(0x00fffff)
     85         );
     86 
     87         /* h = 0 */
     88         $this->h = array(
     89             new ParagonIE_Sodium_Core32_Int32(array(0, 0), true),
     90             new ParagonIE_Sodium_Core32_Int32(array(0, 0), true),
     91             new ParagonIE_Sodium_Core32_Int32(array(0, 0), true),
     92             new ParagonIE_Sodium_Core32_Int32(array(0, 0), true),
     93             new ParagonIE_Sodium_Core32_Int32(array(0, 0), true)
     94         );
     95 
     96         /* save pad for later */
     97         $this->pad = array(
     98             ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 16, 4))
     99                 ->setUnsignedInt(true)->toInt64(),
    100             ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 20, 4))
    101                 ->setUnsignedInt(true)->toInt64(),
    102             ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 24, 4))
    103                 ->setUnsignedInt(true)->toInt64(),
    104             ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 28, 4))
    105                 ->setUnsignedInt(true)->toInt64(),
    106         );
    107 
    108         $this->leftover = 0;
    109         $this->final = false;
    110     }
    111 
    112     /**
    113      * @internal You should not use this directly from another application
    114      *
    115      * @param string $message
    116      * @return self
    117      * @throws SodiumException
    118      * @throws TypeError
    119      */
    120     public function update($message = '')
    121     {
    122         $bytes = self::strlen($message);
    123 
    124         /* handle leftover */
    125         if ($this->leftover) {
    126             /** @var int $want */
    127             $want = ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE - $this->leftover;
    128             if ($want > $bytes) {
    129                 $want = $bytes;
    130             }
    131             for ($i = 0; $i < $want; ++$i) {
    132                 $mi = self::chrToInt($message[$i]);
    133                 $this->buffer[$this->leftover + $i] = $mi;
    134             }
    135             // We snip off the leftmost bytes.
    136             $message = self::substr($message, $want);
    137             $bytes = self::strlen($message);
    138             $this->leftover += $want;
    139             if ($this->leftover < ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE) {
    140                 // We still don't have enough to run $this->blocks()
    141                 return $this;
    142             }
    143 
    144             $this->blocks(
    145                 self::intArrayToString($this->buffer),
    146                 ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE
    147             );
    148             $this->leftover = 0;
    149         }
    150 
    151         /* process full blocks */
    152         if ($bytes >= ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE) {
    153             /** @var int $want */
    154             $want = $bytes & ~(ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE - 1);
    155             if ($want >= ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE) {
    156                 /** @var string $block */
    157                 $block = self::substr($message, 0, $want);
    158                 if (self::strlen($block) >= ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE) {
    159                     $this->blocks($block, $want);
    160                     $message = self::substr($message, $want);
    161                     $bytes = self::strlen($message);
    162                 }
    163             }
    164         }
    165 
    166         /* store leftover */
    167         if ($bytes) {
    168             for ($i = 0; $i < $bytes; ++$i) {
    169                 $mi = self::chrToInt($message[$i]);
    170                 $this->buffer[$this->leftover + $i] = $mi;
    171             }
    172             $this->leftover = (int) $this->leftover + $bytes;
    173         }
    174         return $this;
    175     }
    176 
    177     /**
    178      * @internal You should not use this directly from another application
    179      *
    180      * @param string $message
    181      * @param int $bytes
    182      * @return self
    183      * @throws SodiumException
    184      * @throws TypeError
    185      */
    186     public function blocks($message, $bytes)
    187     {
    188         if (self::strlen($message) < 16) {
    189             $message = str_pad($message, 16, "\x00", STR_PAD_RIGHT);
    190         }
    191         $hibit = ParagonIE_Sodium_Core32_Int32::fromInt((int) ($this->final ? 0 : 1 << 24)); /* 1 << 128 */
    192         $hibit->setUnsignedInt(true);
    193         $zero = new ParagonIE_Sodium_Core32_Int64(array(0, 0, 0, 0), true);
    194         /**
    195          * @var ParagonIE_Sodium_Core32_Int64 $d0
    196          * @var ParagonIE_Sodium_Core32_Int64 $d1
    197          * @var ParagonIE_Sodium_Core32_Int64 $d2
    198          * @var ParagonIE_Sodium_Core32_Int64 $d3
    199          * @var ParagonIE_Sodium_Core32_Int64 $d4
    200          * @var ParagonIE_Sodium_Core32_Int64 $r0
    201          * @var ParagonIE_Sodium_Core32_Int64 $r1
    202          * @var ParagonIE_Sodium_Core32_Int64 $r2
    203          * @var ParagonIE_Sodium_Core32_Int64 $r3
    204          * @var ParagonIE_Sodium_Core32_Int64 $r4
    205          *
    206          * @var ParagonIE_Sodium_Core32_Int32 $h0
    207          * @var ParagonIE_Sodium_Core32_Int32 $h1
    208          * @var ParagonIE_Sodium_Core32_Int32 $h2
    209          * @var ParagonIE_Sodium_Core32_Int32 $h3
    210          * @var ParagonIE_Sodium_Core32_Int32 $h4
    211          */
    212         $r0 = $this->r[0]->toInt64();
    213         $r1 = $this->r[1]->toInt64();
    214         $r2 = $this->r[2]->toInt64();
    215         $r3 = $this->r[3]->toInt64();
    216         $r4 = $this->r[4]->toInt64();
    217 
    218         $s1 = $r1->toInt64()->mulInt(5, 3);
    219         $s2 = $r2->toInt64()->mulInt(5, 3);
    220         $s3 = $r3->toInt64()->mulInt(5, 3);
    221         $s4 = $r4->toInt64()->mulInt(5, 3);
    222 
    223         $h0 = $this->h[0];
    224         $h1 = $this->h[1];
    225         $h2 = $this->h[2];
    226         $h3 = $this->h[3];
    227         $h4 = $this->h[4];
    228 
    229         while ($bytes >= ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE) {
    230             /* h += m[i] */
    231             $h0 = $h0->addInt32(
    232                 ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 0, 4))
    233                     ->mask(0x3ffffff)
    234             )->toInt64();
    235             $h1 = $h1->addInt32(
    236                 ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 3, 4))
    237                     ->shiftRight(2)
    238                     ->mask(0x3ffffff)
    239             )->toInt64();
    240             $h2 = $h2->addInt32(
    241                 ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 6, 4))
    242                     ->shiftRight(4)
    243                     ->mask(0x3ffffff)
    244             )->toInt64();
    245             $h3 = $h3->addInt32(
    246                 ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 9, 4))
    247                     ->shiftRight(6)
    248                     ->mask(0x3ffffff)
    249             )->toInt64();
    250             $h4 = $h4->addInt32(
    251                 ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 12, 4))
    252                     ->shiftRight(8)
    253                     ->orInt32($hibit)
    254             )->toInt64();
    255 
    256             /* h *= r */
    257             $d0 = $zero
    258                 ->addInt64($h0->mulInt64($r0, 25))
    259                 ->addInt64($s4->mulInt64($h1, 26))
    260                 ->addInt64($s3->mulInt64($h2, 26))
    261                 ->addInt64($s2->mulInt64($h3, 26))
    262                 ->addInt64($s1->mulInt64($h4, 26));
    263 
    264             $d1 = $zero
    265                 ->addInt64($h0->mulInt64($r1, 25))
    266                 ->addInt64($h1->mulInt64($r0, 25))
    267                 ->addInt64($s4->mulInt64($h2, 26))
    268                 ->addInt64($s3->mulInt64($h3, 26))
    269                 ->addInt64($s2->mulInt64($h4, 26));
    270 
    271             $d2 = $zero
    272                 ->addInt64($h0->mulInt64($r2, 25))
    273                 ->addInt64($h1->mulInt64($r1, 25))
    274                 ->addInt64($h2->mulInt64($r0, 25))
    275                 ->addInt64($s4->mulInt64($h3, 26))
    276                 ->addInt64($s3->mulInt64($h4, 26));
    277 
    278             $d3 = $zero
    279                 ->addInt64($h0->mulInt64($r3, 25))
    280                 ->addInt64($h1->mulInt64($r2, 25))
    281                 ->addInt64($h2->mulInt64($r1, 25))
    282                 ->addInt64($h3->mulInt64($r0, 25))
    283                 ->addInt64($s4->mulInt64($h4, 26));
    284 
    285             $d4 = $zero
    286                 ->addInt64($h0->mulInt64($r4, 25))
    287                 ->addInt64($h1->mulInt64($r3, 25))
    288                 ->addInt64($h2->mulInt64($r2, 25))
    289                 ->addInt64($h3->mulInt64($r1, 25))
    290                 ->addInt64($h4->mulInt64($r0, 25));
    291 
    292             /* (partial) h %= p */
    293             $c = $d0->shiftRight(26);
    294             $h0 = $d0->toInt32()->mask(0x3ffffff);
    295             $d1 = $d1->addInt64($c);
    296 
    297             $c = $d1->shiftRight(26);
    298             $h1 = $d1->toInt32()->mask(0x3ffffff);
    299             $d2 = $d2->addInt64($c);
    300 
    301             $c = $d2->shiftRight(26);
    302             $h2 = $d2->toInt32()->mask(0x3ffffff);
    303             $d3 = $d3->addInt64($c);
    304 
    305             $c = $d3->shiftRight(26);
    306             $h3 = $d3->toInt32()->mask(0x3ffffff);
    307             $d4 = $d4->addInt64($c);
    308 
    309             $c = $d4->shiftRight(26);
    310             $h4 = $d4->toInt32()->mask(0x3ffffff);
    311             $h0 = $h0->addInt32($c->toInt32()->mulInt(5, 3));
    312 
    313             $c = $h0->shiftRight(26);
    314             $h0 = $h0->mask(0x3ffffff);
    315             $h1 = $h1->addInt32($c);
    316 
    317             // Chop off the left 32 bytes.
    318             $message = self::substr(
    319                 $message,
    320                 ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE
    321             );
    322             $bytes -= ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE;
    323         }
    324 
    325         /** @var array<int, ParagonIE_Sodium_Core32_Int32> $h */
    326         $this->h = array($h0, $h1, $h2, $h3, $h4);
    327         return $this;
    328     }
    329 
    330     /**
    331      * @internal You should not use this directly from another application
    332      *
    333      * @return string
    334      * @throws SodiumException
    335      * @throws TypeError
    336      */
    337     public function finish()
    338     {
    339         /* process the remaining block */
    340         if ($this->leftover) {
    341             $i = $this->leftover;
    342             $this->buffer[$i++] = 1;
    343             for (; $i < ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE; ++$i) {
    344                 $this->buffer[$i] = 0;
    345             }
    346             $this->final = true;
    347             $this->blocks(
    348                 self::substr(
    349                     self::intArrayToString($this->buffer),
    350                     0,
    351                     ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE
    352                 ),
    353                 $b = ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE
    354             );
    355         }
    356 
    357         /**
    358          * @var ParagonIE_Sodium_Core32_Int32 $f
    359          * @var ParagonIE_Sodium_Core32_Int32 $g0
    360          * @var ParagonIE_Sodium_Core32_Int32 $g1
    361          * @var ParagonIE_Sodium_Core32_Int32 $g2
    362          * @var ParagonIE_Sodium_Core32_Int32 $g3
    363          * @var ParagonIE_Sodium_Core32_Int32 $g4
    364          * @var ParagonIE_Sodium_Core32_Int32 $h0
    365          * @var ParagonIE_Sodium_Core32_Int32 $h1
    366          * @var ParagonIE_Sodium_Core32_Int32 $h2
    367          * @var ParagonIE_Sodium_Core32_Int32 $h3
    368          * @var ParagonIE_Sodium_Core32_Int32 $h4
    369          */
    370         $h0 = $this->h[0];
    371         $h1 = $this->h[1];
    372         $h2 = $this->h[2];
    373         $h3 = $this->h[3];
    374         $h4 = $this->h[4];
    375 
    376         $c = $h1->shiftRight(26);           # $c = $h1 >> 26;
    377         $h1 = $h1->mask(0x3ffffff);         # $h1 &= 0x3ffffff;
    378 
    379         $h2 = $h2->addInt32($c);            # $h2 += $c;
    380         $c = $h2->shiftRight(26);           # $c = $h2 >> 26;
    381         $h2 = $h2->mask(0x3ffffff);         # $h2 &= 0x3ffffff;
    382 
    383         $h3 = $h3->addInt32($c);            # $h3 += $c;
    384         $c = $h3->shiftRight(26);           # $c = $h3 >> 26;
    385         $h3 = $h3->mask(0x3ffffff);         # $h3 &= 0x3ffffff;
    386 
    387         $h4 = $h4->addInt32($c);            # $h4 += $c;
    388         $c = $h4->shiftRight(26);           # $c = $h4 >> 26;
    389         $h4 = $h4->mask(0x3ffffff);         # $h4 &= 0x3ffffff;
    390 
    391         $h0 = $h0->addInt32($c->mulInt(5, 3)); # $h0 += self::mul($c, 5);
    392         $c = $h0->shiftRight(26);           # $c = $h0 >> 26;
    393         $h0 = $h0->mask(0x3ffffff);         # $h0 &= 0x3ffffff;
    394         $h1 = $h1->addInt32($c);            # $h1 += $c;
    395 
    396         /* compute h + -p */
    397         $g0 = $h0->addInt(5);
    398         $c  = $g0->shiftRight(26);
    399         $g0 = $g0->mask(0x3ffffff);
    400         $g1 = $h1->addInt32($c);
    401         $c  = $g1->shiftRight(26);
    402         $g1 = $g1->mask(0x3ffffff);
    403         $g2 = $h2->addInt32($c);
    404         $c  = $g2->shiftRight(26);
    405         $g2 = $g2->mask(0x3ffffff);
    406         $g3 = $h3->addInt32($c);
    407         $c  = $g3->shiftRight(26);
    408         $g3 = $g3->mask(0x3ffffff);
    409         $g4 = $h4->addInt32($c)->subInt(1 << 26);
    410 
    411         # $mask = ($g4 >> 31) - 1;
    412         /* select h if h < p, or h + -p if h >= p */
    413         $mask = (int) (($g4->toInt() >> 31) + 1);
    414 
    415         $g0 = $g0->mask($mask);
    416         $g1 = $g1->mask($mask);
    417         $g2 = $g2->mask($mask);
    418         $g3 = $g3->mask($mask);
    419         $g4 = $g4->mask($mask);
    420 
    421         /** @var int $mask */
    422         $mask = (~$mask) & 0xffffffff;
    423 
    424         $h0 = $h0->mask($mask)->orInt32($g0);
    425         $h1 = $h1->mask($mask)->orInt32($g1);
    426         $h2 = $h2->mask($mask)->orInt32($g2);
    427         $h3 = $h3->mask($mask)->orInt32($g3);
    428         $h4 = $h4->mask($mask)->orInt32($g4);
    429 
    430         /* h = h % (2^128) */
    431         $h0 = $h0->orInt32($h1->shiftLeft(26));
    432         $h1 = $h1->shiftRight(6)->orInt32($h2->shiftLeft(20));
    433         $h2 = $h2->shiftRight(12)->orInt32($h3->shiftLeft(14));
    434         $h3 = $h3->shiftRight(18)->orInt32($h4->shiftLeft(8));
    435 
    436         /* mac = (h + pad) % (2^128) */
    437         $f = $h0->toInt64()->addInt64($this->pad[0]);
    438         $h0 = $f->toInt32();
    439         $f = $h1->toInt64()->addInt64($this->pad[1])->addInt($h0->overflow);
    440         $h1 = $f->toInt32();
    441         $f = $h2->toInt64()->addInt64($this->pad[2])->addInt($h1->overflow);
    442         $h2 = $f->toInt32();
    443         $f = $h3->toInt64()->addInt64($this->pad[3])->addInt($h2->overflow);
    444         $h3 = $f->toInt32();
    445 
    446         return $h0->toReverseString() .
    447             $h1->toReverseString() .
    448             $h2->toReverseString() .
    449             $h3->toReverseString();
    450     }
    451 }