WordPress.org

Make WordPress Core

Ticket #39309: 39309.patch

File 39309.patch, 441.3 KB (added by paragoninitiativeenterprises, 2 years ago)

First round of Ed25519 verification

  • wp-includes/sodium_compat/LICENSE

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
     
     1/*
     2 * ISC License
     3 *
     4 * Copyright (c) 2016-2017
     5 * Paragon Initiative Enterprises <security at paragonie dot com>
     6 *
     7 * Copyright (c) 2013-2017
     8 * Frank Denis <j at pureftpd dot org>
     9 *
     10 * Permission to use, copy, modify, and/or distribute this software for any
     11 * purpose with or without fee is hereby granted, provided that the above
     12 * copyright notice and this permission notice appear in all copies.
     13 *
     14 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     15 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     16 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     17 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     18 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     19 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     20 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     21 */
     22 No newline at end of file
  • wp-includes/sodium_compat/composer.json

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
     
     1{
     2  "name": "paragonie/sodium_compat",
     3  "description": "Pure PHP implementation of libsodium; uses the PHP extension if it exists",
     4  "keywords": ["PHP", "cryptography", "elliptic curve", "side-channel resistant"],
     5  "license": "ISC",
     6  "authors": [
     7    {
     8      "name": "Paragon Initiative Enterprises",
     9      "email": "security@paragonie.com"
     10    },
     11    {
     12      "name": "Frank Denis",
     13      "email": "jedisct1@pureftpd.org"
     14    }
     15  ],
     16  "autoload": {
     17    "files": ["autoload.php"]
     18  },
     19  "require": {
     20    "php": "^5.2.4|^5.3|^5.4|^5.5|^5.6|^7",
     21    "paragonie/random_compat": "^1|^2"
     22  },
     23  "require-dev": {
     24    "phpunit/phpunit": "*"
     25  }
     26}
     27 No newline at end of file
  • wp-includes/sodium_compat/src/Core/Poly1305.php

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
     
     1<?php
     2
     3/**
     4 * Class ParagonIE_Sodium_Core_Poly1305
     5 */
     6abstract class ParagonIE_Sodium_Core_Poly1305 extends ParagonIE_Sodium_Core_Util
     7{
     8    const BLOCK_SIZE = 16;
     9
     10    /**
     11     * @param string $m
     12     * @param string $key
     13     * @return string
     14     */
     15    public static function onetimeauth($m, $key)
     16    {
     17        if (self::strlen($key) < 32) {
     18            throw new InvalidArgumentException(
     19                'Key must be 32 bytes long.'
     20            );
     21        }
     22        $state = new ParagonIE_Sodium_Core_Poly1305_State(
     23            self::substr($key, 0, 32)
     24        );
     25        return $state->update($m)->finish();
     26    }
     27
     28    /**
     29     * @param string $mac
     30     * @param string $m
     31     * @param string $key
     32     * @return bool
     33     */
     34    public static function onetimeauth_verify($mac, $m, $key)
     35    {
     36        if (self::strlen($key) < 32) {
     37            throw new InvalidArgumentException(
     38                'Key must be 32 bytes long.'
     39            );
     40        }
     41        $state = new ParagonIE_Sodium_Core_Poly1305_State(
     42            self::substr($key, 0, 32)
     43        );
     44        $calc = $state->update($m)->finish();
     45        return self::verify_16($calc, $mac);
     46    }
     47}
  • wp-includes/sodium_compat/tests/unit/SipHashTest.php

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
     
     1<?php
     2
     3class SipHashTest extends PHPUnit_Framework_TestCase
     4{
     5    public function setUp()
     6    {
     7        ParagonIE_Sodium_Compat::$disableFallbackForUnitTests = true;
     8    }
     9
     10    /**
     11     * @covers ParagonIE_Sodium_Core_SipHash::add()
     12     */
     13    public function testAdd()
     14    {
     15        if (PHP_INT_SIZE === 4) {
     16            $this->markTestSkipped('Test should be performed on a 64-bit OS');
     17            return;
     18        }
     19
     20        $vectors = array(
     21            array(
     22                0x0123456789abcdef,
     23                0x456789abcdef0123,
     24                0x468acf13579acf12
     25            ),
     26            array(
     27                0x0000000100000000,
     28                0x0000000000000100,
     29                0x0000000100000100
     30            ),
     31            array(
     32                0x0000000100000000,
     33                0x0000000000000100,
     34                0x0000000100000100
     35            ),
     36            array(
     37                0x0fffffffffffffff,
     38                0x0000000000000001,
     39                0x1000000000000000
     40            )
     41        );
     42        foreach ($vectors as $v) {
     43            list($a, $b, $c) = $v;
     44            # $this->assertSame($c, PHP_INT_MAX & ($a + $b));
     45
     46            $sA = array(
     47                $a >> 32,
     48                $a & 0xffffffff
     49            );
     50            $sB = array(
     51                $b >> 32,
     52                $b & 0xffffffff
     53            );
     54            $sC = array(
     55                ($c >> 32) & 0xffffffff,
     56                $c & 0xffffffff
     57            );
     58            $this->assertSame(
     59                $sC,
     60                ParagonIE_Sodium_Core_SipHash::add($sA, $sB)
     61            );
     62        }
     63    }
     64
     65    /**
     66     * @covers ParagonIE_Sodium_Core_SipHash::rotl_64()
     67     */
     68    public function testRotl64()
     69    {
     70        $this->assertSame(
     71            array(0x00010000, 0x00000000),
     72            ParagonIE_Sodium_Core_SipHash::rotl_64(0x00000001, 0x00000000, 16),
     73            'rotl_64 by 16'
     74        );
     75        $this->assertSame(
     76            array(0x80000000, 0x00000000),
     77            ParagonIE_Sodium_Core_SipHash::rotl_64(0x00000001, 0x00000000, 31),
     78            'rotl_64 by 31'
     79        );
     80        $this->assertSame(
     81            array(0x80000000, 0x00000000),
     82            ParagonIE_Sodium_Core_SipHash::rotl_64(0x00000001, 0x00000000, 95),
     83            'rotl_64 by 95 (reduce to 31)'
     84        );
     85        $this->assertSame(
     86            array(0x00000000, 0x00000001),
     87            ParagonIE_Sodium_Core_SipHash::rotl_64(0x00000001, 0x00000000, 32),
     88            'rotl_64 by 32'
     89        );
     90        $this->assertSame(
     91            array(0x00000000, 0x00000008),
     92            ParagonIE_Sodium_Core_SipHash::rotl_64(0x00000001, 0x00000000, 35),
     93            'rotl_64 by 35'
     94        );
     95        $this->assertSame(
     96            array(0x00000000, 0x80000000),
     97            ParagonIE_Sodium_Core_SipHash::rotl_64(0x00000001, 0x00000000, 63),
     98            'rotl_64 by 63'
     99        );
     100        $this->assertSame(
     101            array(0x00000001, 0x00000000),
     102            ParagonIE_Sodium_Core_SipHash::rotl_64(0x00000001, 0x00000000, 64),
     103            'rotl_64 by 64'
     104        );
     105        $this->assertSame(
     106            array(0x7DDF575A, 0x3BD5BD5B),
     107            ParagonIE_Sodium_Core_SipHash::rotl_64(0xDEADBEEF, 0xABAD1DEA, 17),
     108            'rotl_64 by 64'
     109        );
     110    }
     111
     112    /**
     113     *
     114     */
     115    public function testCryptoShorthash()
     116    {
     117        $message = 'this is just a test message';
     118        $key = str_repeat("\x80", 16);
     119
     120        $this->assertSame(
     121            '3f188259b01151a7',
     122            bin2hex(ParagonIE_Sodium_Compat::crypto_shorthash($message, $key))
     123        );
     124    }
     125}
     126 No newline at end of file
  • wp-includes/sodium_compat/tests/unit/Poly1305Test.php

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
     
     1<?php
     2
     3class Poly1305Test extends PHPUnit_Framework_TestCase
     4{
     5    public function setUp()
     6    {
     7        ParagonIE_Sodium_Compat::$disableFallbackForUnitTests = true;
     8    }
     9
     10    /**
     11     * @covers ParagonIE_Sodium_Core_Poly1305::onetimeauth()
     12     * @ref https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04#page-12
     13     */
     14    public function testVectorA()
     15    {
     16        $msg = ParagonIE_Sodium_Core_Util::hex2bin('0000000000000000000000000000000000000000000000000000000000000000');
     17        $key = ParagonIE_Sodium_Core_Util::hex2bin('746869732069732033322d62797465206b657920666f7220506f6c7931333035');
     18        $this->assertSame(
     19            '49ec78090e481ec6c26b33b91ccc0307',
     20            bin2hex(ParagonIE_Sodium_Core_Poly1305::onetimeauth($msg, $key)),
     21            'crypto_onetimeauth is broken'
     22        );
     23    }
     24
     25    /**
     26     * @covers ParagonIE_Sodium_Core_Poly1305::onetimeauth()
     27     * @ref https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04#page-12
     28     */
     29    public function testVectorB()
     30    {
     31
     32        $msg = ParagonIE_Sodium_Core_Util::hex2bin('48656c6c6f20776f726c6421');
     33        $key = ParagonIE_Sodium_Core_Util::hex2bin('746869732069732033322d62797465206b657920666f7220506f6c7931333035');
     34        $this->assertSame(
     35            'a6f745008f81c916a20dcc74eef2b2f0',
     36            bin2hex(ParagonIE_Sodium_Core_Poly1305::onetimeauth($msg, $key)),
     37            'crypto_onetimeauth is broken'
     38        );
     39    }
     40
     41    /**
     42     * @covers ParagonIE_Sodium_Core_Poly1305::onetimeauth()
     43     *
     44     * A large message test vector.
     45     *
     46     * @ref https://github.com/jedisct1/libsodium/blob/master/test/default/onetimeauth2.c
     47     */
     48    public function testVectorC()
     49    {
     50
     51        $msg = ParagonIE_Sodium_Core_Util::intArrayToString(
     52            array(
     53                0x8e, 0x99, 0x3b, 0x9f, 0x48, 0x68, 0x12, 0x73, 0xc2, 0x96, 0x50, 0xba,
     54                0x32, 0xfc, 0x76, 0xce, 0x48, 0x33, 0x2e, 0xa7, 0x16, 0x4d, 0x96, 0xa4,
     55                0x47, 0x6f, 0xb8, 0xc5, 0x31, 0xa1, 0x18, 0x6a, 0xc0, 0xdf, 0xc1, 0x7c,
     56                0x98, 0xdc, 0xe8, 0x7b, 0x4d, 0xa7, 0xf0, 0x11, 0xec, 0x48, 0xc9, 0x72,
     57                0x71, 0xd2, 0xc2, 0x0f, 0x9b, 0x92, 0x8f, 0xe2, 0x27, 0x0d, 0x6f, 0xb8,
     58                0x63, 0xd5, 0x17, 0x38, 0xb4, 0x8e, 0xee, 0xe3, 0x14, 0xa7, 0xcc, 0x8a,
     59                0xb9, 0x32, 0x16, 0x45, 0x48, 0xe5, 0x26, 0xae, 0x90, 0x22, 0x43, 0x68,
     60                0x51, 0x7a, 0xcf, 0xea, 0xbd, 0x6b, 0xb3, 0x73, 0x2b, 0xc0, 0xe9, 0xda,
     61                0x99, 0x83, 0x2b, 0x61, 0xca, 0x01, 0xb6, 0xde, 0x56, 0x24, 0x4a, 0x9e,
     62                0x88, 0xd5, 0xf9, 0xb3, 0x79, 0x73, 0xf6, 0x22, 0xa4, 0x3d, 0x14, 0xa6,
     63                0x59, 0x9b, 0x1f, 0x65, 0x4c, 0xb4, 0x5a, 0x74, 0xe3, 0x55, 0xa5
     64            )
     65        );;
     66        $key = ParagonIE_Sodium_Core_Util::intArrayToString(
     67            array(
     68                0xee, 0xa6, 0xa7, 0x25, 0x1c, 0x1e, 0x72, 0x91, 0x6d, 0x11, 0xc2,
     69                0xcb, 0x21, 0x4d, 0x3c, 0x25, 0x25, 0x39, 0x12, 0x1d, 0x8e, 0x23,
     70                0x4e, 0x65, 0x2d, 0x65, 0x1f, 0xa4, 0xc8, 0xcf, 0xf8, 0x80
     71            )
     72        );
     73        $tag = ParagonIE_Sodium_Core_Util::intArrayToString(
     74            array(
     75                0xf3, 0xff, 0xc7, 0x70, 0x3f, 0x94, 0x00, 0xe5,
     76                0x2a, 0x7d, 0xfb, 0x4b, 0x3d, 0x33, 0x05, 0xd9
     77            )
     78        );
     79
     80        $this->assertSame(
     81            bin2hex($tag),
     82            bin2hex(ParagonIE_Sodium_Core_Poly1305::onetimeauth($msg, $key)),
     83            'crypto_onetimeauth is broken'
     84        );
     85        $this->assertTrue(
     86            ParagonIE_Sodium_Core_Poly1305::onetimeauth_verify($tag, $msg, $key),
     87            'crypto_onetimeauth_verify is broken'
     88        );
     89    }
     90
     91    /**
     92     * @covers ParagonIE_Sodium_Core_Poly1305::onetimeauth_verify()
     93     */
     94    public function testRandomVerify()
     95    {
     96        $msg = random_bytes(random_int(1, 1000));
     97        $key = random_bytes(32);
     98
     99        $mac = ParagonIE_Sodium_Core_Poly1305::onetimeauth($msg, $key);
     100        $this->assertTrue(
     101            ParagonIE_Sodium_Core_Poly1305::onetimeauth_verify($mac, $msg, $key),
     102            'crypto_onetimeauth_verify is broken'
     103        );
     104    }
     105}
     106 No newline at end of file
  • wp-includes/sodium_compat/tests/unit/Salsa20Test.php

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
     
     1<?php
     2
     3class Salsa20Test extends PHPUnit_Framework_TestCase
     4{
     5    public function setUp()
     6    {
     7        ParagonIE_Sodium_Compat::$disableFallbackForUnitTests = true;
     8    }
     9
     10    /**
     11     * @covers ParagonIE_Sodium_Core_Salsa20::rotate()
     12     */
     13    public function testRotate()
     14    {
     15        $this->assertEquals(
     16            0x00001000,
     17            ParagonIE_Sodium_Core_Salsa20::rotate(0x00000001, 12),
     18            'Left rotate by 12'
     19        );
     20
     21        $this->assertEquals(
     22            0x00002000,
     23            ParagonIE_Sodium_Core_Salsa20::rotate(0x00000001, 13),
     24            'Left rotate by 13'
     25        );
     26        $this->assertEquals(
     27            0x10000000,
     28            ParagonIE_Sodium_Core_Salsa20::rotate(0x00000001, 28),
     29            'Left rotate by 28'
     30        );
     31        $this->assertEquals(
     32            0x80000000,
     33            ParagonIE_Sodium_Core_Salsa20::rotate(0x00000001, 31),
     34            'Left rotate by 31'
     35        );
     36        $this->assertEquals(
     37            0x00000001,
     38            ParagonIE_Sodium_Core_Salsa20::rotate(0x00000001, 32),
     39            'Left rotate by 32'
     40        );
     41
     42        $this->assertEquals(
     43            0xf0001000,
     44            ParagonIE_Sodium_Core_Salsa20::rotate(0x000f0001, 12),
     45            'Left rotate by 12'
     46        );
     47
     48        $this->assertEquals(
     49            0xe0002001,
     50            ParagonIE_Sodium_Core_Salsa20::rotate(0x000f0001, 13),
     51            'Left rotate by 13'
     52        );
     53
     54        $this->assertEquals(
     55            0xc0004003,
     56            ParagonIE_Sodium_Core_Salsa20::rotate(0x000f0001, 14),
     57            'Left rotate by 14'
     58        );
     59
     60        $this->assertEquals(
     61            0x80008007,
     62            ParagonIE_Sodium_Core_Salsa20::rotate(0x000f0001, 15),
     63            'Left rotate by 15'
     64        );
     65
     66        $this->assertEquals(
     67            0x0001000f,
     68            ParagonIE_Sodium_Core_Salsa20::rotate(0x000f0001, 16),
     69            'Left rotate by 16'
     70        );
     71    }
     72
     73    /**
     74     * @covers ParagonIE_Sodium_Core_Salsa20::salsa20()
     75     */
     76    public function testVectors()
     77    {
     78        $key = "\x80" . str_repeat("\x00", 31);
     79        $iv = str_repeat("\x00", 8);
     80
     81        $output = ParagonIE_Sodium_Core_Salsa20::salsa20(512, $iv, $key);
     82
     83        $this->assertSame(
     84            'E3BE8FDD8BECA2E3EA8EF9475B29A6E7' .
     85            '003951E1097A5C38D23B7A5FAD9F6844' .
     86            'B22C97559E2723C7CBBD3FE4FC8D9A07' .
     87            '44652A83E72A9C461876AF4D7EF1A117',
     88            strtoupper(
     89                bin2hex(
     90                    ParagonIE_Sodium_Core_Util::substr($output, 0, 64)
     91                )
     92            ),
     93            'Test vector #1 failed!'
     94        );
     95
     96        $this->assertSame(
     97            '57BE81F47B17D9AE7C4FF15429A73E10' .
     98            'ACF250ED3A90A93C711308A74C6216A9' .
     99            'ED84CD126DA7F28E8ABF8BB63517E1CA' .
     100            '98E712F4FB2E1A6AED9FDC73291FAA17',
     101            strtoupper(
     102                bin2hex(
     103                    ParagonIE_Sodium_Core_Util::substr($output, 192, 64)
     104                )
     105            ),
     106            'Test vector #1 failed!'
     107        );
     108    }
     109
     110    /**
     111     * @covers ParagonIE_Sodium_Core_Salsa20::core_salsa20()
     112     */
     113    public function testCoreSalsa20()
     114    {
     115        $key = random_bytes(32);
     116        $iv = random_bytes(8);
     117        $outA = ParagonIE_Sodium_Core_Salsa20::salsa20(192, $iv, $key);
     118
     119        // First block
     120        $outB = ParagonIE_Sodium_Core_Salsa20::core_salsa20($iv . str_repeat("\x00", 8), $key);
     121        $this->assertSame(
     122            bin2hex(
     123                ParagonIE_Sodium_Core_Util::substr($outA, 0, 64)
     124            ),
     125            bin2hex($outB)
     126        );
     127
     128        // Second block
     129        $outC = ParagonIE_Sodium_Core_Salsa20::core_salsa20($iv . "\x01" . str_repeat("\x00", 7), $key);
     130        $this->assertSame(
     131            bin2hex(
     132                ParagonIE_Sodium_Core_Util::substr($outA, 64, 64)
     133            ),
     134            bin2hex($outC)
     135        );
     136
     137        // Third block
     138        $outD = ParagonIE_Sodium_Core_Salsa20::core_salsa20($iv . "\x02" . str_repeat("\x00", 7), $key);
     139        $this->assertSame(
     140            bin2hex(
     141                ParagonIE_Sodium_Core_Util::substr($outA, 128, 64)
     142            ),
     143            bin2hex($outD)
     144        );
     145    }
     146}
  • wp-admin/includes/class-wp-upgrader.php

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
     
    5050 */
    5151class WP_Upgrader {
    5252
     53    const ED25519_PUBLIC_KEY = '4d6236cc44829b2f96a26d905aec92162077ef5aa7e0a4e2a6d251258dc83bd1';
     54
    5355        /**
    5456         * The error/notification strings used to update the user on the progress.
    5557         *
     
    274276
    275277                $this->skin->feedback('downloading_package', $package);
    276278
    277                 $download_file = download_url($package);
     279                $download_file = download_url($package, 300, self::ED25519_PUBLIC_KEY);
     280                if ( is_wp_error($download_file) ) {
     281            if ($download_file->get_error_code() === 'ed25519_mismatch') {
     282                $package .= '?ed25519failed=1';
     283                // Try again without Ed25519 verification. Remove this silent fallback in the next version.
     284                $download_file = download_url($package);
     285            }
     286        }
    278287
    279288                if ( is_wp_error($download_file) )
    280289                        return new WP_Error('download_failed', $this->strings['download_failed'], $download_file->get_error_message());
  • wp-includes/sodium_compat/README.md

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
     
     1# Sodium Compat
     2
     3[![Build Status](https://travis-ci.org/paragonie/sodium_compat.svg?branch=master)](https://travis-ci.org/paragonie/sodium_compat)
     4[![Latest Stable Version](https://poser.pugx.org/paragonie/sodium_compat/v/stable)](https://packagist.org/packages/paragonie/sodium_compat)
     5[![Latest Unstable Version](https://poser.pugx.org/paragonie/sodium_compat/v/unstable)](https://packagist.org/packages/paragonie/sodium_compat)
     6[![License](https://poser.pugx.org/paragonie/sodium_compat/license)](https://packagist.org/packages/paragonie/sodium_compat)
     7
     8Sodium Compat is a pure PHP polyfill for the Sodium cryptography library
     9(libsodium), otherwise [available in PECL](https://pecl.php.net/package/libsodium).
     10
     11This library tentativeley supports PHP 5.2.4 - 7.x (latest), but officially
     12only supports [non-EOL'd versions of PHP](https://secure.php.net/supported-versions.php).
     13
     14If you have the PHP extension installed, Sodium Compat will opportunistically
     15and transparently use the PHP extension instead of our implementation.
     16
     17## IMPORTANT!
     18
     19### ![Danger: Experimental](https://camo.githubusercontent.com/275bc882f21b154b5537b9c123a171a30de9e6aa/68747470733a2f2f7261772e6769746875622e636f6d2f63727970746f7370686572652f63727970746f7370686572652f6d61737465722f696d616765732f6578706572696d656e74616c2e706e67)
     20
     21This is an **experimental** cryptography library. It has not been formally
     22audited by an independent third party that specializes in cryptography or
     23cryptanalysis.
     24
     25Until it has received a clean bill of health from independent computer security
     26experts, **use this library at your own risk.**
     27
     28# Installing Sodium Compat
     29
     30If you're using Composer:
     31
     32```bash
     33composer require paragonie/sodium_compat
     34```
     35
     36If you're not using Composer, download a [release tarball](https://github.com/paragonie/sodium_compat/releases)
     37(which should be signed with [our GnuPG public key](https://paragonie.com/static/gpg-public-key.txt)), extract
     38its contents, then include our `autoload.php` script in your project.
     39
     40```php
     41<?php
     42require_once "/path/to/sodium_compat/autoload.php";
     43```
     44
     45# Using Sodium Compat
     46
     47## True Polyfill
     48
     49If you're using PHP 5.3.0 or newer and do not have the PECL extension installed,
     50you can just use the [standard ext/sodium API features as-is](https://paragonie.com/book/pecl-libsodium)
     51and the polyfill will work its magic.
     52
     53```php
     54<?php
     55require_once "/path/to/sodium_compat/autoload.php";
     56
     57$alice_kp = \Sodium\crypto_sign_keypair();
     58$alice_sk = \Sodium\crypto_sign_secretkey($alice_kp);
     59$alice_pk = \Sodium\crypto_sign_publickey($alice_kp);
     60
     61$message = 'This is a test message.';
     62$signature = \Sodium\crypto_sign_detached($message, $alice_sk);
     63if (\Sodium\crypto_sign_verify_detached($signature, $message, $alice_pk)) {
     64    echo 'OK', PHP_EOL;
     65} else {
     66    throw new Exception('Invalid signature');
     67}
     68```
     69
     70The polyfill does not expose this API on PHP < 5.3, or if you have the PHP
     71extension installed already.
     72
     73## General-Use Polyfill
     74
     75If your users are on PHP < 5.3, or you want to write code that will work
     76whether or not the PECL extension is available, you'll want to use the
     77**`ParagonIE_Sodium_Compat`** class for most of your libsodium needs.
     78
     79The above example, written for general use:
     80
     81```php
     82<?php
     83require_once "/path/to/sodium_compat/autoload.php";
     84
     85$alice_kp = ParagonIE_Sodium_Compat::crypto_sign_keypair();
     86$alice_sk = ParagonIE_Sodium_Compat::crypto_sign_secretkey($alice_kp);
     87$alice_pk = ParagonIE_Sodium_Compat::crypto_sign_publickey($alice_kp);
     88
     89$message = 'This is a test message.';
     90$signature = ParagonIE_Sodium_Compat::crypto_sign_detached($message, $alice_sk);
     91if (ParagonIE_Sodium_Compat::crypto_sign_verify_detached($signature, $message, $alice_pk)) {
     92    echo 'OK', PHP_EOL;
     93} else {
     94    throw new Exception('Invalid signature');
     95}
     96```
     97
     98Generally: If you replace `\Sodium\ ` with `ParagonIE_Sodium_Compat::`, any
     99code already written for the libsodium PHP extension should work with our
     100polyfill without additional code changes.
     101
     102To learn how to use Libsodium, read [*Using Libsodium in PHP Projects*](https://paragonie.com/book/pecl-libsodium).
     103
     104## API Coverage
     105
     106* Mainline NaCl Features
     107    * `crypto_auth()`
     108    * `crypto_auth_verify()`
     109    * `crypto_box()`
     110    * `crypto_box_open()`
     111    * `crypto_scalarmult()`
     112    * `crypto_secretbox()`
     113    * `crypto_secretbox_open()`
     114    * `crypto_sign()`
     115    * `crypto_sign_open()`
     116* PECL Libsodium Features
     117    * `crypto_box_seal()`
     118    * `crypto_box_seal_open()`
     119    * `crypto_generichash()`
     120    * `crypto_generichash_init()`
     121    * `crypto_generichash_update()`
     122    * `crypto_generichash_final()`
     123    * `crypto_kx()`
     124    * `crypto_shorthash()`
     125    * `crypto_sign_detached()`
     126    * `crypto_sign_verify_detached()`
     127    * For advanced users only:
     128        * `crypto_stream()`
     129        * `crypto_stream_xor()`
     130    * Other utilities (e.g. `crypto_*_keypair()`)
     131
     132### Features Excluded from this Polyfill
     133
     134* `\Sodium\memzero()` - Although we expose this API endpoint, it's a NOP. We can't
     135  reliably zero buffers from PHP.
     136* `\Sodium\crypto_pwhash()` - It's not feasible to polyfill scrypt or Argon2 into PHP and get
     137  reasonable performance. Users would feel motivated to select parameters that downgrade
     138  security to avoid denial of service (DoS) attacks.
     139 
     140  The only winning move is not to play.
  • wp-includes/sodium_compat/src/Core/Poly1305/State.php

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
     
     1<?php
     2
     3/**
     4 * Class ParagonIE_Sodium_Core_Poly1305_State
     5 */
     6class ParagonIE_Sodium_Core_Poly1305_State extends ParagonIE_Sodium_Core_Util
     7{
     8    /**
     9     * @var int[]
     10     */
     11    protected $buffer = array();
     12
     13    /**
     14     * @var bool
     15     */
     16    protected $final = false;
     17
     18    /**
     19     * @var int[]
     20     */
     21    public $h;
     22
     23    /**
     24     * @var int
     25     */
     26    protected $leftover = 0;
     27
     28    /**
     29     * @var int[]
     30     */
     31    public $r;
     32
     33    /**
     34     * @var int[]
     35     */
     36    public $pad;
     37
     38    /**
     39     * ParagonIE_Sodium_Core_Poly1305_State constructor.
     40     * @param string $key
     41     */
     42    public function __construct($key = '')
     43    {
     44        if (self::strlen($key) < 32) {
     45            throw new InvalidArgumentException(
     46                'Poly1305 requires a 32-byte key'
     47            );
     48        }
     49        /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
     50        $this->r = array(
     51            (self::load_4(self::substr($key,  0, 4))     ) & 0x3ffffff,
     52            (self::load_4(self::substr($key,  3, 4)) >> 2) & 0x3ffff03,
     53            (self::load_4(self::substr($key,  6, 4)) >> 4) & 0x3ffc0ff,
     54            (self::load_4(self::substr($key,  9, 4)) >> 6) & 0x3f03fff,
     55            (self::load_4(self::substr($key, 12, 4)) >> 8) & 0x00fffff
     56        );
     57
     58        /* h = 0 */
     59        $this->h = array(0, 0, 0, 0, 0);
     60
     61        /* save fpad for later */
     62        $this->pad = array(
     63            self::load_4(self::substr($key, 16, 4)),
     64            self::load_4(self::substr($key, 20, 4)),
     65            self::load_4(self::substr($key, 24, 4)),
     66            self::load_4(self::substr($key, 28, 4)),
     67        );
     68
     69        $this->leftover = 0;
     70        $this->final = false;
     71    }
     72
     73    /**
     74     * @param string $message
     75     * @return self
     76     */
     77    public function update($message = '')
     78    {
     79        $bytes = self::strlen($message);
     80
     81        /* handle leftover */
     82        if ($this->leftover) {
     83            $want = ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE - $this->leftover;
     84            if ($want > $bytes) {
     85                $want = $bytes;
     86            }
     87            for ($i = 0; $i < $want; ++$i) {
     88                $mi = self::chrToInt($message[$i]);
     89                $this->buffer[$this->leftover + $i] = $mi;
     90            }
     91            // We snip off the leftmost bytes.
     92            $message = self::substr($message, $want);
     93            $bytes = self::strlen($message);
     94            $this->leftover += $want;
     95            if ($this->leftover < ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE) {
     96                // We still don't have enough to run $this->blocks()
     97                return $this;
     98            }
     99
     100            $this->blocks(
     101                static::intArrayToString($this->buffer),
     102                ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE
     103            );
     104            $this->leftover = 0;
     105        }
     106
     107        /* process full blocks */
     108        if ($bytes >= ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE) {
     109            $want = $bytes & ~(ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE - 1);
     110            if ($want >= ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE) {
     111                $block = self::substr($message, 0, $want);
     112                if (self::strlen($block) >= ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE) {
     113                    $this->blocks($block, $want);
     114                    $message = self::substr($message, $want);
     115                    $bytes = self::strlen($message);
     116                }
     117            }
     118        }
     119
     120        /* store leftover */
     121        if ($bytes) {
     122            for ($i = 0; $i < $bytes; ++$i) {
     123                $mi = self::chrToInt($message[$i]);
     124                $this->buffer[$this->leftover + $i] = $mi;
     125            }
     126            $this->leftover = (int) $this->leftover + $bytes;
     127        }
     128        return $this;
     129    }
     130
     131    /**
     132     * @param string $message
     133     * @param int $bytes
     134     * @return self
     135     */
     136    public function blocks($message, $bytes)
     137    {
     138        if (self::strlen($message) < 16) {
     139            $message = str_pad($message, 16, "\x00", STR_PAD_RIGHT);
     140        }
     141        $hibit = $this->final ? 0 : 1 << 24; /* 1 << 128 */
     142        $r0 = (int) $this->r[0];
     143        $r1 = (int) $this->r[1];
     144        $r2 = (int) $this->r[2];
     145        $r3 = (int) $this->r[3];
     146        $r4 = (int) $this->r[4];
     147
     148        $s1 = $r1 * 5;
     149        $s2 = $r2 * 5;
     150        $s3 = $r3 * 5;
     151        $s4 = $r4 * 5;
     152
     153        $h0 = $this->h[0];
     154        $h1 = $this->h[1];
     155        $h2 = $this->h[2];
     156        $h3 = $this->h[3];
     157        $h4 = $this->h[4];
     158
     159        while ($bytes >= ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE) {
     160            /* h += m[i] */
     161            $h0 +=  self::load_4(self::substr($message,  0, 4))       & 0x3ffffff;
     162            $h1 += (self::load_4(self::substr($message,  3, 4)) >> 2) & 0x3ffffff;
     163            $h2 += (self::load_4(self::substr($message,  6, 4)) >> 4) & 0x3ffffff;
     164            $h3 += (self::load_4(self::substr($message,  9, 4)) >> 6) & 0x3ffffff;
     165            $h4 += (self::load_4(self::substr($message, 12, 4)) >> 8) | $hibit;
     166
     167            /* h *= r */
     168            $d0 = (
     169                ($h0 * $r0) +
     170                ($h1 * $s4) +
     171                ($h2 * $s3) +
     172                ($h3 * $s2) +
     173                ($h4 * $s1)
     174            );
     175            $d1 = (
     176                ($h0 * $r1) +
     177                ($h1 * $r0) +
     178                ($h2 * $s4) +
     179                ($h3 * $s3) +
     180                ($h4 * $s2)
     181            );
     182
     183            $d2 = (
     184                ($h0 * $r2) +
     185                ($h1 * $r1) +
     186                ($h2 * $r0) +
     187                ($h3 * $s4) +
     188                ($h4 * $s3)
     189            );
     190
     191            $d3 = (
     192                ($h0 * $r3) +
     193                ($h1 * $r2) +
     194                ($h2 * $r1) +
     195                ($h3 * $r0) +
     196                ($h4 * $s4)
     197            );
     198
     199            $d4 = (
     200                ($h0 * $r4) +
     201                ($h1 * $r3) +
     202                ($h2 * $r2) +
     203                ($h3 * $r1) +
     204                ($h4 * $r0)
     205            );
     206
     207            /* (partial) h %= p */
     208                                 $c = $d0 >> 26; $h0 = $d0 & 0x3ffffff;
     209            $d1 += $c;           $c = $d1 >> 26; $h1 = $d1 & 0x3ffffff;
     210            $d2 += $c;           $c = $d2 >> 26; $h2 = $d2 & 0x3ffffff;
     211            $d3 += $c;           $c = $d3 >> 26; $h3 = $d3 & 0x3ffffff;
     212            $d4 += $c;           $c = $d4 >> 26; $h4 = $d4 & 0x3ffffff;
     213            $h0 += (int) $c * 5; $c = $h0 >> 26; $h0 &= 0x3ffffff;
     214            $h1 += $c;
     215
     216            // Chop off the left 32 bytes.
     217            $message = self::substr(
     218                $message,
     219                ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE
     220            );
     221            $bytes -= ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE;
     222        }
     223
     224        $this->h = array(
     225            (int) $h0 & 0xffffffff,
     226            (int) $h1 & 0xffffffff,
     227            (int) $h2 & 0xffffffff,
     228            (int) $h3 & 0xffffffff,
     229            (int) $h4 & 0xffffffff
     230        );
     231        return $this;
     232    }
     233
     234    /**
     235     * @return string
     236     */
     237    public function finish()
     238    {
     239        /* process the remaining block */
     240        if ($this->leftover) {
     241            $i = $this->leftover;
     242            $this->buffer[$i++] = 1;
     243            for (; $i < ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE; ++$i) {
     244                $this->buffer[$i] = 0;
     245            }
     246            $this->final = true;
     247            $this->blocks(
     248                self::substr(
     249                    static::intArrayToString($this->buffer),
     250                    0,
     251                    ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE
     252                ),
     253                ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE
     254            );
     255        }
     256
     257        $h0 = (int) $this->h[0];
     258        $h1 = (int) $this->h[1];
     259        $h2 = (int) $this->h[2];
     260        $h3 = (int) $this->h[3];
     261        $h4 = (int) $this->h[4];
     262
     263                       $c = $h1 >> 26; $h1 &= 0x3ffffff;
     264        $h2 += $c;     $c = $h2 >> 26; $h2 &= 0x3ffffff;
     265        $h3 += $c;     $c = $h3 >> 26; $h3 &= 0x3ffffff;
     266        $h4 += $c;     $c = $h4 >> 26; $h4 &= 0x3ffffff;
     267        $h0 += $c * 5; $c = $h0 >> 26; $h0 &= 0x3ffffff;
     268        $h1 += $c;
     269
     270        /* compute h + -p */
     271        $g0 = $h0 +  5; $c = $g0 >> 26; $g0 &= 0x3ffffff;
     272        $g1 = $h1 + $c; $c = $g1 >> 26; $g1 &= 0x3ffffff;
     273        $g2 = $h2 + $c; $c = $g2 >> 26; $g2 &= 0x3ffffff;
     274        $g3 = $h3 + $c; $c = $g3 >> 26; $g3 &= 0x3ffffff;
     275        $g4 = ($h4 + $c - (1 << 26)) & 0xffffffff;
     276
     277        /* select h if h < p, or h + -p if h >= p */
     278        $mask = ($g4 >> 31) - 1;
     279
     280        $g0 &= $mask;
     281        $g1 &= $mask;
     282        $g2 &= $mask;
     283        $g3 &= $mask;
     284        $g4 &= $mask;
     285
     286        $mask = ~$mask & 0xffffffff;
     287        $h0 = ($h0 & $mask) | $g0;
     288        $h1 = ($h1 & $mask) | $g1;
     289        $h2 = ($h2 & $mask) | $g2;
     290        $h3 = ($h3 & $mask) | $g3;
     291        $h4 = ($h4 & $mask) | $g4;
     292
     293        /* h = h % (2^128) */
     294        $h0 = (($h0      ) | ($h1 << 26)) & 0xffffffff;
     295        $h1 = (($h1 >>  6) | ($h2 << 20)) & 0xffffffff;
     296        $h2 = (($h2 >> 12) | ($h3 << 14)) & 0xffffffff;
     297        $h3 = (($h3 >> 18) | ($h4 <<  8)) & 0xffffffff;
     298
     299        /* mac = (h + pad) % (2^128) */
     300        $f = ($h0 + $this->pad[0]);
     301        $h0 = (int) $f;
     302        $f = ($h1 + $this->pad[1] + ($f >> 32));
     303        $h1 = (int) $f;
     304        $f = ($h2 + $this->pad[2] + ($f >> 32));
     305        $h2 = (int) $f;
     306        $f = ($h3 + $this->pad[3] + ($f >> 32));
     307        $h3 = (int) $f;
     308
     309        return self::store32_le($h0 & 0xffffffff) .
     310            self::store32_le($h1 & 0xffffffff) .
     311            self::store32_le($h2 & 0xffffffff) .
     312            self::store32_le($h3 & 0xffffffff);
     313    }
     314}
  • wp-includes/sodium_compat/src/Core/Util.php

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
     
     1<?php
     2
     3/**
     4 * Class ParagonIE_Sodium_Core_Util
     5 */
     6abstract class ParagonIE_Sodium_Core_Util
     7{
     8    /**
     9     * Load a 3 character substring into an integer
     10     *
     11     * @param $string
     12     * @return int;
     13     */
     14    public static function load_3($string)
     15    {
     16        $result = self::chrToInt($string[0]);
     17        $result |= self::chrToInt($string[1]) << 8;
     18        $result |= self::chrToInt($string[2]) << 16;
     19        return $result & 0xffffff;
     20    }
     21
     22    /**
     23     * Load a 4 character substring into an integer
     24     *
     25     * @param $string
     26     * @return int
     27     * @throws Exception
     28     */
     29    public static function load_4($string)
     30    {
     31        if (self::strlen($string) < 4) {
     32            throw new Exception('String must be 4 bytes or more; ' . self::strlen($string) . ' given.');
     33        }
     34        $result = self::chrToInt($string[0]) & 0xff;
     35        $result |= (self::chrToInt($string[1]) & 0xff) << 8;
     36        $result |= (self::chrToInt($string[2]) & 0xff) << 16;
     37        $result |= (self::chrToInt($string[3]) & 0xff) << 24;
     38        return $result & 0xffffffff;
     39    }
     40
     41    /**
     42     * Store a 24-bit integer into a string, treating it as big-endian.
     43     *
     44     * @param $int
     45     * @return string
     46     */
     47    public static function store_3($int)
     48    {
     49        return self::intToChr(($int >> 16)    & 0xff) .
     50            self::intToChr(($int >> 8)     & 0xff) .
     51            self::intToChr( $int           & 0xff);
     52    }
     53
     54    /**
     55     * Store a 32-bit integer into a string, treating it as big-endian.
     56     *
     57     * @param $int
     58     * @return string
     59     */
     60    public static function store_4($int)
     61    {
     62        return self::intToChr(($int >> 24) & 0xff) .
     63            self::intToChr(($int >> 16)    & 0xff) .
     64            self::intToChr(($int >> 8)     & 0xff) .
     65            self::intToChr( $int           & 0xff);
     66    }
     67
     68    /**
     69     * Store a 32-bit integer into a string, treating it as little-endian.
     70     *
     71     * @param $int
     72     * @return string
     73     */
     74    public static function store32_le($int)
     75    {
     76        return self::intToChr($int      & 0xff) .
     77            self::intToChr(($int >> 8)  & 0xff) .
     78            self::intToChr(($int >> 16) & 0xff) .
     79            self::intToChr(($int >> 24) & 0xff);
     80    }
     81
     82    /**
     83     * Convert a binary string into a hexadecimal string without cache-timing
     84     * leaks
     85     *
     86     * @param string $bin_string (raw binary)
     87     * @return string
     88     */
     89    public static function bin2hex($bin_string)
     90    {
     91        $hex = '';
     92        $len = self::strlen($bin_string);
     93        for ($i = 0; $i < $len; ++$i) {
     94            $chunk = unpack('C', self::substr($bin_string, $i, 2));
     95            $c = $chunk[1] & 0xf;
     96            $b = $chunk[1] >> 4;
     97            $hex .= pack(
     98                'CC',
     99                (87 + $b + ((($b - 10) >> 8) & ~38)),
     100                (87 + $c + ((($c - 10) >> 8) & ~38))
     101            );
     102        }
     103        return $hex;
     104    }
     105
     106    /**
     107     * Convert a binary string into a hexadecimal string without cache-timing
     108     * leaks, returning uppercase letters (as per RFC 4648)
     109     *
     110     * @param string $bin_string (raw binary)
     111     * @return string
     112     */
     113    public static function bin2hexUpper($bin_string)
     114    {
     115        $hex = '';
     116        $len = self::strlen($bin_string);
     117        for ($i = 0; $i < $len; ++$i) {
     118            $chunk = unpack('C', self::substr($bin_string, $i, 2));
     119            $c = $chunk[1] & 0xf;
     120            $b = $chunk[1] >> 4;
     121            $hex .= pack(
     122                'CC',
     123                (55 + $b + ((($b - 10) >> 8) & ~6)),
     124                (55 + $c + ((($c - 10) >> 8) & ~6))
     125            );
     126        }
     127        return $hex;
     128    }
     129
     130    /**
     131     * Compares two strings.
     132     *
     133     * @param string $left
     134     * @param string $right
     135     * @param int $len
     136     * @return int
     137     */
     138    public static function compare($left, $right, $len = null)
     139    {
     140        $leftLen = self::strlen($left);
     141        $rightLen = self::strlen($right);
     142        if ($len === null) {
     143            $len = max($leftLen, $rightLen);
     144            $left = str_pad($left, $len, "\x00", STR_PAD_RIGHT);
     145            $right = str_pad($right, $len, "\x00", STR_PAD_RIGHT);
     146        }
     147
     148        $gt = 0;
     149        $eq = 1;
     150        $i = $len;
     151        while ($i !== 0) {
     152            --$i;
     153            $gt |= ((self::chrToInt($right[$i]) - self::chrToInt($left[$i])) >> 8) & $eq;
     154            $eq &= ((self::chrToInt($right[$i]) ^ self::chrToInt($left[$i])) - 1) >> 8;
     155        }
     156        return ($gt + $gt + $eq) - 1;
     157    }
     158
     159    /**
     160     * @param string $left
     161     * @param string $right
     162     * @return int
     163     */
     164    public static function memcmp($left, $right)
     165    {
     166        if (hash_equals($left, $right)) {
     167            return 0;
     168        }
     169        return -1;
     170    }
     171
     172    /**
     173     * Convert a hexadecimal string into a binary string without cache-timing
     174     * leaks
     175     *
     176     * @param string $hexString
     177     * @param bool $strictPadding
     178     * @return string (raw binary)
     179     * @throws RangeException
     180     */
     181    public static function hex2bin($hexString, $strictPadding = false)
     182    {
     183        $hex_pos = 0;
     184        $bin = '';
     185        $c_acc = 0;
     186        $hex_len = self::strlen($hexString);
     187        $state = 0;
     188        if (($hex_len & 1) !== 0) {
     189            if ($strictPadding) {
     190                throw new RangeException(
     191                    'Expected an even number of hexadecimal characters'
     192                );
     193            } else {
     194                $hexString = '0' . $hexString;
     195                ++$hex_len;
     196            }
     197        }
     198
     199        $chunk = unpack('C*', $hexString);
     200        while ($hex_pos < $hex_len) {
     201            ++$hex_pos;
     202            $c = $chunk[$hex_pos];
     203            $c_num = $c ^ 48;
     204            $c_num0 = ($c_num - 10) >> 8;
     205            $c_alpha = ($c & ~32) - 55;
     206            $c_alpha0 = (($c_alpha - 10) ^ ($c_alpha - 16)) >> 8;
     207            if (($c_num0 | $c_alpha0) === 0) {
     208                throw new RangeException(
     209                    'hexEncode() only expects hexadecimal characters'
     210                );
     211            }
     212            $c_val = ($c_num0 & $c_num) | ($c_alpha & $c_alpha0);
     213            if ($state === 0) {
     214                $c_acc = $c_val * 16;
     215            } else {
     216                $bin .= pack('C', $c_acc | $c_val);
     217            }
     218            $state ^= 1;
     219        }
     220        return $bin;
     221    }
     222
     223    /**
     224     * Cache-timing-safe variant of ord()
     225     *
     226     * @param string $chr
     227     * @return int
     228     */
     229    public static function chrToInt($chr)
     230    {
     231        $chunk = unpack('C', self::substr($chr, 0, 1));
     232        return $chunk[1];
     233    }
     234
     235    /**
     236     * Cache-timing-safe variant of ord()
     237     *
     238     * @param int $int
     239     * @return string
     240     */
     241    public static function intToChr($int)
     242    {
     243        return pack('C', $int);
     244    }
     245
     246    /**
     247     * Turn a string into an array of integers
     248     *
     249     * @param $string
     250     * @return int[]
     251     */
     252    public static function stringToIntArray($string)
     253    {
     254        return array_values(
     255            unpack('C*', $string)
     256        );
     257    }
     258
     259    /**
     260     * Turn an array of integers into a string
     261     *
     262     * @param int[] $ints
     263     * @return string
     264     */
     265    public static function intArrayToString(array $ints)
     266    {
     267        $args = $ints;
     268        foreach ($args as $i => $v) {
     269            $args[$i] = $v & 0xff;
     270        }
     271        array_unshift($args, str_repeat('C', count($ints)));
     272        return call_user_func_array('pack', $args);
     273    }
     274
     275    /**
     276     * Safe string length
     277     *
     278     * @ref mbstring.func_overload
     279     *
     280     * @param string $str
     281     * @return int
     282     */
     283    public static function strlen($str)
     284    {
     285        if (!is_string($str)) {
     286            throw new InvalidArgumentException('String expected');
     287        }
     288        if (function_exists('mb_strlen')) {
     289            return mb_strlen($str, '8bit');
     290        } else {
     291            return strlen($str);
     292        }
     293    }
     294
     295    /**
     296     * Safe substring
     297     *
     298     * @ref mbstring.func_overload
     299     *
     300     * @param string $str
     301     * @param int $start
     302     * @param int $length
     303     * @return string
     304     * @throws InvalidArgumentException
     305     */
     306    public static function substr($str, $start = 0, $length = null)
     307    {
     308        if (!is_string($str)) {
     309            throw new InvalidArgumentException('String expected');
     310        }
     311        if (PHP_VERSION_ID < 50400 && $length === null) {
     312            $length = self::strlen($str);
     313        }
     314        if (function_exists('mb_substr')) {
     315            // $length calculation above might result in a 0-length string
     316            if ($length === 0) {
     317                return '';
     318            }
     319            return mb_substr($str, $start, $length, '8bit');
     320        }
     321        if ($length === 0) {
     322            return '';
     323        }
     324        // Unlike mb_substr(), substr() doesn't accept NULL for length
     325        if ($length !== null) {
     326            return substr($str, $start, $length);
     327        } else {
     328            return substr($str, $start);
     329        }
     330    }
     331
     332    /**
     333     * Compare a 16-character byte string in constant time.
     334     *
     335     * @param string $a
     336     * @param string $b
     337     * @return bool
     338     */
     339    public static function verify_16($a, $b)
     340    {
     341        $diff = self::strlen($a) ^ self::strlen($b);
     342        for ($i = 0; $i < 16; ++$i) {
     343            $diff |= self::chrToInt($a[$i]) ^ self::chrToInt($b[$i]);
     344        }
     345        return $diff === 0;
     346    }
     347
     348    /**
     349     * Compare a 32-character byte string in constant time.
     350     *
     351     * @param string $a
     352     * @param string $b
     353     * @return bool
     354     */
     355    public static function verify_32($a, $b)
     356    {
     357        $diff = self::strlen($a) ^ self::strlen($b);
     358        for ($i = 0; $i < 32; ++$i) {
     359            $diff |= self::chrToInt($a[$i]) ^ self::chrToInt($b[$i]);
     360        }
     361        return $diff === 0;
     362    }
     363
     364    /**
     365     * Calculate $a ^ $b for two strings.
     366     *
     367     * @param string $a
     368     * @param string $b
     369     * @return string
     370     */
     371    public static function xorStrings($a, $b)
     372    {
     373        $aLen = self::strlen($a);
     374        $bLen = self::strlen($b);
     375        $d = '';
     376
     377        for ($i = 0; $i < $aLen && $i < $bLen; ++$i) {
     378            $d .= self::intToChr(self::chrToInt($a[$i]) ^ self::chrToInt($b[$i]));
     379        }
     380        return $d;
     381    }
     382}
  • wp-includes/sodium_compat/src/Core/Xsalsa20.php

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
     
     1<?php
     2
     3/**
     4 * Class ParagonIE_Sodium_Core_XSalsa20
     5 */
     6abstract class ParagonIE_Sodium_Core_XSalsa20 extends ParagonIE_Sodium_Core_HSalsa20
     7{
     8    /**
     9     * Expand a key and nonce into an xsalsa20 keystream.
     10     *
     11     * @param string $len
     12     * @param string $nonce
     13     * @param string $key
     14     * @return string;
     15     */
     16    public static function xsalsa20($len, $nonce, $key)
     17    {
     18        $subkey = self::hsalsa20($nonce, $key);
     19        $ret = self::salsa20($len, self::substr($nonce, 16, 8), $subkey);
     20        ParagonIE_Sodium_Compat::memzero($subkey);
     21        return $ret;
     22    }
     23
     24    /**
     25     * Encrypt a string with Xsalsa20. Doesn't provide integrity.
     26     *
     27     * @param string $message
     28     * @param string $nonce
     29     * @param string $key
     30     * @return string
     31     */
     32    public static function xsalsa20_xor($message, $nonce, $key)
     33    {
     34        return self::xorStrings(
     35            $message,
     36            self::xsalsa20(
     37                self::strlen($message),
     38                $nonce,
     39                $key
     40            )
     41        );
     42    }
     43}
  • wp-includes/sodium_compat/src/Core/Curve25519/Ge/P2.php

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
     
     1<?php
     2
     3/**
     4 * Class ParagonIE_Sodium_Core_Curve25519_Ge_P2
     5 */
     6class ParagonIE_Sodium_Core_Curve25519_Ge_P2
     7{
     8    /**
     9     * @var ParagonIE_Sodium_Core_Curve25519_Fe
     10     */
     11    public $X;
     12
     13    /**
     14     * @var ParagonIE_Sodium_Core_Curve25519_Fe
     15     */
     16    public $Y;
     17
     18    /**
     19     * @var ParagonIE_Sodium_Core_Curve25519_Fe
     20     */
     21    public $Z;
     22
     23    /**
     24     * ParagonIE_Sodium_Core_Curve25519_Ge_P2 constructor.
     25     * @param ParagonIE_Sodium_Core_Curve25519_Fe $x
     26     * @param ParagonIE_Sodium_Core_Curve25519_Fe $y
     27     * @param ParagonIE_Sodium_Core_Curve25519_Fe $z
     28     */
     29    public function __construct(
     30        ParagonIE_Sodium_Core_Curve25519_Fe $x = null,
     31        ParagonIE_Sodium_Core_Curve25519_Fe $y = null,
     32        ParagonIE_Sodium_Core_Curve25519_Fe $z = null
     33    ) {
     34        $this->X = $x;
     35        $this->Y = $y;
     36        $this->Z = $z;
     37    }
     38}
  • wp-includes/sodium_compat/tests/unit/Curve25519Test.php

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
     
     1<?php
     2
     3class Curve25519Test extends PHPUnit_Framework_TestCase
     4{
     5    public function setUp()
     6    {
     7        ParagonIE_Sodium_Compat::$disableFallbackForUnitTests = true;
     8    }
     9
     10    /**
     11     * @covers ParagonIE_Sodium_Core_Curve25519::fe_0()
     12     */
     13    public function testFe0()
     14    {
     15        $f = array(
     16            0,
     17            0,
     18            0,
     19            0,
     20            0,
     21            0,
     22            0,
     23            0,
     24            0,
     25            0
     26        );
     27        $fe_f = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray($f);
     28        $r = ParagonIE_Sodium_Core_Curve25519::fe_0();
     29        for ($i = 0; $i < 10; ++$i) {
     30            $this->assertEquals($r[$i], $fe_f[$i]);
     31        }
     32    }
     33
     34    /**
     35     * @covers ParagonIE_Sodium_Core_Curve25519::fe_1()
     36     */
     37    public function testFe1()
     38    {
     39        $f = array(
     40            1,
     41            0,
     42            0,
     43            0,
     44            0,
     45            0,
     46            0,
     47            0,
     48            0,
     49            0
     50        );
     51        $fe_f = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray($f);
     52        $r = ParagonIE_Sodium_Core_Curve25519::fe_1();
     53        for ($i = 0; $i < 10; ++$i) {
     54            $this->assertEquals($r[$i], $fe_f[$i]);
     55        }
     56    }
     57
     58    /**
     59     * @covers ParagonIE_Sodium_Core_Curve25519::fe_add()
     60     */
     61    public function testFeAdd()
     62    {
     63        $f = array(
     64            random_int(0, 65535),
     65            random_int(0, 65535),
     66            random_int(0, 65535),
     67            random_int(0, 65535),
     68            random_int(0, 65535),
     69            random_int(0, 65535),
     70            random_int(0, 65535),
     71            random_int(0, 65535),
     72            random_int(0, 65535),
     73            random_int(0, 65535)
     74        );
     75        $g = array(
     76            random_int(0, 65535),
     77            random_int(0, 65535),
     78            random_int(0, 65535),
     79            random_int(0, 65535),
     80            random_int(0, 65535),
     81            random_int(0, 65535),
     82            random_int(0, 65535),
     83            random_int(0, 65535),
     84            random_int(0, 65535),
     85            random_int(0, 65535)
     86        );
     87        $h = array();
     88        for ($i = 0; $i < 10; ++$i) {
     89            $h[$i] = $f[$i] + $g[$i];
     90        }
     91
     92        $fe_f = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray($f);
     93        $fe_g = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray($g);
     94        $fe_h = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray($h);
     95        $r = ParagonIE_Sodium_Core_Curve25519::fe_add($fe_f, $fe_g);
     96
     97        for ($i = 0; $i < 10; ++$i) {
     98            $this->assertEquals($r[$i], $fe_h[$i]);
     99        }
     100        $this->assertEquals($r, $fe_h, 'Addition error!');
     101    }
     102
     103    /**
     104     * @covers ParagonIE_Sodium_Core_Curve25519::fe_sub()
     105     */
     106    public function testFeSub()
     107    {
     108        $f = array(
     109            random_int(0, 65535),
     110            random_int(0, 65535),
     111            random_int(0, 65535),
     112            random_int(0, 65535),
     113            random_int(0, 65535),
     114            random_int(0, 65535),
     115            random_int(0, 65535),
     116            random_int(0, 65535),
     117            random_int(0, 65535),
     118            random_int(0, 65535)
     119        );
     120        $g = array(
     121            random_int(0, 65535),
     122            random_int(0, 65535),
     123            random_int(0, 65535),
     124            random_int(0, 65535),
     125            random_int(0, 65535),
     126            random_int(0, 65535),
     127            random_int(0, 65535),
     128            random_int(0, 65535),
     129            random_int(0, 65535),
     130            random_int(0, 65535)
     131        );
     132        $h = array();
     133        for ($i = 0; $i < 10; ++$i) {
     134            $h[$i] = $f[$i] - $g[$i];
     135        }
     136
     137        $fe_f = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray($f);
     138        $fe_g = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray($g);
     139        $fe_h = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray($h);
     140        $r = ParagonIE_Sodium_Core_Curve25519::fe_sub($fe_f, $fe_g);
     141
     142        for ($i = 0; $i < 10; ++$i) {
     143            $this->assertEquals($r[$i], $fe_h[$i]);
     144        }
     145        $this->assertEquals($r, $fe_h, 'Subtraction error!');
     146    }
     147
     148    /**
     149     * @covers ParagonIE_Sodium_Core_Curve25519::sc_reduce()
     150     */
     151    public function testReduce()
     152    {
     153        $input = ParagonIE_Sodium_Core_Util::hex2bin(
     154            "dc0e1b48b1f2d9d3a6638a43c986c49ecbfafba209fff7a801f9d8f776c1fc79" .
     155            "5dd9dd8f4c272b92210c923ba7940955136f7e68c4bee52a6562f8171785ce10"
     156        );
     157        $reduced = ParagonIE_Sodium_Core_Curve25519::sc_reduce($input);
     158        $this->assertSame(
     159            'd8e7f39643da186a4a690c8cf6a7987bc4d2fb7bede4e7cec89f8175da27730a',
     160            bin2hex($reduced),
     161            'sd_reduce is not working'
     162        );
     163    }
     164
     165    /**
     166     * @covers ParagonIE_Sodium_Core_Curve25519::ge_select()
     167     */
     168    public function testGeSelect()
     169    {
     170        $this->assertEquals(
     171            ParagonIE_Sodium_Core_Curve25519::ge_select(0, 6),
     172            new ParagonIE_Sodium_Core_Curve25519_Ge_Precomp(
     173                ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
     174                    array(-15371964, -12862754, 32573250, 4720197, -26436522, 5875511, -19188627, -15224819, -9818940, -12085777)
     175                ),
     176                ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
     177                    array(-8549212, 109983, 15149363, 2178705, 22900618, 4543417, 3044240, -15689887, 1762328, 14866737)
     178                ),
     179                ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
     180                    array(-18199695, -15951423, -10473290, 1707278, -17185920, 3916101, -28236412, 3959421, 27914454, 4383652)
     181                )
     182            ),
     183            'ge_select is not working.'
     184        );
     185    }
     186
     187    /**
     188     * @covers ParagonIE_Sodium_Core_Curve25519::fe_mul()
     189     */
     190    public function testFeMul()
     191    {
     192        $f = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
     193            array(
     194                26853523,
     195                -15767542,
     196                10850706,
     197                -434120,
     198                -20393796,
     199                -13094191,
     200                -4793868,
     201                1643574,
     202                11273642,
     203                14083967
     204            )
     205        );
     206
     207        $g = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
     208            array(
     209                -10913610,
     210                13857413,
     211                -15372611,
     212                6949391,
     213                114729,
     214                -8787816,
     215                -6275908,
     216                -3247719,
     217                -18696448,
     218                -12055116
     219            )
     220        );
     221
     222        $expected = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
     223            array(
     224                -25012118,
     225                15881590,
     226                -29167576,
     227                -8241728,
     228                -26366797,
     229                6116011,
     230                -16287663,
     231                -1425685,
     232                -9694368,
     233                -16104023
     234            )
     235        );
     236
     237        $h = ParagonIE_Sodium_Core_Curve25519::fe_mul($f, $g);
     238        $this->assertEquals($expected, $h);
     239
     240        $this->assertEquals(
     241            $expected,
     242            ParagonIE_Sodium_Core_Curve25519::fe_mul($h, ParagonIE_Sodium_Core_Curve25519::fe_1())
     243        );
     244
     245        $this->assertEquals(
     246            $expected,
     247            ParagonIE_Sodium_Core_Curve25519::fe_mul(ParagonIE_Sodium_Core_Curve25519::fe_1(), $h)
     248        );
     249        $z = ParagonIE_Sodium_Core_Curve25519::fe_0();
     250        $this->assertEquals(
     251            $z,
     252            ParagonIE_Sodium_Core_Curve25519::fe_mul($z, $h)
     253        );
     254    }
     255
     256    /**
     257     * @covers ParagonIE_Sodium_Core_Curve25519::ge_madd()
     258     */
     259    public function testGeMAdd()
     260    {
     261        $p = new ParagonIE_Sodium_Core_Curve25519_Ge_P3(
     262            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
     263                array(0,0,0,0,0,0,0,0,0,0)
     264            ),
     265            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
     266                array(1,0,0,0,0,0,0,0,0,0)
     267            ),
     268            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
     269                array(1,0,0,0,0,0,0,0,0,0)
     270            ),
     271            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
     272                array(0,0,0,0,0,0,0,0,0,0)
     273            )
     274        );
     275
     276        $q = new ParagonIE_Sodium_Core_Curve25519_Ge_Precomp(
     277            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
     278                array(-8549212, 109983, 15149363, 2178705, 22900618, 4543417, 3044240, -15689887, 1762328, 14866737)
     279            ),
     280            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
     281                array(-15371964, -12862754, 32573250, 4720197, -26436522, 5875511, -19188627, -15224819, -9818940, -12085777)
     282            ),
     283            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
     284                array(18199695, 15951423, 10473290, -1707278, 17185920, -3916101, 28236412, -3959421, -27914454, -4383652)
     285            )
     286        );
     287
     288        $expected = new ParagonIE_Sodium_Core_Curve25519_Ge_P1p1(
     289            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
     290                array(6822752, 12972737, -17423887, -2541492, 49337140, -1332094, 22232867, -465068, 11581268, 26952514)
     291            ),
     292            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
     293                array(-23921176, -12752771, 47722613, 6898902, -3535904, 10418928, -16144387, -30914706, -8056612, 2780960)
     294            ),
     295            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
     296                array(2,0,0,0,0,0,0,0,0,0)
     297            ),
     298            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
     299                array(2,0,0,0,0,0,0,0,0,0)
     300            )
     301        );
     302
     303        $r = new ParagonIE_Sodium_Core_Curve25519_Ge_P1p1();
     304        $this->assertEquals(
     305            $expected,
     306            ParagonIE_Sodium_Core_Curve25519::ge_madd($r, $p, $q),
     307            'ge_madd is still broken'
     308        );
     309
     310        // $this->assertSame(true, true); return;
     311        $h = new ParagonIE_Sodium_Core_Curve25519_Ge_P3(
     312            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
     313                array(0,0,0,0,0,0,0,0,0,0)
     314            ),
     315            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
     316                array(1,0,0,0,0,0,0,0,0,0)
     317            ),
     318            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
     319                array(1,0,0,0,0,0,0,0,0,0)
     320            ),
     321            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
     322                array(0,0,0,0,0,0,0,0,0,0)
     323            )
     324        );
     325
     326        $t = new ParagonIE_Sodium_Core_Curve25519_Ge_Precomp(
     327            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
     328                array(23599295, -8306047, -11193664, -7687416, 13236774, 10506355, 7464579, 9656445, 13059162, 103743971)
     329            ),
     330            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
     331                array(-17036878, 13921892, 10945806, -6033431, 27105052, -16084379, -28926210, 15006023, 3284568, -6276540)
     332            ),
     333            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
     334                array(-7798556, -16710257, -3033922, -2874086, -28997861, -2835604, -32406664, 3839045, 641708, 101325)
     335            )
     336        );
     337
     338        $expected = new ParagonIE_Sodium_Core_Curve25519_Ge_P1p1(
     339            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
     340                array(40636230, -22227939, -22139470, -1653985, -13868278, 26590734, 36390789, -5349578, 9774594, 9357215)
     341            ),
     342            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
     343                array(6562474, 5615845, -247858, -13720847, 40341826, -5578024, -21461631, 24662468, 16343730, -3195865)
     344            ),
     345            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
     346                array(2,0,0,0,0,0,0,0,0,0)
     347            ),
     348            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
     349                array(2,0,0,0,0,0,0,0,0,0)
     350            )
     351        );
     352
     353        $r = new ParagonIE_Sodium_Core_Curve25519_Ge_P1p1();
     354        $this->assertEquals(
     355            $expected,
     356            ParagonIE_Sodium_Core_Curve25519::ge_madd($r, $h, $t),
     357            'ge_madd is not working'
     358        );
     359
     360        $h = new ParagonIE_Sodium_Core_Curve25519_Ge_P3(
     361            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
     362                array(0,0,0,0,0,0,0,0,0,0)
     363            ),
     364            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
     365                array(1,0,0,0,0,0,0,0,0,0)
     366            ),
     367            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
     368                array(1,0,0,0,0,0,0,0,0,0)
     369            ),
     370            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
     371                array(0,0,0,0,0,0,0,0,0,0)
     372            )
     373        );
     374
     375        $t = new ParagonIE_Sodium_Core_Curve25519_Ge_Precomp(
     376            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
     377                array(-12815894, -12976347, -21581243, 11784320, -25355658, -2750717, -11717903, -3814571, -358445, -10211303)
     378            ),
     379            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
     380                array(-21703237, 6903825, 27185491, 6451973, -29577724, -9554005, -15616551, 11189268, -26829678, -53190817)
     381            ),
     382            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
     383                array(26966642, 11152617, 32442495, 15396054, 14353839, -12752335, -3128826, -9541118, -15472047, -4166697)
     384            )
     385        );
     386
     387        $expected = new ParagonIE_Sodium_Core_Curve25519_Ge_P1p1(
     388            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
     389                array(8887381, -19880172, -48766734, 5332347, 4222066, 6803288, 3898648, -15003839, 26471233, -24129350)
     390            ),
     391            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
     392                array(-34519169, -6072522, 5604248, 18236293, -54933382, -12304722, -27334454, 7374697, -27188123, 3706744)
     393            ),
     394            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
     395                array(2,0,0,0,0,0,0,0,0,0)
     396            ),
     397            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
     398                array(2,0,0,0,0,0,0,0,0,0)
     399            )
     400        );
     401        $r = new ParagonIE_Sodium_Core_Curve25519_Ge_P1p1();
     402        $this->assertEquals(
     403            $expected,
     404            ParagonIE_Sodium_Core_Curve25519::ge_madd($r, $h, $t),
     405            'ge_madd is not working'
     406        );
     407    }
     408
     409   
     410    public function testGeScalarmultBase()
     411    {
     412        $nonce = ParagonIE_Sodium_Core_Util::hex2bin(
     413            'a5cdb7382d5282472312e739b7b8fded4b0bc73a8d3b7ac24e6ee259df74800a' .
     414            'c19b35ef3130ed0474e0f0cc4d9ee277788775036b7025aed15c3beb29ff4eab'
     415        );
     416        $R = ParagonIE_Sodium_Core_Curve25519::ge_scalarmult_base($nonce);
     417        $expected = new ParagonIE_Sodium_Core_Curve25519_Ge_P3(
     418            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(array(
     419                -23932472,
     420                11221871,
     421                27518927,
     422                -12970994,
     423                14275856,
     424                4619861,
     425                -14347453,
     426                6713345,
     427                -33117680,
     428                -10663750
     429            )),
     430            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(array(
     431                14689788,
     432                -10448958,
     433                -30321432,
     434                -9014186,
     435                14446585,
     436                -7985136,
     437                27805771,
     438                -13751241,
     439                -1536736,
     440                -13958946
     441            )),
     442            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(array(
     443                19689758,
     444                -6173146,
     445                -15886452,
     446                5649798,
     447                -24861313,
     448                -12384199,
     449                -2662028,
     450                16072970,
     451                5918454,
     452                14582476
     453            )),
     454            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(array(
     455                -9719484,
     456                -15496290,
     457                -31004425,
     458                -7546822,
     459                12427063,
     460                11453174,
     461                -8594732,
     462                -14149517,
     463                27692259,
     464                -14101917
     465            ))
     466        );
     467        $this->assertEquals(
     468            $expected,
     469            $R,
     470            'Check ge_scalarmult_base for correctness'
     471        );
     472
     473        $bytes = ParagonIE_Sodium_Core_Curve25519::ge_p3_tobytes($R);
     474        $this->assertSame(
     475            '36a6d2748f6ab8f76c122a562d55343cb7c6f15c8a45bd55bd8b9e9fadd2363f',
     476            bin2hex($bytes),
     477            'Check ge_p3_tobytes for correctness'
     478        );
     479    }
     480
     481    /**
     482     * @covers ParagonIE_Sodium_Core_Curve25519::ge_double_scalarmult_vartime()
     483     */
     484    public function testGeDoubleScalarMultVartime()
     485    {
     486        $h = ParagonIE_Sodium_Core_Util::hex2bin(
     487            'fc2ef90e2ddab38c55d0edbf41167048061a03b99d00112dcc92777c1b17300c' .
     488            'bd84d56b93d272eb01a2ffb5557bda3922360e402c29d05cda3f0debabaf5ce5'
     489        );
     490        $A = new ParagonIE_Sodium_Core_Curve25519_Ge_P3(
     491            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(array(
     492                25569346,
     493                24607350,
     494                21422669,
     495                3164952,
     496                51116803,
     497                27944728,
     498                23859688,
     499                12129629,
     500                33577468,
     501                23235570
     502            )),
     503            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(array(
     504                16253166, 2599808, 30616947, -12747262, 372730, 8894334, 9139202, -197177, -24298945, 15942855
     505            )),
     506            ParagonIE_Sodium_Core_Curve25519::fe_1(),
     507            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(array(
     508                -28155508, 13944970, 2511703, 16462880, 15250894, -7952383, -19629302, 16022930, 1783986, 16320964
     509            ))
     510        );
     511        $sig = ParagonIE_Sodium_Core_Util::hex2bin(
     512            '36a6d2748f6ab8f76c122a562d55343cb7c6f15c8a45bd55bd8b9e9fadd2363f' .
     513            '370cb78fba42c550d487b9bd7413312b6490c8b3ee2cea638997172a9c8c250f'
     514        );
     515        $expected = new ParagonIE_Sodium_Core_Curve25519_Ge_P2(
     516            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(array(
     517                -18667682,
     518                9847093,
     519                7256576,
     520                -7033042,
     521                32767777,
     522                -10224836,
     523                25608854,
     524                6989354,
     525                -19138147,
     526                -13642525
     527            )),
     528            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(array(
     529                6317192,
     530                4477233,
     531                24373531,
     532                14977415,
     533                -10754696,
     534                -12573560,
     535                -20847592,
     536                8319048,
     537                13730645,
     538                -7760907
     539            )),
     540            ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(array(
     541                32680048,
     542                -15342934,
     543                3837898,
     544                8050201,
     545                15422085,
     546                14178962,
     547                -6403825,
     548                -627297,
     549                24243949,
     550                12818173
     551            ))
     552        );
     553
     554        $this->assertEquals(
     555            $expected,
     556            ParagonIE_Sodium_Core_Curve25519::ge_double_scalarmult_vartime($h, $A, $sig),
     557            'ge_double_scalarmult_vartime()'
     558        );
     559    }
     560}
  • wp-includes/sodium_compat/tests/compat/SodiumCompatTest.php

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
     
     1<?php
     2
     3/**
     4 * Class SodiumCompatTest
     5 */
     6class SodiumCompatTest extends PHPUnit_Framework_TestCase
     7{
     8    public function setUp()
     9    {
     10        if (!extension_loaded('libsodium')) {
     11            $this->markTestSkipped('Libsodium is not installed; skipping the compatibility test suite.');
     12        }
     13        ParagonIE_Sodium_Compat::$disableFallbackForUnitTests = true;
     14    }
     15
     16    /**
     17     * @covers ParagonIE_Sodium_Core_Util::compare()
     18     */
     19    public function testCompare()
     20    {
     21        $a = pack('H*', '589a84d7ec2db8f982841cedca674ec1');
     22        $b = $a;
     23        $b[15] = 'a';
     24        $this->assertSame(
     25            \Sodium\compare($a, $b),
     26            ParagonIE_Sodium_Core_Util::compare($a, $b),
     27            bin2hex($a) . ' vs ' . bin2hex($b)
     28        );
     29
     30        $a = random_bytes(16);
     31        $b = $a;
     32        $b[15] = 'a';
     33
     34        $this->assertSame(
     35            \Sodium\compare($a, $b),
     36            ParagonIE_Sodium_Core_Util::compare($a, $b),
     37            bin2hex($a)
     38        );
     39    }
     40
     41    /**
     42     * @covers ParagonIE_Sodium_Core_Util::bin2hex()
     43     */
     44    public function testBin2hex()
     45    {
     46        $str = random_bytes(random_int(1, 63));
     47        $this->assertSame(
     48            \Sodium\bin2hex($str),
     49            ParagonIE_Sodium_Core_Util::bin2hex($str)
     50        );
     51    }
     52
     53    /**
     54     * @covers ParagonIE_Sodium_Core_Util::hex2bin()
     55     */
     56    public function testHex2bin()
     57    {
     58        $str = bin2hex(random_bytes(random_int(1, 63)));
     59        $this->assertSame(
     60            \Sodium\hex2bin($str),
     61            ParagonIE_Sodium_Core_Util::hex2bin($str)
     62        );
     63    }
     64
     65    /**
     66     *
     67     */
     68    public function testCryptoAuth()
     69    {
     70        $message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
     71        $key = random_bytes(32);
     72
     73        $this->assertSame(
     74            bin2hex(\Sodium\crypto_auth($message, $key)),
     75            bin2hex(ParagonIE_Sodium_Compat::crypto_auth($message, $key))
     76        );
     77        $mac = \Sodium\crypto_auth($message, $key);
     78        $this->assertTrue(
     79            ParagonIE_Sodium_Compat::crypto_auth_verify($mac, $message, $key)
     80        );
     81    }
     82
     83    /**
     84     * @covers ParagonIE_Sodium_Compat::crypto_box()
     85     * @covers ParagonIE_Sodium_Compat::crypto_box_open()
     86     */
     87    public function testCryptoBox()
     88    {
     89        $nonce = str_repeat("\x00", 24);
     90        $message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
     91
     92        $alice_box_kp = \Sodium\crypto_box_keypair();
     93        $alice_box_secretkey = \Sodium\crypto_box_secretkey($alice_box_kp);
     94        $alice_box_publickey = \Sodium\crypto_box_publickey($alice_box_kp);
     95
     96        $bob_box_kp = \Sodium\crypto_box_keypair();
     97        $bob_box_secretkey = \Sodium\crypto_box_secretkey($bob_box_kp);
     98        $bob_box_publickey = \Sodium\crypto_box_publickey($bob_box_kp);
     99
     100        $alice_to_bob = \Sodium\crypto_box_keypair_from_secretkey_and_publickey(
     101            $alice_box_secretkey,
     102            $bob_box_publickey
     103        );
     104        $bob_to_alice = \Sodium\crypto_box_keypair_from_secretkey_and_publickey(
     105            $bob_box_secretkey,
     106            $alice_box_publickey
     107        );
     108        $bob_to_alice2 = ParagonIE_Sodium_Crypto::box_keypair_from_secretkey_and_publickey(
     109            $bob_box_secretkey,
     110            $alice_box_publickey
     111        );
     112        $this->assertSame($bob_to_alice, $bob_to_alice2);
     113
     114        $this->assertSame(
     115            bin2hex(\Sodium\crypto_box($message, $nonce, $alice_to_bob)),
     116            bin2hex(ParagonIE_Sodium_Compat::crypto_box($message, $nonce, $alice_to_bob)),
     117            'box'
     118        );
     119        $this->assertSame(
     120            $message,
     121            ParagonIE_Sodium_Compat::crypto_box_open(
     122                \Sodium\crypto_box($message, $nonce, $alice_to_bob),
     123                $nonce,
     124                $bob_to_alice
     125            )
     126        );
     127
     128        $message = str_repeat("Lorem ipsum dolor sit amet, consectetur adipiscing elit. ", 8);
     129        $this->assertSame(
     130            bin2hex(\Sodium\crypto_box($message, $nonce, $alice_to_bob)),
     131            bin2hex(ParagonIE_Sodium_Compat::crypto_box($message, $nonce, $alice_to_bob)),
     132            'crypto_box is failing with large messages'
     133        );
     134        $this->assertSame(
     135            bin2hex($message),
     136            bin2hex(
     137                ParagonIE_Sodium_Compat::crypto_box_open(
     138                    \Sodium\crypto_box($message, $nonce, $alice_to_bob),
     139                    $nonce,
     140                    $bob_to_alice
     141                )
     142            )
     143        );
     144    }
     145
     146    public function testCryptoBoxSeal()
     147    {
     148        $msg = ParagonIE_Sodium_Core_Util::hex2bin(
     149            '7375f4094f1151640bd853cb13dbc1a0ee9e13b0287a89d34fa2f6732be9de13f88457553d'.
     150            '768347116522d6d32c9cb353ef07aa7c83bd129b2bb5db35b28334c935b24f2639405a0604'
     151        );
     152        $kp = ParagonIE_Sodium_Core_Util::hex2bin(
     153            '36a6c2b96a650d80bf7e025e0f58f3d636339575defb370801a54213bd54582d'.
     154            '5aecbcf7866e7a4d58a6c1317e2b955f54ecbe2fcbbf7d262c10636ed524480c'
     155        );
     156        $alice_opened2 = ParagonIE_Sodium_Compat::crypto_box_seal_open($msg, $kp);
     157        $this->assertSame(
     158            bin2hex('This is for your eyes only'),
     159            bin2hex($alice_opened2),
     160            'Decryption failed #2'
     161        );
     162        $alice_box_kp = ParagonIE_Sodium_Core_Util::hex2bin(
     163            '15b36cb00213373fb3fb03958fb0cc0012ecaca112fd249d3cf0961e311caac9' .
     164            'fb4cb34f74a928b79123333c1e63d991060244cda98affee14c3398c6d315574'
     165        );
     166        $alice_box_publickey = ParagonIE_Sodium_Core_Util::hex2bin(
     167            'fb4cb34f74a928b79123333c1e63d991060244cda98affee14c3398c6d315574'
     168        );
     169        $anonymous_message_to_alice = \Sodium\crypto_box_seal(
     170            'Anonymous message',
     171            $alice_box_publickey);
     172        $decrypted_message = ParagonIE_Sodium_Compat::crypto_box_seal_open(
     173            $anonymous_message_to_alice,
     174            $alice_box_kp
     175        );
     176        $this->assertSame(
     177            'Anonymous message',
     178            $decrypted_message
     179        );
     180
     181        $messages = array(
     182            'test',
     183            'slightly longer message',
     184            str_repeat('a', 29) . ' 32',
     185            str_repeat('a', 30) . ' 33',
     186            str_repeat('a', 31) . ' 34',
     187            "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
     188        );
     189        foreach ($messages as $message) {
     190            $sealed_to_alice1 = \Sodium\crypto_box_seal($message, $alice_box_publickey);
     191            $sealed_to_alice2 = ParagonIE_Sodium_Compat::crypto_box_seal(
     192                $message,
     193                $alice_box_publickey
     194            );
     195
     196            $this->assertSame(
     197                strlen($sealed_to_alice1),
     198                strlen($sealed_to_alice2),
     199                'String length should not differ'
     200            );
     201
     202            $alice_opened1 = ParagonIE_Sodium_Compat::crypto_box_seal_open($sealed_to_alice1, $alice_box_kp);
     203            $this->assertSame(
     204                bin2hex(\Sodium\crypto_box_seal_open($sealed_to_alice1, $alice_box_kp)),
     205                bin2hex($message),
     206                'Decryption failed #1: ' . $message
     207            );
     208            $this->assertSame(
     209                bin2hex($message),
     210                bin2hex($alice_opened1),
     211                'Decryption failed #1: ' . $message
     212            );
     213            $this->assertSame(
     214                bin2hex($alice_opened1),
     215                bin2hex(\Sodium\crypto_box_seal_open($sealed_to_alice1, $alice_box_kp)),
     216                'Decryption failed #1: ' . $message
     217            );
     218
     219            $alice_opened2 = ParagonIE_Sodium_Compat::crypto_box_seal_open(
     220                $sealed_to_alice2,
     221                $alice_box_kp
     222            );
     223
     224            $this->assertSame(
     225                $message,
     226                $alice_opened2,
     227                'Decryption failed #2: ' . $message
     228            );
     229            $this->assertSame(
     230                bin2hex(\Sodium\crypto_box_seal_open($sealed_to_alice2, $alice_box_kp)),
     231                bin2hex($message),
     232                'Decryption failed #2: ' . $message
     233            );
     234            $this->assertSame(
     235                bin2hex(\Sodium\crypto_box_seal_open($sealed_to_alice2, $alice_box_kp)),
     236                bin2hex($alice_opened2),
     237                'Decryption failed #2: ' . $message
     238            );
     239        }
     240    }
     241
     242    /**
     243     * @covers ParagonIE_Sodium_Crypto::generichash()
     244     */
     245    public function testCryptoGenerichash()
     246    {
     247        $this->assertSame(
     248            bin2hex(\Sodium\crypto_generichash('apple')),
     249            bin2hex(ParagonIE_Sodium_Compat::crypto_generichash('apple')),
     250            'BLAKE2b implementation'
     251        );
     252
     253        $this->assertSame(
     254            bin2hex(\Sodium\crypto_generichash('apple', 'catastrophic failure')),
     255            bin2hex(ParagonIE_Sodium_Compat::crypto_generichash('apple', 'catastrophic failure')),
     256            'BLAKE2b with a key'
     257        );
     258
     259        $this->assertSame(
     260            bin2hex(\Sodium\crypto_generichash('apple', '', 64)),
     261            bin2hex(ParagonIE_Sodium_Compat::crypto_generichash('apple', '', 64)),
     262            'BLAKE2b implementation with output length'
     263        );
     264
     265        $this->assertSame(
     266            bin2hex(\Sodium\crypto_generichash('apple', 'catastrophic failure', 24)),
     267            bin2hex(ParagonIE_Sodium_Compat::crypto_generichash('apple', 'catastrophic failure', 24)),
     268            'BLAKE2b implementation with output length'
     269        );
     270    }
     271
     272    /**
     273     * @covers ParagonIE_Sodium_Crypto::generichash_init()
     274     * @covers ParagonIE_Sodium_Crypto::generichash_update()
     275     * @covers ParagonIE_Sodium_Crypto::generichash_final()
     276     */
     277    public function testCryptoGenerichashStream()
     278    {
     279        $key =  "\x1c" . str_repeat("\x80", 30) . "\xaf";
     280        $ctx = \Sodium\crypto_generichash_init($key);
     281        $this->assertSame(
     282            bin2hex($ctx),
     283            bin2hex(ParagonIE_Sodium_Compat::crypto_generichash_init($key)),
     284            'BLAKE2b Context Serialization'
     285        );
     286
     287        $subCtx = ParagonIE_Sodium_Core_BLAKE2b::stringToContext($ctx);
     288        $this->assertSame(
     289            bin2hex($ctx),
     290            bin2hex(ParagonIE_Sodium_Core_BLAKE2b::contextToString($subCtx)),
     291            'Context serialization / deserialization'
     292        );
     293        $this->assertEquals(
     294            $subCtx,
     295            ParagonIE_Sodium_Core_BLAKE2b::stringToContext(
     296                ParagonIE_Sodium_Core_BLAKE2b::contextToString($subCtx)
     297            ),
     298            'Determinism'
     299        );
     300
     301        $nativeCtx = '';
     302        for ($i = 0; $i < ParagonIE_Sodium_Core_Util::strlen($ctx); ++$i) {
     303            $nativeCtx .= $ctx[$i];
     304        }
     305
     306        \Sodium\crypto_generichash_update($nativeCtx, 'Paragon Initiative');
     307        ParagonIE_Sodium_Compat::crypto_generichash_update($ctx, 'Paragon Initiative');
     308
     309        $this->assertSame(
     310            bin2hex($nativeCtx),
     311            bin2hex($ctx),
     312            'generichash_update() 1'
     313        );
     314        \Sodium\crypto_generichash_update($nativeCtx, ' Enterprises, LLC');
     315        ParagonIE_Sodium_Compat::crypto_generichash_update($ctx, ' Enterprises, LLC');
     316
     317        $this->assertSame(
     318            bin2hex($nativeCtx),
     319            bin2hex($ctx),
     320            'generichash_update() 2'
     321        );
     322
     323        $this->assertSame(
     324            bin2hex(\Sodium\crypto_generichash_final($nativeCtx, 32)),
     325            bin2hex(ParagonIE_Sodium_Compat::crypto_generichash_final($ctx, 32)),
     326            'generichash_final()'
     327        );
     328    }
     329
     330    public function testSignKeypair()
     331    {
     332        $seed = random_bytes(32);
     333        $kp = \Sodium\crypto_sign_seed_keypair($seed);
     334        $this->assertSame(
     335            bin2hex($kp),
     336            bin2hex(
     337                ParagonIE_Sodium_Compat::crypto_sign_seed_keypair($seed)
     338            ),
     339            'crypto_sign_seed_keypair() is invalid.'
     340        );
     341        $secret = \Sodium\crypto_sign_secretkey($kp);
     342        $public = \Sodium\crypto_sign_publickey($kp);
     343
     344        $pk = '';
     345        $sk = '';
     346        ParagonIE_Sodium_Core_Ed25519::seed_keypair($pk, $sk, $seed);
     347        $this->assertSame(
     348            bin2hex($secret),
     349            bin2hex($sk),
     350            'Seed secret key'
     351        );
     352        $this->assertSame(
     353            bin2hex($public),
     354            bin2hex($pk),
     355            'Seed public key'
     356        );
     357        $keypair = ParagonIE_Sodium_Compat::crypto_sign_keypair();
     358        $secret = \Sodium\crypto_sign_secretkey($keypair);
     359        $public = \Sodium\crypto_sign_publickey($keypair);
     360
     361        $this->assertSame(
     362            bin2hex($public),
     363            bin2hex(
     364                \Sodium\crypto_sign_publickey_from_secretkey($secret)
     365            ),
     366            'Conversion from existing secret key is failing. This is a very bad thing!'
     367        );
     368
     369    }
     370
     371    public function testSignKeypair2()
     372    {
     373        $keypair = \Sodium\crypto_sign_keypair();
     374        $secret = \Sodium\crypto_sign_secretkey($keypair);
     375        $public = \Sodium\crypto_sign_publickey($keypair);
     376
     377        $this->assertSame(
     378            bin2hex($public),
     379            bin2hex(
     380                ParagonIE_Sodium_Compat::crypto_sign_publickey_from_secretkey($secret)
     381            ),
     382            'Conversion from existing secret key is failing. This is a very bad thing!'
     383        );
     384    }
     385
     386    /**
     387     * @covers ParagonIE_Sodium_Compat::crypto_sign()
     388     * @covers ParagonIE_Sodium_Compat::crypto_sign_open()
     389     * @covers ParagonIE_Sodium_Compat::crypto_sign_detached()
     390     * @covers ParagonIE_Sodium_Compat::crypto_sign_verify_detached()
     391     */
     392    public function testCryptoSign()
     393    {
     394        $keypair = ParagonIE_Sodium_Core_Util::hex2bin(
     395            'fcdf31aae72e280cc760186d83e41be216fe1f2c7407dd393ad3a45a2fa501a4' .
     396            'ee00f800ae9e986b994ec0af67fe6b017eb78704e81639eee7efa3d3a831d1bc' .
     397            'ee00f800ae9e986b994ec0af67fe6b017eb78704e81639eee7efa3d3a831d1bc'
     398        );
     399        $secret = \Sodium\crypto_sign_secretkey($keypair);
     400        $public = \Sodium\crypto_sign_publickey($keypair);
     401
     402        $this->assertSame(
     403            $secret,
     404            ParagonIE_Sodium_Compat::crypto_sign_secretkey($keypair),
     405            'crypto_sign_secretkey() is broken'
     406        );
     407        $this->assertSame(
     408            $public,
     409            ParagonIE_Sodium_Compat::crypto_sign_publickey($keypair),
     410            'crypto_sign_publickey() is broken'
     411        );
     412
     413        $message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
     414        $expected =
     415        '36a6d2748f6ab8f76c122a562d55343cb7c6f15c8a45bd55bd8b9e9fadd2363f' .
     416        '370cb78fba42c550d487b9bd7413312b6490c8b3ee2cea638997172a9c8c250f';
     417
     418        $this->assertSame(
     419            $expected,
     420            bin2hex(\Sodium\crypto_sign_detached($message, $secret)),
     421            'Generated different signatures'
     422        );
     423
     424        $this->assertSame(
     425            bin2hex(\Sodium\crypto_sign_detached($message, $secret)),
     426            bin2hex(ParagonIE_Sodium_Crypto::sign_detached($message, $secret)),
     427            'Generated different signatures'
     428        ); 
     429
     430        $this->assertSame(
     431            $expected,
     432            bin2hex(ParagonIE_Sodium_Crypto::sign_detached($message, $secret)),
     433            'Generated different signatures'
     434        );
     435
     436        $message = 'Test message: ' . base64_encode(random_bytes(33));
     437        $keypair = \Sodium\crypto_sign_keypair();
     438        $secret = \Sodium\crypto_sign_secretkey($keypair);
     439        $public = \Sodium\crypto_sign_publickey($keypair);
     440        $public2 = ParagonIE_Sodium_Compat::crypto_sign_publickey($keypair);
     441        $this->assertSame($public, $public2);
     442
     443        $signature = \Sodium\crypto_sign_detached($message, $secret);
     444        $this->assertSame(
     445            bin2hex($signature),
     446            bin2hex(ParagonIE_Sodium_Crypto::sign_detached($message, $secret)),
     447            'Generated different signatures'
     448        );
     449        $this->assertTrue(
     450            ParagonIE_Sodium_Crypto::sign_verify_detached($signature, $message, $public),
     451            'Signature verification failed in compatibility test.'
     452        );
     453
     454        // Signed messages (NaCl compatibility):
     455        $signed = \Sodium\crypto_sign($message, $secret);
     456        $this->assertSame(
     457            bin2hex($signed),
     458            bin2hex(ParagonIE_Sodium_Crypto::sign($message, $secret)),
     459            'Basic crypto_sign works'
     460        );
     461
     462        $this->assertSame(
     463            bin2hex(\Sodium\crypto_sign_open($signed, $public)),
     464            bin2hex(ParagonIE_Sodium_Crypto::sign_open($signed, $public)),
     465            'Basic crypto_sign_open works'
     466        );
     467    }
     468
     469    /**
     470     * @covers ParagonIE_Sodium_Compat::crypto_secretbox()
     471     */
     472    public function testCryptoSecretBox()
     473    {
     474        $key = str_repeat("\x80", 32);
     475        $nonce = str_repeat("\x00", 24);
     476        $message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
     477
     478        $this->assertSame(
     479            substr(
     480                bin2hex(\Sodium\crypto_secretbox($message, $nonce, $key)),
     481                0, 32
     482            ),
     483            substr(
     484                bin2hex(ParagonIE_Sodium_Crypto::secretbox($message, $nonce, $key)),
     485                0, 32
     486            ),
     487            'secretbox - short messages'
     488        );
     489        $this->assertSame(
     490            $message,
     491            ParagonIE_Sodium_Crypto::secretbox_open(
     492                \Sodium\crypto_secretbox($message, $nonce, $key),
     493                $nonce,
     494                $key
     495            )
     496        );
     497        $this->assertSame(
     498            $message,
     499            \Sodium\crypto_secretbox_open(
     500                ParagonIE_Sodium_Crypto::secretbox($message, $nonce, $key),
     501                $nonce,
     502                $key
     503            )
     504        );
     505        $message = str_repeat('a', 97);
     506        $this->assertSame(
     507            bin2hex(\Sodium\crypto_secretbox($message, $nonce, $key)),
     508            bin2hex(ParagonIE_Sodium_Crypto::secretbox($message, $nonce, $key)),
     509            'secretbox - long messages (multiple of 16)'
     510        );
     511
     512        $message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
     513
     514        $message = str_repeat($message, 16);
     515
     516        $this->assertSame(
     517            bin2hex(\Sodium\crypto_secretbox($message, $nonce, $key)),
     518            bin2hex(ParagonIE_Sodium_Crypto::secretbox($message, $nonce, $key)),
     519            'secretbox - long messages (multiple of 16)'
     520        );
     521
     522        $message .= 'a';
     523
     524        $this->assertSame(
     525            bin2hex(\Sodium\crypto_secretbox($message, $nonce, $key)),
     526            bin2hex(ParagonIE_Sodium_Crypto::secretbox($message, $nonce, $key)),
     527            'secretbox - long messages (NOT a multiple of 16)'
     528        );
     529
     530        $message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
     531
     532        $this->assertSame(
     533            bin2hex(\Sodium\crypto_secretbox($message, $nonce, $key)),
     534            bin2hex(ParagonIE_Sodium_Crypto::secretbox($message, $nonce, $key)),
     535            'secretbox - medium messages'
     536        );
     537    }
     538
     539    /**
     540     * @covers ParagonIE_Sodium_Compat::crypto_scalarmult_base()
     541     */
     542    public function testCryptoScalarmultBase()
     543    {
     544        $keypair = \Sodium\crypto_box_keypair();
     545        $secret = \Sodium\crypto_box_secretkey($keypair);
     546        $public = \Sodium\crypto_box_publickey($keypair);
     547
     548        $this->assertSame(
     549            $public,
     550            ParagonIE_Sodium_Compat::crypto_scalarmult_base($secret)
     551        );
     552    }
     553    /**
     554     * @covers ParagonIE_Sodium_Compat::crypto_scalarmult()
     555     */
     556    public function testCryptoScalarmult()
     557    {
     558        $alice_box_kp = \Sodium\crypto_box_keypair();
     559        $alice_box_secretkey = \Sodium\crypto_box_secretkey($alice_box_kp);
     560        $alice_box_publickey = \Sodium\crypto_box_publickey($alice_box_kp);
     561
     562        $bob_box_kp = \Sodium\crypto_box_keypair();
     563        $bob_box_secretkey = \Sodium\crypto_box_secretkey($bob_box_kp);
     564        $bob_box_publickey = \Sodium\crypto_box_publickey($bob_box_kp);
     565
     566        $this->assertSame(
     567            \Sodium\crypto_scalarmult($alice_box_secretkey, $bob_box_publickey),
     568            ParagonIE_Sodium_Compat::crypto_scalarmult($alice_box_secretkey, $bob_box_publickey)
     569        );
     570
     571        $this->assertSame(
     572            \Sodium\crypto_scalarmult($bob_box_secretkey, $alice_box_publickey),
     573            ParagonIE_Sodium_Compat::crypto_scalarmult($bob_box_secretkey, $alice_box_publickey)
     574        );
     575    }
     576
     577    /**
     578     * @covers ParagonIE_Sodium_Compat::crypto_box_secretkey()
     579     * @covers ParagonIE_Sodium_Compat::crypto_box_publickey()
     580     */
     581    public function testCryptoBoxKeypairs()
     582    {
     583        $keypair = \Sodium\crypto_box_keypair();
     584        $secret = \Sodium\crypto_box_secretkey($keypair);
     585        $public = \Sodium\crypto_box_publickey($keypair);
     586
     587        $this->assertSame(
     588            $secret,
     589            ParagonIE_Sodium_Compat::crypto_box_secretkey($keypair)
     590        );
     591        $this->assertSame(
     592            $public,
     593            ParagonIE_Sodium_Compat::crypto_box_publickey($keypair)
     594        );
     595    }
     596
     597    /**
     598     * @covers ParagonIE_Sodium_Compat::crypto_stream()
     599     */
     600    public function testCryptoStream()
     601    {
     602        $key = str_repeat("\x80", 32);
     603        $nonce = str_repeat("\x00", 24);
     604
     605        $streamed = \Sodium\crypto_stream(64, $nonce, $key);
     606        $this->assertSame(
     607            bin2hex($streamed),
     608            bin2hex(ParagonIE_Sodium_Compat::crypto_stream(64, $nonce, $key)),
     609            'crypto_stream_xor() is not working'
     610        );
     611        $key = random_bytes(32);
     612        $nonce = random_bytes(24);
     613
     614        $streamed = \Sodium\crypto_stream(1024, $nonce, $key);
     615        $this->assertSame(
     616            bin2hex($streamed),
     617            bin2hex(ParagonIE_Sodium_Compat::crypto_stream(1024, $nonce, $key)),
     618            'crypto_stream() is not working'
     619        );
     620    }
     621
     622    /**
     623     * @covers ParagonIE_Sodium_Compat::crypto_stream_xor()
     624     */
     625    public function testCryptoStreamXor()
     626    {
     627        $key = str_repeat("\x80", 32);
     628        $nonce = str_repeat("\x00", 24);
     629        $message = 'Test message';
     630
     631        $streamed = \Sodium\crypto_stream_xor($message, $nonce, $key);
     632        $this->assertSame(
     633            bin2hex($streamed),
     634            bin2hex(ParagonIE_Sodium_Compat::crypto_stream_xor($message, $nonce, $key)),
     635            'crypto_stream_xor() is not working'
     636        );
     637
     638        $key = random_bytes(32);
     639        $nonce = random_bytes(24);
     640
     641        $message = 'Test message: ' . base64_encode(random_bytes(93));
     642
     643        $streamed = \Sodium\crypto_stream_xor($message, $nonce, $key);
     644        $this->assertSame(
     645            bin2hex($streamed),
     646            bin2hex(ParagonIE_Sodium_Compat::crypto_stream_xor($message, $nonce, $key)),
     647            'crypto_stream_xor() is not working'
     648        );
     649    }
     650
     651    /**
     652     * @covers ParagonIE_Sodium_Compat::crypto_kx()
     653     */
     654    public function testCryptoKx()
     655    {
     656        $alice_box_kp = \Sodium\crypto_box_keypair();
     657        $alice_box_secretkey = \Sodium\crypto_box_secretkey($alice_box_kp);
     658        $alice_box_publickey = \Sodium\crypto_box_publickey($alice_box_kp);
     659
     660        $bob_box_kp = \Sodium\crypto_box_keypair();
     661        $bob_box_publickey = \Sodium\crypto_box_publickey($bob_box_kp);
     662
     663        // Let's designate Bob as the server.
     664
     665        $this->assertSame(
     666            bin2hex(
     667                \Sodium\crypto_kx(
     668                    $alice_box_secretkey, $bob_box_publickey,
     669                    $alice_box_publickey, $bob_box_publickey
     670                )
     671            ),
     672            bin2hex(
     673                ParagonIE_Sodium_Compat::crypto_kx(
     674                    $alice_box_secretkey, $bob_box_publickey,
     675                    $alice_box_publickey, $bob_box_publickey
     676                )
     677            )
     678        );
     679    }
     680
     681    /**
     682     *
     683     */
     684    public function testCryptoShorthash()
     685    {
     686        $message = str_repeat("\x00", 8);
     687        $key = str_repeat("\x00", 16);
     688        $this->shorthashVerify($message, $key);
     689
     690        $key = str_repeat("\xff", 16);
     691        $this->shorthashVerify($message, $key);
     692
     693        $message = str_repeat("\x01", 8);
     694        $this->shorthashVerify($message, $key);
     695
     696        $message = str_repeat("\x01", 7) . "\x02";
     697        $this->shorthashVerify($message, $key);
     698
     699        $key = str_repeat("\xff", 8) . str_repeat("\x00", 8);
     700        $this->shorthashVerify($message, $key);
     701
     702        $message = str_repeat("\x00", 8);
     703        $key = random_bytes(16);
     704
     705        $this->shorthashVerify($message, $key);
     706
     707        $message = random_bytes(random_int(1, 100));
     708        $this->shorthashVerify($message, $key);
     709    }
     710   
     711    protected function shorthashVerify($m, $k)
     712    {
     713        $this->assertSame(
     714            bin2hex(\Sodium\crypto_shorthash($m, $k)),
     715            bin2hex(ParagonIE_Sodium_Compat::crypto_shorthash($m, $k))
     716        );
     717    }
     718}
  • wp-includes/sodium_compat/tests/unit/UtilTest.php

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
     
     1<?php
     2
     3class UtilTest extends PHPUnit_Framework_TestCase
     4{
     5    public function setUp()
     6    {
     7        ParagonIE_Sodium_Compat::$disableFallbackForUnitTests = true;
     8    }
     9
     10    /**
     11     * @covers ParagonIE_Sodium_Core_Util::bin2hex()
     12     * @covers ParagonIE_Sodium_Core_Util::hex2bin()
     13     */
     14    public function testBin2hex()
     15    {
     16        $data = random_bytes(32);
     17        $this->assertSame(
     18            bin2hex($data),
     19            ParagonIE_Sodium_Core_Util::bin2hex($data),
     20            'bin2hex should be the compatible with PHP'
     21        );
     22        $this->assertSame(
     23            $data,
     24            ParagonIE_Sodium_Core_Util::hex2bin(
     25                ParagonIE_Sodium_Core_Util::bin2hex($data)
     26            ),
     27            'bin2hex and hex2bin should decode a string to itself'
     28        );
     29        $this->assertSame(
     30            $data,
     31            ParagonIE_Sodium_Core_Util::hex2bin(
     32                bin2hex($data)
     33            ),
     34            'hex2bin should be compatible with PHP'
     35        );
     36    }
     37
     38    /**
     39     * @covers ParagonIE_Sodium_Compat::randombytes_buf()
     40     * @covers ParagonIE_Sodium_Compat::randombytes_random16()
     41     * @covers ParagonIE_Sodium_Compat::randombytes_uniform()
     42     */
     43    public function testRandombytes()
     44    {
     45        $random = ParagonIE_Sodium_Compat::randombytes_buf(32);
     46        $this->assertSame(32, ParagonIE_Sodium_Core_Util::strlen($random));
     47
     48        $other = ParagonIE_Sodium_Compat::randombytes_buf(32);
     49        $this->assertNotSame($random, $other);
     50
     51        $int = ParagonIE_Sodium_Compat::randombytes_uniform(1000);
     52        $this->assertLessThan(1000, $int, 'Out of bounds (> 1000)');
     53        $this->assertGreaterThan(0, $int, 'Out of bounds (< 0)');
     54
     55        $int = ParagonIE_Sodium_Compat::randombytes_random16();
     56        $this->assertLessThan(65536, $int, 'Out of bounds (> 65535)');
     57        $this->assertGreaterThan(0, $int, 'Out of bounds (< 0)');
     58    }
     59
     60    /**
     61     * @covers ParagonIE_Sodium_Core_Util::intArrayToString()
     62     * @covers ParagonIE_Sodium_Core_Util::stringToIntArray()
     63     */
     64    public function testConversion()
     65    {
     66        $sample = array(80, 97, 114, 97, 103, 111, 110);
     67
     68        $this->assertSame(
     69            'Paragon',
     70            ParagonIE_Sodium_Core_Util::intArrayToString($sample)
     71        );
     72
     73        $this->assertSame(
     74            $sample,
     75            ParagonIE_Sodium_Core_Util::stringToIntArray('Paragon')
     76        );
     77
     78    }
     79
     80    /**
     81     * @covers ParagonIE_Sodium_Core_Util::load_3()
     82     */
     83    public function testLoad3()
     84    {
     85        $this->assertSame(
     86            8451279,
     87            ParagonIE_Sodium_Core_Curve25519::load_3("\xcf\xf4\x80"),
     88            'Unexpected result from load_3'
     89        );
     90        $this->assertSame(
     91            8516815,
     92            ParagonIE_Sodium_Core_Curve25519::load_3("\xcf\xf4\x81"),
     93            'Verify endianness is correct'
     94        );
     95        $this->assertSame(
     96            8451280,
     97            ParagonIE_Sodium_Core_Curve25519::load_3("\xd0\xf4\x80"),
     98            'Verify endianness is correct'
     99        );
     100    }
     101
     102    /**
     103     * @covers ParagonIE_Sodium_Core_Util::load_3()
     104     */
     105    public function testLoad4()
     106    {
     107        $this->assertSame(
     108            8451279,
     109            ParagonIE_Sodium_Core_Curve25519::load_4("\xcf\xf4\x80\x00"),
     110            'Unexpected result from load_4'
     111        );
     112        $this->assertSame(
     113            2163527424,
     114            ParagonIE_Sodium_Core_Curve25519::load_4("\x00\xcf\xf4\x80"),
     115            'Unexpected result from load_4'
     116        );
     117    }
     118
     119    /**
     120     * @covers ParagonIE_Sodium_Core_Util::strlen()
     121     */
     122    public function testStrlen()
     123    {
     124        $this->assertSame(4, ParagonIE_Sodium_Core_Util::strlen("\xF0\x9D\x92\xB3"));
     125    }
     126
     127    /**
     128     * @covers ParagonIE_Sodium_Core_Util::strlen()
     129     */
     130    public function testSubstr()
     131    {
     132        $string = \str_repeat("\xF0\x9D\x92\xB3", 4);
     133        $this->assertSame(ParagonIE_Sodium_Core_Util::substr($string, 0, 1), "\xF0");
     134        $this->assertSame(ParagonIE_Sodium_Core_Util::substr($string, 1, 1), "\x9D");
     135        $this->assertSame(ParagonIE_Sodium_Core_Util::substr($string, 2, 1), "\x92");
     136        $this->assertSame(ParagonIE_Sodium_Core_Util::substr($string, 3, 1), "\xB3");
     137        $this->assertSame(ParagonIE_Sodium_Core_Util::substr($string, 0, 2), "\xF0\x9D");
     138        $this->assertSame(ParagonIE_Sodium_Core_Util::substr($string, 2, 2), "\x92\xB3");
     139    }
     140}
  • wp-includes/sodium_compat/src/Core/Curve25519/Ge/P1p1.php

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
     
     1<?php
     2
     3/**
     4 * Class ParagonIE_Sodium_Core_Curve25519_Ge_P1p1
     5 */
     6class ParagonIE_Sodium_Core_Curve25519_Ge_P1p1
     7{
     8    /**
     9     * @var ParagonIE_Sodium_Core_Curve25519_Fe
     10     */
     11    public $X;
     12
     13    /**
     14     * @var ParagonIE_Sodium_Core_Curve25519_Fe
     15     */
     16    public $Y;
     17
     18    /**
     19     * @var ParagonIE_Sodium_Core_Curve25519_Fe
     20     */
     21    public $Z;
     22
     23    /**
     24     * @var ParagonIE_Sodium_Core_Curve25519_Fe
     25     */
     26    public $T;
     27
     28    /**
     29     * ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 constructor.
     30     * @param ParagonIE_Sodium_Core_Curve25519_Fe $x
     31     * @param ParagonIE_Sodium_Core_Curve25519_Fe $y
     32     * @param ParagonIE_Sodium_Core_Curve25519_Fe $z
     33     * @param ParagonIE_Sodium_Core_Curve25519_Fe $t
     34     */
     35    public function __construct(
     36        ParagonIE_Sodium_Core_Curve25519_Fe $x = null,
     37        ParagonIE_Sodium_Core_Curve25519_Fe $y = null,
     38        ParagonIE_Sodium_Core_Curve25519_Fe $z = null,
     39        ParagonIE_Sodium_Core_Curve25519_Fe $t = null
     40    ) {
     41        $this->X = $x;
     42        $this->Y = $y;
     43        $this->Z = $z;
     44        $this->T = $t;
     45    }
     46}
  • wp-includes/sodium_compat/autoload.php

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
     
     1<?php
     2
     3/**
     4 * @param string $class
     5 * @return bool
     6 */
     7function sodiumCompatAutoader($class)
     8{
     9    $namespace = 'ParagonIE_Sodium_';
     10    // does the class use the namespace prefix?
     11    $len = strlen($namespace);
     12    if (strncmp($namespace, $class, $len) !== 0) {
     13        // no, move to the next registered autoloader
     14        return false;
     15    }
     16    // get the relative class name
     17    $relative_class = substr($class, $len);
     18    // replace the namespace prefix with the base directory, replace namespace
     19    // separators with directory separators in the relative class name, append
     20    // with .php
     21    $file = __DIR__ . '/src/' . str_replace('_', '/', $relative_class) . '.php';
     22    // if the file exists, require it
     23    if (file_exists($file)) {
     24        require $file;
     25        return true;
     26    }
     27    return false;
     28}
     29spl_autoload_register('sodiumCompatAutoader');
     30
     31if (PHP_VERSION_ID >= 50300) {
     32    // Namespaces didn't exist before 5.3.0, so don't even try to use this
     33    // unless PHP >= 5.3.0
     34    require_once __DIR__ . '/lib/sodium_compat.php';
     35}
  • wp-includes/sodium_compat/src/Core/BLAKE2b.php

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
     
     1<?php
     2
     3/**
     4 * Class ParagonIE_Sodium_Core_BLAKE2b
     5 *
     6 * Based on the work of Devi Mandiri in devi/salt.
     7 */
     8abstract class ParagonIE_Sodium_Core_BLAKE2b extends ParagonIE_Sodium_Core_Util
     9{
     10    /**
     11     * @var SplFixedArray[]
     12     */
     13    protected static $iv;
     14
     15    /**
     16     * @var int[][]
     17     */
     18    protected static $sigma = array(
     19        array(  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15),
     20        array( 14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5,  3),
     21        array( 11,  8, 12,  0,  5,  2, 15, 13, 10, 14,  3,  6,  7,  1,  9,  4),
     22        array(  7,  9,  3,  1, 13, 12, 11, 14,  2,  6,  5, 10,  4,  0, 15,  8),
     23        array(  9,  0,  5,  7,  2,  4, 10, 15, 14,  1, 11, 12,  6,  8,  3, 13),
     24        array(  2, 12,  6, 10,  0, 11,  8,  3,  4, 13,  7,  5, 15, 14,  1,  9),
     25        array( 12,  5,  1, 15, 14, 13,  4, 10,  0,  7,  6,  3,  9,  2,  8, 11),
     26        array( 13, 11,  7, 14, 12,  1,  3,  9,  5,  0, 15,  4,  8,  6,  2, 10),
     27        array(  6, 15, 14,  9, 11,  3,  0,  8, 12,  2, 13,  7,  1,  4, 10,  5),
     28        array( 10,  2,  8,  4,  7,  6,  1,  5, 15, 11,  9, 14,  3, 12, 13 , 0),
     29        array(  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15),
     30        array( 14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5,  3)
     31    );
     32
     33    const BLOCKBYTES = 128;
     34    const OUTBYTES   = 64;
     35    const KEYBYTES   = 64;
     36
     37    /**
     38     * Turn two 32-bit integers into a fixed array representing a 64-bit integer.
     39     *
     40     * @param int $high
     41     * @param int $low
     42     * @return SplFixedArray
     43     */
     44    protected static function new64($high, $low)
     45    {
     46        $i64 = new SplFixedArray(2);
     47        $i64[0] = $high & 0xffffffff;
     48        $i64[1] = $low & 0xffffffff;
     49        return $i64;
     50    }
     51
     52    /**
     53     * Convert an arbitrary number into an SplFixedArray of two 32-bit integers
     54     * that represents a 64-bit integer.
     55     *
     56     * @param int $num
     57     * @return SplFixedArray
     58     */
     59    protected static function to64($num)
     60    {
     61        $hi = 0; $lo = $num & 0xffffffff;
     62
     63        if ((+(abs($num))) >= 1) {
     64            if ($num > 0) {
     65                $hi = min((+(floor($num/4294967296))), 4294967295);
     66            } else {
     67                $hi = ~~((+(ceil(($num - (+((~~($num)))))/4294967296))));
     68            }
     69        }
     70
     71        return self::new64($hi, $lo);
     72    }
     73
     74    /**
     75     * Adds two 64-bit integers together, returning their sum as a SplFixedArray
     76     * containing two 32-bit integers (representing a 64-bit integer).
     77     *
     78     * @param SplFixedArray $x
     79     * @param SplFixedArray $y
     80     * @return SplFixedArray
     81     */
     82    protected static function add64($x, $y)
     83    {
     84        $l = ($x[1] + $y[1]) & 0xffffffff;
     85        return self::new64($x[0] + $y[0] + (($l < $x[1]) ? 1 : 0), $l);
     86    }
     87
     88    /**
     89     * @param SplFixedArray $x
     90     * @param SplFixedArray $y
     91     * @param SplFixedArray $z
     92     * @return SplFixedArray
     93     */
     94    protected static function add364($x, $y, $z)
     95    {
     96        return self::add64($x, self::add64($y, $z));
     97    }
     98
     99    /**
     100     * @param SplFixedArray $x
     101     * @param SplFixedArray $y
     102     * @return SplFixedArray
     103     * @throws Exception
     104     */
     105    protected static function xor64(SplFixedArray $x, SplFixedArray $y)
     106    {
     107        if (!is_numeric($x[0])) {
     108            throw new Exception('x[0] is not an integer');
     109        }
     110        if (!is_numeric($x[1])) {
     111            throw new Exception('x[1] is not an integer');
     112        }
     113        if (!is_numeric($y[0])) {
     114            throw new Exception('y[0] is not an integer');
     115        }
     116        if (!is_numeric($y[1])) {
     117            throw new Exception('y[1] is not an integer');
     118        }
     119        return self::new64($x[0] ^ $y[0], $x[1] ^ $y[1]);
     120    }
     121
     122    /**
     123     * @param SplFixedArray $x
     124     * @param int $c
     125     * @return SplFixedArray
     126     */
     127    protected static function rotr64($x, $c)
     128    {
     129        $l0 = 0;
     130        $c = 64 - $c;
     131
     132        if ($c < 32) {
     133            $h0 = ($x[0] << $c) | (($x[1] & ((1 << $c) - 1) << (32 - $c)) >> (32 - $c));
     134            $l0 = $x[1] << $c;
     135        } else {
     136            $h0 = $x[1] << ($c - 32);
     137        }
     138
     139        $h1 = 0;
     140        $c1 = 64 - $c;
     141
     142        if ($c1 < 32) {
     143            $h1 = $x[0] >> $c1;
     144            $l1 = ($x[1] >> $c1) | ($x[0] & ((1 << $c1) - 1)) << (32 - $c1);
     145        } else {
     146            $l1 = $x[0] >> ($c1 - 32);
     147        }
     148
     149        return self::new64($h0 | $h1, $l0 | $l1);
     150    }
     151
     152    /**
     153     * @param SplFixedArray $x
     154     * @return int
     155     */
     156    protected static function flatten64($x)
     157    {
     158        return ($x[0] * 4294967296 + $x[1]);
     159    }
     160
     161    /**
     162     * @param $x
     163     * @param $i
     164     * @return SplFixedArray
     165     */
     166    protected static function load64($x, $i)
     167    {
     168        $l = $x[$i]   | ($x[$i+1]<<8) | ($x[$i+2]<<16) | ($x[$i+3]<<24);
     169        $h = $x[$i+4] | ($x[$i+5]<<8) | ($x[$i+6]<<16) | ($x[$i+7]<<24);
     170        return self::new64($h, $l);
     171    }
     172
     173    /**
     174     * @param $x
     175     * @param $i
     176     * @param $u
     177     */
     178    protected static function store64($x, $i, $u)
     179    {
     180        $x[$i]   = ($u[1] & 0xff); $u[1] >>= 8;
     181        $x[$i+1] = ($u[1] & 0xff); $u[1] >>= 8;
     182        $x[$i+2] = ($u[1] & 0xff); $u[1] >>= 8;
     183        $x[$i+3] = ($u[1] & 0xff);
     184        $x[$i+4] = ($u[0] & 0xff); $u[0] >>= 8;
     185        $x[$i+5] = ($u[0] & 0xff); $u[0] >>= 8;
     186        $x[$i+6] = ($u[0] & 0xff); $u[0] >>= 8;
     187        $x[$i+7] = ($u[0] & 0xff);
     188    }
     189
     190    /**
     191     * This just sets the $iv static variable.
     192     */
     193    public static function pseudoConstructor()
     194    {
     195        static $called = false;
     196        if ($called) {
     197            return;
     198        }
     199        self::$iv = new SplFixedArray(8);
     200        self::$iv[0] = self::new64(0x6a09e667, 0xf3bcc908);
     201        self::$iv[1] = self::new64(0xbb67ae85, 0x84caa73b);
     202        self::$iv[2] = self::new64(0x3c6ef372, 0xfe94f82b);
     203        self::$iv[3] = self::new64(0xa54ff53a, 0x5f1d36f1);
     204        self::$iv[4] = self::new64(0x510e527f, 0xade682d1);
     205        self::$iv[5] = self::new64(0x9b05688c, 0x2b3e6c1f);
     206        self::$iv[6] = self::new64(0x1f83d9ab, 0xfb41bd6b);
     207        self::$iv[7] = self::new64(0x5be0cd19, 0x137e2179);
     208
     209        $called = true;
     210    }
     211
     212    /**
     213     * Returns a fresh BLAKE2 context.
     214     *
     215     * @return SplFixedArray
     216     */
     217    protected static function context()
     218    {
     219        $ctx    = new SplFixedArray(5);
     220        $ctx[0] = new SplFixedArray(8);   // h
     221        $ctx[1] = new SplFixedArray(2);   // t
     222        $ctx[2] = new SplFixedArray(2);   // f
     223        $ctx[3] = new SplFixedArray(256); // buf
     224        $ctx[4] = 0;                      // buflen
     225
     226        for ($i = 8; $i--;) {
     227            $ctx[0][$i] = self::$iv[$i];
     228        }
     229        for ($i = 256; $i--;) {
     230            $ctx[3][$i] = 0;
     231        }
     232
     233        $zero = self::new64(0, 0);
     234        $ctx[1][0] = $zero;
     235        $ctx[1][1] = $zero;
     236        $ctx[2][0] = $zero;
     237        $ctx[2][1] = $zero;
     238
     239        return $ctx;
     240    }
     241
     242    /**
     243     * @param SplFixedArray $ctx
     244     * @param SplFixedArray $buf
     245     */
     246    protected static function compress(SplFixedArray $ctx, SplFixedArray $buf)
     247    {
     248        $m = new SplFixedArray(16);
     249        $v = new SplFixedArray(16);
     250
     251        for ($i = 16; $i--;) {
     252            $m[$i] = self::load64($buf, $i*8);
     253        }
     254
     255        for ($i = 8; $i--;) {
     256            $v[$i] = $ctx[0][$i];
     257        }
     258
     259        $v[ 8] = self::$iv[0];
     260        $v[ 9] = self::$iv[1];
     261        $v[10] = self::$iv[2];
     262        $v[11] = self::$iv[3];
     263
     264        $v[12] = self::xor64($ctx[1][0], self::$iv[4]);
     265        $v[13] = self::xor64($ctx[1][1], self::$iv[5]);
     266        $v[14] = self::xor64($ctx[2][0], self::$iv[6]);
     267        $v[15] = self::xor64($ctx[2][1], self::$iv[7]);
     268
     269        for ($r = 0; $r < 12; ++$r) {
     270            $v = self::G($r, 0,  0,  4,  8, 12, $v, $m);
     271            $v = self::G($r, 1,  1,  5,  9, 13, $v, $m);
     272            $v = self::G($r, 2,  2,  6, 10, 14, $v, $m);
     273            $v = self::G($r, 3,  3,  7, 11, 15, $v, $m);
     274            $v = self::G($r, 4,  0,  5, 10, 15, $v, $m);
     275            $v = self::G($r, 5,  1,  6, 11, 12, $v, $m);
     276            $v = self::G($r, 6,  2,  7,  8, 13, $v, $m);
     277            $v = self::G($r, 7,  3,  4,  9, 14, $v, $m);
     278        }
     279
     280        for ($i = 8; $i--;) {
     281            $ctx[0][$i] = self::xor64(
     282                $ctx[0][$i], self::xor64($v[$i], $v[$i+8])
     283            );
     284        }
     285    }
     286
     287    /**
     288     * @param int $r
     289     * @param int $i
     290     * @param int $a
     291     * @param int $b
     292     * @param int $c
     293     * @param int $d
     294     * @param SplFixedArray $v
     295     * @param SplFixedArray $m
     296     * @return SplFixedArray
     297     */
     298    public static function G($r, $i, $a, $b, $c, $d, SplFixedArray $v, SplFixedArray $m)
     299    {
     300        $v[$a] = self::add364($v[$a], $v[$b], $m[self::$sigma[$r][2*$i]]);
     301        $v[$d] = self::rotr64(self::xor64($v[$d], $v[$a]), 32);
     302        $v[$c] = self::add64($v[$c], $v[$d]);
     303        $v[$b] = self::rotr64(self::xor64($v[$b], $v[$c]), 24);
     304        $v[$a] = self::add364($v[$a], $v[$b], $m[self::$sigma[$r][2*$i+1]]);
     305        $v[$d] = self::rotr64(self::xor64($v[$d], $v[$a]), 16);
     306        $v[$c] = self::add64($v[$c], $v[$d]);
     307        $v[$b] = self::rotr64(self::xor64($v[$b], $v[$c]), 63);
     308        return $v;
     309    }
     310
     311    /**
     312     * @param SplFixedArray $ctx
     313     * @param int $inc
     314     */
     315    protected static function increment_counter($ctx, $inc)
     316    {
     317        $t = self::to64($inc);
     318        $ctx[1][0] = self::add64($ctx[1][0], $t);
     319        if (self::flatten64($ctx[1][0]) < $inc) {
     320            $ctx[1][1] = self::add64($ctx[1][1], self::to64(1));
     321        }
     322    }
     323
     324    /**
     325     * @param SplFixedArray $ctx
     326     * @param SplFixedArray $p
     327     * @param int $plen
     328     */
     329    public static function update(SplFixedArray $ctx, $p, $plen)
     330    {
     331        $offset = 0;
     332        while ($plen > 0) {
     333            $left = $ctx[4];
     334            $fill = 256 - $left;
     335
     336            if ($plen > $fill) {
     337                for ($i = $fill; $i--;) {
     338                    $ctx[3][$i+$left] = $p[$i+$offset];
     339                }
     340
     341                $ctx[4] += $fill;
     342
     343                self::increment_counter($ctx, 128);
     344                self::compress($ctx, $ctx[3]);
     345
     346                for ($i = 128; $i--;) {
     347                    $ctx[3][$i] = $ctx[3][$i+128];
     348                }
     349
     350                $ctx[4] -= 128;
     351                $offset += $fill;
     352                $plen -= $fill;
     353            } else {
     354                for ($i = $plen; $i--;) {
     355                    $ctx[3][$i+$left] = $p[$i+$offset];
     356                }
     357                $ctx[4] += $plen;
     358                $offset += $plen;
     359                $plen -= $plen;
     360            }
     361        }
     362    }
     363
     364    /**
     365     * @param SplFixedArray $ctx
     366     * @param SplFixedArray $out
     367     * @return SplFixedArray
     368     */
     369    public static function finish(SplFixedArray $ctx, SplFixedArray $out)
     370    {
     371        if ($ctx[4] > 128) {
     372            self::increment_counter($ctx, 128);
     373            self::compress($ctx, $ctx[3]);
     374            $ctx[4] -= 128;
     375            for ($i = $ctx[4]; $i--;) {
     376                $ctx[3][$i] = $ctx[3][$i+128];
     377            }
     378        }
     379
     380        self::increment_counter($ctx, $ctx[4]);
     381        $ctx[2][0] = self::new64(0xffffffff, 0xffffffff);
     382
     383        for ($i = 256 - $ctx[4]; $i--;) {
     384            $ctx[3][$i+$ctx[4]] = 0;
     385        }
     386
     387        self::compress($ctx, $ctx[3]);
     388
     389        $i = (int) (($out->getSize() - 1) / 8);
     390        for (; $i >= 0; --$i) {
     391            self::store64($out, $i * 8, $ctx[0][$i]);
     392        }
     393        return $out;
     394    }
     395
     396    /**
     397     * @param SplFixedArray|null $key
     398     * @param int $outlen
     399     * @return SplFixedArray
     400     * @throws Exception
     401     */
     402    public static function init($key = null, $outlen = 64)
     403    {
     404        $klen = 0;
     405
     406        if ($key !== null) {
     407            if (count($key) > 64) {
     408                throw new Exception('Invalid key size');
     409            }
     410            $klen = count($key);
     411        }
     412
     413        if ($outlen > 64) {
     414            throw new Exception('Invalid output size');
     415        }
     416
     417        $ctx = self::context();
     418
     419        $p = new SplFixedArray(64);
     420        for ($i = 64; --$i;) $p[$i] = 0;
     421
     422        $p[0] = $outlen; // digest_length
     423        $p[1] = $klen;   // key_length
     424        $p[2] = 1;       // fanout
     425        $p[3] = 1;       // depth
     426
     427        $ctx[0][0] = self::xor64(
     428            $ctx[0][0],
     429            self::load64($p, 0)
     430        );
     431
     432        if ($klen > 0) {
     433            $block = new SplFixedArray(128);
     434            for ($i = 128; $i--;) {
     435                $block[$i] = 0;
     436            }
     437            for ($i = $klen; $i--;) {
     438                $block[$i] = $key[$i];
     439            }
     440            self::update($ctx, $block, 128);
     441        }
     442
     443        return $ctx;
     444    }
     445
     446    /**
     447     * Convert a string into an SplFixedArray of integers
     448     *
     449     * @param string $str
     450     * @return SplFixedArray
     451     */
     452    public static function stringToSplFixedArray($str = '')
     453    {
     454        $values = unpack('C*', $str);
     455        return SplFixedArray::fromArray(array_values($values));
     456    }
     457
     458    /**
     459     * Convert an SplFixedArray of integers into a string
     460     *
     461     * @param SplFixedArray $a
     462     * @return string
     463     */
     464    public static function SplFixedArrayToString(SplFixedArray $a)
     465    {
     466        $arr = $a->toArray();
     467        $c = $a->count();
     468        array_unshift($arr, str_repeat('C', $c));
     469        return call_user_func_array('pack', $arr);
     470    }
     471
     472    /**
     473     * @param SplFixedArray[SplFixedArray] $ctx
     474     * @return string
     475     */
     476    public static function contextToString(SplFixedArray $ctx)
     477    {
     478        $str = '';
     479        $ctxA = $ctx[0]->toArray();
     480        for ($i = 0; $i < 8; ++$i) {
     481            $str .= self::store32_le($ctxA[$i][1]);
     482            $str .= self::store32_le($ctxA[$i][0]);
     483        }
     484        for ($i = 0; $i < 2; ++$i) {
     485            $ctxA = $ctx[$i + 1]->toArray();
     486            $str .= self::store32_le($ctxA[0][1]);
     487            $str .= self::store32_le($ctxA[0][0]);
     488            $str .= self::store32_le($ctxA[1][1]);
     489            $str .= self::store32_le($ctxA[1][0]);
     490        }
     491        $str .= self::SplFixedArrayToString($ctx[3]);
     492        $str .= implode('', array(
     493            self::intToChr($ctx[4] & 0xff),
     494            self::intToChr(($ctx[4] << 8) & 0xff),
     495            self::intToChr(($ctx[4] << 16) & 0xff),
     496            self::intToChr(($ctx[4] << 24) & 0xff),
     497            self::intToChr(($ctx[4] << 32) & 0xff),
     498            self::intToChr(($ctx[4] << 40) & 0xff),
     499            self::intToChr(($ctx[4] << 48) & 0xff),
     500            self::intToChr(($ctx[4] << 56) & 0xff)
     501        ));
     502        return $str . "\x00";
     503    }
     504
     505    /**
     506     * Creates an SplFixedArray containing other SplFixedArray elements, from
     507     * a string (compatible with \Sodium\crypto_generichash_{init, update, final})
     508     *
     509     * @param $string
     510     * @return SplFixedArray
     511     */
     512    public static function stringToContext($string)
     513    {
     514        $ctx = self::context();
     515        for ($i = 0; $i < 8; ++$i) {
     516            $ctx[0][$i] = SplFixedArray::fromArray(
     517                array(
     518                    self::load_4(
     519                        self::substr($string, (8 * $i + 4), 4)
     520                    ),
     521                    self::load_4(
     522                        self::substr($string, (8 * $i + 0), 4)
     523                    )
     524                )
     525            );
     526        }
     527        for ($i = 1; $i <= 2; ++$i) {
     528            $ctx[$i][0] = SplFixedArray::fromArray(
     529                array(
     530                    self::load_4(self::substr($string, 64 + (8 * $i), 4)),
     531                    self::load_4(self::substr($string, 60 + (8 * $i), 4))
     532                )
     533            );
     534        }
     535        $ctx[3] = self::stringToSplFixedArray(self::substr($string, 96, 256));
     536        $int = 0;
     537        for ($i = 0; $i < 8; ++$i) {
     538            $int |= self::chrToInt($string[352 + $i]) << (8 * $i);
     539        }
     540        $ctx[4] = $int;
     541        return $ctx;
     542    }
     543}
  • wp-includes/sodium_compat/src/Core/Ed25519.php

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
     
     1<?php
     2
     3/**
     4 * Class ParagonIE_Sodium_Core_Ed25519
     5 */
     6abstract class ParagonIE_Sodium_Core_Ed25519 extends ParagonIE_Sodium_Core_Curve25519
     7{
     8    const KEYPAIR_BYTES = 96;
     9    const SEED_BYTES = 32;
     10
     11    /**
     12     * @return string (96 bytes)
     13     */
     14    public static function keypair()
     15    {
     16        $seed = random_bytes(self::SEED_BYTES);
     17        $pk = '';
     18        $sk = '';
     19        self::seed_keypair($pk, $sk, $seed);
     20        return $sk . $pk;
     21    }
     22
     23    /**
     24     * @param string $pk
     25     * @param string $sk
     26     * @param string $seed
     27     */
     28    public static function seed_keypair(&$pk, &$sk, $seed)
     29    {
     30        if (self::strlen($seed) !== self::SEED_BYTES) {
     31            throw new RangeException('crypto_sign keypair seed must be 32 bytes long');
     32        }
     33        $pk = self::publickey_from_secretkey($seed);
     34        $sk = self::substr($seed, 0, self::SEED_BYTES) . $pk;
     35    }
     36
     37    /**
     38     * @param string $keypair
     39     * @return string
     40     */
     41    public static function secretkey($keypair)
     42    {
     43        if (self::strlen($keypair) !== self::KEYPAIR_BYTES) {
     44            throw new RangeException('crypto_sign keypair seed must be 32 bytes long');
     45        }
     46        return self::substr($keypair, 0, 64);
     47    }
     48
     49    /**
     50     * @param string $keypair
     51     * @return string
     52     */
     53    public static function publickey($keypair)
     54    {
     55        if (self::strlen($keypair) !== self::KEYPAIR_BYTES) {
     56            throw new RangeException('crypto_sign keypair seed must be 32 bytes long');
     57        }
     58        return self::substr($keypair, 64, 32);
     59    }
     60
     61    /**
     62     * @param $sk
     63     * @return string
     64     */
     65    public static function publickey_from_secretkey($sk)
     66    {
     67        $sk = hash('sha512', self::substr($sk, 0, 32), true);
     68        $sk[0] = self::intToChr(
     69            self::chrToInt($sk[0]) & 248
     70        );
     71        $sk[31] = self::intToChr(
     72            (self::chrToInt($sk[31]) & 63) | 64
     73        );
     74        return self::sk_to_pk($sk);
     75    }
     76
     77    /**
     78     * @param $sk
     79     * @return string
     80     */
     81    public static function sk_to_pk($sk)
     82    {
     83        return self::ge_p3_tobytes(
     84            self::ge_scalarmult_base(self::substr($sk, 0, 32))
     85        );
     86    }
     87
     88    /**
     89     * @param string $message
     90     * @param string $sk
     91     * @return string
     92     */
     93    public static function sign($message, $sk)
     94    {
     95        $signature = self::sign_detached($message, $sk);
     96        return $signature . $message;
     97    }
     98
     99    /**
     100     * @param string $message
     101     * @param string $pk
     102     * @return string
     103     * @throws Exception
     104     */
     105    public static function sign_open($message, $pk)
     106    {
     107        $signature = self::substr($message, 0, 64);
     108        $message = self::substr($message, 64);
     109        if (self::verify_detached($signature, $message, $pk)) {
     110            return $message;
     111        }
     112        throw new Exception('Invalid signature');
     113    }
     114
     115    /**
     116     * @param string $message
     117     * @param string $sk
     118     * @return string
     119     */
     120    public static function sign_detached($message, $sk)
     121    {
     122        # crypto_hash_sha512(az, sk, 32);
     123        $az =  hash('sha512', self::substr($sk, 0, 32), true);
     124
     125        # az[0] &= 248;
     126        # az[31] &= 63;
     127        # az[31] |= 64;
     128        $az[0] = self::intToChr(self::chrToInt($az[0]) & 248);
     129        $az[31] = self::intToChr((self::chrToInt($az[31]) & 63) | 64);
     130
     131        # crypto_hash_sha512_init(&hs);
     132        # crypto_hash_sha512_update(&hs, az + 32, 32);
     133        # crypto_hash_sha512_update(&hs, m, mlen);
     134        # crypto_hash_sha512_final(&hs, nonce);
     135        $hs = hash_init('sha512');
     136        hash_update($hs, self::substr($az, 32, 32));
     137        hash_update($hs, $message);
     138        $nonceHash = hash_final($hs, true);
     139
     140        # memmove(sig + 32, sk + 32, 32);
     141        $pk = self::substr($sk, 32, 32);
     142
     143        # sc_reduce(nonce);
     144        # ge_scalarmult_base(&R, nonce);
     145        # ge_p3_tobytes(sig, &R);
     146        $nonce = self::sc_reduce($nonceHash) . self::substr($nonceHash, 32);
     147        $sig = self::ge_p3_tobytes(
     148            self::ge_scalarmult_base($nonce)
     149        );
     150
     151        # crypto_hash_sha512_init(&hs);
     152        # crypto_hash_sha512_update(&hs, sig, 64);
     153        # crypto_hash_sha512_update(&hs, m, mlen);
     154        # crypto_hash_sha512_final(&hs, hram);
     155        $hs = hash_init('sha512');
     156        hash_update($hs, $sig);
     157        hash_update($hs, $pk);
     158        hash_update($hs, $message);
     159        $hramHash = hash_final($hs, true);
     160
     161        # sc_reduce(hram);
     162        # sc_muladd(sig + 32, hram, az, nonce);
     163        $hram = self::sc_reduce($hramHash);
     164        $sigAfter = self::sc_muladd($hram, $az, $nonce);
     165        $sig = self::substr($sig, 0, 32) . self::substr($sigAfter, 0, 32);
     166
     167        ParagonIE_Sodium_Compat::memzero($az);
     168        return $sig;
     169    }
     170
     171    /**
     172     * @param string $sig
     173     * @param string $message
     174     * @param string $pk
     175     * @return bool
     176     * @throws Exception
     177     */
     178    public static function verify_detached($sig, $message, $pk)
     179    {
     180        if (self::strlen($sig) < 64) {
     181            throw new Exception('Signature is too short');
     182        }
     183        if (self::check_S_lt_L(self::substr($sig, 32, 32))) {
     184            throw new Exception('S < L - Invalid signature');
     185        }
     186        if (self::small_order($sig)) {
     187            throw new Exception('Signature is on too small of an order');
     188        }
     189        if ((self::chrToInt($sig[63]) & 224) !== 0) {
     190            throw new Exception('Invalid signature');
     191        }
     192
     193        $A = self::ge_frombytes_negate_vartime($pk);
     194        $d = 0;
     195        for ($i = 0; $i < 32; ++$i) {
     196            $d |= self::chrToInt($pk[$i]);
     197        }
     198        if ($d === 0) {
     199            throw new \Exception('All zero public key');
     200        }
     201
     202        $hDigest = hash('sha512', self::substr($sig, 0, 32) . $pk . $message, true);
     203        $h = self::sc_reduce($hDigest) . self::substr($hDigest, 32);
     204        $R = self::ge_double_scalarmult_vartime(
     205            $h,
     206            $A,
     207            self::substr($sig, 32)
     208        );
     209        $rcheck = self::ge_tobytes($R);
     210        return self::verify_32($rcheck, self::substr($sig, 0, 32));
     211    }
     212
     213    /**
     214     * @param string $S
     215     * @return bool
     216     * @throws Exception
     217     */
     218    public static function check_S_lt_L($S)
     219    {
     220        if (self::strlen($S) < 32) {
     221            throw new Exception('Signature must be 32 bytes');
     222        }
     223        static $L = array(
     224            0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
     225            0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
     226            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     227            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10
     228        );
     229        $c = 0;
     230        $n = 1;
     231        $i = 32;
     232
     233        do {
     234            --$i;
     235            $x = self::chrToInt($S[$i]);
     236            $c |= (
     237                (($x - $L[$i]) >> 8) & $n
     238            );
     239            $n &= (
     240                (($x ^ $L[$i]) - 1) >> 8
     241            );
     242        } while ($i !== 0);
     243
     244        return $c === 0;
     245    }
     246
     247    /**
     248     * @param string $R
     249     * @return bool
     250     */
     251    public static function small_order($R)
     252    {
     253        static $blacklist = array(
     254            /* 0 (order 4) */
     255            array(
     256                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     257                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     258                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     259                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
     260            ),
     261            /* 1 (order 1) */
     262            array(
     263                0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     264                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     265                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     266                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
     267            ),
     268            /* 2707385501144840649318225287225658788936804267575313519463743609750303402022 (order 8) */
     269            array(
     270                0x26, 0xe8, 0x95, 0x8f, 0xc2, 0xb2, 0x27, 0xb0,
     271                0x45, 0xc3, 0xf4, 0x89, 0xf2, 0xef, 0x98, 0xf0,
     272                0xd5, 0xdf, 0xac, 0x05, 0xd3, 0xc6, 0x33, 0x39,
     273                0xb1, 0x38, 0x02, 0x88, 0x6d, 0x53, 0xfc, 0x05
     274            ),
     275            /* 55188659117513257062467267217118295137698188065244968500265048394206261417927 (order 8) */
     276            array(
     277                0xc7, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f,
     278                0xba, 0x3c, 0x0b, 0x76, 0x0d, 0x10, 0x67, 0x0f,
     279                0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39, 0xcc, 0xc6,
     280                0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0x7a
     281            ),
     282            /* p-1 (order 2) */
     283            array(
     284                0x13, 0xe8, 0x95, 0x8f, 0xc2, 0xb2, 0x27, 0xb0,
     285                0x45, 0xc3, 0xf4, 0x89, 0xf2, 0xef, 0x98, 0xf0,
     286                0xd5, 0xdf, 0xac, 0x05, 0xd3, 0xc6, 0x33, 0x39,
     287                0xb1, 0x38, 0x02, 0x88, 0x6d, 0x53, 0xfc, 0x85
     288            ),
     289            /* p (order 4) */
     290            array(
     291                0xb4, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f,
     292                0xba, 0x3c, 0x0b, 0x76, 0x0d, 0x10, 0x67, 0x0f,
     293                0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39, 0xcc, 0xc6,
     294                0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0xfa
     295            ),
     296            /* p+1 (order 1) */
     297            array(
     298                0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     299                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     300                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     301                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f
     302            ),
     303            /* p+2707385501144840649318225287225658788936804267575313519463743609750303402022 (order 8) */
     304            array(
     305                0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     306                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     307                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     308                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f
     309            ),
     310            /* p+55188659117513257062467267217118295137698188065244968500265048394206261417927 (order 8) */
     311            array(
     312                0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     313                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     314                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     315                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f
     316            ),
     317            /* 2p-1 (order 2) */
     318            array(
     319                0xd9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     320                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     321                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     322                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
     323            ),
     324            /* 2p (order 4) */
     325            array(
     326                0xda, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     327                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     328                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     329                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
     330            ),
     331            /* 2p+1 (order 1) */
     332            array(
     333                0xdb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     334                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     335                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     336                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
     337            )
     338        );
     339        $countBlacklist = count($blacklist);
     340
     341        for ($i = 0; $i < $countBlacklist; ++$i) {
     342            $c = 0;
     343            for ($j = 0; $j < 32; ++$j) {
     344                $c |= self::chrToInt($R[$j]) ^ $blacklist[$i][$j];
     345            }
     346            if ($c === 0) {
     347                return true;
     348            }
     349        }
     350        return false;
     351    }
     352}
  • wp-includes/sodium_compat/src/Core/Curve25519/Ge/Precomp.php

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
     
     1<?php
     2
     3/**
     4 * Class ParagonIE_Sodium_Core_Curve25519_Ge_Precomp
     5 */
     6class ParagonIE_Sodium_Core_Curve25519_Ge_Precomp
     7{
     8    /**
     9     * @var ParagonIE_Sodium_Core_Curve25519_Fe
     10     */
     11    public $yplusx;
     12
     13    /**
     14     * @var ParagonIE_Sodium_Core_Curve25519_Fe
     15     */
     16    public $yminusx;
     17
     18    /**
     19     * @var ParagonIE_Sodium_Core_Curve25519_Fe
     20     */
     21    public $xy2d;
     22
     23    /**
     24     * ParagonIE_Sodium_Core_Curve25519_Ge_Precomp constructor.
     25     * @param ParagonIE_Sodium_Core_Curve25519_Fe $yplusx
     26     * @param ParagonIE_Sodium_Core_Curve25519_Fe $yminusx
     27     * @param ParagonIE_Sodium_Core_Curve25519_Fe $xy2d
     28     */
     29    public function __construct(
     30        ParagonIE_Sodium_Core_Curve25519_Fe $yplusx = null,
     31        ParagonIE_Sodium_Core_Curve25519_Fe $yminusx = null,
     32        ParagonIE_Sodium_Core_Curve25519_Fe $xy2d = null
     33    ) {
     34        $this->yplusx = $yplusx;
     35        $this->yminusx = $yminusx;
     36        $this->xy2d = $xy2d;
     37    }
     38
     39}
     40 No newline at end of file
  • wp-includes/sodium_compat/src/Core/SipHash.php

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
     
     1<?php
     2
     3/**
     4 * Class ParagonIE_SodiumCompat_Core_SipHash
     5 */
     6class ParagonIE_Sodium_Core_SipHash extends ParagonIE_Sodium_Core_Util
     7{
     8    /**
     9     * @param int[] $v
     10     * @return int[]
     11     */
     12    public static function sipRound(array $v)
     13    {
     14        # v0 += v1;
     15        list($v[0], $v[1]) = self::add(
     16            array($v[0], $v[1]),
     17            array($v[2], $v[3])
     18        );
     19
     20        #  v1=ROTL(v1,13);
     21        list($v[2], $v[3]) = self::rotl_64($v[2], $v[3], 13);
     22
     23        #  v1 ^= v0;
     24        $v[2] ^= $v[0];
     25        $v[3] ^= $v[1];
     26
     27        #  v0=ROTL(v0,32);
     28        list($v[0], $v[1]) = self::rotl_64($v[0], $v[1], 32);
     29
     30        # v2 += v3;
     31        list($v[4], $v[5]) = self::add(
     32            array($v[4], $v[5]),
     33            array($v[6], $v[7])
     34        );
     35
     36        # v3=ROTL(v3,16);
     37        list($v[6], $v[7]) = self::rotl_64($v[6], $v[7], 16);
     38
     39        #  v3 ^= v2;
     40        $v[6] ^= $v[4];
     41        $v[7] ^= $v[5];
     42
     43        # v0 += v3;
     44        list($v[0], $v[1]) = self::add(
     45            array($v[0], $v[1]),
     46            array($v[6], $v[7])
     47        );
     48
     49        # v3=ROTL(v3,21);
     50        list($v[6], $v[7]) = self::rotl_64($v[6], $v[7], 21);
     51
     52        # v3 ^= v0;
     53        $v[6] ^= $v[0];
     54        $v[7] ^= $v[1];
     55
     56        # v2 += v1;
     57        list($v[4], $v[5]) = self::add(
     58            array($v[4], $v[5]),
     59            array($v[2], $v[3])
     60        );
     61
     62        # v1=ROTL(v1,17);
     63        list($v[2], $v[3]) = self::rotl_64($v[2], $v[3], 17);
     64
     65        #  v1 ^= v2;;
     66        $v[2] ^= $v[4];
     67        $v[3] ^= $v[5];
     68
     69        # v2=ROTL(v2,32)
     70        list($v[4], $v[5]) = self::rotl_64($v[4], $v[5], 32);
     71
     72        return $v;
     73    }
     74
     75    /**
     76     * Add two 32 bit integers representing a 64-bit integer.
     77     *
     78     * @param int[] $a
     79     * @param int[] $b
     80     * @return int[]
     81     */
     82    public static function add(array $a, array $b)
     83    {
     84        $x1 = $a[1] + $b[1];
     85        $c = $x1 >> 32; // Carry if ($a + $b) > 0xffffffff
     86        $x0 = $a[0] + $b[0] + $c;
     87        return array(
     88            $x0 & 0xffffffff,
     89            $x1 & 0xffffffff
     90        );
     91    }
     92
     93    /**
     94     * @param int $int0
     95     * @param int $int1
     96     * @param int $c
     97     * @return int[]
     98     */
     99    public static function rotl_64($int0, $int1, $c)
     100    {
     101        $int0 &= 0xffffffff;
     102        $int1 &= 0xffffffff;
     103        $c &= 63;
     104        if ($c === 32) {
     105            return array($int1, $int0);
     106        }
     107        if ($c > 31) {
     108            $tmp = $int1;
     109            $int1 = $int0;
     110            $int0 = $tmp;
     111            $c &= 31;
     112        }
     113        if ($c === 0) {
     114            return array($int0, $int1);
     115        }
     116        return array(
     117            0xffffffff & (
     118                ($int0 << $c)
     119                    |
     120                ($int1 >> (32 - $c))
     121            ),
     122            0xffffffff & (
     123                ($int1 << $c)
     124                    |
     125                ($int0 >> (32 - $c))
     126            ),
     127        );
     128    }
     129
     130    /**
     131     * Implements Siphash-2-4 using only 32-bit numbers.
     132     *
     133     * When we split an int into two, the higher bits go to the lower index.
     134     * e.g. 0xDEADBEEFAB10C92D becomes [
     135     *     0 => 0xDEADBEEF,
     136     *     1 => 0xAB10C92D
     137     * ].
     138     *
     139     * @param string $in
     140     * @param string $key
     141     * @return string
     142     */
     143    public static function sipHash24($in, $key)
     144    {
     145        $inlen = self::strlen($in);
     146
     147        # /* "somepseudorandomlygeneratedbytes" */
     148        # u64 v0 = 0x736f6d6570736575ULL;
     149        # u64 v1 = 0x646f72616e646f6dULL;
     150        # u64 v2 = 0x6c7967656e657261ULL;
     151        # u64 v3 = 0x7465646279746573ULL;
     152        $v = array(
     153            0x736f6d65, // 0
     154            0x70736575, // 1
     155            0x646f7261, // 2
     156            0x6e646f6d, // 3
     157            0x6c796765, // 4
     158            0x6e657261, // 5
     159            0x74656462, // 6
     160            0x79746573  // 7
     161        );
     162        // v0 => $v[0], $v[1]
     163        // v1 => $v[2], $v[3]
     164        // v2 => $v[4], $v[5]
     165        // v3 => $v[6], $v[7]
     166
     167        # u64 k0 = LOAD64_LE( k );
     168        # u64 k1 = LOAD64_LE( k + 8 );
     169        $k = array(
     170            self::load_4(self::substr($key, 4, 4)),
     171            self::load_4(self::substr($key, 0, 4)),
     172            self::load_4(self::substr($key, 12, 4)),
     173            self::load_4(self::substr($key, 8, 4))
     174        );
     175        // k0 => $k[0], $k[1]
     176        // k1 => $k[2], $k[3]
     177
     178        # b = ( ( u64 )inlen ) << 56;
     179        $b = array(
     180            $inlen << 24,
     181            0
     182        );
     183        // See docblock for why the 0th index gets the higher bits.
     184
     185        # v3 ^= k1;
     186        $v[6] ^= $k[2];
     187        $v[7] ^= $k[3];
     188        # v2 ^= k0;
     189        $v[4] ^= $k[0];
     190        $v[5] ^= $k[1];
     191        # v1 ^= k1;
     192        $v[2] ^= $k[2];
     193        $v[3] ^= $k[3];
     194        # v0 ^= k0;
     195        $v[0] ^= $k[0];
     196        $v[1] ^= $k[1];
     197
     198        $left = $inlen;
     199        # for ( ; in != end; in += 8 )
     200        while ($left >= 8) {
     201            # m = LOAD64_LE( in );
     202            $m = array(
     203                self::load_4(self::substr($in, 4, 4)),
     204                self::load_4(self::substr($in, 0, 4))
     205            );
     206
     207            # v3 ^= m;
     208            $v[6] ^= $m[0];
     209            $v[7] ^= $m[1];
     210
     211            # SIPROUND;
     212            # SIPROUND;
     213            $v = self::sipRound($v);
     214            $v = self::sipRound($v);
     215
     216            # v0 ^= m;
     217            $v[0] ^= $m[0];
     218            $v[1] ^= $m[1];
     219
     220            $in = self::substr($in, 8);
     221            $left -= 8;
     222        }
     223
     224        # switch( left )
     225        #  {
     226        #     case 7: b |= ( ( u64 )in[ 6] )  << 48;
     227        #     case 6: b |= ( ( u64 )in[ 5] )  << 40;
     228        #     case 5: b |= ( ( u64 )in[ 4] )  << 32;
     229        #     case 4: b |= ( ( u64 )in[ 3] )  << 24;
     230        #     case 3: b |= ( ( u64 )in[ 2] )  << 16;
     231        #     case 2: b |= ( ( u64 )in[ 1] )  <<  8;
     232        #     case 1: b |= ( ( u64 )in[ 0] ); break;
     233        #     case 0: break;
     234        # }
     235        switch ($left) {
     236            case 7:
     237                $b[0] |= self::chrToInt($in[6]) << 16;
     238            case 6:
     239                $b[0] |= self::chrToInt($in[5]) << 8;
     240            case 5:
     241                $b[0] |= self::chrToInt($in[4]);
     242            case 4:
     243                $b[1] |= self::chrToInt($in[3]) << 24;
     244            case 3:
     245                $b[1] |= self::chrToInt($in[2]) << 16;
     246            case 2:
     247                $b[1] |= self::chrToInt($in[1]) << 8;
     248            case 1:
     249                $b[1] |= self::chrToInt($in[0]);
     250            case 0:
     251                break;
     252        }
     253        // See docblock for why the 0th index gets the higher bits.
     254
     255        # v3 ^= b;
     256        $v[6] ^= $b[0];
     257        $v[7] ^= $b[1];
     258
     259        # SIPROUND;
     260        # SIPROUND;
     261        $v = self::sipRound($v);
     262        $v = self::sipRound($v);
     263
     264        # v0 ^= b;
     265        $v[0] ^= $b[0];
     266        $v[1] ^= $b[1];
     267
     268        // Flip the lower 8 bits of v2 which is ($v[4], $v[5]) in our implementation
     269        # v2 ^= 0xff;
     270        $v[5] ^= 0xff;
     271
     272        # SIPROUND;
     273        # SIPROUND;
     274        # SIPROUND;
     275        # SIPROUND;
     276        $v = self::sipRound($v);
     277        $v = self::sipRound($v);
     278        $v = self::sipRound($v);
     279        $v = self::sipRound($v);
     280
     281        # b = v0 ^ v1 ^ v2 ^ v3;
     282        # STORE64_LE( out, b );
     283        return  self::store32_le($v[1] ^ $v[3] ^ $v[5] ^ $v[7]) .
     284            self::store32_le($v[0] ^ $v[2] ^ $v[4] ^ $v[6]);
     285    }
     286}
  • wp-includes/compat.php

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
     
    435435        require ABSPATH . WPINC . '/random_compat/random.php';
    436436}
    437437
     438// libsodium - modern cryptography
     439if ( ! extension_loaded( 'libsodium' ) ) {
     440    require ABSPATH . WPINC . '/sodium_compat/autoload.php';
     441}
     442
    438443if ( ! function_exists( 'array_replace_recursive' ) ) :
    439444        /**
    440445         * PHP-agnostic version of {@link array_replace_recursive()}.
  • wp-includes/sodium_compat/src/Crypto.php

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
     
     1<?php
     2
     3/**
     4 * Class ParagonIE_Sodium_Crypto
     5 *
     6 * ATTENTION!
     7 *
     8 * If you are using this library, you should be using
     9 * ParagonIE_Sodium_Compat in your code, not this class.
     10 */
     11abstract class ParagonIE_Sodium_Crypto
     12{
     13    const box_curve25519xsalsa20poly1305_SEEDBYTES = 32;
     14    const box_curve25519xsalsa20poly1305_PUBLICKEYBYTES = 32;
     15    const box_curve25519xsalsa20poly1305_SECRETKEYBYTES = 32;
     16    const box_curve25519xsalsa20poly1305_BEFORENMBYTES = 32;
     17    const box_curve25519xsalsa20poly1305_NONCEBYTES = 24;
     18    const box_curve25519xsalsa20poly1305_MACBYTES = 16;
     19    const box_curve25519xsalsa20poly1305_BOXZEROBYTES = 16;
     20    const box_curve25519xsalsa20poly1305_ZEROBYTES = 32;
     21
     22    const onetimeauth_poly1305_BYTES = 16;
     23    const onetimeauth_poly1305_KEYBYTES = 32;
     24
     25    const secretbox_xsalsa20poly1305_KEYBYTES = 32;
     26    const secretbox_xsalsa20poly1305_NONCEBYTES = 24;
     27    const secretbox_xsalsa20poly1305_MACBYTES = 16;
     28    const secretbox_xsalsa20poly1305_BOXZEROBYTES = 16;
     29    const secretbox_xsalsa20poly1305_ZEROBYTES = 32;
     30
     31    const stream_salsa20_KEYBYTES = 32;
     32
     33    /**
     34     * HMAC-SHA-512-256 (a.k.a. the leftmost 256 bits of HMAC-SHA-512)
     35     *
     36     * @param string $message
     37     * @param string $key
     38     * @return string
     39     */
     40    public static function auth($message, $key)
     41    {
     42        return ParagonIE_Sodium_Core_Util::substr(
     43            hash_hmac('sha512', $message, $key, true),
     44            0,
     45            32
     46        );
     47    }
     48
     49    /**
     50     * HMAC-SHA-512-256 validation. Constant-time via hash_equals().
     51     *
     52     * @param string $mac
     53     * @param string $message
     54     * @param string $key
     55     * @return bool
     56     */
     57    public static function auth_verify($mac, $message, $key)
     58    {
     59        return hash_equals(
     60            $mac,
     61            self::auth($message, $key)
     62        );
     63    }
     64
     65    /**
     66     * X25519 key exchange followed by Xsalsa20Poly1305 symmetric encryption
     67     *
     68     * @param string $plaintext
     69     * @param string $nonce
     70     * @param string $keypair
     71     * @return string
     72     */
     73    public static function box($plaintext, $nonce, $keypair)
     74    {
     75        $k = self::box_beforenm(
     76            self::box_secretkey($keypair),
     77            self::box_publickey($keypair)
     78        );
     79        $c = self::secretbox($plaintext, $nonce, $k);
     80        ParagonIE_Sodium_Compat::memzero($k);
     81        return $c;
     82    }
     83
     84    /**
     85     * X25519-Xsalsa20-Poly1305 with one ephemeral X25519 keypair.
     86     *
     87     * @param string $message
     88     * @param string $publicKey
     89     * @return string
     90     */
     91    public static function box_seal($message, $publicKey)
     92    {
     93        $ephemeralKeypair = self::box_keypair();
     94        $ephemeralSK = self::box_secretkey($ephemeralKeypair);
     95        $ephemeralPK = self::box_publickey($ephemeralKeypair);
     96
     97        $nonce = self::generichash(
     98            $ephemeralPK . $publicKey,
     99            '',
     100            24
     101        );
     102        $keypair = self::box_keypair_from_secretkey_and_publickey($ephemeralSK, $publicKey);
     103
     104        $c = self::box($message, $nonce, $keypair);
     105        ParagonIE_Sodium_Compat::memzero($ephemeralSK);
     106        ParagonIE_Sodium_Compat::memzero($nonce);
     107        return $ephemeralPK . $c;
     108    }
     109
     110    /**
     111     * Opens a message encrypted via box_seal().
     112     *
     113     * @param string $message
     114     * @param string $keypair
     115     * @return string
     116     */
     117    public static function box_seal_open($message, $keypair)
     118    {
     119        $ephemeralPK = ParagonIE_Sodium_Core_Util::substr($message, 0, 32);
     120        $c = ParagonIE_Sodium_Core_Util::substr($message, 32);
     121
     122        $secretKey = self::box_secretkey($keypair);
     123        $publicKey = self::box_publickey($keypair);
     124
     125        $nonce = self::generichash(
     126            $ephemeralPK . $publicKey,
     127            '',
     128            24
     129        );
     130        $keypair = self::box_keypair_from_secretkey_and_publickey($secretKey, $ephemeralPK);
     131        $m = self::box_open($c, $nonce, $keypair);
     132        ParagonIE_Sodium_Compat::memzero($secretKey);
     133        ParagonIE_Sodium_Compat::memzero($ephemeralPK);
     134        ParagonIE_Sodium_Compat::memzero($nonce);
     135        return $m;
     136    }
     137
     138    /**
     139     * Used by crypto_box() to get the crypto_secretbox() key.
     140     *
     141     * @param string $sk
     142     * @param string $pk
     143     * @return string
     144     */
     145    public static function box_beforenm($sk, $pk)
     146    {
     147        $s = self::scalarmult($sk, $pk);
     148        return ParagonIE_Sodium_Core_HSalsa20::hsalsa20(
     149            str_repeat("\x00", 16),
     150            $s
     151        );
     152    }
     153
     154    /**
     155     * @return string
     156     */
     157    public static function box_keypair()
     158    {
     159        $sk = random_bytes(32);
     160        $pk = self::scalarmult_base($sk);
     161        return $sk . $pk;
     162    }
     163
     164    /**
     165     * @param string $sk
     166     * @param string $pk
     167     * @return string
     168     */
     169    public static function box_keypair_from_secretkey_and_publickey($sk, $pk)
     170    {
     171        return ParagonIE_Sodium_Core_Util::substr($sk, 0, 32) .
     172            ParagonIE_Sodium_Core_Util::substr($pk, 0, 32);
     173    }
     174
     175    /**
     176     * @param string $keypair
     177     * @return string
     178     */
     179    public static function box_secretkey($keypair)
     180    {
     181        if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== 64) {
     182            throw new RangeException('Must be a keypair.');
     183        }
     184        return ParagonIE_Sodium_Core_Util::substr($keypair, 0, 32);
     185    }
     186
     187    /**
     188     * @param string $keypair
     189     * @return string
     190     */
     191    public static function box_publickey($keypair)
     192    {
     193        if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== 64) {
     194            throw new RangeException('Must be a keypair.');
     195        }
     196        return ParagonIE_Sodium_Core_Util::substr($keypair, 32, 32);
     197    }
     198
     199    /**
     200     * @param $sk
     201     * @return string
     202     * @throws RangeException
     203     */
     204    public static function box_publickey_from_secretkey($sk)
     205    {
     206        if (ParagonIE_Sodium_Core_Util::strlen($sk) !== 32) {
     207            throw new RangeException('Must be 32 bytes long.');
     208        }
     209        return self::scalarmult_base($sk);
     210    }
     211
     212    /**
     213     * Decrypt a message encrypted with box().
     214     *
     215     * @param string $ciphertext
     216     * @param string $nonce
     217     * @param string $nonce
     218     * @param string $keypair
     219     * @return string
     220     */
     221    public static function box_open($ciphertext, $nonce, $keypair)
     222    {
     223        $k = self::box_beforenm(
     224            self::box_secretkey($keypair),
     225            self::box_publickey($keypair)
     226        );
     227        $p = self::secretbox_open($ciphertext, $nonce, $k);
     228        ParagonIE_Sodium_Compat::memzero($k);
     229        return $p;
     230    }
     231
     232    /**
     233     * Calculate a BLAKE2b hash.
     234     *
     235     * @param string $message
     236     * @param string|null $key
     237     * @param int $outlen
     238     * @return string
     239     * @throws Exception
     240     */
     241    public static function generichash($message, $key = '', $outlen = 32)
     242    {
     243        ParagonIE_Sodium_Core_BLAKE2b::pseudoConstructor();
     244
     245        $k = null;
     246        if (!empty($key)) {
     247            $k = ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($key);
     248            if ($k->count() > ParagonIE_Sodium_Core_BLAKE2b::KEYBYTES) {
     249                throw new Exception('Invalid key size');
     250            }
     251        }
     252
     253        $in = ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($message);
     254        $ctx = ParagonIE_Sodium_Core_BLAKE2b::init($k, $outlen);
     255        ParagonIE_Sodium_Core_BLAKE2b::update($ctx, $in, $in->count());
     256        $out = new SplFixedArray($outlen);
     257        $out = ParagonIE_Sodium_Core_BLAKE2b::finish($ctx, $out);
     258        return ParagonIE_Sodium_Core_Util::intArrayToString($out->toArray());
     259    }
     260
     261    /**
     262     * Finalize a BLAKE2b hashing context, returning the hash.
     263     *
     264     * @param string $ctx
     265     * @param int $outlen
     266     * @return string
     267     */
     268    public static function generichash_final($ctx, $outlen = 32)
     269    {
     270        if (!is_string($ctx)) {
     271            throw new InvalidArgumentException('Context must be a string');
     272        }
     273        $out = new SplFixedArray($outlen);
     274        $context = ParagonIE_Sodium_Core_BLAKE2b::stringToContext($ctx);
     275        $out = ParagonIE_Sodium_Core_BLAKE2b::finish($context, $out);
     276        return ParagonIE_Sodium_Core_Util::intArrayToString($out->toArray());
     277    }
     278
     279    /**
     280     * Initialize a hashing context for BLAKE2b.
     281     *
     282     * @param string $key
     283     * @param int $outputLength
     284     * @return string
     285     * @throws Exception
     286     */
     287    public static function generichash_init($key = '', $outputLength = 32)
     288    {
     289        ParagonIE_Sodium_Core_BLAKE2b::pseudoConstructor();
     290
     291        $k = null;
     292        if (!empty($key)) {
     293            $k = ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($key);
     294            if ($k->count() > ParagonIE_Sodium_Core_BLAKE2b::KEYBYTES) {
     295                throw new Exception('Invalid key size');
     296            }
     297        }
     298
     299        $ctx = ParagonIE_Sodium_Core_BLAKE2b::init($k, $outputLength);
     300        return ParagonIE_Sodium_Core_BLAKE2b::contextToString($ctx);
     301    }
     302
     303    /**
     304     * Update a hashing context for BLAKE2b with $message
     305     *
     306     * @param string $ctx
     307     * @param string $message
     308     * @return string
     309     */
     310    public static function generichash_update($ctx, $message)
     311    {
     312        ParagonIE_Sodium_Core_BLAKE2b::pseudoConstructor();
     313        $in = ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($message);
     314        $context = ParagonIE_Sodium_Core_BLAKE2b::stringToContext($ctx);
     315        ParagonIE_Sodium_Core_BLAKE2b::update($context, $in, $in->count());
     316        return ParagonIE_Sodium_Core_BLAKE2b::contextToString($context);
     317    }
     318
     319    /**
     320     * Libsodium's crypto_kx().
     321     *
     322     * @param string $my_sk
     323     * @param string $their_pk
     324     * @param string $client_pk
     325     * @param string $server_pk
     326     * @return string
     327     */
     328    public static function kx($my_sk, $their_pk, $client_pk, $server_pk)
     329    {
     330        return self::generichash(
     331            self::scalarmult($my_sk, $their_pk) .
     332            $client_pk .
     333            $server_pk
     334        );
     335    }
     336
     337    /**
     338     * ECDH over Curve25519
     339     *
     340     * @param string $sk
     341     * @param string $pk
     342     * @return string
     343     */
     344    public static function scalarmult($sk, $pk)
     345    {
     346        return ParagonIE_Sodium_Core_X25519::crypto_scalarmult_curve25519_ref10($sk, $pk);
     347    }
     348
     349    /**
     350     * ECDH over Curve25519, using the basepoint.
     351     * Used to get a secret key from a public key.
     352     *
     353     * @param string $n
     354     * @return string
     355     */
     356    public static function scalarmult_base($n)
     357    {
     358        return ParagonIE_Sodium_Core_X25519::crypto_scalarmult_curve25519_ref10_base($n);
     359    }
     360
     361    /**
     362     * Xsalsa20-Poly1305 authenticated symmetric-key encryption.
     363     *
     364     * @param string $plaintext
     365     * @param string $nonce
     366     * @param string $key
     367     * @return string
     368     */
     369    public static function secretbox($plaintext, $nonce, $key)
     370    {
     371        $subkey = ParagonIE_Sodium_Core_HSalsa20::hsalsa20($nonce, $key);
     372
     373        $block0 = str_repeat("\x00", 32);
     374        $mlen = ParagonIE_Sodium_Core_Util::strlen($plaintext);
     375        $mlen0 = $mlen;
     376        if ($mlen0 > 64 - self::secretbox_xsalsa20poly1305_ZEROBYTES) {
     377            $mlen0 = 64 - self::secretbox_xsalsa20poly1305_ZEROBYTES;
     378        }
     379        $block0 .= ParagonIE_Sodium_Core_Util::substr($plaintext, 0, $mlen0);
     380        $block0 = ParagonIE_Sodium_Core_Salsa20::salsa20_xor(
     381            $block0,
     382            ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8),
     383            $subkey
     384        );
     385        $state = new ParagonIE_Sodium_Core_Poly1305_State(
     386            ParagonIE_Sodium_Core_Util::substr(
     387                $block0,
     388                0,
     389                self::onetimeauth_poly1305_KEYBYTES
     390            )
     391        );
     392
     393        $c = ParagonIE_Sodium_Core_Util::substr(
     394            $block0,
     395            self::secretbox_xsalsa20poly1305_ZEROBYTES
     396        );
     397        if ($mlen > $mlen0) {
     398            $c .= ParagonIE_Sodium_Core_Salsa20::salsa20_xor_ic(
     399                ParagonIE_Sodium_Core_Util::substr(
     400                    $plaintext,
     401                    self::secretbox_xsalsa20poly1305_ZEROBYTES
     402                ),
     403                ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8),
     404                1,
     405                $subkey
     406            );
     407        }
     408        ParagonIE_Sodium_Compat::memzero($block0);
     409        ParagonIE_Sodium_Compat::memzero($subkey);
     410
     411        $state->update($c);
     412        $c = $state->finish() . $c;
     413        unset($state);
     414
     415        return $c;
     416    }
     417
     418    /**
     419     * Decrypt a ciphertext generated via secretbox().
     420     *
     421     * @param string $ciphertext
     422     * @param string $nonce
     423     * @param string $key
     424     * @return string
     425     * @throws Exception
     426     */
     427    public static function secretbox_open($ciphertext, $nonce, $key)
     428    {
     429        $mac = ParagonIE_Sodium_Core_Util::substr(
     430            $ciphertext,
     431            0,
     432            self::box_curve25519xsalsa20poly1305_MACBYTES
     433        );
     434        $c = ParagonIE_Sodium_Core_Util::substr(
     435            $ciphertext,
     436            self::box_curve25519xsalsa20poly1305_MACBYTES
     437        );
     438        $clen = ParagonIE_Sodium_Core_Util::strlen($c);
     439
     440        $subkey = ParagonIE_Sodium_Core_HSalsa20::hsalsa20($nonce, $key);
     441        $block0 = ParagonIE_Sodium_Core_Salsa20::salsa20(
     442            64,
     443            ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8),
     444            $subkey
     445        );
     446        if (!ParagonIE_Sodium_Core_Poly1305::onetimeauth_verify($mac, $c, $block0)) {
     447            ParagonIE_Sodium_Compat::memzero($subkey);
     448            throw new Exception('Invalid MAC');
     449        }
     450
     451        $m = ParagonIE_Sodium_Core_Util::xorStrings(
     452            ParagonIE_Sodium_Core_Util::substr($block0, self::secretbox_xsalsa20poly1305_ZEROBYTES),
     453            ParagonIE_Sodium_Core_Util::substr($c, 0, self::secretbox_xsalsa20poly1305_ZEROBYTES)
     454        );
     455        if ($clen > self::secretbox_xsalsa20poly1305_ZEROBYTES) {
     456            $m .= ParagonIE_Sodium_Core_Salsa20::salsa20_xor_ic(
     457                ParagonIE_Sodium_Core_Util::substr(
     458                    $c,
     459                    self::secretbox_xsalsa20poly1305_ZEROBYTES
     460                ),
     461                ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8),
     462                1,
     463                $subkey
     464            );
     465        }
     466        return $m;
     467    }
     468
     469    /**
     470     * Detached Ed25519 signature.
     471     *
     472     * @param string $message
     473     * @param string $sk
     474     * @return string
     475     */
     476    public static function sign_detached($message, $sk)
     477    {
     478        return ParagonIE_Sodium_Core_Ed25519::sign_detached($message, $sk);
     479    }
     480
     481    /**
     482     * Attached Ed25519 signature. (Returns a signed message.)
     483     *
     484     * @param string $message
     485     * @param string $sk
     486     * @return string
     487     */
     488    public static function sign($message, $sk)
     489    {
     490        return ParagonIE_Sodium_Core_Ed25519::sign($message, $sk);
     491    }
     492
     493    /**
     494     * Opens a signed message. If valid, returns the message.
     495     *
     496     * @param string $signedMessage
     497     * @param string $pk
     498     * @return string
     499     */
     500    public static function sign_open($signedMessage, $pk)
     501    {
     502        return ParagonIE_Sodium_Core_Ed25519::sign_open($signedMessage, $pk);
     503    }
     504
     505    /**
     506     * Verify a detached signature of a given message and public key.
     507     *
     508     * @param string $signature
     509     * @param string $message
     510     * @param string $pk
     511     * @return bool
     512     */
     513    public static function sign_verify_detached($signature, $message, $pk)
     514    {
     515        return ParagonIE_Sodium_Core_Ed25519::verify_detached($signature, $message, $pk);
     516    }
     517}
  • wp-includes/sodium_compat/src/Compat.php

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
     
     1<?php
     2
     3/**
     4 * Libsodium compatibility layer
     5 */
     6class ParagonIE_Sodium_Compat
     7{
     8    /**
     9     * @var bool
     10     */
     11    public static $disableFallbackForUnitTests = false;
     12
     13    const LIBRARY_VERSION_MAJOR = 9;
     14    const LIBRARY_VERSION_MINOR = 1;
     15    const VERSION_STRING = 'polyfill-1.0.8';
     16
     17    // From libsodium
     18    const CRYPTO_AUTH_BYTES = 32;
     19    const CRYPTO_AUTH_KEYBYTES = 32;
     20    const CRYPTO_BOX_SEALBYTES = 16;
     21    const CRYPTO_BOX_SECRETKEYBYTES = 32;
     22    const CRYPTO_BOX_PUBLICKEYBYTES = 32;
     23    const CRYPTO_BOX_KEYPAIRBYTES = 64;
     24    const CRYPTO_BOX_MACBYTES = 16;
     25    const CRYPTO_BOX_NONCEBYTES = 24;
     26    const CRYPTO_BOX_SEEDBYTES = 32;
     27    const CRYPTO_KX_BYTES = 32;
     28    const CRYPTO_KX_PUBLICKEYBYTES = 32;
     29    const CRYPTO_KX_SECRETKEYBYTES = 32;
     30    const CRYPTO_GENERICHASH_BYTES = 32;
     31    const CRYPTO_GENERICHASH_BYTES_MIN = 16;
     32    const CRYPTO_GENERICHASH_BYTES_MAX = 64;
     33    const CRYPTO_GENERICHASH_KEYBYTES = 32;
     34    const CRYPTO_GENERICHASH_KEYBYTES_MIN = 16;
     35    const CRYPTO_GENERICHASH_KEYBYTES_MAX = 64;
     36    const CRYPTO_SCALARMULT_BYTES = 32;
     37    const CRYPTO_SCALARMULT_SCALARBYTES = 32;
     38    const CRYPTO_SHORTHASH_BYTES = 8;
     39    const CRYPTO_SHORTHASH_KEYBYTES = 16;
     40    const CRYPTO_SECRETBOX_KEYBYTES = 32;
     41    const CRYPTO_SECRETBOX_MACBYTES = 16;
     42    const CRYPTO_SECRETBOX_NONCEBYTES = 24;
     43    const CRYPTO_SIGN_BYTES = 64;
     44    const CRYPTO_SIGN_SEEDBYTES = 32;
     45    const CRYPTO_SIGN_PUBLICKEYBYTES = 32;
     46    const CRYPTO_SIGN_SECRETKEYBYTES = 64;
     47    const CRYPTO_SIGN_KEYPAIRBYTES = 96;
     48    const CRYPTO_STREAM_KEYBYTES = 32;
     49    const CRYPTO_STREAM_NONCEBYTES = 24;
     50
     51    /**
     52     * Cache-timing-safe implementation of bin2hex().
     53     *
     54     * @param $string
     55     * @return string
     56     * @throws TypeError
     57     */
     58    public static function bin2hex($string)
     59    {
     60        if (!is_string($string)) {
     61            throw new TypeError('Argument 1 must be a string');
     62        }
     63        if (self::use_fallback('bin2hex')) {
     64            return call_user_func_array(
     65                '\\Sodium\\bin2hex',
     66                array($string)
     67            );
     68        }
     69        return ParagonIE_Sodium_Core_Util::bin2hex($string);
     70    }
     71
     72    /**
     73     * Compare two strings, in constant-time.
     74     *
     75     * @param string $left
     76     * @param string $right
     77     * @return int
     78     * @throws TypeError
     79     */
     80    public static function compare($left, $right)
     81    {
     82        if (!is_string($left)) {
     83            throw new TypeError('Argument 1 must be a string');
     84        }
     85        if (!is_string($right)) {
     86            throw new TypeError('Argument 2 must be a string');
     87        }
     88        if (self::use_fallback('compare')) {
     89            return call_user_func_array(
     90                '\\Sodium\\compare',
     91                array($left, $right)
     92            );
     93        }
     94        return ParagonIE_Sodium_Core_Util::compare($left, $right);
     95    }
     96
     97    /**
     98     * Authenticate a message. Uses symmetric-key cryptography.
     99     *
     100     * Algorithm:
     101     *     HMAC-SHA512-256. Which is HMAC-SHA-512 truncated to 256 bits.
     102     *     Not to be confused with HMAC-SHA-512/256 which would use the
     103     *     SHA-512/256 hash function (uses different initial parameters
     104     *     but still truncates to 256 bits to sidestep length-extension
     105     *     attacks.
     106     *
     107     * @param string $message
     108     * @param string $key
     109     * @return string
     110     * @throws Error
     111     * @throws TypeError
     112     */
     113    public static function crypto_auth($message, $key)
     114    {
     115        if (!is_string($message)) {
     116            throw new TypeError('Argument 1 must be a string');
     117        }
     118        if (!is_string($key)) {
     119            throw new TypeError('Argument 2 must be a string');
     120        }
     121        if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_AUTH_KEYBYTES) {
     122            throw new Error('Argument 2 must be CRYPTO_AUTH_KEYBYTES long.');
     123        }
     124        if (self::use_fallback('crypto_auth')) {
     125            return call_user_func_array(
     126                '\\Sodium\\crypto_auth',
     127                array($message, $key)
     128            );
     129        }
     130        return ParagonIE_Sodium_Crypto::auth($message, $key);
     131    }
     132
     133    /**
     134     * Verify the MAC of a message previously authenticated with crypto_auth.
     135     *
     136     * @param string $mac
     137     * @param string $message
     138     * @param string $key
     139     * @return bool
     140     * @throws Error
     141     * @throws TypeError
     142     */
     143    public static function crypto_auth_verify($mac, $message, $key)
     144    {
     145        if (!is_string($message)) {
     146            throw new TypeError('Argument 2 must be a string');
     147        }
     148        if (!is_string($key)) {
     149            throw new TypeError('Argument 3 must be a string');
     150        }
     151        if (ParagonIE_Sodium_Core_Util::strlen($mac) !== self::CRYPTO_AUTH_BYTES) {
     152            throw new Error('Argument 1 must be CRYPTO_AUTH_BYTES long.');
     153        }
     154        if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_AUTH_KEYBYTES) {
     155            throw new Error('Argument 3 must be CRYPTO_AUTH_KEYBYTES long.');
     156        }
     157        if (self::use_fallback('crypto_auth_verify')) {
     158            return call_user_func_array(
     159                '\\Sodium\\crypto_auth_verify',
     160                array($mac, $message, $key)
     161            );
     162        }
     163        return ParagonIE_Sodium_Crypto::auth_verify($mac, $message, $key);
     164    }
     165
     166    /**
     167     * Authenticated asymmetric-key encryption. Both the sender and recipient
     168     * may decrypt messages.
     169     *
     170     * Algorithm: X25519-Xsalsa20-Poly1305.
     171     *     X25519: Elliptic-Curve Diffie Hellman over Curve25519.
     172     *     Xsalsa20: Extended-nonce variant of salsa20.
     173     *     Poyl1305: Polynomial MAC for one-time message authentication.
     174     *
     175     * @param string $plaintext
     176     * @param string $nonce
     177     * @param string $keypair
     178     * @return string
     179     * @throws Error
     180     * @throws TypeError
     181     */
     182    public static function crypto_box($plaintext, $nonce, $keypair)
     183    {
     184        if (!is_string($plaintext)) {
     185            throw new TypeError('Argument 1 must be a string');
     186        }
     187        if (!is_string($nonce)) {
     188            throw new TypeError('Argument 2 must be a string');
     189        }
     190        if (!is_string($keypair)) {
     191            throw new TypeError('Argument 3 must be a string');
     192        }
     193        if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_BOX_NONCEBYTES) {
     194            throw new Error('Argument 2 must be CRYPTO_BOX_NONCEBYTES long.');
     195        }
     196        if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== self::CRYPTO_BOX_KEYPAIRBYTES) {
     197            throw new Error('Argument 3 must be CRYPTO_BOX_KEYPAIRBYTES long.');
     198        }
     199        if (self::use_fallback('crypto_box')) {
     200            return call_user_func_array(
     201                '\\Sodium\\crypto_box',
     202                array($plaintext, $nonce, $keypair)
     203            );
     204        }
     205        return ParagonIE_Sodium_Crypto::box($plaintext, $nonce, $keypair);
     206    }
     207
     208    /**
     209     * Anonymous public-key encryption. Only the recipient may decrypt messages.
     210     *
     211     * Algorithm: X25519-Xsalsa20-Poly1305, as with crypto_box.
     212     *     The sender's X25519 keypair is ephemeral.
     213     *     Nonce is generated from the BLAKE2b hash of both public keys.
     214     *
     215     * This provides ciphertext integrity.
     216     *
     217     * @param string $plaintext
     218     * @param string $publicKey
     219     * @return string
     220     * @throws Error
     221     * @throws TypeError
     222     */
     223    public static function crypto_box_seal($plaintext, $publicKey)
     224    {
     225        if (!is_string($plaintext)) {
     226            throw new TypeError('Argument 1 must be a string');
     227        }
     228        if (!is_string($publicKey)) {
     229            throw new TypeError('Argument 2 must be a string');
     230        }
     231        if (ParagonIE_Sodium_Core_Util::strlen($publicKey) !== self::CRYPTO_BOX_PUBLICKEYBYTES) {
     232            throw new Error('Argument 2 must be CRYPTO_BOX_PUBLICKEYBYTES long.');
     233        }
     234        if (self::use_fallback('crypto_box_seal')) {
     235            return call_user_func_array(
     236                '\\Sodium\\crypto_box_seal',
     237                array($plaintext, $publicKey)
     238            );
     239        }
     240        return ParagonIE_Sodium_Crypto::box_seal($plaintext, $publicKey);
     241    }
     242
     243    /**
     244     * Opens a message encrypted with crypto_box_seal(). Requires
     245     * the recipient's keypair (sk || pk) to decrypt successfully.
     246     *
     247     * This validates ciphertext integrity.
     248     *
     249     * @param string $ciphertext
     250     * @param string $keypair
     251     * @return string
     252     * @throws Error
     253     * @throws TypeError
     254     */
     255    public static function crypto_box_seal_open($ciphertext, $keypair)
     256    {
     257        if (!is_string($ciphertext)) {
     258            throw new TypeError('Argument 1 must be a string');
     259        }
     260        if (!is_string($keypair)) {
     261            throw new TypeError('Argument 2 must be a string');
     262        }
     263        if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== self::CRYPTO_BOX_KEYPAIRBYTES) {
     264            throw new Error('Argument 2 must be CRYPTO_BOX_KEYPAIRBYTES long.');
     265        }
     266        if (self::use_fallback('crypto_box_seal_open')) {
     267            return call_user_func_array(
     268                '\\Sodium\\crypto_box_seal_open',
     269                array($ciphertext, $keypair)
     270            );
     271        }
     272        return ParagonIE_Sodium_Crypto::box_seal_open($ciphertext, $keypair);
     273    }
     274
     275    /**
     276     * Generate a new random X25519 keypair.
     277     *
     278     * @return string
     279     */
     280    public static function crypto_box_keypair()
     281    {
     282        if (self::use_fallback('crypto_sign_keypair')) {
     283            return call_user_func(
     284                '\\Sodium\\crypto_box_keypair'
     285            );
     286        }
     287        return ParagonIE_Sodium_Crypto::box_keypair();
     288    }
     289
     290    /**
     291     * Combine two keys into a keypair for use in library methods that expect
     292     * a keypair. This doesn't necessarily have to be the same person's keys.
     293     *
     294     * @param string $sk Secret key
     295     * @param string $pk Public key
     296     * @return string
     297     * @throws Error
     298     * @throws TypeError
     299     */
     300    public static function crypto_box_keypair_from_secretkey_and_publickey($sk, $pk)
     301    {
     302        if (!is_string($sk)) {
     303            throw new TypeError('Argument 1 must be a string');
     304        }
     305        if (ParagonIE_Sodium_Core_Util::strlen($sk) !== self::CRYPTO_BOX_SECRETKEYBYTES) {
     306            throw new Error('Argument 1 must be CRYPTO_BOX_SECRETKEYBYTES long.');
     307        }
     308        if (!is_string($pk)) {
     309            throw new TypeError('Argument 2 must be a string');
     310        }
     311        if (ParagonIE_Sodium_Core_Util::strlen($pk) !== self::CRYPTO_BOX_PUBLICKEYBYTES) {
     312            throw new Error('Argument 2 must be CRYPTO_BOX_PUBLICKEYBYTES long.');
     313        }
     314        if (self::use_fallback('box_keypair_from_secretkey_and_publickey')) {
     315            return call_user_func_array(
     316                '\\Sodium\\box_keypair_from_secretkey_and_publickey',
     317                array($sk, $pk)
     318            );
     319        }
     320        return ParagonIE_Sodium_Crypto::box_keypair_from_secretkey_and_publickey($sk, $pk);
     321    }
     322
     323    /**
     324     * Extract the public key from a crypto_box keypair.
     325     *
     326     * @param string $keypair
     327     * @return string
     328     * @throws Error
     329     * @throws TypeError
     330     */
     331    public static function crypto_box_publickey($keypair)
     332    {
     333        if (!is_string($keypair)) {
     334            throw new TypeError('Argument 1 must be a string');
     335        }
     336        if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== self::CRYPTO_BOX_KEYPAIRBYTES) {
     337            throw new Error('Argument 1 must be CRYPTO_BOX_KEYPAIRBYTES long.');
     338        }
     339        if (self::use_fallback('crypto_box_publickey')) {
     340            return call_user_func_array(
     341                '\\Sodium\\crypto_box_publickey',
     342                array($keypair)
     343            );
     344        }
     345        return ParagonIE_Sodium_Crypto::box_publickey($keypair);
     346    }
     347
     348    /**
     349     * Calculate the X25519 public key from a given X25519 secret key.
     350     *
     351     * @param string $sk
     352     * @return string
     353     * @throws Error
     354     * @throws TypeError
     355     */
     356    public static function crypto_box_publickey_from_secretkey($sk)
     357    {
     358        if (!is_string($sk)) {
     359            throw new TypeError('Argument 1 must be a string');
     360        }
     361        if (ParagonIE_Sodium_Core_Util::strlen($sk) !== self::CRYPTO_BOX_SECRETKEYBYTES) {
     362            throw new Error('Argument 1 must be CRYPTO_BOX_SECRETKEYBYTES long.');
     363        }
     364        if (self::use_fallback('crypto_box_publickey_from_secretkey')) {
     365            return call_user_func_array(
     366                '\\Sodium\\crypto_box_publickey_from_secretkey',
     367                array($sk)
     368            );
     369        }
     370        return ParagonIE_Sodium_Crypto::box_publickey_from_secretkey($sk);
     371    }
     372
     373    /**
     374     * Extract the secret key from a crypto_box keypair.
     375     *
     376     * @param string $keypair
     377     * @return string
     378     * @throws Error
     379     * @throws TypeError
     380     */
     381    public static function crypto_box_secretkey($keypair)
     382    {
     383        if (!is_string($keypair)) {
     384            throw new TypeError('Argument 1 must be a string');
     385        }
     386        if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== self::CRYPTO_BOX_KEYPAIRBYTES) {
     387            throw new Error('Argument 1 must be CRYPTO_BOX_KEYPAIRBYTES long.');
     388        }
     389        if (self::use_fallback('crypto_box_secretkey')) {
     390            return call_user_func_array(
     391                '\\Sodium\\crypto_box_secretkey',
     392                array($keypair)
     393            );
     394        }
     395        return ParagonIE_Sodium_Crypto::box_secretkey($keypair);
     396    }
     397
     398    /**
     399     * Decrypt a message previously encrypted with crypto_box().
     400     *
     401     * @param string $ciphertext
     402     * @param string $nonce
     403     * @param string $keypair
     404     * @return string
     405     * @throws Error
     406     * @throws TypeError
     407     */
     408    public static function crypto_box_open($ciphertext, $nonce, $keypair)
     409    {
     410        if (!is_string($ciphertext)) {
     411            throw new TypeError('Argument 1 must be a string');
     412        }
     413        if (!is_string($nonce)) {
     414            throw new TypeError('Argument 2 must be a string');
     415        }
     416        if (!is_string($keypair)) {
     417            throw new TypeError('Argument 3 must be a string');
     418        }
     419        if (ParagonIE_Sodium_Core_Util::strlen($ciphertext) < self::CRYPTO_BOX_MACBYTES) {
     420            throw new Error('Argument 1 must be at least CRYPTO_BOX_MACBYTES long.');
     421        }
     422        if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_BOX_NONCEBYTES) {
     423            throw new Error('Argument 2 must be CRYPTO_BOX_NONCEBYTES long.');
     424        }
     425        if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== self::CRYPTO_BOX_KEYPAIRBYTES) {
     426            throw new Error('Argument 3 must be CRYPTO_BOX_KEYPAIRBYTES long.');
     427        }
     428        if (self::use_fallback('crypto_box_open')) {
     429            return call_user_func_array(
     430                '\\Sodium\\crypto_box_open',
     431                array($ciphertext, $nonce, $keypair)
     432            );
     433        }
     434        return ParagonIE_Sodium_Crypto::box_open($ciphertext, $nonce, $keypair);
     435    }
     436
     437    /**
     438     * Calculates a BLAKE2b hash, with an optional key.
     439     *
     440     * @param string $message
     441     * @param string $key
     442     * @param int $length
     443     * @return string
     444     * @throws Error
     445     * @throws TypeError
     446     */
     447    public static function crypto_generichash($message, $key = '', $length = 32)
     448    {
     449        if (!is_string($message)) {
     450            throw new TypeError('Argument 1 must be a string');
     451        }
     452        if (!is_string($key)) {
     453            throw new TypeError('Argument 2 must be a string');
     454        }
     455        if (!is_int($length)) {
     456            if (is_numeric($length)) {
     457                $length = (int) $length;
     458            } else {
     459                throw new TypeError('Argument 3 must be an integer');
     460            }
     461        }
     462        if (!empty($key)) {
     463            if (ParagonIE_Sodium_Core_Util::strlen($key) < self::CRYPTO_GENERICHASH_KEYBYTES_MIN) {
     464                throw new Error('Unsupported key size. Must be at least CRYPTO_GENERICHASH_KEYBYTES_MIN bytes long.');
     465            }
     466            if (ParagonIE_Sodium_Core_Util::strlen($key) > self::CRYPTO_GENERICHASH_KEYBYTES_MAX) {
     467                throw new Error('Unsupported key size. Must be at most CRYPTO_GENERICHASH_KEYBYTES_MAX bytes long.');
     468            }
     469        }
     470        if (self::use_fallback('crypto_generichash')) {
     471            return call_user_func_array(
     472                '\\Sodium\\crypto_generichash',
     473                array($message, $key, $length)
     474            );
     475        }
     476        return ParagonIE_Sodium_Crypto::generichash($message, $key, $length);
     477    }
     478
     479    /**
     480     * Get the final BLAKE2b hash output for a given context.
     481     *
     482     * @param string& $ctx
     483     * @param int $length
     484     * @return string
     485     * @throws Error
     486     * @throws TypeError
     487     */
     488    public static function crypto_generichash_final(&$ctx, $length = 32)
     489    {
     490        if (!is_string($ctx)) {
     491            throw new TypeError('Argument 1 must be a string');
     492        }
     493        if (!is_int($length)) {
     494            if (is_numeric($length)) {
     495                $length = (int) $length;
     496            } else {
     497                throw new TypeError('Argument 2 must be an integer');
     498            }
     499        }
     500        if (self::use_fallback('crypto_generichash_final')) {
     501            $func = '\\Sodium\\crypto_generichash_final';
     502            return $func($ctx, $length);
     503        }
     504        $result = ParagonIE_Sodium_Crypto::generichash_final($ctx, $length);
     505        self::memzero($ctx);
     506        return $result;
     507    }
     508
     509    /**
     510     * Initialize a BLAKE2b hashing context, for use in a streaming interface.
     511     *
     512     * @param string $key
     513     * @param int $length
     514     * @return string
     515     * @throws Error
     516     * @throws TypeError
     517     */
     518    public static function crypto_generichash_init($key = '', $length = 32)
     519    {
     520        if (!is_string($key)) {
     521            throw new TypeError('Argument 1 must be a string');
     522        }
     523        if (!is_int($length)) {
     524            if (is_numeric($length)) {
     525                $length = (int) $length;
     526            } else {
     527                throw new TypeError('Argument 2 must be an integer');
     528            }
     529        }
     530        if (!empty($key)) {
     531            if (ParagonIE_Sodium_Core_Util::strlen($key) < self::CRYPTO_GENERICHASH_KEYBYTES_MIN) {
     532                throw new Error('Unsupported key size. Must be at least CRYPTO_GENERICHASH_KEYBYTES_MIN bytes long.');
     533            }
     534            if (ParagonIE_Sodium_Core_Util::strlen($key) > self::CRYPTO_GENERICHASH_KEYBYTES_MAX) {
     535                throw new Error('Unsupported key size. Must be at most CRYPTO_GENERICHASH_KEYBYTES_MAX bytes long.');
     536            }
     537        }
     538        if (self::use_fallback('crypto_generichash_init')) {
     539            return call_user_func_array(
     540                '\\Sodium\\crypto_generichash_init',
     541                array($key, $length)
     542            );
     543        }
     544        return ParagonIE_Sodium_Crypto::generichash_init($key, $length);
     545    }
     546
     547    /**
     548     * Update a BLAKE2b hashing context with additional data.
     549     *
     550     * @param string& $ctx
     551     * @param string $message
     552     * @return void
     553     * @throws TypeError
     554     */
     555    public static function crypto_generichash_update(&$ctx, $message)
     556    {
     557        if (!is_string($ctx)) {
     558            throw new TypeError('Argument 1 must be a string');
     559        }
     560        if (!is_string($message)) {
     561            throw new TypeError('Argument 2 must be a string');
     562        }
     563        if (self::use_fallback('crypto_generichash_update')) {
     564            $func = '\\Sodium\\crypto_generichash_update';
     565            $func($ctx, $message);
     566            return;
     567        }
     568        $ctx = ParagonIE_Sodium_Crypto::generichash_update($ctx, $message);
     569    }
     570
     571    /**
     572     * Perform a key exchange, between a designated client and a server.
     573     *
     574     * @param string $my_secret
     575     * @param string $their_public
     576     * @param string $client_public
     577     * @param string $server_public
     578     * @return string
     579     * @throws Error
     580     * @throws TypeError
     581     */
     582    public static function crypto_kx($my_secret, $their_public, $client_public, $server_public)
     583    {
     584        if (!is_string($my_secret)) {
     585            throw new TypeError('Argument 1 must be a string');
     586        }
     587        if (ParagonIE_Sodium_Core_Util::strlen($my_secret) !== self::CRYPTO_BOX_SECRETKEYBYTES) {
     588            throw new Error('Argument 1 must be CRYPTO_BOX_SECRETKEYBYTES long.');
     589        }
     590        if (!is_string($their_public)) {
     591            throw new TypeError('Argument 2 must be a string');
     592        }
     593        if (ParagonIE_Sodium_Core_Util::strlen($their_public) !== self::CRYPTO_BOX_PUBLICKEYBYTES) {
     594            throw new Error('Argument 2 must be CRYPTO_BOX_PUBLICKEYBYTES long.');
     595        }
     596        if (!is_string($client_public)) {
     597            throw new TypeError('Argument 3 must be a string');
     598        }
     599        if (ParagonIE_Sodium_Core_Util::strlen($client_public) !== self::CRYPTO_BOX_PUBLICKEYBYTES) {
     600            throw new Error('Argument 3 must be CRYPTO_BOX_PUBLICKEYBYTES long.');
     601        }
     602        if (!is_string($server_public)) {
     603            throw new TypeError('Argument 4 must be a string');
     604        }
     605        if (ParagonIE_Sodium_Core_Util::strlen($server_public) !== self::CRYPTO_BOX_PUBLICKEYBYTES) {
     606            throw new Error('Argument 4 must be CRYPTO_BOX_PUBLICKEYBYTES long.');
     607        }
     608        if (self::use_fallback('crypto_kx')) {
     609            return call_user_func_array(
     610                '\\Sodium\\crypto_kx',
     611                func_get_args()
     612            );
     613        }
     614        return ParagonIE_Sodium_Crypto::kx(
     615            $my_secret,
     616            $their_public,
     617            $client_public,
     618            $server_public
     619        );
     620    }
     621
     622    /**
     623     * Calculate the shared secret between your secret key and your
     624     * recipient's public key.
     625     *
     626     * Algorithm: X25519 (ECDH over Curve25519)
     627     *
     628     * @param string $sk
     629     * @param string $pk
     630     * @return string
     631     * @throws Error
     632     * @throws TypeError
     633     */
     634    public static function crypto_scalarmult($sk, $pk)
     635    {
     636        if (!is_string($sk)) {
     637            throw new TypeError('Argument 1 must be a string');
     638        }
     639        if (ParagonIE_Sodium_Core_Util::strlen($sk) !== self::CRYPTO_BOX_SECRETKEYBYTES) {
     640            throw new Error('Argument 1 must be CRYPTO_BOX_SECRETKEYBYTES long.');
     641        }
     642        if (!is_string($pk)) {
     643            throw new TypeError('Argument 2 must be a string');
     644        }
     645        if (ParagonIE_Sodium_Core_Util::strlen($pk) !== self::CRYPTO_BOX_PUBLICKEYBYTES) {
     646            throw new Error('Argument 2 must be CRYPTO_BOX_PUBLICKEYBYTES long.');
     647        }
     648        if (self::use_fallback('crypto_scalarmult')) {
     649            return call_user_func_array(
     650                '\\Sodium\\crypto_scalarmult',
     651                array($sk, $pk)
     652            );
     653        }
     654        return ParagonIE_Sodium_Crypto::scalarmult($sk, $pk);
     655    }
     656
     657    /**
     658     * Calculate an X25519 public key from an X25519 secret key.
     659     *
     660     * @param $sk
     661     * @return string
     662     * @throws Error
     663     * @throws TypeError
     664     */
     665    public static function crypto_scalarmult_base($sk)
     666    {
     667        if (!is_string($sk)) {
     668            throw new TypeError('Argument 1 must be a string');
     669        }
     670        if (ParagonIE_Sodium_Core_Util::strlen($sk) !== self::CRYPTO_BOX_SECRETKEYBYTES) {
     671            throw new Error('Argument 1 must be CRYPTO_BOX_SECRETKEYBYTES long.');
     672        }
     673        if (self::use_fallback('crypto_scalarmult_base')) {
     674            return call_user_func_array(
     675                '\\Sodium\\crypto_scalarmult_base',
     676                array($sk)
     677            );
     678        }
     679        return ParagonIE_Sodium_Crypto::scalarmult_base($sk);
     680    }
     681
     682    /**
     683     * Authenticated symmetric-key encryption.
     684     *
     685     * Algorithm: Xsalsa20-Poly1305
     686     *
     687     * @param string $plaintext
     688     * @param string $nonce
     689     * @param string $key
     690     * @return string
     691     * @throws Error
     692     * @throws TypeError
     693     */
     694    public static function crypto_secretbox($plaintext, $nonce, $key)
     695    {
     696        if (!is_string($plaintext)) {
     697            throw new TypeError('Argument 1 must be a string');
     698        }
     699        if (!is_string($nonce)) {
     700            throw new TypeError('Argument 2 must be a string');
     701        }
     702        if (!is_string($key)) {
     703            throw new TypeError('Argument 3 must be a string');
     704        }
     705        if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_SECRETBOX_NONCEBYTES) {
     706            throw new Error('Argument 2 must be CRYPTO_SECRETBOX_NONCEBYTES long.');
     707        }
     708        if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_SECRETBOX_KEYBYTES) {
     709            throw new Error('Argument 3 must be CRYPTO_SECRETBOX_KEYBYTES long.');
     710        }
     711        if (self::use_fallback('crypto_secretbox')) {
     712            return call_user_func_array(
     713                '\\Sodium\\crypto_secretbox',
     714                array($plaintext, $nonce, $key)
     715            );
     716        }
     717        return ParagonIE_Sodium_Crypto::secretbox($plaintext, $nonce, $key);
     718    }
     719
     720    /**
     721     * Decrypts a message previously encrypted with crypto_secretbox().
     722     *
     723     * @param string $ciphertext
     724     * @param string $nonce
     725     * @param string $key
     726     * @return string
     727     * @throws Error
     728     * @throws TypeError
     729     */
     730    public static function crypto_secretbox_open($ciphertext, $nonce, $key)
     731    {
     732        if (!is_string($ciphertext)) {
     733            throw new TypeError('Argument 1 must be a string');
     734        }
     735        if (!is_string($nonce)) {
     736            throw new TypeError('Argument 2 must be a string');
     737        }
     738        if (!is_string($key)) {
     739            throw new TypeError('Argument 3 must be a string');
     740        }
     741        if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_SECRETBOX_NONCEBYTES) {
     742            throw new Error('Argument 2 must be CRYPTO_SECRETBOX_NONCEBYTES long.');
     743        }
     744        if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_SECRETBOX_KEYBYTES) {
     745            throw new Error('Argument 3 must be CRYPTO_SECRETBOX_KEYBYTES long.');
     746        }
     747        if (self::use_fallback('crypto_secretbox_open')) {
     748            return call_user_func_array(
     749                '\\Sodium\\crypto_secretbox_open',
     750                array($ciphertext, $nonce, $key)
     751            );
     752        }
     753        return ParagonIE_Sodium_Crypto::secretbox_open($ciphertext, $nonce, $key);
     754    }
     755
     756    /**
     757     * Calculates a SipHash-2-4 hash of a message for a given key.
     758     *
     759     * @param string $message
     760     * @param string $key
     761     * @return string
     762     * @throws Error
     763     * @throws TypeError
     764     */
     765    public static function crypto_shorthash($message, $key)
     766    {
     767        if (!is_string($message)) {
     768            throw new TypeError('Argument 1 must be a string');
     769        }
     770        if (!is_string($key)) {
     771            throw new TypeError('Argument 2 must be a string');
     772        }
     773        if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_SHORTHASH_KEYBYTES) {
     774            throw new Error('Argument 2 must be CRYPTO_SHORTHASH_KEYBYTES long.');
     775        }
     776        if (self::use_fallback('crypto_shorthash')) {
     777            return call_user_func_array(
     778                '\\Sodium\\crypto_shorthash',
     779                array($message, $key)
     780            );
     781        }
     782        return ParagonIE_Sodium_Core_SipHash::sipHash24($message, $key);
     783    }
     784
     785    /**
     786     * Expand a key and nonce into a keystream of pseudorandom bytes.
     787     *
     788     * @param int $len
     789     * @param string $nonce
     790     * @param string $key
     791     * @return string
     792     * @throws Error
     793     * @throws TypeError
     794     */
     795    public static function crypto_stream($len, $nonce, $key)
     796    {
     797        if (!is_int($len)) {
     798            if (is_numeric($len)) {
     799                $len = (int) $len;
     800            } else {
     801                throw new TypeError('Argument 1 must be an integer');
     802            }
     803        }
     804        if (!is_string($nonce)) {
     805            throw new TypeError('Argument 2 must be a string');
     806        }
     807        if (!is_string($key)) {
     808            throw new TypeError('Argument 3 must be a string');
     809        }
     810        if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_STREAM_NONCEBYTES) {
     811            throw new Error('Argument 2 must be CRYPTO_SECRETBOX_NONCEBYTES long.');
     812        }
     813        if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_STREAM_KEYBYTES) {
     814            throw new Error('Argument 3 must be CRYPTO_STREAM_KEYBYTES long.');
     815        }
     816        if (self::use_fallback('crypto_stream')) {
     817            return call_user_func_array(
     818                '\\Sodium\\crypto_stream',
     819                array($len, $nonce, $key)
     820            );
     821        }
     822        return ParagonIE_Sodium_Core_Xsalsa20::xsalsa20($len, $nonce, $key);
     823    }
     824
     825    /**
     826     * DANGER! UNAUTHENTICATED ENCRYPTION!
     827     *
     828     * Unless you are following expert advice, do not used this feature.
     829     *
     830     * Algorithm: Xsalsa20
     831     *
     832     * This DOES NOT provide ciphertext integrity.
     833     *
     834     * @param string $message
     835     * @param string $nonce
     836     * @param string $key
     837     * @return string
     838     * @throws Error
     839     * @throws TypeError
     840     */
     841    public static function crypto_stream_xor($message, $nonce, $key)
     842    {
     843        if (!is_string($message)) {
     844            throw new TypeError('Argument 1 must be a string');
     845        }
     846        if (!is_string($nonce)) {
     847            throw new TypeError('Argument 2 must be a string');
     848        }
     849        if (!is_string($key)) {
     850            throw new TypeError('Argument 3 must be a string');
     851        }
     852        if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_STREAM_NONCEBYTES) {
     853            throw new Error('Argument 2 must be CRYPTO_SECRETBOX_NONCEBYTES long.');
     854        }
     855        if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_STREAM_KEYBYTES) {
     856            throw new Error('Argument 3 must be CRYPTO_SECRETBOX_KEYBYTES long.');
     857        }
     858        if (self::use_fallback('crypto_stream_xor')) {
     859            return call_user_func_array(
     860                '\\Sodium\\crypto_stream_xor',
     861                array($message, $nonce, $key)
     862            );
     863        }
     864        return ParagonIE_Sodium_Core_Xsalsa20::xsalsa20_xor($message, $nonce, $key);
     865    }
     866
     867    /**
     868     * Returns a signed message. You probably want crypto_sign_detached()
     869     * instead, which only returns the signature.
     870     *
     871     * Algorithm: Ed25519 (EdDSA over Curve25519)
     872     *
     873     * @param string $message
     874     * @param string $sk
     875     * @return string
     876     * @throws Error
     877     * @throws TypeError
     878     */
     879    public static function crypto_sign($message, $sk)
     880    {
     881        if (!is_string($message)) {
     882            throw new TypeError('Argument 1 must be a string');
     883        }
     884        if (!is_string($sk)) {
     885            throw new TypeError('Argument 2 must be a string');
     886        }
     887        if (ParagonIE_Sodium_Core_Util::strlen($sk) !== self::CRYPTO_SIGN_SECRETKEYBYTES) {
     888            throw new Error('Argument 2 must be CRYPTO_SIGN_SECRETKEYBYTES long.');
     889        }
     890        if (self::use_fallback('crypto_sign')) {
     891            return call_user_func_array(
     892                '\\Sodium\\crypto_sign',
     893                array($message, $sk)
     894            );
     895        }
     896        return ParagonIE_Sodium_Crypto::sign($message, $sk);
     897    }
     898
     899    /**
     900     * Validates a signed message then returns the message.
     901     *
     902     * @param string $sm
     903     * @param string $pk
     904     * @return string
     905     * @throws Error
     906     * @throws TypeError
     907     */
     908    public static function crypto_sign_open($sm, $pk)
     909    {
     910        if (!is_string($sm)) {
     911            throw new TypeError('Argument 1 must be a string');
     912        }
     913        if (!is_string($pk)) {
     914            throw new TypeError('Argument 2 must be a string');
     915        }
     916        if (ParagonIE_Sodium_Core_Util::strlen($pk) !== self::CRYPTO_SIGN_PUBLICKEYBYTES) {
     917            throw new Error('Argument 2 must be CRYPTO_SIGN_PUBLICKEYBYTES long.');
     918        }
     919        if (self::use_fallback('crypto_sign_open')) {
     920            return call_user_func_array(
     921                '\\Sodium\\crypto_sign_open',
     922                array($sm, $pk)
     923            );
     924        }
     925        return ParagonIE_Sodium_Crypto::sign_open($sm, $pk);
     926    }
     927
     928    /**
     929     * Generate a new random Ed25519 keypair.
     930     *
     931     * @return string
     932     */
     933    public static function crypto_sign_keypair()
     934    {
     935        if (self::use_fallback('crypto_sign_keypair')) {
     936            return call_user_func(
     937                '\\Sodium\\crypto_sign_keypair'
     938            );
     939        }
     940        return ParagonIE_Sodium_Core_Ed25519::keypair();
     941    }
     942
     943    /**
     944     * Generate an Ed25519 keypair from a seed.
     945     *
     946     * @return string
     947     */
     948    public static function crypto_sign_seed_keypair($seed)
     949    {
     950        if (self::use_fallback('crypto_sign_keypair')) {
     951            return call_user_func_array(
     952                '\\Sodium\\crypto_sign_seed_keypair',
     953                array($seed)
     954            );
     955        }
     956        $pk = '';
     957        $sk = '';
     958        ParagonIE_Sodium_Core_Ed25519::seed_keypair($pk, $sk, $seed);
     959        return $sk . $pk;
     960    }
     961
     962    /**
     963     * Extract an Ed25519 public key from an Ed25519 keypair.
     964     *
     965     * @param string $keypair
     966     * @return string
     967     * @throws Error
     968     * @throws TypeError
     969     */
     970    public static function crypto_sign_publickey($keypair)
     971    {
     972        if (!is_string($keypair)) {
     973            throw new TypeError('Argument 1 must be a string');
     974        }
     975        if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== self::CRYPTO_SIGN_KEYPAIRBYTES) {
     976            throw new Error('Argument 1 must be CRYPTO_SIGN_KEYPAIRBYTES long.');
     977        }
     978        if (self::use_fallback('crypto_sign_publickey')) {
     979            return call_user_func_array(
     980                '\\Sodium\\crypto_sign_publickey',
     981                array($keypair)
     982            );
     983        }
     984        return ParagonIE_Sodium_Core_Ed25519::publickey($keypair);
     985    }
     986    /**
     987     * Calculate an Ed25519 public key from an Ed25519 secret key.
     988     *
     989     * @param string $sk
     990     * @return string
     991     * @throws Error
     992     * @throws TypeError
     993     */
     994    public static function crypto_sign_publickey_from_secretkey($sk)
     995    {
     996        if (!is_string($sk)) {
     997            throw new TypeError('Argument 1 must be a string');
     998        }
     999        if (ParagonIE_Sodium_Core_Util::strlen($sk) !== self::CRYPTO_SIGN_SECRETKEYBYTES) {
     1000            throw new Error('Argument 1 must be CRYPTO_SIGN_SECRETKEYBYTES long.');
     1001        }
     1002        if (self::use_fallback('crypto_sign_publickey_from_publickey')) {
     1003            return call_user_func_array(
     1004                '\\Sodium\\crypto_sign_publickey_from_publickey',
     1005                array($sk)
     1006            );
     1007        }
     1008        return ParagonIE_Sodium_Core_Ed25519::publickey_from_secretkey($sk);
     1009    }
     1010
     1011    /**
     1012     * Extract an Ed25519 secret key from an Ed25519 keypair.
     1013     *
     1014     * @param string $keypair
     1015     * @return string
     1016     * @throws Error
     1017     * @throws TypeError
     1018     */
     1019    public static function crypto_sign_secretkey($keypair)
     1020    {
     1021        if (!is_string($keypair)) {
     1022            throw new TypeError('Argument 1 must be a string');
     1023        }
     1024        if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== self::CRYPTO_SIGN_KEYPAIRBYTES) {
     1025            throw new Error('Argument 1 must be CRYPTO_SIGN_KEYPAIRBYTES long.');
     1026        }
     1027        if (self::use_fallback('crypto_sign_secretkey')) {
     1028            return call_user_func_array(
     1029                '\\Sodium\\crypto_sign_secretkey',
     1030                array($keypair)
     1031            );
     1032        }
     1033        return ParagonIE_Sodium_Core_Ed25519::secretkey($keypair);
     1034    }
     1035
     1036    /**
     1037     * Calculate the Ed25519 signature of a message and return ONLY the signature.
     1038     *
     1039     * Algorithm: Ed25519 (EdDSA over Curve25519)
     1040     *
     1041     * @param string $message
     1042     * @param string $sk
     1043     * @return string
     1044     * @throws Error
     1045     * @throws TypeError
     1046     */
     1047    public static function crypto_sign_detached($message, $sk)
     1048    {
     1049        if (!is_string($message)) {
     1050            throw new TypeError('Argument 1 must be a string');
     1051        }
     1052        if (!is_string($sk)) {
     1053            throw new TypeError('Argument 2 must be a string');
     1054        }
     1055        if (ParagonIE_Sodium_Core_Util::strlen($sk) !== self::CRYPTO_SIGN_SECRETKEYBYTES) {
     1056            throw new Error('Argument 2 must be CRYPTO_SIGN_SECRETKEYBYTES long.');
     1057        }
     1058        if (self::use_fallback('crypto_sign_detached')) {
     1059            return call_user_func_array(
     1060                '\\Sodium\\crypto_sign_detached',
     1061                array($message, $sk)
     1062            );
     1063        }
     1064        return ParagonIE_Sodium_Crypto::sign_detached($message, $sk);
     1065    }
     1066
     1067    /**
     1068     * Verify the signature of a message.
     1069     *
     1070     * @param string $signature
     1071     * @param string $message
     1072     * @param string $pk
     1073     * @return bool
     1074     * @throws Error
     1075     * @throws TypeError
     1076     */
     1077    public static function crypto_sign_verify_detached($signature, $message, $pk)
     1078    {
     1079        if (!is_string($signature)) {
     1080            throw new TypeError('Argument 1 must be a string');
     1081        }
     1082        if (!is_string($message)) {
     1083            throw new TypeError('Argument 2 must be a string');
     1084        }
     1085        if (!is_string($pk)) {
     1086            throw new TypeError('Argument 3 must be a string');
     1087        }
     1088        if (ParagonIE_Sodium_Core_Util::strlen($signature) !== self::CRYPTO_SIGN_BYTES) {
     1089            throw new Error('Argument 1 must be CRYPTO_SIGN_BYTES long.');
     1090        }
     1091        if (ParagonIE_Sodium_Core_Util::strlen($pk) !== self::CRYPTO_SIGN_PUBLICKEYBYTES) {
     1092            throw new Error('Argument 3 must be CRYPTO_SIGN_PUBLICKEYBYTES long.');
     1093        }
     1094        if (self::use_fallback('crypto_sign_verify_detached')) {
     1095            return call_user_func_array(
     1096                '\\Sodium\\crypto_sign_verify_detached',
     1097                array($signature, $message, $pk)
     1098            );
     1099        }
     1100        return ParagonIE_Sodium_Crypto::sign_verify_detached($signature, $message, $pk);
     1101    }
     1102
     1103    /**
     1104     * Cache-timing-safe implementation of hex2bin().
     1105     *
     1106     * @param $string
     1107     * @return string
     1108     * @throws TypeError
     1109     */
     1110    public static function hex2bin($string)
     1111    {
     1112        if (!is_string($string)) {
     1113            throw new TypeError('Argument 1 must be a string');
     1114        }
     1115        if (self::use_fallback('hex2bin')) {
     1116            return call_user_func_array(
     1117                '\\Sodium\\hex2bin',
     1118                array($string)
     1119            );
     1120        }
     1121        return ParagonIE_Sodium_Core_Util::hex2bin($string);
     1122    }
     1123
     1124    /**
     1125     * @return int
     1126     */
     1127    public static function library_version_major()
     1128    {
     1129        if (self::use_fallback('hex2bin')) {
     1130            return (int) call_user_func('\\Sodium\\library_version_minor');
     1131        }
     1132        return self::LIBRARY_VERSION_MAJOR;
     1133    }
     1134
     1135    /**
     1136     * @return int
     1137     */
     1138    public static function library_version_minor()
     1139    {
     1140        if (self::use_fallback('library_version_minor')) {
     1141            return (int) call_user_func('\\Sodium\\library_version_minor');
     1142        }
     1143        return self::LIBRARY_VERSION_MINOR;
     1144    }
     1145
     1146    /**
     1147     * Compare two strings.
     1148     *
     1149     * @param string $left
     1150     * @param string $right
     1151     * @return int
     1152     * @throws TypeError
     1153     */
     1154    public static function memcmp($left, $right)
     1155    {
     1156        if (!is_string($left)) {
     1157            throw new TypeError('Argument 1 must be a string');
     1158        }
     1159        if (!is_string($right)) {
     1160            throw new TypeError('Argument 1 must be a string');
     1161        }
     1162        if (self::use_fallback('memcmp')) {
     1163            return call_user_func_array(
     1164                '\\Sodium\\memcmp',
     1165                array($left, $right)
     1166            );
     1167        }
     1168        return ParagonIE_Sodium_Core_Util::memcmp($left, $right);
     1169    }
     1170
     1171    /**
     1172     * This is a NOP in the userland implementation. It's actually not possible
     1173     * to zero memory buffers in PHP. You need the native library for that.
     1174     *
     1175     * @param &string $var
     1176     * @throws TypeError
     1177     */
     1178    public static function memzero(&$var)
     1179    {
     1180        if (!is_string($var)) {
     1181            throw new TypeError('Argument 1 must be a string');
     1182        }
     1183        if (self::use_fallback('memzero')) {
     1184            call_user_func_array(
     1185                '\\Sodium\\memzero',
     1186                array(&$var)
     1187            );
     1188            return;
     1189        }
     1190        // This is the best we can do.
     1191        unset($var);
     1192    }
     1193
     1194    /**
     1195     * Generate a string of bytes from the kernel's CSPRNG.
     1196     * Proudly uses /dev/urandom (if getrandom(2) is not available).
     1197     *
     1198     * @param int $numBytes
     1199     * @return string
     1200     * @throws TypeError
     1201     */
     1202    public static function randombytes_buf($numBytes)
     1203    {
     1204        if (!is_int($numBytes)) {
     1205            if (is_numeric($numBytes)) {
     1206                $numBytes = (int) $numBytes;
     1207            } else {
     1208                throw new TypeError('Argument 1 must be an integer');
     1209            }
     1210        }
     1211        if (self::use_fallback('randombytes_buf')) {
     1212            return call_user_func_array(
     1213                '\\Sodium\\randombytes_buf',
     1214                array($numBytes)
     1215            );
     1216        }
     1217        return random_bytes($numBytes);
     1218    }
     1219
     1220    /**
     1221     * Generate an integer between 0 and $range (non-inclusive).
     1222     *
     1223     * @param int $range
     1224     * @return int
     1225     * @throws TypeError
     1226     */
     1227    public static function randombytes_uniform($range)
     1228    {
     1229        if (!is_int($range)) {
     1230            if (is_numeric($range)) {
     1231                $range = (int) $range;
     1232            } else {
     1233                throw new TypeError('Argument 1 must be an integer');
     1234            }
     1235        }
     1236        if (self::use_fallback('randombytes_uniform')) {
     1237            return (int) call_user_func_array(
     1238                '\\Sodium\\randombytes_uniform',
     1239                array($range)
     1240            );
     1241        }
     1242        return random_int(0, $range - 1);
     1243    }
     1244
     1245    /**
     1246     * Generate a random 16-bit integer.
     1247     *
     1248     * @return int
     1249     */
     1250    public static function randombytes_random16()
     1251    {
     1252        if (self::use_fallback('randombytes_random16')) {
     1253            return (int) call_user_func('\\Sodium\\randombytes_random16');
     1254        }
     1255        return random_int(0, 65535);
     1256    }
     1257
     1258    /**
     1259     * @return string
     1260     */
     1261    public static function version_string()
     1262    {
     1263        if (self::use_fallback('version_string')) {
     1264            return (int) call_user_func('\\Sodium\\version_string');
     1265        }
     1266        return self::VERSION_STRING;
     1267    }
     1268
     1269    /**
     1270     * Should we use the libsodium core function instead?
     1271     *
     1272     * @param string $sodium_func_name
     1273     * @return bool
     1274     */
     1275    protected static function use_fallback($sodium_func_name = '')
     1276    {
     1277        static $res = null;
     1278        if ($res === null) {
     1279            $res = extension_loaded('libsodium') && PHP_VERSION_ID >= 50300;
     1280        }
     1281        if ($res === false) {
     1282            // No libsodium installed
     1283            return false;
     1284        }
     1285        if (self::$disableFallbackForUnitTests) {
     1286            // Don't fallback. Use the PHP implementation.
     1287            return false;
     1288        }
     1289        if (!empty($sodium_func_name)) {
     1290            return is_callable('\\Sodium\\' . $sodium_func_name);
     1291        }
     1292        return true;
     1293    }
     1294}
  • wp-includes/sodium_compat/src/Core/Curve25519/Ge/Cached.php

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
     
     1<?php
     2
     3/**
     4 * Class ParagonIE_Sodium_Core_Curve25519_Ge_Cached
     5 */
     6class ParagonIE_Sodium_Core_Curve25519_Ge_Cached
     7{
     8    /**
     9     * @var ParagonIE_Sodium_Core_Curve25519_Fe
     10     */
     11    public $YplusX;
     12
     13    /**
     14     * @var ParagonIE_Sodium_Core_Curve25519_Fe
     15     */
     16    public $YminusX;
     17
     18    /**
     19     * @var ParagonIE_Sodium_Core_Curve25519_Fe
     20     */
     21    public $Z;
     22
     23    /**
     24     * @var ParagonIE_Sodium_Core_Curve25519_Fe
     25     */
     26    public $T2d;
     27
     28    /**
     29     * ParagonIE_Sodium_Core_Curve25519_Ge_Cached constructor.
     30     * @param ParagonIE_Sodium_Core_Curve25519_Fe|null $YplusX
     31     * @param ParagonIE_Sodium_Core_Curve25519_Fe|null $YminusX
     32     * @param ParagonIE_Sodium_Core_Curve25519_Fe|null $Z
     33     * @param ParagonIE_Sodium_Core_Curve25519_Fe|null $T2d
     34     */
     35    public function __construct(
     36        ParagonIE_Sodium_Core_Curve25519_Fe $YplusX = null,
     37        ParagonIE_Sodium_Core_Curve25519_Fe $YminusX = null,
     38        ParagonIE_Sodium_Core_Curve25519_Fe $Z = null,
     39        ParagonIE_Sodium_Core_Curve25519_Fe $T2d = null
     40    ) {
     41        $this->YplusX = $YplusX;
     42        $this->YminusX = $YminusX;
     43        $this->Z = $Z;
     44        $this->T2d = $T2d;
     45    }
     46}
     47 No newline at end of file
  • wp-includes/sodium_compat/lib/sodium_compat.php

    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
     
     1<?php
     2namespace Sodium;
     3
     4use ParagonIE_Sodium_Compat;
     5
     6/**
     7 * This file will monkey patch the pure-PHP implementation in place of the
     8 * PECL functions, but only if they do not already exist.
     9 *
     10 * Thus, the functions just proxy to the appropriate ParagonIE_Sodium_Compat
     11 * method.
     12 */
     13if (!is_callable('\\Sodium\\bin2hex')) {
     14    /**
     15     * @param $string
     16     * @return string
     17     */
     18    function bin2hex($string)
     19    {
     20        return ParagonIE_Sodium_Compat::bin2hex($string);
     21    }
     22}
     23if (!is_callable('\\Sodium\\compare')) {
     24    /**
     25     * @param string $a
     26     * @param string $b
     27     * @return int
     28     */
     29    function compare($a, $b)
     30    {
     31        return ParagonIE_Sodium_Compat::compare($a, $b);
     32    }
     33}
     34if (!is_callable('\\Sodium\\crypto_auth')) {
     35    /**
     36     * @param string $message
     37     * @param string $key
     38     * @return string
     39     */
     40    function crypto_auth($message, $key)
     41    {
     42        return ParagonIE_Sodium_Compat::crypto_auth($message, $key);
     43    }
     44}
     45if (!is_callable('\\Sodium\\crypto_auth_verify')) {
     46    /**
     47     * @param string $mac
     48     * @param string $message
     49     * @param string $key
     50     * @return bool
     51     */
     52    function crypto_auth_verify($mac, $message, $key)
     53    {
     54        return ParagonIE_Sodium_Compat::crypto_auth_verify($mac, $message, $key);
     55    }
     56}
     57if (!is_callable('\\Sodium\\crypto_box')) {
     58    /**
     59     * @param string $message
     60     * @param string $nonce
     61     * @param string $kp
     62     * @return string
     63     */
     64    function crypto_box($message, $nonce, $kp)
     65    {
     66        return ParagonIE_Sodium_Compat::crypto_box($message, $nonce, $kp);
     67    }
     68}
     69if (!is_callable('\\Sodium\\crypto_box_keypair')) {
     70    /**
     71     * @return string
     72     */
     73    function crypto_box_keypair()
     74    {
     75        return ParagonIE_Sodium_Compat::crypto_box_keypair();
     76    }
     77}
     78if (!is_callable('\\Sodium\\crypto_box_keypair_from_secretkey_and_publickey')) {
     79    /**
     80     * @param string $sk
     81     * @param string $pk
     82     * @return string
     83     */
     84    function crypto_box_keypair_from_secretkey_and_publickey($sk, $pk)
     85    {
     86        return ParagonIE_Sodium_Compat::crypto_box_keypair_from_secretkey_and_publickey($sk, $pk);
     87    }
     88}
     89if (!is_callable('\\Sodium\\crypto_box_open')) {
     90    /**
     91     * @param string $message
     92     * @param string $nonce
     93     * @param string $kp
     94     * @return string
     95     */
     96    function crypto_box_open($message, $nonce, $kp)
     97    {
     98        return ParagonIE_Sodium_Compat::crypto_box_open($message, $nonce, $kp);
     99    }
     100}
     101if (!is_callable('\\Sodium\\crypto_box_publickey')) {
     102    /**
     103     * @param string $keypair
     104     * @return string
     105     */
     106    function crypto_box_publickey($keypair)
     107    {
     108        return ParagonIE_Sodium_Compat::crypto_box_publickey($keypair);
     109    }
     110}
     111if (!is_callable('\\Sodium\\crypto_box_publickey_from_secretkey')) {
     112    /**
     113     * @param string $sk
     114     * @return string
     115     */
     116    function crypto_box_publickey_from_secretkey($sk)
     117    {
     118        return ParagonIE_Sodium_Compat::crypto_box_publickey_from_secretkey($sk);
     119    }
     120}
     121if (!is_callable('\\Sodium\\crypto_box_seal')) {
     122    /**
     123     * @param string $message
     124     * @param string $publicKey
     125     * @return string
     126     */
     127    function crypto_box_seal($message, $publicKey)
     128    {
     129        return ParagonIE_Sodium_Compat::crypto_box_seal($message, $publicKey);
     130    }
     131}
     132if (!is_callable('\\Sodium\\crypto_box_seal_open')) {
     133    /**
     134     * @param string $message
     135     * @param string $kp
     136     * @return string
     137     */
     138    function crypto_box_seal_open($message, $kp)
     139    {
     140        return ParagonIE_Sodium_Compat::crypto_box_seal_open($message, $kp);
     141    }
     142}
     143if (!is_callable('\\Sodium\\crypto_box_secretkey')) {
     144    /**
     145     * @param string $keypair
     146     * @return string
     147     */
     148    function crypto_box_secretkey($keypair)
     149    {
     150        return ParagonIE_Sodium_Compat::crypto_box_secretkey($keypair);
     151    }
     152}
     153if (!is_callable('\\Sodium\\crypto_generichash')) {
     154    /**
     155     * @param string $message
     156     * @param string|null $key
     157     * @param int $outLen
     158     * @return string
     159     */
     160    function crypto_generichash($message, $key = null, $outLen = 32)
     161    {
     162        return ParagonIE_Sodium_Compat::crypto_generichash($message, $key, $outLen);
     163    }
     164}
     165if (!is_callable('\\Sodium\\crypto_generichash_final')) {
     166    /**
     167     * @param string|null $ctx
     168     * @param int $outputLength
     169     * @return string
     170     */
     171    function crypto_generichash_final(&$ctx, $outputLength = 32)
     172    {
     173        return ParagonIE_Sodium_Compat::crypto_generichash_final($ctx, $outputLength);
     174    }
     175}
     176if (!is_callable('\\Sodium\\crypto_generichash_init')) {
     177    /**
     178     * @param string|null $key
     179     * @param int $outLen
     180     * @return string
     181     */
     182    function crypto_generichash_init($key = null, $outLen = 32)
     183    {
     184        return ParagonIE_Sodium_Compat::crypto_generichash_init($key, $outLen);
     185    }
     186}
     187if (!is_callable('\\Sodium\\crypto_generichash_update')) {
     188    /**
     189     * @param string|null $ctx
     190     * @param string $message
     191     * @return void
     192     */
     193    function crypto_generichash_update(&$ctx, $message = '')
     194    {
     195        ParagonIE_Sodium_Compat::crypto_generichash_update($ctx, $message);
     196    }
     197}
     198if (!is_callable('\\Sodium\\crypto_kx')) {
     199    /**
     200     * @param string $my_secret
     201     * @param string $their_public
     202     * @param string $client_public
     203     * @param string $server_public
     204     * @return string
     205     */
     206    function crypto_kx($my_secret, $their_public, $client_public, $server_public)
     207    {
     208        return ParagonIE_Sodium_Compat::crypto_kx(
     209            $my_secret,
     210            $their_public,
     211            $client_public,
     212            $server_public
     213        );
     214    }
     215}
     216if (!is_callable('\\Sodium\\crypto_scalarmult')) {
     217    /**
     218     * @param string $n
     219     * @param string $p
     220     * @return string
     221     */
     222    function crypto_scalarmult($n, $p)
     223    {
     224        return ParagonIE_Sodium_Compat::crypto_scalarmult($n, $p);
     225    }
     226}
     227if (!is_callable('\\Sodium\\crypto_secretbox')) {
     228    /**
     229     * @param string $message
     230     * @param string $nonce
     231     * @param string $key
     232     * @return string
     233     */
     234    function crypto_secretbox($message, $nonce, $key)
     235    {
     236        return ParagonIE_Sodium_Compat::crypto_secretbox($message, $nonce, $key);
     237    }
     238}
     239if (!is_callable('\\Sodium\\crypto_secretbox_open')) {
     240    /**
     241     * @param string $message
     242     * @param string $nonce
     243     * @param string $key
     244     * @return string
     245     */
     246    function crypto_secretbox_open($message, $nonce, $key)
     247    {
     248        return ParagonIE_Sodium_Compat::crypto_secretbox_open($message, $nonce, $key);
     249    }
     250}
     251if (!is_callable('\\Sodium\\crypto_shorthash')) {
     252    /**
     253     * @param string $message
     254     * @param string $key
     255     * @return string
     256     */
     257    function crypto_shorthash($message, $key = '')
     258    {
     259        return ParagonIE_Sodium_Compat::crypto_shorthash($message, $key);
     260    }
     261}
     262if (!is_callable('\\Sodium\\crypto_sign')) {
     263    /**
     264     * @param string $message
     265     * @param string $sk
     266     * @return string
     267     */
     268    function crypto_sign($message, $sk)
     269    {
     270        return ParagonIE_Sodium_Compat::crypto_sign($message, $sk);
     271    }
     272}
     273if (!is_callable('\\Sodium\\crypto_sign_detached')) {
     274    /**
     275     * @param string $message
     276     * @param string $sk
     277     * @return string
     278     */
     279    function crypto_sign_detached($message, $sk)
     280    {
     281        return ParagonIE_Sodium_Compat::crypto_sign_detached($message, $sk);
     282    }
     283}
     284if (!is_callable('\\Sodium\\crypto_sign_keypair')) {
     285    /**
     286     * @return string
     287     */
     288    function crypto_sign_keypair()
     289    {
     290        return ParagonIE_Sodium_Compat::crypto_sign_keypair();
     291    }
     292}
     293if (!is_callable('\\Sodium\\crypto_sign_open')) {
     294    /**
     295     * @param string $signedMessage
     296     * @param string $pk
     297     * @return string
     298     */
     299    function crypto_sign_open($signedMessage, $pk)
     300    {
     301        return ParagonIE_Sodium_Compat::crypto_sign_open($signedMessage, $pk);
     302    }
     303}
     304if (!is_callable('\\Sodium\\crypto_sign_publickey')) {
     305    /**
     306     * @param string $keypair
     307     * @return string
     308     */
     309    function crypto_sign_publickey($keypair)
     310    {
     311        return ParagonIE_Sodium_Compat::crypto_sign_publickey($keypair);
     312    }
     313}
     314if (!is_callable('\\Sodium\\crypto_sign_publickey_from_secretkey')) {
     315    /**
     316     * @param string $sk
     317     * @return string
     318     */
     319    function crypto_sign_publickey_from_secretkey($sk)
     320    {
     321        return ParagonIE_Sodium_Compat::crypto_sign_publickey_from_secretkey($sk);
     322    }
     323}
     324if (!is_callable('\\Sodium\\crypto_sign_secretkey')) {
     325    /**
     326     * @param string $keypair
     327     * @return string
     328     */
     329    function crypto_sign_secretkey($keypair)
     330    {
     331        return ParagonIE_Sodium_Compat::crypto_sign_secretkey($keypair);
     332    }
     333}
     334if (!is_callable('\\Sodium\\crypto_sign_verify_detached')) {
     335    /**
     336     * @param string $signature
     337     * @param string $message
     338     * @param string $pk
     339     * @return bool
     340     */
     341    function crypto_sign_verify_detached($signature, $message, $pk)
     342    {
     343        return ParagonIE_Sodium_Compat::crypto_sign_verify_detached($signature, $message, $pk);
     344    }
     345}
     346if (!is_callable('\\Sodium\\crypto_stream')) {
     347    /**
     348     * @param int $len
     349     * @param string $nonce
     350     * @param string $key
     351     * @return string
     352     */
     353    function crypto_stream($len, $nonce, $key)
     354    {
     355        return ParagonIE_Sodium_Compat::crypto_stream($len, $nonce, $key);
     356    }
     357}
     358if (!is_callable('\\Sodium\\crypto_stream_xor')) {
     359    /**
     360     * @param $message
     361     * @param $nonce
     362     * @param $key
     363     * @return mixed
     364     */
     365    function crypto_stream_xor($message, $nonce, $key)
     366    {
     367        return ParagonIE_Sodium_Compat::crypto_stream_xor($message, $nonce, $key);
     368    }
     369}
     370if (!is_callable('\\Sodium\\hex2bin')) {
     371    /**
     372     * @param $string
     373     * @return string
     374     */
     375    function hex2bin($string)
     376    {
     377        return ParagonIE_Sodium_Compat::hex2bin($string);
     378    }
     379}
     380if (!is_callable('\\Sodium\\memcmp')) {
     381    /**
     382     * @param string $a
     383     * @param string $b
     384     * @return int
     385     */
     386    function memcmp($a, $b)
     387    {
     388        return ParagonIE_Sodium_Compat::memcmp($a, $b);
     389    }
     390}
     391if (!is_callable('\\Sodium\\randombytes_buf')) {
     392    /**
     393     * @param int $amount
     394     * @return string
     395     */
     396    function randombytes_buf($amount)
     397    {
     398        return ParagonIE_Sodium_Compat::randombytes_buf($amount);
     399    }
     400}
     401
     402if (!is_callable('\\Sodium\\randombytes_uniform')) {
     403    /**
     404     * @param int $upperLimit
     405     * @return int
     406     */
     407    function randombytes_uniform($upperLimit)
     408    {
     409        return ParagonIE_Sodium_Compat::randombytes_uniform($upperLimit);
     410    }
     411}
     412
     413if (!is_callable('\\Sodium\\randombytes_random16')) {
     414    /**
     415     * @return int
     416     */
     417    function randombytes_random16()
     418    {
     419        return ParagonIE_Sodium_Compat::randombytes_random16();
     420    }
     421}
     422
     423if (!defined('\\Sodium\\CRYPTO_AUTH_BYTES')) {
     424    define('\\Sodium\\CRYPTO_AUTH_BYTES', ParagonIE_Sodium_Compat::CRYPTO_AUTH_BYTES);
     425}
     426if (!defined('\\Sodium\\CRYPTO_AUTH_KEYBYTES')) {
     427    define('\\Sodium\\CRYPTO_AUTH_KEYBYTES', ParagonIE_Sodium_Compat::CRYPTO_AUTH_KEYBYTES);
     428}
     429if (!defined('\\Sodium\\CRYPTO_BOX_SEALBYTES')) {
     430    define('\\Sodium\\CRYPTO_BOX_SEALBYTES', ParagonIE_Sodium_Compat::CRYPTO_BOX_SEALBYTES);
     431}
     432if (!defined('\\Sodium\\CRYPTO_BOX_SECRETKEYBYTES')) {
     433    define('\\Sodium\\CRYPTO_BOX_SECRETKEYBYTES', ParagonIE_Sodium_Compat::CRYPTO_BOX_SECRETKEYBYTES);
     434}
     435if (!defined('\\Sodium\\CRYPTO_BOX_PUBLICKEYBYTES')) {
     436    define('\\Sodium\\CRYPTO_BOX_PUBLICKEYBYTES', ParagonIE_Sodium_Compat::CRYPTO_BOX_PUBLICKEYBYTES);
     437}
     438if (!defined('\\Sodium\\CRYPTO_BOX_KEYPAIRBYTES')) {
     439    define('\\Sodium\\CRYPTO_BOX_KEYPAIRBYTES', ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES);
     440}
     441if (!defined('\\Sodium\\CRYPTO_BOX_MACBYTES')) {
     442    define('\\Sodium\\CRYPTO_BOX_MACBYTES', ParagonIE_Sodium_Compat::CRYPTO_BOX_MACBYTES);
     443}
     444if (!defined('\\Sodium\\CRYPTO_BOX_NONCEBYTES')) {