* MAW-874: plugin install(okta-wordpress-sign-in)
* MAW-874: remove plugin(wordfence)
This commit is contained in:
1
wp/wp-content/plugins/okta-wordpress-sign-in-widget-main/.gitignore
vendored
Normal file
1
wp/wp-content/plugins/okta-wordpress-sign-in-widget-main/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
env.php
|
||||
@@ -0,0 +1,8 @@
|
||||
Cleanup with pbcbf
|
||||
Change style to PSR2
|
||||
Automatically log users in if they have an Okta session already
|
||||
Use promises for sign-out
|
||||
Remove templating from sign-in page
|
||||
Log users out of Okta when they log out of Wordpress
|
||||
Remove all hardcoded values
|
||||
Validate OIDC tokens via /token endpoint
|
||||
@@ -0,0 +1,41 @@
|
||||
# WordPress Okta Sign-In Widget
|
||||
|
||||
This plugin replaces the WordPress login screen with the Okta sign-in widget.
|
||||
|
||||
🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
||||
|
||||
This plugin was created to demonstrate the capability of replacing the WordPress login screen with the Okta sign-in widget for [this 2018 blog post](https://developer.okta.com/blog/2018/10/30/wordpress-authentication-with-okta).
|
||||
|
||||
🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
||||
|
||||
This plugin is not supported by Okta, and not updated regularly.
|
||||
|
||||
🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
||||
|
||||
If you would like to use an officially supported Okta WordPress integration, please see [this guide](https://plugins.miniorange.com/okta-single-sign-on-wordpress-sso-oauth-openid-connect) to configuring the [miniOrange WordPress SSO Plugin](https://www.okta.com/integrations/wordpress-oauth-single-sign-on-sso-by-miniorange/) with Okta.
|
||||
|
||||
🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
||||
|
||||
|
||||
## Setup Instructions
|
||||
|
||||
After dropping this folder into the WordPress plugins folder and activating the plugin, you should see a new Settings menu where you can configure your Okta settings to enable the plugin.
|
||||
|
||||
Make sure your admin user in WordPress has an email address that matches an Okta user, or enable native WordPress logins, otherwise you'll be locked out of your WordPress after configuring the plugin.
|
||||
|
||||
TODO:
|
||||
|
||||
* Clean up the UX around installing the plugin, like making sure the admin user can still log in after the plugin is activated
|
||||
* Handle errors better (or at all really)
|
||||
|
||||
## Development Environment
|
||||
|
||||
### Manual
|
||||
|
||||
Install WordPress and move plugin to `wp-content/plugins` directory
|
||||
|
||||
### Docker
|
||||
|
||||
Install Docker and docker-compose and run `docker-compose up`
|
||||
|
||||
Navigate to http://localhost:8080
|
||||
@@ -0,0 +1,18 @@
|
||||
version: '3.1'
|
||||
|
||||
services:
|
||||
wordpress:
|
||||
image: wordpress
|
||||
depends_on:
|
||||
- mysql
|
||||
ports:
|
||||
- 8080:80
|
||||
environment:
|
||||
WORDPRESS_DB_PASSWORD: password
|
||||
volumes:
|
||||
- .:/var/www/html/wp-content/plugins/okta-wordpress-sign-in-widget
|
||||
|
||||
mysql:
|
||||
image: mysql:5.7
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: password
|
||||
@@ -0,0 +1,9 @@
|
||||
var oktaSignIn = new OktaSignIn({
|
||||
baseUrl: '<?php echo parse_url($issuer = get_option('okta-issuer-url'), PHP_URL_SCHEME).'://'.parse_url($issuer, PHP_URL_HOST) ?>',
|
||||
redirectUri: '<?php echo wp_login_url() ?>',
|
||||
clientId: '<?php echo get_option('okta-widget-client-id') ?>',
|
||||
scopes: '<?php echo apply_filters( 'okta_widget_token_scope', 'openid email') ?>'.split(' '),
|
||||
authParams: {
|
||||
issuer: '<?php echo get_option('okta-issuer-url') ?>'
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
namespace Okta;
|
||||
|
||||
class OktaAdmin{
|
||||
|
||||
public function __construct(){
|
||||
// https://codex.wordpress.org/Creating_Options_Pages
|
||||
add_action('admin_init', array($this, 'registerSettingsAction'));
|
||||
|
||||
// https://codex.wordpress.org/Adding_Administration_Menus
|
||||
add_action('admin_menu', array($this, 'optionsMenuAction'));
|
||||
}
|
||||
|
||||
public function registerSettingsAction() {
|
||||
add_settings_section(
|
||||
'okta-sign-in-widget-options-section',
|
||||
'',
|
||||
null,
|
||||
'okta-sign-in-widget'
|
||||
);
|
||||
|
||||
register_setting('okta-sign-in-widget', 'okta-issuer-url', array(
|
||||
'type' => 'string',
|
||||
'show_in_rest' => false,
|
||||
));
|
||||
add_settings_field(
|
||||
'okta-issuer-url',
|
||||
'Okta Issuer URI',
|
||||
function() { $this->optionsPageTextInputAction('okta-issuer-url', 'text', 'e.g. https://youroktadomain.okta.com/oauth2/default', 'Find your Issuer URI in the Admin console under <b>Security -> API</b>, or in the Developer console under <b>API -> Authorization Servers</b>'); },
|
||||
'okta-sign-in-widget',
|
||||
'okta-sign-in-widget-options-section'
|
||||
);
|
||||
|
||||
register_setting('okta-sign-in-widget', 'okta-widget-client-id', array(
|
||||
'type' => 'string',
|
||||
'show_in_rest' => false,
|
||||
));
|
||||
add_settings_field(
|
||||
'okta-widget-client-id',
|
||||
'Sign-In Widget Client ID',
|
||||
function() { $this->optionsPageTextInputAction('okta-widget-client-id', 'text', null, 'Register a "SPA" app in Okta and provide its Client ID here. Set the Login redirect URI in Okta to <code>'.wp_login_url().'</code>, and set the Logout redirect URI to <code>'.home_url().'</code>'); },
|
||||
'okta-sign-in-widget',
|
||||
'okta-sign-in-widget-options-section'
|
||||
);
|
||||
|
||||
register_setting('okta-sign-in-widget', 'okta-allow-wordpress-login', array(
|
||||
'type' => 'boolean',
|
||||
'show_in_rest' => false,
|
||||
));
|
||||
add_settings_field(
|
||||
'okta-allow-wordpress-login',
|
||||
'Allow Native WordPress Login',
|
||||
function() { $this->optionsPageCheckboxInputAction('okta-allow-wordpress-login', 'checkbox', 'Check this to allow local WordPress users to log in with a password. When unchecked, Okta will be the only way users can log in. Make sure you have a WordPress admin user with an email address matching an Okta user already.'); },
|
||||
'okta-sign-in-widget',
|
||||
'okta-sign-in-widget-options-section'
|
||||
);
|
||||
}
|
||||
|
||||
public function optionsMenuAction() {
|
||||
add_options_page(
|
||||
'Okta Sign-In Widget Options',
|
||||
'Okta Sign-In Widget',
|
||||
'manage_options',
|
||||
'okta-sign-in-widget',
|
||||
array($this, 'optionsPageAction')
|
||||
);
|
||||
}
|
||||
|
||||
public function optionsPageAction() {
|
||||
if (current_user_can('manage_options')) {
|
||||
include(plugin_dir_path(__FILE__)."../templates/options-form.php");
|
||||
} else {
|
||||
wp_die( 'You do not have sufficient permissions to access this page.' );
|
||||
}
|
||||
}
|
||||
|
||||
public function optionsPageTextInputAction($option_name, $type, $placeholder=false, $description=false) {
|
||||
$option_value = get_option($option_name, '');
|
||||
printf(
|
||||
'<input type="%s" id="%s" name="%s" value="%s" style="width: 100%%" autocomplete="off" placeholder="%s" />',
|
||||
esc_attr($type),
|
||||
esc_attr($option_name),
|
||||
esc_attr($option_name),
|
||||
esc_attr($option_value),
|
||||
esc_attr($placeholder)
|
||||
);
|
||||
if($description)
|
||||
echo '<p class="description">'.$description.'</p>';
|
||||
}
|
||||
|
||||
public function optionsPageCheckboxInputAction($option_name, $type, $description=false) {
|
||||
$option_value = get_option($option_name, false);
|
||||
printf(
|
||||
'<input type="%s" id="%s" name="%s" value="1" %s>',
|
||||
esc_attr($type),
|
||||
esc_attr($option_name),
|
||||
esc_attr($option_name),
|
||||
$option_value ? 'checked="checked"' : ''
|
||||
);
|
||||
if($description)
|
||||
echo '<p class="description">'.$description.'</p>';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
<script src="https://global.oktacdn.com/okta-signin-widget/5.12.0/js/okta-sign-in.min.js" type="text/javascript"></script>
|
||||
<link href="https://global.oktacdn.com/okta-signin-widget/5.12.0/css/okta-sign-in.min.css" type="text/css" rel="stylesheet"/>
|
||||
@@ -0,0 +1,226 @@
|
||||
<?php
|
||||
namespace Okta;
|
||||
|
||||
/**
|
||||
* Plugin Name: Okta Sign-In Widget
|
||||
* Plugin URI: https://github.com/oktadeveloper/okta-wordpress-sign-in-widget
|
||||
* Description: Log in to your site using the Okta Sign-In Widget
|
||||
* Version: 0.3.0
|
||||
* Author: Aaron Parecki, Tom Smith, Nico Triballier, Joël Franusic
|
||||
* Author URI: https://developer.okta.com/
|
||||
* License: MIT
|
||||
* License URI: http://opensource.org/licenses/MIT
|
||||
* Text Domain: okta
|
||||
* Domain Path: /languages
|
||||
* Update URI: false
|
||||
*/
|
||||
|
||||
include plugin_dir_path(__FILE__).'/includes/okta-admin.php';
|
||||
|
||||
class OktaSignIn
|
||||
{
|
||||
private $OktaAdmin;
|
||||
private $base_url = false;
|
||||
private $introspection_endpoint = false;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->OktaAdmin = new OktaAdmin;
|
||||
|
||||
$this->setBaseUrl();
|
||||
|
||||
// https://developer.wordpress.org/reference/hooks/login_init/
|
||||
add_action('login_init', array($this, 'loginAction'));
|
||||
|
||||
// This runs on every pageload to insert content into the HTML <head> section
|
||||
// https://codex.wordpress.org/Plugin_API/Action_Reference/wp_head
|
||||
add_action('wp_head', array($this, 'addLogInExistingSessionAction'));
|
||||
|
||||
add_action('init', array($this, 'startSessionAction'));
|
||||
}
|
||||
|
||||
private function setBaseUrl()
|
||||
{
|
||||
if($issuer = get_option('okta-issuer-url')) {
|
||||
$this->base_url = parse_url($issuer, PHP_URL_SCHEME).'://'.parse_url($issuer, PHP_URL_HOST);
|
||||
}
|
||||
}
|
||||
|
||||
private function getIntrospectionEndpoint() {
|
||||
if($this->introspection_endpoint)
|
||||
return $this->introspection_endpoint;
|
||||
|
||||
if(!$this->base_url)
|
||||
return false;
|
||||
|
||||
$response = wp_remote_get(get_option('okta-issuer-url').'/.well-known/openid-configuration');
|
||||
if(!$response)
|
||||
return false;
|
||||
|
||||
$metadata = json_decode($response['body'], true);
|
||||
if(!$metadata)
|
||||
return false;
|
||||
|
||||
if(!isset($metadata['introspection_endpoint']))
|
||||
return false;
|
||||
|
||||
return $this->introspection_endpoint = $metadata['introspection_endpoint'];
|
||||
}
|
||||
|
||||
public function startSessionAction()
|
||||
{
|
||||
if (session_status() != PHP_SESSION_ACTIVE) {
|
||||
session_start();
|
||||
}
|
||||
}
|
||||
|
||||
public function addLogInExistingSessionAction()
|
||||
{
|
||||
if (!is_user_logged_in()) {
|
||||
$this->startSessionAction();
|
||||
$_SESSION['redirect_to'] = $_SERVER['REQUEST_URI'];
|
||||
include("templates/log-in-existing-session.php");
|
||||
}
|
||||
}
|
||||
|
||||
private function httpPost($url, $body)
|
||||
{
|
||||
$args = array(
|
||||
'headers' => array(
|
||||
'Accept' => 'application/json',
|
||||
'Content-Type' => 'application/x-www-form-urlencoded',
|
||||
),
|
||||
'body' => $body,
|
||||
);
|
||||
return wp_remote_post($url, $args);
|
||||
}
|
||||
|
||||
public function loginAction()
|
||||
{
|
||||
// Support redirecting back to the page the user was on before they clicked log in
|
||||
$redirect_to = false;
|
||||
if (isset($_GET['redirect_to'])) {
|
||||
$redirect_to = $_GET['redirect_to'];
|
||||
$_SESSION['redirect_to'] = $_GET['redirect_to'];
|
||||
}
|
||||
|
||||
// When signing out of WordPress, tell the Okta JS library to log out of Okta as well
|
||||
if (isset($_GET["action"]) && $_GET["action"] === "logout") {
|
||||
$this->logUserOutOfOkta();
|
||||
}
|
||||
|
||||
if (isset($_GET['log_in_from_id_token'])) {
|
||||
$this->logUserIntoWordPressWithIDToken($_GET['log_in_from_id_token'], $redirect_to);
|
||||
exit;
|
||||
}
|
||||
|
||||
if($this->useWordpressLogin()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If there is no code in the query string, show the Okta sign-in widget
|
||||
$template = plugin_dir_path(__FILE__) . 'templates/sign-in-form.php';
|
||||
load_template($template);
|
||||
exit;
|
||||
}
|
||||
|
||||
private function useWordpressLogin()
|
||||
{
|
||||
// Always skip showing the Okta widget on POST requests
|
||||
if($_SERVER['REQUEST_METHOD'] === 'POST')
|
||||
return true;
|
||||
|
||||
// If the plugin isn't configured yet, don't show the Okta widget
|
||||
if(!$this->base_url)
|
||||
return true;
|
||||
|
||||
// null when plugin is not configured, "1"/"0" after
|
||||
if(get_option('okta-allow-wordpress-login') === null || get_option('okta-allow-wordpress-login') === "1")
|
||||
{
|
||||
if(isset($_GET['wordpress_login']) && $_GET['wordpress_login'] == 'true')
|
||||
return true;
|
||||
|
||||
if(isset($_GET['action']) && $_GET['action'] == 'lostpassword')
|
||||
return true;
|
||||
|
||||
if(isset($_GET['checkemail']))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function logUserOutOfOkta() {
|
||||
$user = wp_get_current_user();
|
||||
|
||||
wp_clear_auth_cookie();
|
||||
|
||||
$template = plugin_dir_path(__FILE__) . 'templates/sign-out.php';
|
||||
load_template($template);
|
||||
exit;
|
||||
}
|
||||
|
||||
private function logUserIntoWordPressWithIDToken($id_token, $redirect_to)
|
||||
{
|
||||
$introspection_endpoint = $this->getIntrospectionEndpoint();
|
||||
|
||||
if(!$this->introspection_endpoint)
|
||||
die("The plugin is not configured properly. Please double check the Issuer URI in the configuration.");
|
||||
|
||||
/********************************************/
|
||||
// [jpf] TODO: Implement client-side id_token validation to speed up the verification process
|
||||
// (~300ms for /introspect endpoint v. ~5ms for client-side validation)
|
||||
$payload = array(
|
||||
'client_id' => get_option('okta-widget-client-id'),
|
||||
'token' => $id_token,
|
||||
'token_type_hint' => 'id_token'
|
||||
);
|
||||
$response = $this->httpPost($this->introspection_endpoint, $payload);
|
||||
if ($response === false) {
|
||||
die("Invalid id_token received from Okta");
|
||||
}
|
||||
$claims = json_decode($response['body'], true);
|
||||
if (!$claims['active']) {
|
||||
die("Okta reports that id_token is not active or client authentication failed:" . $claims['error_description']);
|
||||
}
|
||||
/********************************************/
|
||||
|
||||
$this->logUserIntoWordPressFromEmail($claims, $redirect_to);
|
||||
}
|
||||
|
||||
private function logUserIntoWordPressFromEmail($claims, $redirect_to)
|
||||
{
|
||||
$email = $claims['email'];
|
||||
|
||||
// Find or create the WordPress user for this email address
|
||||
$user = get_user_by('email', $email);
|
||||
if (!$user) {
|
||||
$random_password = wp_generate_password($length = 64, $include_standard_special_chars = false);
|
||||
$user_id = wp_create_user($email, $random_password, $email);
|
||||
$user = get_user_by('id', $user_id);
|
||||
} else {
|
||||
$user_id = $user->ID;
|
||||
}
|
||||
|
||||
do_action('okta_widget_before_login', $claims, $user);
|
||||
|
||||
// Actually log the user in now
|
||||
wp_set_current_user($user_id);
|
||||
wp_set_auth_cookie($user_id);
|
||||
error_log("Logging in WordPress user with ID of: " . $user_id);
|
||||
|
||||
// See also: https://developer.wordpress.org/reference/functions/do_action/
|
||||
// Run the wp_login actions now that the user is logged in
|
||||
do_action('wp_login', $user->user_login, $user);
|
||||
|
||||
if (isset($_SESSION['redirect_to'])) {
|
||||
$redirect_uri = $_SESSION['redirect_to'];
|
||||
unset($_SESSION['redirect_to']);
|
||||
} else {
|
||||
$redirect_uri = home_url();
|
||||
}
|
||||
wp_redirect($redirect_uri);
|
||||
}
|
||||
}
|
||||
|
||||
$okta = new OktaSignIn();
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php include plugin_dir_path(__FILE__).'/../includes/widget.php'; ?>
|
||||
|
||||
<script>
|
||||
<?php include plugin_dir_path(__FILE__).'/../includes/initialize-widget.js.php'; ?>
|
||||
|
||||
oktaSignIn.authClient.session.exists()
|
||||
.then(function(exists) {
|
||||
if(exists) {
|
||||
oktaSignIn.authClient.token.getWithoutPrompt({
|
||||
responseType: ['id_token'],
|
||||
})
|
||||
.then(function(tokens){
|
||||
window.location.href = '<?php echo wp_login_url() ?>' + '?log_in_from_id_token=' + tokens.tokens.idToken.value;
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,9 @@
|
||||
<div class="wrap">
|
||||
<h1>Okta Sign-In Widget</h1>
|
||||
|
||||
<form method="post" action="options.php">
|
||||
<?php settings_fields( 'okta-sign-in-widget' ); ?>
|
||||
<?php do_settings_sections( 'okta-sign-in-widget' ); ?>
|
||||
<?php submit_button(); ?>
|
||||
</form>
|
||||
</div>
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php include plugin_dir_path(__FILE__).'/../includes/widget.php'; ?>
|
||||
|
||||
<style type="text/css">
|
||||
body {
|
||||
font-family: montserrat,Arial,Helvetica,sans-serif;
|
||||
}
|
||||
|
||||
#wordpress-login{
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#wordpress-login a{
|
||||
font-size:10px;
|
||||
color: #999;
|
||||
text-decoration:none;
|
||||
}
|
||||
|
||||
#error {
|
||||
max-width: 500px;
|
||||
margin: 20px auto;
|
||||
padding: 20px;
|
||||
border: 1px #d93934 solid;
|
||||
border-radius: 6px;
|
||||
}
|
||||
#error h2 {
|
||||
color: #d93934;
|
||||
}
|
||||
</style>
|
||||
|
||||
<?php if(isset($_GET['error'])): ?>
|
||||
<div id="error">
|
||||
<h2>Error: <?php echo htmlspecialchars($_GET['error']) ?></h2>
|
||||
<p><?php echo htmlspecialchars($_GET['error_description']) ?></p>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
|
||||
<div id="primary" class="content-area">
|
||||
<div id="okta-login-container"></div>
|
||||
<?php if(get_option('okta-allow-wordpress-login')): ?>
|
||||
<div id="wordpress-login"><a href="<?php echo wp_login_url(); ?>?wordpress_login=true">Login via Wordpress</a></div>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
<?php include plugin_dir_path(__FILE__).'/../includes/initialize-widget.js.php'; ?>
|
||||
|
||||
oktaSignIn.authClient.token.getUserInfo().then(function(user) {
|
||||
console.log("Already logged in");
|
||||
oktaSignIn.authClient.tokenManager.get('idToken').then(function(idToken){
|
||||
window.location = '<?php echo wp_login_url() ?>?log_in_from_id_token='+idToken.value;
|
||||
});
|
||||
}, function(error) {
|
||||
oktaSignIn.showSignInToGetTokens({
|
||||
el: '#okta-login-container'
|
||||
}).then(function(tokens) {
|
||||
oktaSignIn.authClient.tokenManager.setTokens(tokens);
|
||||
|
||||
oktaSignIn.remove(); // Remove the widget from the DOM
|
||||
|
||||
const idToken = tokens.idToken;
|
||||
window.location = '<?php echo wp_login_url() ?>?log_in_from_id_token='+idToken.value;
|
||||
|
||||
}).catch(function(err) {
|
||||
console.error(err);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php include plugin_dir_path(__FILE__).'/../includes/widget.php'; ?>
|
||||
|
||||
<script>
|
||||
<?php include plugin_dir_path(__FILE__).'/../includes/initialize-widget.js.php'; ?>
|
||||
|
||||
oktaSignIn.authClient.tokenManager.get('idToken').then(function(idToken){
|
||||
if(idToken) {
|
||||
oktaSignIn.authClient.signOut({
|
||||
idToken: idToken,
|
||||
postLogoutRedirectUri: '<?php echo home_url() ?>'
|
||||
});
|
||||
} else {
|
||||
window.location = '<?php echo home_url() ?>';
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -1,9 +0,0 @@
|
||||
<?php
|
||||
|
||||
// autoload.php @generated by Composer
|
||||
|
||||
if (!class_exists('ComposerAutoloaderInite213e65b2dafae4ad799b13fe0d36f8e')) {
|
||||
require_once __DIR__ . '/composer/autoload_real.php';
|
||||
}
|
||||
|
||||
return ComposerAutoloaderInite213e65b2dafae4ad799b13fe0d36f8e::getLoader();
|
||||
@@ -1,481 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
/**
|
||||
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
|
||||
*
|
||||
* $loader = new \Composer\Autoload\ClassLoader();
|
||||
*
|
||||
* // register classes with namespaces
|
||||
* $loader->add('Symfony\Component', __DIR__.'/component');
|
||||
* $loader->add('Symfony', __DIR__.'/framework');
|
||||
*
|
||||
* // activate the autoloader
|
||||
* $loader->register();
|
||||
*
|
||||
* // to enable searching the include path (eg. for PEAR packages)
|
||||
* $loader->setUseIncludePath(true);
|
||||
*
|
||||
* In this example, if you try to use a class in the Symfony\Component
|
||||
* namespace or one of its children (Symfony\Component\Console for instance),
|
||||
* the autoloader will first look for the class under the component/
|
||||
* directory, and it will then fallback to the framework/ directory if not
|
||||
* found before giving up.
|
||||
*
|
||||
* This class is loosely based on the Symfony UniversalClassLoader.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
* @see https://www.php-fig.org/psr/psr-0/
|
||||
* @see https://www.php-fig.org/psr/psr-4/
|
||||
*/
|
||||
class ClassLoader
|
||||
{
|
||||
private $vendorDir;
|
||||
|
||||
// PSR-4
|
||||
private $prefixLengthsPsr4 = array();
|
||||
private $prefixDirsPsr4 = array();
|
||||
private $fallbackDirsPsr4 = array();
|
||||
|
||||
// PSR-0
|
||||
private $prefixesPsr0 = array();
|
||||
private $fallbackDirsPsr0 = array();
|
||||
|
||||
private $useIncludePath = false;
|
||||
private $classMap = array();
|
||||
private $classMapAuthoritative = false;
|
||||
private $missingClasses = array();
|
||||
private $apcuPrefix;
|
||||
|
||||
private static $registeredLoaders = array();
|
||||
|
||||
public function __construct($vendorDir = null)
|
||||
{
|
||||
$this->vendorDir = $vendorDir;
|
||||
}
|
||||
|
||||
public function getPrefixes()
|
||||
{
|
||||
if (!empty($this->prefixesPsr0)) {
|
||||
return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
public function getPrefixesPsr4()
|
||||
{
|
||||
return $this->prefixDirsPsr4;
|
||||
}
|
||||
|
||||
public function getFallbackDirs()
|
||||
{
|
||||
return $this->fallbackDirsPsr0;
|
||||
}
|
||||
|
||||
public function getFallbackDirsPsr4()
|
||||
{
|
||||
return $this->fallbackDirsPsr4;
|
||||
}
|
||||
|
||||
public function getClassMap()
|
||||
{
|
||||
return $this->classMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $classMap Class to filename map
|
||||
*/
|
||||
public function addClassMap(array $classMap)
|
||||
{
|
||||
if ($this->classMap) {
|
||||
$this->classMap = array_merge($this->classMap, $classMap);
|
||||
} else {
|
||||
$this->classMap = $classMap;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-0 directories for a given prefix, either
|
||||
* appending or prepending to the ones previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param array|string $paths The PSR-0 root directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*/
|
||||
public function add($prefix, $paths, $prepend = false)
|
||||
{
|
||||
if (!$prefix) {
|
||||
if ($prepend) {
|
||||
$this->fallbackDirsPsr0 = array_merge(
|
||||
(array) $paths,
|
||||
$this->fallbackDirsPsr0
|
||||
);
|
||||
} else {
|
||||
$this->fallbackDirsPsr0 = array_merge(
|
||||
$this->fallbackDirsPsr0,
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$first = $prefix[0];
|
||||
if (!isset($this->prefixesPsr0[$first][$prefix])) {
|
||||
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
|
||||
|
||||
return;
|
||||
}
|
||||
if ($prepend) {
|
||||
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||
(array) $paths,
|
||||
$this->prefixesPsr0[$first][$prefix]
|
||||
);
|
||||
} else {
|
||||
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||
$this->prefixesPsr0[$first][$prefix],
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-4 directories for a given namespace, either
|
||||
* appending or prepending to the ones previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param array|string $paths The PSR-4 base directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function addPsr4($prefix, $paths, $prepend = false)
|
||||
{
|
||||
if (!$prefix) {
|
||||
// Register directories for the root namespace.
|
||||
if ($prepend) {
|
||||
$this->fallbackDirsPsr4 = array_merge(
|
||||
(array) $paths,
|
||||
$this->fallbackDirsPsr4
|
||||
);
|
||||
} else {
|
||||
$this->fallbackDirsPsr4 = array_merge(
|
||||
$this->fallbackDirsPsr4,
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
|
||||
// Register directories for a new namespace.
|
||||
$length = strlen($prefix);
|
||||
if ('\\' !== $prefix[$length - 1]) {
|
||||
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||
}
|
||||
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
||||
} elseif ($prepend) {
|
||||
// Prepend directories for an already registered namespace.
|
||||
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||
(array) $paths,
|
||||
$this->prefixDirsPsr4[$prefix]
|
||||
);
|
||||
} else {
|
||||
// Append directories for an already registered namespace.
|
||||
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||
$this->prefixDirsPsr4[$prefix],
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-0 directories for a given prefix,
|
||||
* replacing any others previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param array|string $paths The PSR-0 base directories
|
||||
*/
|
||||
public function set($prefix, $paths)
|
||||
{
|
||||
if (!$prefix) {
|
||||
$this->fallbackDirsPsr0 = (array) $paths;
|
||||
} else {
|
||||
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-4 directories for a given namespace,
|
||||
* replacing any others previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param array|string $paths The PSR-4 base directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function setPsr4($prefix, $paths)
|
||||
{
|
||||
if (!$prefix) {
|
||||
$this->fallbackDirsPsr4 = (array) $paths;
|
||||
} else {
|
||||
$length = strlen($prefix);
|
||||
if ('\\' !== $prefix[$length - 1]) {
|
||||
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||
}
|
||||
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns on searching the include path for class files.
|
||||
*
|
||||
* @param bool $useIncludePath
|
||||
*/
|
||||
public function setUseIncludePath($useIncludePath)
|
||||
{
|
||||
$this->useIncludePath = $useIncludePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can be used to check if the autoloader uses the include path to check
|
||||
* for classes.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getUseIncludePath()
|
||||
{
|
||||
return $this->useIncludePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns off searching the prefix and fallback directories for classes
|
||||
* that have not been registered with the class map.
|
||||
*
|
||||
* @param bool $classMapAuthoritative
|
||||
*/
|
||||
public function setClassMapAuthoritative($classMapAuthoritative)
|
||||
{
|
||||
$this->classMapAuthoritative = $classMapAuthoritative;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should class lookup fail if not found in the current class map?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isClassMapAuthoritative()
|
||||
{
|
||||
return $this->classMapAuthoritative;
|
||||
}
|
||||
|
||||
/**
|
||||
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
|
||||
*
|
||||
* @param string|null $apcuPrefix
|
||||
*/
|
||||
public function setApcuPrefix($apcuPrefix)
|
||||
{
|
||||
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The APCu prefix in use, or null if APCu caching is not enabled.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getApcuPrefix()
|
||||
{
|
||||
return $this->apcuPrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers this instance as an autoloader.
|
||||
*
|
||||
* @param bool $prepend Whether to prepend the autoloader or not
|
||||
*/
|
||||
public function register($prepend = false)
|
||||
{
|
||||
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
|
||||
|
||||
if (null === $this->vendorDir) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($prepend) {
|
||||
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
|
||||
} else {
|
||||
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||
self::$registeredLoaders[$this->vendorDir] = $this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters this instance as an autoloader.
|
||||
*/
|
||||
public function unregister()
|
||||
{
|
||||
spl_autoload_unregister(array($this, 'loadClass'));
|
||||
|
||||
if (null !== $this->vendorDir) {
|
||||
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the given class or interface.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
* @return true|null True if loaded, null otherwise
|
||||
*/
|
||||
public function loadClass($class)
|
||||
{
|
||||
if ($file = $this->findFile($class)) {
|
||||
includeFile($file);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the path to the file where the class is defined.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
*
|
||||
* @return string|false The path if found, false otherwise
|
||||
*/
|
||||
public function findFile($class)
|
||||
{
|
||||
// class map lookup
|
||||
if (isset($this->classMap[$class])) {
|
||||
return $this->classMap[$class];
|
||||
}
|
||||
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
|
||||
return false;
|
||||
}
|
||||
if (null !== $this->apcuPrefix) {
|
||||
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
|
||||
if ($hit) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
$file = $this->findFileWithExtension($class, '.php');
|
||||
|
||||
// Search for Hack files if we are running on HHVM
|
||||
if (false === $file && defined('HHVM_VERSION')) {
|
||||
$file = $this->findFileWithExtension($class, '.hh');
|
||||
}
|
||||
|
||||
if (null !== $this->apcuPrefix) {
|
||||
apcu_add($this->apcuPrefix.$class, $file);
|
||||
}
|
||||
|
||||
if (false === $file) {
|
||||
// Remember that this class does not exist.
|
||||
$this->missingClasses[$class] = true;
|
||||
}
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently registered loaders indexed by their corresponding vendor directories.
|
||||
*
|
||||
* @return self[]
|
||||
*/
|
||||
public static function getRegisteredLoaders()
|
||||
{
|
||||
return self::$registeredLoaders;
|
||||
}
|
||||
|
||||
private function findFileWithExtension($class, $ext)
|
||||
{
|
||||
// PSR-4 lookup
|
||||
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
|
||||
|
||||
$first = $class[0];
|
||||
if (isset($this->prefixLengthsPsr4[$first])) {
|
||||
$subPath = $class;
|
||||
while (false !== $lastPos = strrpos($subPath, '\\')) {
|
||||
$subPath = substr($subPath, 0, $lastPos);
|
||||
$search = $subPath . '\\';
|
||||
if (isset($this->prefixDirsPsr4[$search])) {
|
||||
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
|
||||
foreach ($this->prefixDirsPsr4[$search] as $dir) {
|
||||
if (file_exists($file = $dir . $pathEnd)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-4 fallback dirs
|
||||
foreach ($this->fallbackDirsPsr4 as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 lookup
|
||||
if (false !== $pos = strrpos($class, '\\')) {
|
||||
// namespaced class name
|
||||
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
|
||||
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
|
||||
} else {
|
||||
// PEAR-like class name
|
||||
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
|
||||
}
|
||||
|
||||
if (isset($this->prefixesPsr0[$first])) {
|
||||
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
|
||||
if (0 === strpos($class, $prefix)) {
|
||||
foreach ($dirs as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 fallback dirs
|
||||
foreach ($this->fallbackDirsPsr0 as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 include paths.
|
||||
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope isolated include.
|
||||
*
|
||||
* Prevents access to $this/self from included files.
|
||||
*/
|
||||
function includeFile($file)
|
||||
{
|
||||
include $file;
|
||||
}
|
||||
@@ -1,337 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer;
|
||||
|
||||
use Composer\Autoload\ClassLoader;
|
||||
use Composer\Semver\VersionParser;
|
||||
|
||||
/**
|
||||
* This class is copied in every Composer installed project and available to all
|
||||
*
|
||||
* See also https://getcomposer.org/doc/07-runtime.md#installed-versions
|
||||
*
|
||||
* To require it's presence, you can require `composer-runtime-api ^2.0`
|
||||
*/
|
||||
class InstalledVersions
|
||||
{
|
||||
private static $installed;
|
||||
private static $canGetVendors;
|
||||
private static $installedByVendor = array();
|
||||
|
||||
/**
|
||||
* Returns a list of all package names which are present, either by being installed, replaced or provided
|
||||
*
|
||||
* @return string[]
|
||||
* @psalm-return list<string>
|
||||
*/
|
||||
public static function getInstalledPackages()
|
||||
{
|
||||
$packages = array();
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
$packages[] = array_keys($installed['versions']);
|
||||
}
|
||||
|
||||
if (1 === \count($packages)) {
|
||||
return $packages[0];
|
||||
}
|
||||
|
||||
return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all package names with a specific type e.g. 'library'
|
||||
*
|
||||
* @param string $type
|
||||
* @return string[]
|
||||
* @psalm-return list<string>
|
||||
*/
|
||||
public static function getInstalledPackagesByType($type)
|
||||
{
|
||||
$packagesByType = array();
|
||||
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
foreach ($installed['versions'] as $name => $package) {
|
||||
if (isset($package['type']) && $package['type'] === $type) {
|
||||
$packagesByType[] = $name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $packagesByType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given package is installed
|
||||
*
|
||||
* This also returns true if the package name is provided or replaced by another package
|
||||
*
|
||||
* @param string $packageName
|
||||
* @param bool $includeDevRequirements
|
||||
* @return bool
|
||||
*/
|
||||
public static function isInstalled($packageName, $includeDevRequirements = true)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (isset($installed['versions'][$packageName])) {
|
||||
return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given package satisfies a version constraint
|
||||
*
|
||||
* e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
|
||||
*
|
||||
* Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
|
||||
*
|
||||
* @param VersionParser $parser Install composer/semver to have access to this class and functionality
|
||||
* @param string $packageName
|
||||
* @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
|
||||
* @return bool
|
||||
*/
|
||||
public static function satisfies(VersionParser $parser, $packageName, $constraint)
|
||||
{
|
||||
$constraint = $parser->parseConstraints($constraint);
|
||||
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
|
||||
|
||||
return $provided->matches($constraint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a version constraint representing all the range(s) which are installed for a given package
|
||||
*
|
||||
* It is easier to use this via isInstalled() with the $constraint argument if you need to check
|
||||
* whether a given version of a package is installed, and not just whether it exists
|
||||
*
|
||||
* @param string $packageName
|
||||
* @return string Version constraint usable with composer/semver
|
||||
*/
|
||||
public static function getVersionRanges($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$ranges = array();
|
||||
if (isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||
$ranges[] = $installed['versions'][$packageName]['pretty_version'];
|
||||
}
|
||||
if (array_key_exists('aliases', $installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
|
||||
}
|
||||
if (array_key_exists('replaced', $installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
|
||||
}
|
||||
if (array_key_exists('provided', $installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
|
||||
}
|
||||
|
||||
return implode(' || ', $ranges);
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
|
||||
*/
|
||||
public static function getVersion($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($installed['versions'][$packageName]['version'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $installed['versions'][$packageName]['version'];
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
|
||||
*/
|
||||
public static function getPrettyVersion($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $installed['versions'][$packageName]['pretty_version'];
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
|
||||
*/
|
||||
public static function getReference($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($installed['versions'][$packageName]['reference'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $installed['versions'][$packageName]['reference'];
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
|
||||
*/
|
||||
public static function getInstallPath($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string}
|
||||
*/
|
||||
public static function getRootPackage()
|
||||
{
|
||||
$installed = self::getInstalled();
|
||||
|
||||
return $installed[0]['root'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw installed.php data for custom implementations
|
||||
*
|
||||
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
|
||||
* @return array[]
|
||||
* @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string}>}
|
||||
*/
|
||||
public static function getRawData()
|
||||
{
|
||||
@trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
|
||||
|
||||
if (null === self::$installed) {
|
||||
// only require the installed.php file if this file is loaded from its dumped location,
|
||||
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
||||
if (substr(__DIR__, -8, 1) !== 'C') {
|
||||
self::$installed = include __DIR__ . '/installed.php';
|
||||
} else {
|
||||
self::$installed = array();
|
||||
}
|
||||
}
|
||||
|
||||
return self::$installed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw data of all installed.php which are currently loaded for custom implementations
|
||||
*
|
||||
* @return array[]
|
||||
* @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string}>}>
|
||||
*/
|
||||
public static function getAllRawData()
|
||||
{
|
||||
return self::getInstalled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Lets you reload the static array from another file
|
||||
*
|
||||
* This is only useful for complex integrations in which a project needs to use
|
||||
* this class but then also needs to execute another project's autoloader in process,
|
||||
* and wants to ensure both projects have access to their version of installed.php.
|
||||
*
|
||||
* A typical case would be PHPUnit, where it would need to make sure it reads all
|
||||
* the data it needs from this class, then call reload() with
|
||||
* `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
|
||||
* the project in which it runs can then also use this class safely, without
|
||||
* interference between PHPUnit's dependencies and the project's dependencies.
|
||||
*
|
||||
* @param array[] $data A vendor/composer/installed.php data set
|
||||
* @return void
|
||||
*
|
||||
* @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string}>} $data
|
||||
*/
|
||||
public static function reload($data)
|
||||
{
|
||||
self::$installed = $data;
|
||||
self::$installedByVendor = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string}>}>
|
||||
*/
|
||||
private static function getInstalled()
|
||||
{
|
||||
if (null === self::$canGetVendors) {
|
||||
self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
|
||||
}
|
||||
|
||||
$installed = array();
|
||||
|
||||
if (self::$canGetVendors) {
|
||||
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
|
||||
if (isset(self::$installedByVendor[$vendorDir])) {
|
||||
$installed[] = self::$installedByVendor[$vendorDir];
|
||||
} elseif (is_file($vendorDir.'/composer/installed.php')) {
|
||||
$installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
|
||||
if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
|
||||
self::$installed = $installed[count($installed) - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (null === self::$installed) {
|
||||
// only require the installed.php file if this file is loaded from its dumped location,
|
||||
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
||||
if (substr(__DIR__, -8, 1) !== 'C') {
|
||||
self::$installed = require __DIR__ . '/installed.php';
|
||||
} else {
|
||||
self::$installed = array();
|
||||
}
|
||||
}
|
||||
$installed[] = self::$installed;
|
||||
|
||||
return $installed;
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
|
||||
Copyright (c) Nils Adermann, Jordi Boggiano
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
<?php
|
||||
|
||||
// autoload_classmap.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
|
||||
);
|
||||
@@ -1,11 +0,0 @@
|
||||
<?php
|
||||
|
||||
// autoload_files.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'5255c38a0faeba867671b61dfda6d864' => $vendorDir . '/paragonie/random_compat/lib/random.php',
|
||||
'3109cb1a231dcd04bee1f9f620d46975' => $vendorDir . '/paragonie/sodium_compat/autoload.php',
|
||||
);
|
||||
@@ -1,9 +0,0 @@
|
||||
<?php
|
||||
|
||||
// autoload_namespaces.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
);
|
||||
@@ -1,9 +0,0 @@
|
||||
<?php
|
||||
|
||||
// autoload_psr4.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
);
|
||||
@@ -1,75 +0,0 @@
|
||||
<?php
|
||||
|
||||
// autoload_real.php @generated by Composer
|
||||
|
||||
class ComposerAutoloaderInite213e65b2dafae4ad799b13fe0d36f8e
|
||||
{
|
||||
private static $loader;
|
||||
|
||||
public static function loadClassLoader($class)
|
||||
{
|
||||
if ('Composer\Autoload\ClassLoader' === $class) {
|
||||
require __DIR__ . '/ClassLoader.php';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Composer\Autoload\ClassLoader
|
||||
*/
|
||||
public static function getLoader()
|
||||
{
|
||||
if (null !== self::$loader) {
|
||||
return self::$loader;
|
||||
}
|
||||
|
||||
require __DIR__ . '/platform_check.php';
|
||||
|
||||
spl_autoload_register(array('ComposerAutoloaderInite213e65b2dafae4ad799b13fe0d36f8e', 'loadClassLoader'), true, true);
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInite213e65b2dafae4ad799b13fe0d36f8e', 'loadClassLoader'));
|
||||
|
||||
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
|
||||
if ($useStaticLoader) {
|
||||
require __DIR__ . '/autoload_static.php';
|
||||
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInite213e65b2dafae4ad799b13fe0d36f8e::getInitializer($loader));
|
||||
} else {
|
||||
$map = require __DIR__ . '/autoload_namespaces.php';
|
||||
foreach ($map as $namespace => $path) {
|
||||
$loader->set($namespace, $path);
|
||||
}
|
||||
|
||||
$map = require __DIR__ . '/autoload_psr4.php';
|
||||
foreach ($map as $namespace => $path) {
|
||||
$loader->setPsr4($namespace, $path);
|
||||
}
|
||||
|
||||
$classMap = require __DIR__ . '/autoload_classmap.php';
|
||||
if ($classMap) {
|
||||
$loader->addClassMap($classMap);
|
||||
}
|
||||
}
|
||||
|
||||
$loader->register(true);
|
||||
|
||||
if ($useStaticLoader) {
|
||||
$includeFiles = Composer\Autoload\ComposerStaticInite213e65b2dafae4ad799b13fe0d36f8e::$files;
|
||||
} else {
|
||||
$includeFiles = require __DIR__ . '/autoload_files.php';
|
||||
}
|
||||
foreach ($includeFiles as $fileIdentifier => $file) {
|
||||
composerRequiree213e65b2dafae4ad799b13fe0d36f8e($fileIdentifier, $file);
|
||||
}
|
||||
|
||||
return $loader;
|
||||
}
|
||||
}
|
||||
|
||||
function composerRequiree213e65b2dafae4ad799b13fe0d36f8e($fileIdentifier, $file)
|
||||
{
|
||||
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
||||
require $file;
|
||||
|
||||
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
<?php
|
||||
|
||||
// autoload_static.php @generated by Composer
|
||||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
class ComposerStaticInite213e65b2dafae4ad799b13fe0d36f8e
|
||||
{
|
||||
public static $files = array (
|
||||
'5255c38a0faeba867671b61dfda6d864' => __DIR__ . '/..' . '/paragonie/random_compat/lib/random.php',
|
||||
'3109cb1a231dcd04bee1f9f620d46975' => __DIR__ . '/..' . '/paragonie/sodium_compat/autoload.php',
|
||||
);
|
||||
|
||||
public static $classMap = array (
|
||||
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
|
||||
);
|
||||
|
||||
public static function getInitializer(ClassLoader $loader)
|
||||
{
|
||||
return \Closure::bind(function () use ($loader) {
|
||||
$loader->classMap = ComposerStaticInite213e65b2dafae4ad799b13fe0d36f8e::$classMap;
|
||||
|
||||
}, null, ClassLoader::class);
|
||||
}
|
||||
}
|
||||
@@ -1,152 +0,0 @@
|
||||
{
|
||||
"packages": [
|
||||
{
|
||||
"name": "paragonie/random_compat",
|
||||
"version": "v2.0.21",
|
||||
"version_normalized": "2.0.21.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/paragonie/random_compat.git",
|
||||
"reference": "96c132c7f2f7bc3230723b66e89f8f150b29d5ae"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/paragonie/random_compat/zipball/96c132c7f2f7bc3230723b66e89f8f150b29d5ae",
|
||||
"reference": "96c132c7f2f7bc3230723b66e89f8f150b29d5ae",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "*"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
|
||||
},
|
||||
"time": "2022-02-16T17:07:03+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"lib/random.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Paragon Initiative Enterprises",
|
||||
"email": "security@paragonie.com",
|
||||
"homepage": "https://paragonie.com"
|
||||
}
|
||||
],
|
||||
"description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
|
||||
"keywords": [
|
||||
"csprng",
|
||||
"polyfill",
|
||||
"pseudorandom",
|
||||
"random"
|
||||
],
|
||||
"support": {
|
||||
"email": "info@paragonie.com",
|
||||
"issues": "https://github.com/paragonie/random_compat/issues",
|
||||
"source": "https://github.com/paragonie/random_compat"
|
||||
},
|
||||
"install-path": "../paragonie/random_compat"
|
||||
},
|
||||
{
|
||||
"name": "paragonie/sodium_compat",
|
||||
"version": "v1.20.0",
|
||||
"version_normalized": "1.20.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/paragonie/sodium_compat.git",
|
||||
"reference": "e592a3e06d1fa0d43988c7c7d9948ca836f644b6"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/paragonie/sodium_compat/zipball/e592a3e06d1fa0d43988c7c7d9948ca836f644b6",
|
||||
"reference": "e592a3e06d1fa0d43988c7c7d9948ca836f644b6",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"paragonie/random_compat": ">=1",
|
||||
"php": "^5.2.4|^5.3|^5.4|^5.5|^5.6|^7|^8"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^3|^4|^5|^6|^7|^8|^9"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-libsodium": "PHP < 7.0: Better performance, password hashing (Argon2i), secure memory management (memzero), and better security.",
|
||||
"ext-sodium": "PHP >= 7.0: Better performance, password hashing (Argon2i), secure memory management (memzero), and better security."
|
||||
},
|
||||
"time": "2023-04-30T00:54:53+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"autoload.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"ISC"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Paragon Initiative Enterprises",
|
||||
"email": "security@paragonie.com"
|
||||
},
|
||||
{
|
||||
"name": "Frank Denis",
|
||||
"email": "jedisct1@pureftpd.org"
|
||||
}
|
||||
],
|
||||
"description": "Pure PHP implementation of libsodium; uses the PHP extension if it exists",
|
||||
"keywords": [
|
||||
"Authentication",
|
||||
"BLAKE2b",
|
||||
"ChaCha20",
|
||||
"ChaCha20-Poly1305",
|
||||
"Chapoly",
|
||||
"Curve25519",
|
||||
"Ed25519",
|
||||
"EdDSA",
|
||||
"Edwards-curve Digital Signature Algorithm",
|
||||
"Elliptic Curve Diffie-Hellman",
|
||||
"Poly1305",
|
||||
"Pure-PHP cryptography",
|
||||
"RFC 7748",
|
||||
"RFC 8032",
|
||||
"Salpoly",
|
||||
"Salsa20",
|
||||
"X25519",
|
||||
"XChaCha20-Poly1305",
|
||||
"XSalsa20-Poly1305",
|
||||
"Xchacha20",
|
||||
"Xsalsa20",
|
||||
"aead",
|
||||
"cryptography",
|
||||
"ecdh",
|
||||
"elliptic curve",
|
||||
"elliptic curve cryptography",
|
||||
"encryption",
|
||||
"libsodium",
|
||||
"php",
|
||||
"public-key cryptography",
|
||||
"secret-key cryptography",
|
||||
"side-channel resistant"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/paragonie/sodium_compat/issues",
|
||||
"source": "https://github.com/paragonie/sodium_compat/tree/v1.20.0"
|
||||
},
|
||||
"install-path": "../paragonie/sodium_compat"
|
||||
}
|
||||
],
|
||||
"dev": true,
|
||||
"dev-package-names": []
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
<?php return array(
|
||||
'root' => array(
|
||||
'pretty_version' => 'dev-master',
|
||||
'version' => 'dev-master',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'reference' => '4dbf15a23f788f9f3a3e57f5971bf957e5f9ba01',
|
||||
'name' => '__root__',
|
||||
'dev' => true,
|
||||
),
|
||||
'versions' => array(
|
||||
'__root__' => array(
|
||||
'pretty_version' => 'dev-master',
|
||||
'version' => 'dev-master',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'reference' => '4dbf15a23f788f9f3a3e57f5971bf957e5f9ba01',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'paragonie/random_compat' => array(
|
||||
'pretty_version' => 'v2.0.21',
|
||||
'version' => '2.0.21.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../paragonie/random_compat',
|
||||
'aliases' => array(),
|
||||
'reference' => '96c132c7f2f7bc3230723b66e89f8f150b29d5ae',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'paragonie/sodium_compat' => array(
|
||||
'pretty_version' => 'v1.20.0',
|
||||
'version' => '1.20.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../paragonie/sodium_compat',
|
||||
'aliases' => array(),
|
||||
'reference' => 'e592a3e06d1fa0d43988c7c7d9948ca836f644b6',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -1,26 +0,0 @@
|
||||
<?php
|
||||
|
||||
// platform_check.php @generated by Composer
|
||||
|
||||
$issues = array();
|
||||
|
||||
if (!(PHP_VERSION_ID >= 50204)) {
|
||||
$issues[] = 'Your Composer dependencies require a PHP version ">= 5.2.4". You are running ' . PHP_VERSION . '.';
|
||||
}
|
||||
|
||||
if ($issues) {
|
||||
if (!headers_sent()) {
|
||||
header('HTTP/1.1 500 Internal Server Error');
|
||||
}
|
||||
if (!ini_get('display_errors')) {
|
||||
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
|
||||
fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
|
||||
} elseif (!headers_sent()) {
|
||||
echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
|
||||
}
|
||||
}
|
||||
trigger_error(
|
||||
'Composer detected issues in your platform: ' . implode(' ', $issues),
|
||||
E_USER_ERROR
|
||||
);
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Paragon Initiative Enterprises
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEEd+wCqJDrx5B4OldM0dQE0ZMX+lx1ZWm
|
||||
pui0SUqD4G29L3NGsz9UhJ/0HjBdbnkhIK5xviT0X5vtjacF6ajgcCArbTB+ds+p
|
||||
+h7Q084NuSuIpNb6YPfoUFgC/CL9kAoc
|
||||
-----END PUBLIC KEY-----
|
||||
@@ -1,11 +0,0 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: GnuPG v2.0.22 (MingW32)
|
||||
|
||||
iQEcBAABAgAGBQJWtW1hAAoJEGuXocKCZATaJf0H+wbZGgskK1dcRTsuVJl9IWip
|
||||
QwGw/qIKI280SD6/ckoUMxKDCJiFuPR14zmqnS36k7N5UNPnpdTJTS8T11jttSpg
|
||||
1LCmgpbEIpgaTah+cELDqFCav99fS+bEiAL5lWDAHBTE/XPjGVCqeehyPYref4IW
|
||||
NDBIEsvnHPHPLsn6X5jq4+Yj5oUixgxaMPiR+bcO4Sh+RzOVB6i2D0upWfRXBFXA
|
||||
NNnsg9/zjvoC7ZW73y9uSH+dPJTt/Vgfeiv52/v41XliyzbUyLalf02GNPY+9goV
|
||||
JHG1ulEEBJOCiUD9cE1PUIJwHA/HqyhHIvV350YoEFiHl8iSwm7SiZu5kPjaq74=
|
||||
=B6+8
|
||||
-----END PGP SIGNATURE-----
|
||||
@@ -1,196 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
/**
|
||||
* Random_* Compatibility Library
|
||||
* for using the new PHP 7 random_* API in PHP 5 projects
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015 - 2018 Paragon Initiative Enterprises
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
if (!is_callable('RandomCompat_strlen')) {
|
||||
if (
|
||||
defined('MB_OVERLOAD_STRING')
|
||||
&&
|
||||
((int) ini_get('mbstring.func_overload')) & MB_OVERLOAD_STRING
|
||||
) {
|
||||
/**
|
||||
* strlen() implementation that isn't brittle to mbstring.func_overload
|
||||
*
|
||||
* This version uses mb_strlen() in '8bit' mode to treat strings as raw
|
||||
* binary rather than UTF-8, ISO-8859-1, etc
|
||||
*
|
||||
* @param string $binary_string
|
||||
*
|
||||
* @throws TypeError
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
function RandomCompat_strlen($binary_string)
|
||||
{
|
||||
if (!is_string($binary_string)) {
|
||||
throw new TypeError(
|
||||
'RandomCompat_strlen() expects a string'
|
||||
);
|
||||
}
|
||||
|
||||
return (int) mb_strlen($binary_string, '8bit');
|
||||
}
|
||||
|
||||
} else {
|
||||
/**
|
||||
* strlen() implementation that isn't brittle to mbstring.func_overload
|
||||
*
|
||||
* This version just used the default strlen()
|
||||
*
|
||||
* @param string $binary_string
|
||||
*
|
||||
* @throws TypeError
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
function RandomCompat_strlen($binary_string)
|
||||
{
|
||||
if (!is_string($binary_string)) {
|
||||
throw new TypeError(
|
||||
'RandomCompat_strlen() expects a string'
|
||||
);
|
||||
}
|
||||
return (int) strlen($binary_string);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_callable('RandomCompat_substr')) {
|
||||
|
||||
if (
|
||||
defined('MB_OVERLOAD_STRING')
|
||||
&&
|
||||
((int) ini_get('mbstring.func_overload')) & MB_OVERLOAD_STRING
|
||||
) {
|
||||
/**
|
||||
* substr() implementation that isn't brittle to mbstring.func_overload
|
||||
*
|
||||
* This version uses mb_substr() in '8bit' mode to treat strings as raw
|
||||
* binary rather than UTF-8, ISO-8859-1, etc
|
||||
*
|
||||
* @param string $binary_string
|
||||
* @param int $start
|
||||
* @param int|null $length (optional)
|
||||
*
|
||||
* @throws TypeError
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function RandomCompat_substr($binary_string, $start, $length = null)
|
||||
{
|
||||
if (!is_string($binary_string)) {
|
||||
throw new TypeError(
|
||||
'RandomCompat_substr(): First argument should be a string'
|
||||
);
|
||||
}
|
||||
|
||||
if (!is_int($start)) {
|
||||
throw new TypeError(
|
||||
'RandomCompat_substr(): Second argument should be an integer'
|
||||
);
|
||||
}
|
||||
|
||||
if ($length === null) {
|
||||
/**
|
||||
* mb_substr($str, 0, NULL, '8bit') returns an empty string on
|
||||
* PHP 5.3, so we have to find the length ourselves.
|
||||
*/
|
||||
/** @var int $length */
|
||||
$length = RandomCompat_strlen($binary_string) - $start;
|
||||
} elseif (!is_int($length)) {
|
||||
throw new TypeError(
|
||||
'RandomCompat_substr(): Third argument should be an integer, or omitted'
|
||||
);
|
||||
}
|
||||
|
||||
// Consistency with PHP's behavior
|
||||
if ($start === RandomCompat_strlen($binary_string) && $length === 0) {
|
||||
return '';
|
||||
}
|
||||
if ($start > RandomCompat_strlen($binary_string)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return (string) mb_substr(
|
||||
(string) $binary_string,
|
||||
(int) $start,
|
||||
(int) $length,
|
||||
'8bit'
|
||||
);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/**
|
||||
* substr() implementation that isn't brittle to mbstring.func_overload
|
||||
*
|
||||
* This version just uses the default substr()
|
||||
*
|
||||
* @param string $binary_string
|
||||
* @param int $start
|
||||
* @param int|null $length (optional)
|
||||
*
|
||||
* @throws TypeError
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function RandomCompat_substr($binary_string, $start, $length = null)
|
||||
{
|
||||
if (!is_string($binary_string)) {
|
||||
throw new TypeError(
|
||||
'RandomCompat_substr(): First argument should be a string'
|
||||
);
|
||||
}
|
||||
|
||||
if (!is_int($start)) {
|
||||
throw new TypeError(
|
||||
'RandomCompat_substr(): Second argument should be an integer'
|
||||
);
|
||||
}
|
||||
|
||||
if ($length !== null) {
|
||||
if (!is_int($length)) {
|
||||
throw new TypeError(
|
||||
'RandomCompat_substr(): Third argument should be an integer, or omitted'
|
||||
);
|
||||
}
|
||||
|
||||
return (string) substr(
|
||||
(string )$binary_string,
|
||||
(int) $start,
|
||||
(int) $length
|
||||
);
|
||||
}
|
||||
|
||||
return (string) substr(
|
||||
(string) $binary_string,
|
||||
(int) $start
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
/**
|
||||
* Random_* Compatibility Library
|
||||
* for using the new PHP 7 random_* API in PHP 5 projects
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015 - 2018 Paragon Initiative Enterprises
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
if (!is_callable('RandomCompat_intval')) {
|
||||
|
||||
/**
|
||||
* Cast to an integer if we can, safely.
|
||||
*
|
||||
* If you pass it a float in the range (~PHP_INT_MAX, PHP_INT_MAX)
|
||||
* (non-inclusive), it will sanely cast it to an int. If you it's equal to
|
||||
* ~PHP_INT_MAX or PHP_INT_MAX, we let it fail as not an integer. Floats
|
||||
* lose precision, so the <= and => operators might accidentally let a float
|
||||
* through.
|
||||
*
|
||||
* @param int|float $number The number we want to convert to an int
|
||||
* @param bool $fail_open Set to true to not throw an exception
|
||||
*
|
||||
* @return float|int
|
||||
* @psalm-suppress InvalidReturnType
|
||||
*
|
||||
* @throws TypeError
|
||||
*/
|
||||
function RandomCompat_intval($number, $fail_open = false)
|
||||
{
|
||||
if (is_int($number) || is_float($number)) {
|
||||
$number += 0;
|
||||
} elseif (is_numeric($number)) {
|
||||
/** @psalm-suppress InvalidOperand */
|
||||
$number += 0;
|
||||
}
|
||||
/** @var int|float $number */
|
||||
|
||||
if (
|
||||
is_float($number)
|
||||
&&
|
||||
$number > ~PHP_INT_MAX
|
||||
&&
|
||||
$number < PHP_INT_MAX
|
||||
) {
|
||||
$number = (int) $number;
|
||||
}
|
||||
|
||||
if (is_int($number)) {
|
||||
return (int) $number;
|
||||
} elseif (!$fail_open) {
|
||||
throw new TypeError(
|
||||
'Expected an integer.'
|
||||
);
|
||||
}
|
||||
return $number;
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
/**
|
||||
* Random_* Compatibility Library
|
||||
* for using the new PHP 7 random_* API in PHP 5 projects
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015 - 2018 Paragon Initiative Enterprises
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
if (!class_exists('Error', false)) {
|
||||
// We can't really avoid making this extend Exception in PHP 5.
|
||||
class Error extends Exception
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (!class_exists('TypeError', false)) {
|
||||
if (is_subclass_of('Error', 'Exception')) {
|
||||
class TypeError extends Error
|
||||
{
|
||||
|
||||
}
|
||||
} else {
|
||||
class TypeError extends Exception
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,227 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
/**
|
||||
* Random_* Compatibility Library
|
||||
* for using the new PHP 7 random_* API in PHP 5 projects
|
||||
*
|
||||
* @version 2.0.17
|
||||
* @released 2018-07-04
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015 - 2018 Paragon Initiative Enterprises
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
if (!defined('PHP_VERSION_ID')) {
|
||||
// This constant was introduced in PHP 5.2.7
|
||||
$RandomCompatversion = array_map('intval', explode('.', PHP_VERSION));
|
||||
define(
|
||||
'PHP_VERSION_ID',
|
||||
$RandomCompatversion[0] * 10000
|
||||
+ $RandomCompatversion[1] * 100
|
||||
+ $RandomCompatversion[2]
|
||||
);
|
||||
$RandomCompatversion = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* PHP 7.0.0 and newer have these functions natively.
|
||||
*/
|
||||
if (PHP_VERSION_ID >= 70000) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!defined('RANDOM_COMPAT_READ_BUFFER')) {
|
||||
define('RANDOM_COMPAT_READ_BUFFER', 8);
|
||||
}
|
||||
|
||||
$RandomCompatDIR = dirname(__FILE__);
|
||||
|
||||
require_once $RandomCompatDIR.DIRECTORY_SEPARATOR.'byte_safe_strings.php';
|
||||
require_once $RandomCompatDIR.DIRECTORY_SEPARATOR.'cast_to_int.php';
|
||||
require_once $RandomCompatDIR.DIRECTORY_SEPARATOR.'error_polyfill.php';
|
||||
|
||||
if (!is_callable('random_bytes')) {
|
||||
/**
|
||||
* PHP 5.2.0 - 5.6.x way to implement random_bytes()
|
||||
*
|
||||
* We use conditional statements here to define the function in accordance
|
||||
* to the operating environment. It's a micro-optimization.
|
||||
*
|
||||
* In order of preference:
|
||||
* 1. Use libsodium if available.
|
||||
* 2. fread() /dev/urandom if available (never on Windows)
|
||||
* 3. mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM)
|
||||
* 4. COM('CAPICOM.Utilities.1')->GetRandom()
|
||||
*
|
||||
* See RATIONALE.md for our reasoning behind this particular order
|
||||
*/
|
||||
if (extension_loaded('libsodium')) {
|
||||
// See random_bytes_libsodium.php
|
||||
if (PHP_VERSION_ID >= 50300 && is_callable('\\Sodium\\randombytes_buf')) {
|
||||
require_once $RandomCompatDIR.DIRECTORY_SEPARATOR.'random_bytes_libsodium.php';
|
||||
} elseif (method_exists('Sodium', 'randombytes_buf')) {
|
||||
require_once $RandomCompatDIR.DIRECTORY_SEPARATOR.'random_bytes_libsodium_legacy.php';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reading directly from /dev/urandom:
|
||||
*/
|
||||
if (DIRECTORY_SEPARATOR === '/') {
|
||||
// DIRECTORY_SEPARATOR === '/' on Unix-like OSes -- this is a fast
|
||||
// way to exclude Windows.
|
||||
$RandomCompatUrandom = true;
|
||||
$RandomCompat_basedir = ini_get('open_basedir');
|
||||
|
||||
if (!empty($RandomCompat_basedir)) {
|
||||
$RandomCompat_open_basedir = explode(
|
||||
PATH_SEPARATOR,
|
||||
strtolower($RandomCompat_basedir)
|
||||
);
|
||||
$RandomCompatUrandom = (array() !== array_intersect(
|
||||
array('/dev', '/dev/', '/dev/urandom'),
|
||||
$RandomCompat_open_basedir
|
||||
));
|
||||
$RandomCompat_open_basedir = null;
|
||||
}
|
||||
|
||||
if (
|
||||
!is_callable('random_bytes')
|
||||
&&
|
||||
$RandomCompatUrandom
|
||||
&&
|
||||
@is_readable('/dev/urandom')
|
||||
) {
|
||||
// Error suppression on is_readable() in case of an open_basedir
|
||||
// or safe_mode failure. All we care about is whether or not we
|
||||
// can read it at this point. If the PHP environment is going to
|
||||
// panic over trying to see if the file can be read in the first
|
||||
// place, that is not helpful to us here.
|
||||
|
||||
// See random_bytes_dev_urandom.php
|
||||
require_once $RandomCompatDIR.DIRECTORY_SEPARATOR.'random_bytes_dev_urandom.php';
|
||||
}
|
||||
// Unset variables after use
|
||||
$RandomCompat_basedir = null;
|
||||
} else {
|
||||
$RandomCompatUrandom = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* mcrypt_create_iv()
|
||||
*
|
||||
* We only want to use mcypt_create_iv() if:
|
||||
*
|
||||
* - random_bytes() hasn't already been defined
|
||||
* - the mcrypt extensions is loaded
|
||||
* - One of these two conditions is true:
|
||||
* - We're on Windows (DIRECTORY_SEPARATOR !== '/')
|
||||
* - We're not on Windows and /dev/urandom is readabale
|
||||
* (i.e. we're not in a chroot jail)
|
||||
* - Special case:
|
||||
* - If we're not on Windows, but the PHP version is between
|
||||
* 5.6.10 and 5.6.12, we don't want to use mcrypt. It will
|
||||
* hang indefinitely. This is bad.
|
||||
* - If we're on Windows, we want to use PHP >= 5.3.7 or else
|
||||
* we get insufficient entropy errors.
|
||||
*/
|
||||
if (
|
||||
!is_callable('random_bytes')
|
||||
&&
|
||||
// Windows on PHP < 5.3.7 is broken, but non-Windows is not known to be.
|
||||
(DIRECTORY_SEPARATOR === '/' || PHP_VERSION_ID >= 50307)
|
||||
&&
|
||||
// Prevent this code from hanging indefinitely on non-Windows;
|
||||
// see https://bugs.php.net/bug.php?id=69833
|
||||
(
|
||||
DIRECTORY_SEPARATOR !== '/' ||
|
||||
(PHP_VERSION_ID <= 50609 || PHP_VERSION_ID >= 50613)
|
||||
)
|
||||
&&
|
||||
extension_loaded('mcrypt')
|
||||
) {
|
||||
// See random_bytes_mcrypt.php
|
||||
require_once $RandomCompatDIR.DIRECTORY_SEPARATOR.'random_bytes_mcrypt.php';
|
||||
}
|
||||
$RandomCompatUrandom = null;
|
||||
|
||||
/**
|
||||
* This is a Windows-specific fallback, for when the mcrypt extension
|
||||
* isn't loaded.
|
||||
*/
|
||||
if (
|
||||
!is_callable('random_bytes')
|
||||
&&
|
||||
extension_loaded('com_dotnet')
|
||||
&&
|
||||
class_exists('COM')
|
||||
) {
|
||||
$RandomCompat_disabled_classes = preg_split(
|
||||
'#\s*,\s*#',
|
||||
strtolower(ini_get('disable_classes'))
|
||||
);
|
||||
|
||||
if (!in_array('com', $RandomCompat_disabled_classes)) {
|
||||
try {
|
||||
$RandomCompatCOMtest = new COM('CAPICOM.Utilities.1');
|
||||
/** @psalm-suppress TypeDoesNotContainType */
|
||||
if (is_callable(array($RandomCompatCOMtest, 'GetRandom'))) {
|
||||
// See random_bytes_com_dotnet.php
|
||||
require_once $RandomCompatDIR.DIRECTORY_SEPARATOR.'random_bytes_com_dotnet.php';
|
||||
}
|
||||
} catch (com_exception $e) {
|
||||
// Don't try to use it.
|
||||
}
|
||||
}
|
||||
$RandomCompat_disabled_classes = null;
|
||||
$RandomCompatCOMtest = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* throw new Exception
|
||||
*/
|
||||
if (!is_callable('random_bytes')) {
|
||||
/**
|
||||
* We don't have any more options, so let's throw an exception right now
|
||||
* and hope the developer won't let it fail silently.
|
||||
*
|
||||
* @param mixed $length
|
||||
* @psalm-suppress InvalidReturnType
|
||||
* @throws Exception
|
||||
* @return string
|
||||
*/
|
||||
function random_bytes($length)
|
||||
{
|
||||
unset($length); // Suppress "variable not used" warnings.
|
||||
throw new Exception(
|
||||
'There is no suitable CSPRNG installed on your system'
|
||||
);
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_callable('random_int')) {
|
||||
require_once $RandomCompatDIR.DIRECTORY_SEPARATOR.'random_int.php';
|
||||
}
|
||||
|
||||
$RandomCompatDIR = null;
|
||||
@@ -1,92 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
/**
|
||||
* Random_* Compatibility Library
|
||||
* for using the new PHP 7 random_* API in PHP 5 projects
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015 - 2018 Paragon Initiative Enterprises
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
if (!is_callable('random_bytes')) {
|
||||
/**
|
||||
* Windows with PHP < 5.3.0 will not have the function
|
||||
* openssl_random_pseudo_bytes() available, so let's use
|
||||
* CAPICOM to work around this deficiency.
|
||||
*
|
||||
* @param int $bytes
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function random_bytes($bytes)
|
||||
{
|
||||
try {
|
||||
/** @var int $bytes */
|
||||
$bytes = RandomCompat_intval($bytes);
|
||||
} catch (TypeError $ex) {
|
||||
throw new TypeError(
|
||||
'random_bytes(): $bytes must be an integer'
|
||||
);
|
||||
}
|
||||
|
||||
if ($bytes < 1) {
|
||||
throw new Error(
|
||||
'Length must be greater than 0'
|
||||
);
|
||||
}
|
||||
|
||||
/** @var string $buf */
|
||||
$buf = '';
|
||||
if (!class_exists('COM')) {
|
||||
throw new Error(
|
||||
'COM does not exist'
|
||||
);
|
||||
}
|
||||
/** @var COM $util */
|
||||
$util = new COM('CAPICOM.Utilities.1');
|
||||
$execCount = 0;
|
||||
|
||||
/**
|
||||
* Let's not let it loop forever. If we run N times and fail to
|
||||
* get N bytes of random data, then CAPICOM has failed us.
|
||||
*/
|
||||
do {
|
||||
$buf .= base64_decode((string) $util->GetRandom($bytes, 0));
|
||||
if (RandomCompat_strlen($buf) >= $bytes) {
|
||||
/**
|
||||
* Return our random entropy buffer here:
|
||||
*/
|
||||
return (string) RandomCompat_substr($buf, 0, $bytes);
|
||||
}
|
||||
++$execCount;
|
||||
} while ($execCount < $bytes);
|
||||
|
||||
/**
|
||||
* If we reach here, PHP has failed us.
|
||||
*/
|
||||
throw new Exception(
|
||||
'Could not gather sufficient random data'
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,191 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
/**
|
||||
* Random_* Compatibility Library
|
||||
* for using the new PHP 7 random_* API in PHP 5 projects
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015 - 2018 Paragon Initiative Enterprises
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
if (!defined('RANDOM_COMPAT_READ_BUFFER')) {
|
||||
define('RANDOM_COMPAT_READ_BUFFER', 8);
|
||||
}
|
||||
|
||||
if (!is_callable('random_bytes')) {
|
||||
/**
|
||||
* Unless open_basedir is enabled, use /dev/urandom for
|
||||
* random numbers in accordance with best practices
|
||||
*
|
||||
* Why we use /dev/urandom and not /dev/random
|
||||
* @ref https://www.2uo.de/myths-about-urandom
|
||||
* @ref http://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers
|
||||
*
|
||||
* @param int $bytes
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function random_bytes($bytes)
|
||||
{
|
||||
/** @var resource $fp */
|
||||
static $fp = null;
|
||||
|
||||
/**
|
||||
* This block should only be run once
|
||||
*/
|
||||
if (empty($fp)) {
|
||||
/**
|
||||
* We don't want to ever read C:\dev\random, only /dev/urandom on
|
||||
* Unix-like operating systems. While we guard against this
|
||||
* condition in random.php, it doesn't hurt to be defensive in depth
|
||||
* here.
|
||||
*
|
||||
* To that end, we only try to open /dev/urandom if we're on a Unix-
|
||||
* like operating system (which means the directory separator is set
|
||||
* to "/" not "\".
|
||||
*/
|
||||
if (DIRECTORY_SEPARATOR === '/') {
|
||||
if (!is_readable('/dev/urandom')) {
|
||||
throw new Exception(
|
||||
'Environment misconfiguration: ' .
|
||||
'/dev/urandom cannot be read.'
|
||||
);
|
||||
}
|
||||
/**
|
||||
* We use /dev/urandom if it is a char device.
|
||||
* We never fall back to /dev/random
|
||||
*/
|
||||
/** @var resource|bool $fp */
|
||||
$fp = fopen('/dev/urandom', 'rb');
|
||||
if (is_resource($fp)) {
|
||||
/** @var array<string, int> $st */
|
||||
$st = fstat($fp);
|
||||
if (($st['mode'] & 0170000) !== 020000) {
|
||||
fclose($fp);
|
||||
$fp = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (is_resource($fp)) {
|
||||
/**
|
||||
* stream_set_read_buffer() does not exist in HHVM
|
||||
*
|
||||
* If we don't set the stream's read buffer to 0, PHP will
|
||||
* internally buffer 8192 bytes, which can waste entropy
|
||||
*
|
||||
* stream_set_read_buffer returns 0 on success
|
||||
*/
|
||||
if (is_callable('stream_set_read_buffer')) {
|
||||
stream_set_read_buffer($fp, RANDOM_COMPAT_READ_BUFFER);
|
||||
}
|
||||
if (is_callable('stream_set_chunk_size')) {
|
||||
stream_set_chunk_size($fp, RANDOM_COMPAT_READ_BUFFER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
/** @var int $bytes */
|
||||
$bytes = RandomCompat_intval($bytes);
|
||||
} catch (TypeError $ex) {
|
||||
throw new TypeError(
|
||||
'random_bytes(): $bytes must be an integer'
|
||||
);
|
||||
}
|
||||
|
||||
if ($bytes < 1) {
|
||||
throw new Error(
|
||||
'Length must be greater than 0'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* This if() block only runs if we managed to open a file handle
|
||||
*
|
||||
* It does not belong in an else {} block, because the above
|
||||
* if (empty($fp)) line is logic that should only be run once per
|
||||
* page load.
|
||||
*/
|
||||
if (is_resource($fp)) {
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
$remaining = $bytes;
|
||||
|
||||
/**
|
||||
* @var string|bool
|
||||
*/
|
||||
$buf = '';
|
||||
|
||||
/**
|
||||
* We use fread() in a loop to protect against partial reads
|
||||
*/
|
||||
do {
|
||||
/**
|
||||
* @var string|bool
|
||||
*/
|
||||
$read = fread($fp, $remaining);
|
||||
if (!is_string($read)) {
|
||||
/**
|
||||
* We cannot safely read from the file. Exit the
|
||||
* do-while loop and trigger the exception condition
|
||||
*
|
||||
* @var string|bool
|
||||
*/
|
||||
$buf = false;
|
||||
break;
|
||||
}
|
||||
/**
|
||||
* Decrease the number of bytes returned from remaining
|
||||
*/
|
||||
$remaining -= RandomCompat_strlen($read);
|
||||
/**
|
||||
* @var string $buf
|
||||
*/
|
||||
$buf .= $read;
|
||||
} while ($remaining > 0);
|
||||
|
||||
/**
|
||||
* Is our result valid?
|
||||
* @var string|bool $buf
|
||||
*/
|
||||
if (is_string($buf)) {
|
||||
if (RandomCompat_strlen($buf) === $bytes) {
|
||||
/**
|
||||
* Return our random entropy buffer here:
|
||||
*/
|
||||
return $buf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If we reach here, PHP has failed us.
|
||||
*/
|
||||
throw new Exception(
|
||||
'Error reading from source device'
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
/**
|
||||
* Random_* Compatibility Library
|
||||
* for using the new PHP 7 random_* API in PHP 5 projects
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015 - 2018 Paragon Initiative Enterprises
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
if (!is_callable('random_bytes')) {
|
||||
/**
|
||||
* If the libsodium PHP extension is loaded, we'll use it above any other
|
||||
* solution.
|
||||
*
|
||||
* libsodium-php project:
|
||||
* @ref https://github.com/jedisct1/libsodium-php
|
||||
*
|
||||
* @param int $bytes
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function random_bytes($bytes)
|
||||
{
|
||||
try {
|
||||
/** @var int $bytes */
|
||||
$bytes = RandomCompat_intval($bytes);
|
||||
} catch (TypeError $ex) {
|
||||
throw new TypeError(
|
||||
'random_bytes(): $bytes must be an integer'
|
||||
);
|
||||
}
|
||||
|
||||
if ($bytes < 1) {
|
||||
throw new Error(
|
||||
'Length must be greater than 0'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* \Sodium\randombytes_buf() doesn't allow more than 2147483647 bytes to be
|
||||
* generated in one invocation.
|
||||
*/
|
||||
/** @var string|bool $buf */
|
||||
if ($bytes > 2147483647) {
|
||||
$buf = '';
|
||||
for ($i = 0; $i < $bytes; $i += 1073741824) {
|
||||
$n = ($bytes - $i) > 1073741824
|
||||
? 1073741824
|
||||
: $bytes - $i;
|
||||
$buf .= \Sodium\randombytes_buf($n);
|
||||
}
|
||||
} else {
|
||||
/** @var string|bool $buf */
|
||||
$buf = \Sodium\randombytes_buf($bytes);
|
||||
}
|
||||
|
||||
if (is_string($buf)) {
|
||||
if (RandomCompat_strlen($buf) === $bytes) {
|
||||
return $buf;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If we reach here, PHP has failed us.
|
||||
*/
|
||||
throw new Exception(
|
||||
'Could not gather sufficient random data'
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
/**
|
||||
* Random_* Compatibility Library
|
||||
* for using the new PHP 7 random_* API in PHP 5 projects
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015 - 2018 Paragon Initiative Enterprises
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
if (!is_callable('random_bytes')) {
|
||||
/**
|
||||
* If the libsodium PHP extension is loaded, we'll use it above any other
|
||||
* solution.
|
||||
*
|
||||
* libsodium-php project:
|
||||
* @ref https://github.com/jedisct1/libsodium-php
|
||||
*
|
||||
* @param int $bytes
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function random_bytes($bytes)
|
||||
{
|
||||
try {
|
||||
/** @var int $bytes */
|
||||
$bytes = RandomCompat_intval($bytes);
|
||||
} catch (TypeError $ex) {
|
||||
throw new TypeError(
|
||||
'random_bytes(): $bytes must be an integer'
|
||||
);
|
||||
}
|
||||
|
||||
if ($bytes < 1) {
|
||||
throw new Error(
|
||||
'Length must be greater than 0'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
$buf = '';
|
||||
|
||||
/**
|
||||
* \Sodium\randombytes_buf() doesn't allow more than 2147483647 bytes to be
|
||||
* generated in one invocation.
|
||||
*/
|
||||
if ($bytes > 2147483647) {
|
||||
for ($i = 0; $i < $bytes; $i += 1073741824) {
|
||||
$n = ($bytes - $i) > 1073741824
|
||||
? 1073741824
|
||||
: $bytes - $i;
|
||||
$buf .= Sodium::randombytes_buf((int) $n);
|
||||
}
|
||||
} else {
|
||||
$buf .= Sodium::randombytes_buf((int) $bytes);
|
||||
}
|
||||
|
||||
if (is_string($buf)) {
|
||||
if (RandomCompat_strlen($buf) === $bytes) {
|
||||
return $buf;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If we reach here, PHP has failed us.
|
||||
*/
|
||||
throw new Exception(
|
||||
'Could not gather sufficient random data'
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
/**
|
||||
* Random_* Compatibility Library
|
||||
* for using the new PHP 7 random_* API in PHP 5 projects
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015 - 2018 Paragon Initiative Enterprises
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
if (!is_callable('random_bytes')) {
|
||||
/**
|
||||
* Powered by ext/mcrypt (and thankfully NOT libmcrypt)
|
||||
*
|
||||
* @ref https://bugs.php.net/bug.php?id=55169
|
||||
* @ref https://github.com/php/php-src/blob/c568ffe5171d942161fc8dda066bce844bdef676/ext/mcrypt/mcrypt.c#L1321-L1386
|
||||
*
|
||||
* @param int $bytes
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function random_bytes($bytes)
|
||||
{
|
||||
try {
|
||||
/** @var int $bytes */
|
||||
$bytes = RandomCompat_intval($bytes);
|
||||
} catch (TypeError $ex) {
|
||||
throw new TypeError(
|
||||
'random_bytes(): $bytes must be an integer'
|
||||
);
|
||||
}
|
||||
|
||||
if ($bytes < 1) {
|
||||
throw new Error(
|
||||
'Length must be greater than 0'
|
||||
);
|
||||
}
|
||||
|
||||
/** @var string|bool $buf */
|
||||
$buf = @mcrypt_create_iv((int) $bytes, (int) MCRYPT_DEV_URANDOM);
|
||||
if (
|
||||
is_string($buf)
|
||||
&&
|
||||
RandomCompat_strlen($buf) === $bytes
|
||||
) {
|
||||
/**
|
||||
* Return our random entropy buffer here:
|
||||
*/
|
||||
return $buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* If we reach here, PHP has failed us.
|
||||
*/
|
||||
throw new Exception(
|
||||
'Could not gather sufficient random data'
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,205 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
|
||||
if (!is_callable('random_int')) {
|
||||
/**
|
||||
* Random_* Compatibility Library
|
||||
* for using the new PHP 7 random_* API in PHP 5 projects
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015 - 2018 Paragon Initiative Enterprises
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fetch a random integer between $min and $max inclusive
|
||||
*
|
||||
* @param int $min
|
||||
* @param int $max
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
function random_int($min, $max)
|
||||
{
|
||||
/**
|
||||
* Type and input logic checks
|
||||
*
|
||||
* If you pass it a float in the range (~PHP_INT_MAX, PHP_INT_MAX)
|
||||
* (non-inclusive), it will sanely cast it to an int. If you it's equal to
|
||||
* ~PHP_INT_MAX or PHP_INT_MAX, we let it fail as not an integer. Floats
|
||||
* lose precision, so the <= and => operators might accidentally let a float
|
||||
* through.
|
||||
*/
|
||||
|
||||
try {
|
||||
/** @var int $min */
|
||||
$min = RandomCompat_intval($min);
|
||||
} catch (TypeError $ex) {
|
||||
throw new TypeError(
|
||||
'random_int(): $min must be an integer'
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
/** @var int $max */
|
||||
$max = RandomCompat_intval($max);
|
||||
} catch (TypeError $ex) {
|
||||
throw new TypeError(
|
||||
'random_int(): $max must be an integer'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Now that we've verified our weak typing system has given us an integer,
|
||||
* let's validate the logic then we can move forward with generating random
|
||||
* integers along a given range.
|
||||
*/
|
||||
if ($min > $max) {
|
||||
throw new Error(
|
||||
'Minimum value must be less than or equal to the maximum value'
|
||||
);
|
||||
}
|
||||
|
||||
if ($max === $min) {
|
||||
return (int) $min;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize variables to 0
|
||||
*
|
||||
* We want to store:
|
||||
* $bytes => the number of random bytes we need
|
||||
* $mask => an integer bitmask (for use with the &) operator
|
||||
* so we can minimize the number of discards
|
||||
*/
|
||||
$attempts = $bits = $bytes = $mask = $valueShift = 0;
|
||||
/** @var int $attempts */
|
||||
/** @var int $bits */
|
||||
/** @var int $bytes */
|
||||
/** @var int $mask */
|
||||
/** @var int $valueShift */
|
||||
|
||||
/**
|
||||
* At this point, $range is a positive number greater than 0. It might
|
||||
* overflow, however, if $max - $min > PHP_INT_MAX. PHP will cast it to
|
||||
* a float and we will lose some precision.
|
||||
*
|
||||
* @var int|float $range
|
||||
*/
|
||||
$range = $max - $min;
|
||||
|
||||
/**
|
||||
* Test for integer overflow:
|
||||
*/
|
||||
if (!is_int($range)) {
|
||||
|
||||
/**
|
||||
* Still safely calculate wider ranges.
|
||||
* Provided by @CodesInChaos, @oittaa
|
||||
*
|
||||
* @ref https://gist.github.com/CodesInChaos/03f9ea0b58e8b2b8d435
|
||||
*
|
||||
* We use ~0 as a mask in this case because it generates all 1s
|
||||
*
|
||||
* @ref https://eval.in/400356 (32-bit)
|
||||
* @ref http://3v4l.org/XX9r5 (64-bit)
|
||||
*/
|
||||
$bytes = PHP_INT_SIZE;
|
||||
/** @var int $mask */
|
||||
$mask = ~0;
|
||||
|
||||
} else {
|
||||
|
||||
/**
|
||||
* $bits is effectively ceil(log($range, 2)) without dealing with
|
||||
* type juggling
|
||||
*/
|
||||
while ($range > 0) {
|
||||
if ($bits % 8 === 0) {
|
||||
++$bytes;
|
||||
}
|
||||
++$bits;
|
||||
$range >>= 1;
|
||||
/** @var int $mask */
|
||||
$mask = $mask << 1 | 1;
|
||||
}
|
||||
$valueShift = $min;
|
||||
}
|
||||
|
||||
/** @var int $val */
|
||||
$val = 0;
|
||||
/**
|
||||
* Now that we have our parameters set up, let's begin generating
|
||||
* random integers until one falls between $min and $max
|
||||
*/
|
||||
/** @psalm-suppress RedundantCondition */
|
||||
do {
|
||||
/**
|
||||
* The rejection probability is at most 0.5, so this corresponds
|
||||
* to a failure probability of 2^-128 for a working RNG
|
||||
*/
|
||||
if ($attempts > 128) {
|
||||
throw new Exception(
|
||||
'random_int: RNG is broken - too many rejections'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Let's grab the necessary number of random bytes
|
||||
*/
|
||||
$randomByteString = random_bytes($bytes);
|
||||
|
||||
/**
|
||||
* Let's turn $randomByteString into an integer
|
||||
*
|
||||
* This uses bitwise operators (<< and |) to build an integer
|
||||
* out of the values extracted from ord()
|
||||
*
|
||||
* Example: [9F] | [6D] | [32] | [0C] =>
|
||||
* 159 + 27904 + 3276800 + 201326592 =>
|
||||
* 204631455
|
||||
*/
|
||||
$val &= 0;
|
||||
for ($i = 0; $i < $bytes; ++$i) {
|
||||
$val |= ord($randomByteString[$i]) << ($i * 8);
|
||||
}
|
||||
/** @var int $val */
|
||||
|
||||
/**
|
||||
* Apply mask
|
||||
*/
|
||||
$val &= $mask;
|
||||
$val += $valueShift;
|
||||
|
||||
++$attempts;
|
||||
/**
|
||||
* If $val overflows to a floating point number,
|
||||
* ... or is larger than $max,
|
||||
* ... or smaller than $min,
|
||||
* then try again.
|
||||
*/
|
||||
} while (!is_int($val) || $val > $max || $val < $min);
|
||||
|
||||
return (int) $val;
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
ISC License
|
||||
|
||||
Copyright (c) 2016-2023, Paragon Initiative Enterprises <security at paragonie dot com>
|
||||
Copyright (c) 2013-2019, Frank Denis <j at pureftpd dot org>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
@@ -1,32 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
/*
|
||||
This file should only ever be loaded on PHP 7+
|
||||
*/
|
||||
if (PHP_VERSION_ID < 70000) {
|
||||
return;
|
||||
}
|
||||
|
||||
spl_autoload_register(function ($class) {
|
||||
$namespace = 'ParagonIE_Sodium_';
|
||||
// Does the class use the namespace prefix?
|
||||
$len = strlen($namespace);
|
||||
if (strncmp($namespace, $class, $len) !== 0) {
|
||||
// no, move to the next registered autoloader
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the relative class name
|
||||
$relative_class = substr($class, $len);
|
||||
|
||||
// Replace the namespace prefix with the base directory, replace namespace
|
||||
// separators with directory separators in the relative class name, append
|
||||
// with .php
|
||||
$file = dirname(__FILE__) . '/src/' . str_replace('_', '/', $relative_class) . '.php';
|
||||
// if the file exists, require it
|
||||
if (file_exists($file)) {
|
||||
require_once $file;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
@@ -1,76 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
|
||||
if (PHP_VERSION_ID < 70000) {
|
||||
if (!is_callable('sodiumCompatAutoloader')) {
|
||||
/**
|
||||
* Sodium_Compat autoloader.
|
||||
*
|
||||
* @param string $class Class name to be autoloaded.
|
||||
*
|
||||
* @return bool Stop autoloading?
|
||||
*/
|
||||
function sodiumCompatAutoloader($class)
|
||||
{
|
||||
$namespace = 'ParagonIE_Sodium_';
|
||||
// Does the class use the namespace prefix?
|
||||
$len = strlen($namespace);
|
||||
if (strncmp($namespace, $class, $len) !== 0) {
|
||||
// no, move to the next registered autoloader
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the relative class name
|
||||
$relative_class = substr($class, $len);
|
||||
|
||||
// Replace the namespace prefix with the base directory, replace namespace
|
||||
// separators with directory separators in the relative class name, append
|
||||
// with .php
|
||||
$file = dirname(__FILE__) . '/src/' . str_replace('_', '/', $relative_class) . '.php';
|
||||
// if the file exists, require it
|
||||
if (file_exists($file)) {
|
||||
require_once $file;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now that we have an autoloader, let's register it!
|
||||
spl_autoload_register('sodiumCompatAutoloader');
|
||||
}
|
||||
} else {
|
||||
require_once dirname(__FILE__) . '/autoload-php7.php';
|
||||
}
|
||||
|
||||
/* Explicitly, always load the Compat class: */
|
||||
if (!class_exists('ParagonIE_Sodium_Compat', false)) {
|
||||
require_once dirname(__FILE__) . '/src/Compat.php';
|
||||
}
|
||||
|
||||
if (!class_exists('SodiumException', false)) {
|
||||
require_once dirname(__FILE__) . '/src/SodiumException.php';
|
||||
}
|
||||
if (PHP_VERSION_ID >= 50300) {
|
||||
// Namespaces didn't exist before 5.3.0, so don't even try to use this
|
||||
// unless PHP >= 5.3.0
|
||||
require_once dirname(__FILE__) . '/lib/namespaced.php';
|
||||
require_once dirname(__FILE__) . '/lib/sodium_compat.php';
|
||||
} else {
|
||||
require_once dirname(__FILE__) . '/src/PHP52/SplFixedArray.php';
|
||||
}
|
||||
if (PHP_VERSION_ID < 70200 || !extension_loaded('sodium')) {
|
||||
if (PHP_VERSION_ID >= 50300 && !defined('SODIUM_CRYPTO_SCALARMULT_BYTES')) {
|
||||
require_once dirname(__FILE__) . '/lib/php72compat_const.php';
|
||||
}
|
||||
if (PHP_VERSION_ID >= 70000) {
|
||||
assert(class_exists('ParagonIE_Sodium_Compat'), 'Possible filesystem/autoloader bug?');
|
||||
} else {
|
||||
assert(class_exists('ParagonIE_Sodium_Compat'));
|
||||
}
|
||||
require_once(dirname(__FILE__) . '/lib/php72compat.php');
|
||||
} elseif (!function_exists('sodium_crypto_stream_xchacha20_xor')) {
|
||||
// Older versions of {PHP, ext/sodium} will not define these
|
||||
require_once(dirname(__FILE__) . '/lib/php72compat.php');
|
||||
}
|
||||
require_once(dirname(__FILE__) . '/lib/stream-xchacha20.php');
|
||||
require_once(dirname(__FILE__) . '/lib/ristretto255.php');
|
||||
@@ -1,87 +0,0 @@
|
||||
{
|
||||
"name": "paragonie/sodium_compat",
|
||||
"description": "Pure PHP implementation of libsodium; uses the PHP extension if it exists",
|
||||
"keywords": [
|
||||
"PHP",
|
||||
"cryptography",
|
||||
"elliptic curve",
|
||||
"elliptic curve cryptography",
|
||||
"Pure-PHP cryptography",
|
||||
"side-channel resistant",
|
||||
"Curve25519",
|
||||
"X25519",
|
||||
"ECDH",
|
||||
"Elliptic Curve Diffie-Hellman",
|
||||
"Ed25519",
|
||||
"RFC 7748",
|
||||
"RFC 8032",
|
||||
"EdDSA",
|
||||
"Edwards-curve Digital Signature Algorithm",
|
||||
"ChaCha20",
|
||||
"Salsa20",
|
||||
"Xchacha20",
|
||||
"Xsalsa20",
|
||||
"Poly1305",
|
||||
"BLAKE2b",
|
||||
"public-key cryptography",
|
||||
"secret-key cryptography",
|
||||
"AEAD",
|
||||
"Chapoly",
|
||||
"Salpoly",
|
||||
"ChaCha20-Poly1305",
|
||||
"XSalsa20-Poly1305",
|
||||
"XChaCha20-Poly1305",
|
||||
"encryption",
|
||||
"authentication",
|
||||
"libsodium"
|
||||
],
|
||||
"license": "ISC",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Paragon Initiative Enterprises",
|
||||
"email": "security@paragonie.com"
|
||||
},
|
||||
{
|
||||
"name": "Frank Denis",
|
||||
"email": "jedisct1@pureftpd.org"
|
||||
}
|
||||
],
|
||||
"autoload": {
|
||||
"files": ["autoload.php"]
|
||||
},
|
||||
"repositories": [
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/garex/phpunit"
|
||||
},
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/garex/phpunit-mock-objects"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^5.2.4|^5.3|^5.4|^5.5|^5.6|^7|^8",
|
||||
"xrstf/composer-php52": "1.*",
|
||||
"paragonie/random_compat": ">=1"
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"require-dev": {
|
||||
"phpunit/phpunit-php52": "dev-3.6.12-php52",
|
||||
"phpunit/phpunit-mock-objects-php52": "dev-1.1.0-php52"
|
||||
},
|
||||
"scripts": {
|
||||
"post-install-cmd": [
|
||||
"xrstf\\Composer52\\Generator::onPostInstallCmd"
|
||||
],
|
||||
"post-update-cmd": [
|
||||
"xrstf\\Composer52\\Generator::onPostInstallCmd"
|
||||
],
|
||||
"post-autoload-dump": [
|
||||
"xrstf\\Composer52\\Generator::onPostInstallCmd"
|
||||
]
|
||||
},
|
||||
"suggest": {
|
||||
"ext-libsodium": "PHP < 7.0: Better performance, password hashing (Argon2i), secure memory management (memzero), and better security.",
|
||||
"ext-sodium": "PHP >= 7.0: Better performance, password hashing (Argon2i), secure memory management (memzero), and better security."
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
namespace Sodium;
|
||||
|
||||
require_once dirname(dirname(__FILE__)) . '/autoload.php';
|
||||
|
||||
use ParagonIE_Sodium_Compat;
|
||||
|
||||
const CRYPTO_AEAD_AES256GCM_KEYBYTES = ParagonIE_Sodium_Compat::CRYPTO_AEAD_AES256GCM_KEYBYTES;
|
||||
const CRYPTO_AEAD_AES256GCM_NSECBYTES = ParagonIE_Sodium_Compat::CRYPTO_AEAD_AES256GCM_NSECBYTES;
|
||||
const CRYPTO_AEAD_AES256GCM_NPUBBYTES = ParagonIE_Sodium_Compat::CRYPTO_AEAD_AES256GCM_NPUBBYTES;
|
||||
const CRYPTO_AEAD_AES256GCM_ABYTES = ParagonIE_Sodium_Compat::CRYPTO_AEAD_AES256GCM_ABYTES;
|
||||
const CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES = ParagonIE_Sodium_Compat::CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES;
|
||||
const CRYPTO_AEAD_CHACHA20POLY1305_NSECBYTES = ParagonIE_Sodium_Compat::CRYPTO_AEAD_CHACHA20POLY1305_NSECBYTES;
|
||||
const CRYPTO_AEAD_CHACHA20POLY1305_NPUBBYTES = ParagonIE_Sodium_Compat::CRYPTO_AEAD_CHACHA20POLY1305_NPUBBYTES;
|
||||
const CRYPTO_AEAD_CHACHA20POLY1305_ABYTES = ParagonIE_Sodium_Compat::CRYPTO_AEAD_CHACHA20POLY1305_ABYTES;
|
||||
const CRYPTO_AEAD_CHACHA20POLY1305_IETF_KEYBYTES = ParagonIE_Sodium_Compat::CRYPTO_AEAD_CHACHA20POLY1305_IETF_KEYBYTES;
|
||||
const CRYPTO_AEAD_CHACHA20POLY1305_IETF_NSECBYTES = ParagonIE_Sodium_Compat::CRYPTO_AEAD_CHACHA20POLY1305_IETF_NSECBYTES;
|
||||
const CRYPTO_AEAD_CHACHA20POLY1305_IETF_NPUBBYTES = ParagonIE_Sodium_Compat::CRYPTO_AEAD_CHACHA20POLY1305_IETF_NPUBBYTES;
|
||||
const CRYPTO_AEAD_CHACHA20POLY1305_IETF_ABYTES = ParagonIE_Sodium_Compat::CRYPTO_AEAD_CHACHA20POLY1305_IETF_ABYTES;
|
||||
const CRYPTO_AUTH_BYTES = ParagonIE_Sodium_Compat::CRYPTO_AUTH_BYTES;
|
||||
const CRYPTO_AUTH_KEYBYTES = ParagonIE_Sodium_Compat::CRYPTO_AUTH_KEYBYTES;
|
||||
const CRYPTO_BOX_SEALBYTES = ParagonIE_Sodium_Compat::CRYPTO_BOX_SEALBYTES;
|
||||
const CRYPTO_BOX_SECRETKEYBYTES = ParagonIE_Sodium_Compat::CRYPTO_BOX_SECRETKEYBYTES;
|
||||
const CRYPTO_BOX_PUBLICKEYBYTES = ParagonIE_Sodium_Compat::CRYPTO_BOX_PUBLICKEYBYTES;
|
||||
const CRYPTO_BOX_KEYPAIRBYTES = ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES;
|
||||
const CRYPTO_BOX_MACBYTES = ParagonIE_Sodium_Compat::CRYPTO_BOX_MACBYTES;
|
||||
const CRYPTO_BOX_NONCEBYTES = ParagonIE_Sodium_Compat::CRYPTO_BOX_NONCEBYTES;
|
||||
const CRYPTO_BOX_SEEDBYTES = ParagonIE_Sodium_Compat::CRYPTO_BOX_SEEDBYTES;
|
||||
const CRYPTO_KX_BYTES = ParagonIE_Sodium_Compat::CRYPTO_KX_BYTES;
|
||||
const CRYPTO_KX_SEEDBYTES = ParagonIE_Sodium_Compat::CRYPTO_KX_SEEDBYTES;
|
||||
const CRYPTO_KX_PUBLICKEYBYTES = ParagonIE_Sodium_Compat::CRYPTO_KX_PUBLICKEYBYTES;
|
||||
const CRYPTO_KX_SECRETKEYBYTES = ParagonIE_Sodium_Compat::CRYPTO_KX_SECRETKEYBYTES;
|
||||
const CRYPTO_GENERICHASH_BYTES = ParagonIE_Sodium_Compat::CRYPTO_GENERICHASH_BYTES;
|
||||
const CRYPTO_GENERICHASH_BYTES_MIN = ParagonIE_Sodium_Compat::CRYPTO_GENERICHASH_BYTES_MIN;
|
||||
const CRYPTO_GENERICHASH_BYTES_MAX = ParagonIE_Sodium_Compat::CRYPTO_GENERICHASH_BYTES_MAX;
|
||||
const CRYPTO_GENERICHASH_KEYBYTES = ParagonIE_Sodium_Compat::CRYPTO_GENERICHASH_KEYBYTES;
|
||||
const CRYPTO_GENERICHASH_KEYBYTES_MIN = ParagonIE_Sodium_Compat::CRYPTO_GENERICHASH_KEYBYTES_MIN;
|
||||
const CRYPTO_GENERICHASH_KEYBYTES_MAX = ParagonIE_Sodium_Compat::CRYPTO_GENERICHASH_KEYBYTES_MAX;
|
||||
const CRYPTO_SCALARMULT_BYTES = ParagonIE_Sodium_Compat::CRYPTO_SCALARMULT_BYTES;
|
||||
const CRYPTO_SCALARMULT_SCALARBYTES = ParagonIE_Sodium_Compat::CRYPTO_SCALARMULT_SCALARBYTES;
|
||||
const CRYPTO_SHORTHASH_BYTES = ParagonIE_Sodium_Compat::CRYPTO_SHORTHASH_BYTES;
|
||||
const CRYPTO_SHORTHASH_KEYBYTES = ParagonIE_Sodium_Compat::CRYPTO_SHORTHASH_KEYBYTES;
|
||||
const CRYPTO_SECRETBOX_KEYBYTES = ParagonIE_Sodium_Compat::CRYPTO_SECRETBOX_KEYBYTES;
|
||||
const CRYPTO_SECRETBOX_MACBYTES = ParagonIE_Sodium_Compat::CRYPTO_SECRETBOX_MACBYTES;
|
||||
const CRYPTO_SECRETBOX_NONCEBYTES = ParagonIE_Sodium_Compat::CRYPTO_SECRETBOX_NONCEBYTES;
|
||||
const CRYPTO_SIGN_BYTES = ParagonIE_Sodium_Compat::CRYPTO_SIGN_BYTES;
|
||||
const CRYPTO_SIGN_SEEDBYTES = ParagonIE_Sodium_Compat::CRYPTO_SIGN_SEEDBYTES;
|
||||
const CRYPTO_SIGN_PUBLICKEYBYTES = ParagonIE_Sodium_Compat::CRYPTO_SIGN_PUBLICKEYBYTES;
|
||||
const CRYPTO_SIGN_SECRETKEYBYTES = ParagonIE_Sodium_Compat::CRYPTO_SIGN_SECRETKEYBYTES;
|
||||
const CRYPTO_SIGN_KEYPAIRBYTES = ParagonIE_Sodium_Compat::CRYPTO_SIGN_KEYPAIRBYTES;
|
||||
const CRYPTO_STREAM_KEYBYTES = ParagonIE_Sodium_Compat::CRYPTO_STREAM_KEYBYTES;
|
||||
const CRYPTO_STREAM_NONCEBYTES = ParagonIE_Sodium_Compat::CRYPTO_STREAM_NONCEBYTES;
|
||||
@@ -1,49 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
|
||||
require_once dirname(dirname(__FILE__)) . '/autoload.php';
|
||||
|
||||
if (PHP_VERSION_ID < 50300) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* This file is just for convenience, to allow developers to reduce verbosity when
|
||||
* they add this project to their libraries.
|
||||
*
|
||||
* Replace this:
|
||||
*
|
||||
* $x = ParagonIE_Sodium_Compat::crypto_aead_xchacha20poly1305_encrypt(...$args);
|
||||
*
|
||||
* with this:
|
||||
*
|
||||
* use ParagonIE\Sodium\Compat;
|
||||
*
|
||||
* $x = Compat::crypto_aead_xchacha20poly1305_encrypt(...$args);
|
||||
*/
|
||||
spl_autoload_register(function ($class) {
|
||||
if ($class[0] === '\\') {
|
||||
$class = substr($class, 1);
|
||||
}
|
||||
$namespace = 'ParagonIE\\Sodium';
|
||||
// Does the class use the namespace prefix?
|
||||
$len = strlen($namespace);
|
||||
if (strncmp($namespace, $class, $len) !== 0) {
|
||||
// no, move to the next registered autoloader
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the relative class name
|
||||
$relative_class = substr($class, $len);
|
||||
|
||||
// Replace the namespace prefix with the base directory, replace namespace
|
||||
// separators with directory separators in the relative class name, append
|
||||
// with .php
|
||||
$file = dirname(dirname(__FILE__)) . '/namespaced/' . str_replace('\\', '/', $relative_class) . '.php';
|
||||
// if the file exists, require it
|
||||
if (file_exists($file)) {
|
||||
require_once $file;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,93 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
|
||||
const SODIUM_LIBRARY_MAJOR_VERSION = 9;
|
||||
const SODIUM_LIBRARY_MINOR_VERSION = 1;
|
||||
const SODIUM_LIBRARY_VERSION = '1.0.8';
|
||||
|
||||
const SODIUM_BASE64_VARIANT_ORIGINAL = 1;
|
||||
const SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING = 3;
|
||||
const SODIUM_BASE64_VARIANT_URLSAFE = 5;
|
||||
const SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING = 7;
|
||||
const SODIUM_CRYPTO_AEAD_AES256GCM_KEYBYTES = 32;
|
||||
const SODIUM_CRYPTO_AEAD_AES256GCM_NSECBYTES = 0;
|
||||
const SODIUM_CRYPTO_AEAD_AES256GCM_NPUBBYTES = 12;
|
||||
const SODIUM_CRYPTO_AEAD_AES256GCM_ABYTES = 16;
|
||||
const SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES = 32;
|
||||
const SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_NSECBYTES = 0;
|
||||
const SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_NPUBBYTES = 8;
|
||||
const SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_ABYTES = 16;
|
||||
const SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_IETF_KEYBYTES = 32;
|
||||
const SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_IETF_NSECBYTES = 0;
|
||||
const SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_IETF_NPUBBYTES = 12;
|
||||
const SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_IETF_ABYTES = 16;
|
||||
const SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_KEYBYTES = 32;
|
||||
const SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NSECBYTES = 0;
|
||||
const SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NPUBBYTES = 24;
|
||||
const SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_ABYTES = 16;
|
||||
const SODIUM_CRYPTO_AUTH_BYTES = 32;
|
||||
const SODIUM_CRYPTO_AUTH_KEYBYTES = 32;
|
||||
const SODIUM_CRYPTO_BOX_SEALBYTES = 16;
|
||||
const SODIUM_CRYPTO_BOX_SECRETKEYBYTES = 32;
|
||||
const SODIUM_CRYPTO_BOX_PUBLICKEYBYTES = 32;
|
||||
const SODIUM_CRYPTO_BOX_KEYPAIRBYTES = 64;
|
||||
const SODIUM_CRYPTO_BOX_MACBYTES = 16;
|
||||
const SODIUM_CRYPTO_BOX_NONCEBYTES = 24;
|
||||
const SODIUM_CRYPTO_BOX_SEEDBYTES = 32;
|
||||
const SODIUM_CRYPTO_KDF_BYTES_MIN = 16;
|
||||
const SODIUM_CRYPTO_KDF_BYTES_MAX = 64;
|
||||
const SODIUM_CRYPTO_KDF_CONTEXTBYTES = 8;
|
||||
const SODIUM_CRYPTO_KDF_KEYBYTES = 32;
|
||||
const SODIUM_CRYPTO_KX_BYTES = 32;
|
||||
const SODIUM_CRYPTO_KX_PRIMITIVE = 'x25519blake2b';
|
||||
const SODIUM_CRYPTO_KX_SEEDBYTES = 32;
|
||||
const SODIUM_CRYPTO_KX_KEYPAIRBYTES = 64;
|
||||
const SODIUM_CRYPTO_KX_PUBLICKEYBYTES = 32;
|
||||
const SODIUM_CRYPTO_KX_SECRETKEYBYTES = 32;
|
||||
const SODIUM_CRYPTO_KX_SESSIONKEYBYTES = 32;
|
||||
const SODIUM_CRYPTO_GENERICHASH_BYTES = 32;
|
||||
const SODIUM_CRYPTO_GENERICHASH_BYTES_MIN = 16;
|
||||
const SODIUM_CRYPTO_GENERICHASH_BYTES_MAX = 64;
|
||||
const SODIUM_CRYPTO_GENERICHASH_KEYBYTES = 32;
|
||||
const SODIUM_CRYPTO_GENERICHASH_KEYBYTES_MIN = 16;
|
||||
const SODIUM_CRYPTO_GENERICHASH_KEYBYTES_MAX = 64;
|
||||
const SODIUM_CRYPTO_PWHASH_SALTBYTES = 16;
|
||||
const SODIUM_CRYPTO_PWHASH_STRPREFIX = '$argon2id$';
|
||||
const SODIUM_CRYPTO_PWHASH_ALG_ARGON2I13 = 1;
|
||||
const SODIUM_CRYPTO_PWHASH_ALG_ARGON2ID13 = 2;
|
||||
const SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE = 33554432;
|
||||
const SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE = 4;
|
||||
const SODIUM_CRYPTO_PWHASH_MEMLIMIT_MODERATE = 134217728;
|
||||
const SODIUM_CRYPTO_PWHASH_OPSLIMIT_MODERATE = 6;
|
||||
const SODIUM_CRYPTO_PWHASH_MEMLIMIT_SENSITIVE = 536870912;
|
||||
const SODIUM_CRYPTO_PWHASH_OPSLIMIT_SENSITIVE = 8;
|
||||
const SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_SALTBYTES = 32;
|
||||
const SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_STRPREFIX = '$7$';
|
||||
const SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_OPSLIMIT_INTERACTIVE = 534288;
|
||||
const SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_MEMLIMIT_INTERACTIVE = 16777216;
|
||||
const SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_OPSLIMIT_SENSITIVE = 33554432;
|
||||
const SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_MEMLIMIT_SENSITIVE = 1073741824;
|
||||
const SODIUM_CRYPTO_SCALARMULT_BYTES = 32;
|
||||
const SODIUM_CRYPTO_SCALARMULT_SCALARBYTES = 32;
|
||||
const SODIUM_CRYPTO_SHORTHASH_BYTES = 8;
|
||||
const SODIUM_CRYPTO_SHORTHASH_KEYBYTES = 16;
|
||||
const SODIUM_CRYPTO_SECRETBOX_KEYBYTES = 32;
|
||||
const SODIUM_CRYPTO_SECRETBOX_MACBYTES = 16;
|
||||
const SODIUM_CRYPTO_SECRETBOX_NONCEBYTES = 24;
|
||||
const SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_ABYTES = 17;
|
||||
const SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_HEADERBYTES = 24;
|
||||
const SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_KEYBYTES = 32;
|
||||
const SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_PUSH = 0;
|
||||
const SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_PULL = 1;
|
||||
const SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_REKEY = 2;
|
||||
const SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_FINAL = 3;
|
||||
const SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_MESSAGEBYTES_MAX = 0x3fffffff80;
|
||||
const SODIUM_CRYPTO_SIGN_BYTES = 64;
|
||||
const SODIUM_CRYPTO_SIGN_SEEDBYTES = 32;
|
||||
const SODIUM_CRYPTO_SIGN_PUBLICKEYBYTES = 32;
|
||||
const SODIUM_CRYPTO_SIGN_SECRETKEYBYTES = 64;
|
||||
const SODIUM_CRYPTO_SIGN_KEYPAIRBYTES = 96;
|
||||
const SODIUM_CRYPTO_STREAM_KEYBYTES = 32;
|
||||
const SODIUM_CRYPTO_STREAM_NONCEBYTES = 24;
|
||||
const SODIUM_CRYPTO_STREAM_XCHACHA20_KEYBYTES = 32;
|
||||
const SODIUM_CRYPTO_STREAM_XCHACHA20_NONCEBYTES = 24;
|
||||
@@ -1,240 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
|
||||
if (!defined('SODIUM_CRYPTO_CORE_RISTRETTO255_BYTES')) {
|
||||
define(
|
||||
'SODIUM_CRYPTO_CORE_RISTRETTO255_BYTES',
|
||||
ParagonIE_Sodium_Compat::CRYPTO_CORE_RISTRETTO255_BYTES
|
||||
);
|
||||
define('SODIUM_COMPAT_POLYFILLED_RISTRETTO255', true);
|
||||
}
|
||||
if (!defined('SODIUM_CRYPTO_CORE_RISTRETTO255_HASHBYTES')) {
|
||||
define(
|
||||
'SODIUM_CRYPTO_CORE_RISTRETTO255_HASHBYTES',
|
||||
ParagonIE_Sodium_Compat::CRYPTO_CORE_RISTRETTO255_HASHBYTES
|
||||
);
|
||||
}
|
||||
if (!defined('SODIUM_CRYPTO_CORE_RISTRETTO255_SCALARBYTES')) {
|
||||
define(
|
||||
'SODIUM_CRYPTO_CORE_RISTRETTO255_SCALARBYTES',
|
||||
ParagonIE_Sodium_Compat::CRYPTO_CORE_RISTRETTO255_SCALARBYTES
|
||||
);
|
||||
}
|
||||
if (!defined('SODIUM_CRYPTO_CORE_RISTRETTO255_NONREDUCEDSCALARBYTES')) {
|
||||
define(
|
||||
'SODIUM_CRYPTO_CORE_RISTRETTO255_NONREDUCEDSCALARBYTES',
|
||||
ParagonIE_Sodium_Compat::CRYPTO_CORE_RISTRETTO255_NONREDUCEDSCALARBYTES
|
||||
);
|
||||
}
|
||||
if (!defined('SODIUM_CRYPTO_SCALARMULT_RISTRETTO255_SCALARBYTES')) {
|
||||
define(
|
||||
'SODIUM_CRYPTO_SCALARMULT_RISTRETTO255_SCALARBYTES',
|
||||
ParagonIE_Sodium_Compat::CRYPTO_SCALARMULT_RISTRETTO255_SCALARBYTES
|
||||
);
|
||||
}
|
||||
if (!defined('SODIUM_CRYPTO_SCALARMULT_RISTRETTO255_BYTES')) {
|
||||
define(
|
||||
'SODIUM_CRYPTO_SCALARMULT_RISTRETTO255_BYTES',
|
||||
ParagonIE_Sodium_Compat::CRYPTO_SCALARMULT_RISTRETTO255_BYTES
|
||||
);
|
||||
}
|
||||
|
||||
if (!is_callable('sodium_crypto_core_ristretto255_add')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::ristretto255_add()
|
||||
*
|
||||
* @param string $p
|
||||
* @param string $q
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
*/
|
||||
function sodium_crypto_core_ristretto255_add($p, $q)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::ristretto255_add($p, $q, true);
|
||||
}
|
||||
}
|
||||
if (!is_callable('sodium_crypto_core_ristretto255_from_hash')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::ristretto255_from_hash()
|
||||
*
|
||||
* @param string $s
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
*/
|
||||
function sodium_crypto_core_ristretto255_from_hash($s)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::ristretto255_from_hash($s, true);
|
||||
}
|
||||
}
|
||||
if (!is_callable('sodium_crypto_core_ristretto255_is_valid_point')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::ristretto255_is_valid_point()
|
||||
*
|
||||
* @param string $s
|
||||
* @return bool
|
||||
* @throws SodiumException
|
||||
*/
|
||||
function sodium_crypto_core_ristretto255_is_valid_point($s)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::ristretto255_is_valid_point($s, true);
|
||||
}
|
||||
}
|
||||
if (!is_callable('sodium_crypto_core_ristretto255_random')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::ristretto255_random()
|
||||
*
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
*/
|
||||
function sodium_crypto_core_ristretto255_random()
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::ristretto255_random(true);
|
||||
}
|
||||
}
|
||||
if (!is_callable('sodium_crypto_core_ristretto255_scalar_add')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::ristretto255_scalar_add()
|
||||
*
|
||||
* @param string $x
|
||||
* @param string $y
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
*/
|
||||
function sodium_crypto_core_ristretto255_scalar_add($x, $y)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::ristretto255_scalar_add($x, $y, true);
|
||||
}
|
||||
}
|
||||
if (!is_callable('sodium_crypto_core_ristretto255_scalar_complement')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::ristretto255_scalar_complement()
|
||||
*
|
||||
* @param string $s
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
*/
|
||||
function sodium_crypto_core_ristretto255_scalar_complement($s)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::ristretto255_scalar_complement($s, true);
|
||||
}
|
||||
}
|
||||
if (!is_callable('sodium_crypto_core_ristretto255_scalar_invert')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::ristretto255_scalar_invert()
|
||||
*
|
||||
* @param string $p
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
*/
|
||||
function sodium_crypto_core_ristretto255_scalar_invert($p)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::ristretto255_scalar_invert($p, true);
|
||||
}
|
||||
}
|
||||
if (!is_callable('sodium_crypto_core_ristretto255_scalar_mul')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::ristretto255_scalar_mul()
|
||||
*
|
||||
* @param string $x
|
||||
* @param string $y
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
*/
|
||||
function sodium_crypto_core_ristretto255_scalar_mul($x, $y)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::ristretto255_scalar_mul($x, $y, true);
|
||||
}
|
||||
}
|
||||
if (!is_callable('sodium_crypto_core_ristretto255_scalar_negate')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::ristretto255_scalar_negate()
|
||||
*
|
||||
* @param string $s
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
*/
|
||||
function sodium_crypto_core_ristretto255_scalar_negate($s)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::ristretto255_scalar_negate($s, true);
|
||||
}
|
||||
}
|
||||
if (!is_callable('sodium_crypto_core_ristretto255_scalar_random')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::ristretto255_scalar_random()
|
||||
*
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
*/
|
||||
function sodium_crypto_core_ristretto255_scalar_random()
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::ristretto255_scalar_random(true);
|
||||
}
|
||||
}
|
||||
if (!is_callable('sodium_crypto_core_ristretto255_scalar_reduce')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::ristretto255_scalar_reduce()
|
||||
*
|
||||
* @param string $s
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
*/
|
||||
function sodium_crypto_core_ristretto255_scalar_reduce($s)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::ristretto255_scalar_reduce($s, true);
|
||||
}
|
||||
}
|
||||
if (!is_callable('sodium_crypto_core_ristretto255_scalar_sub')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::ristretto255_scalar_sub()
|
||||
*
|
||||
* @param string $x
|
||||
* @param string $y
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
*/
|
||||
function sodium_crypto_core_ristretto255_scalar_sub($x, $y)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::ristretto255_scalar_sub($x, $y, true);
|
||||
}
|
||||
}
|
||||
if (!is_callable('sodium_crypto_core_ristretto255_sub')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::ristretto255_sub()
|
||||
*
|
||||
* @param string $p
|
||||
* @param string $q
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
*/
|
||||
function sodium_crypto_core_ristretto255_sub($p, $q)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::ristretto255_sub($p, $q, true);
|
||||
}
|
||||
}
|
||||
if (!is_callable('sodium_crypto_scalarmult_ristretto255')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_scalarmult_ristretto255()
|
||||
* @param string $n
|
||||
* @param string $p
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
* @throws TypeError
|
||||
*/
|
||||
function sodium_crypto_scalarmult_ristretto255($n, $p)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::scalarmult_ristretto255($n, $p, true);
|
||||
}
|
||||
}
|
||||
if (!is_callable('sodium_crypto_scalarmult_ristretto255_base')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_scalarmult_ristretto255_base()
|
||||
* @param string $n
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
* @throws TypeError
|
||||
*/
|
||||
function sodium_crypto_scalarmult_ristretto255_base($n)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::scalarmult_ristretto255_base($n, true);
|
||||
}
|
||||
}
|
||||
@@ -1,832 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
namespace Sodium;
|
||||
|
||||
require_once dirname(dirname(__FILE__)) . '/autoload.php';
|
||||
|
||||
use ParagonIE_Sodium_Compat;
|
||||
|
||||
/**
|
||||
* This file will monkey patch the pure-PHP implementation in place of the
|
||||
* PECL functions, but only if they do not already exist.
|
||||
*
|
||||
* Thus, the functions just proxy to the appropriate ParagonIE_Sodium_Compat
|
||||
* method.
|
||||
*/
|
||||
if (!is_callable('\\Sodium\\bin2hex')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::bin2hex()
|
||||
* @param string $string
|
||||
* @return string
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function bin2hex($string)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::bin2hex($string);
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\compare')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::compare()
|
||||
* @param string $a
|
||||
* @param string $b
|
||||
* @return int
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function compare($a, $b)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::compare($a, $b);
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_aead_aes256gcm_decrypt')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_aead_aes256gcm_decrypt()
|
||||
* @param string $message
|
||||
* @param string $assocData
|
||||
* @param string $nonce
|
||||
* @param string $key
|
||||
* @return string|bool
|
||||
*/
|
||||
function crypto_aead_aes256gcm_decrypt($message, $assocData, $nonce, $key)
|
||||
{
|
||||
try {
|
||||
return ParagonIE_Sodium_Compat::crypto_aead_aes256gcm_decrypt($message, $assocData, $nonce, $key);
|
||||
} catch (\TypeError $ex) {
|
||||
return false;
|
||||
} catch (\SodiumException $ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_aead_aes256gcm_encrypt')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_aead_aes256gcm_encrypt()
|
||||
* @param string $message
|
||||
* @param string $assocData
|
||||
* @param string $nonce
|
||||
* @param string $key
|
||||
* @return string
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function crypto_aead_aes256gcm_encrypt($message, $assocData, $nonce, $key)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_aead_aes256gcm_encrypt($message, $assocData, $nonce, $key);
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_aead_aes256gcm_is_available')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_aead_aes256gcm_is_available()
|
||||
* @return bool
|
||||
*/
|
||||
function crypto_aead_aes256gcm_is_available()
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_aead_aes256gcm_is_available();
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_aead_chacha20poly1305_decrypt')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_aead_chacha20poly1305_decrypt()
|
||||
* @param string $message
|
||||
* @param string $assocData
|
||||
* @param string $nonce
|
||||
* @param string $key
|
||||
* @return string|bool
|
||||
*/
|
||||
function crypto_aead_chacha20poly1305_decrypt($message, $assocData, $nonce, $key)
|
||||
{
|
||||
try {
|
||||
return ParagonIE_Sodium_Compat::crypto_aead_chacha20poly1305_decrypt($message, $assocData, $nonce, $key);
|
||||
} catch (\TypeError $ex) {
|
||||
return false;
|
||||
} catch (\SodiumException $ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_aead_chacha20poly1305_encrypt')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_aead_chacha20poly1305_encrypt()
|
||||
* @param string $message
|
||||
* @param string $assocData
|
||||
* @param string $nonce
|
||||
* @param string $key
|
||||
* @return string
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function crypto_aead_chacha20poly1305_encrypt($message, $assocData, $nonce, $key)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_aead_chacha20poly1305_encrypt($message, $assocData, $nonce, $key);
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_aead_chacha20poly1305_ietf_decrypt')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_aead_chacha20poly1305_ietf_decrypt()
|
||||
* @param string $message
|
||||
* @param string $assocData
|
||||
* @param string $nonce
|
||||
* @param string $key
|
||||
* @return string|bool
|
||||
*/
|
||||
function crypto_aead_chacha20poly1305_ietf_decrypt($message, $assocData, $nonce, $key)
|
||||
{
|
||||
try {
|
||||
return ParagonIE_Sodium_Compat::crypto_aead_chacha20poly1305_ietf_decrypt($message, $assocData, $nonce, $key);
|
||||
} catch (\TypeError $ex) {
|
||||
return false;
|
||||
} catch (\SodiumException $ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_aead_chacha20poly1305_ietf_encrypt')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_aead_chacha20poly1305_ietf_encrypt()
|
||||
* @param string $message
|
||||
* @param string $assocData
|
||||
* @param string $nonce
|
||||
* @param string $key
|
||||
* @return string
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function crypto_aead_chacha20poly1305_ietf_encrypt($message, $assocData, $nonce, $key)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_aead_chacha20poly1305_ietf_encrypt($message, $assocData, $nonce, $key);
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_auth')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_auth()
|
||||
* @param string $message
|
||||
* @param string $key
|
||||
* @return string
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function crypto_auth($message, $key)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_auth($message, $key);
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_auth_verify')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_auth_verify()
|
||||
* @param string $mac
|
||||
* @param string $message
|
||||
* @param string $key
|
||||
* @return bool
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function crypto_auth_verify($mac, $message, $key)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_auth_verify($mac, $message, $key);
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_box')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_box()
|
||||
* @param string $message
|
||||
* @param string $nonce
|
||||
* @param string $kp
|
||||
* @return string
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function crypto_box($message, $nonce, $kp)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_box($message, $nonce, $kp);
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_box_keypair')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_box_keypair()
|
||||
* @return string
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function crypto_box_keypair()
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_box_keypair();
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_box_keypair_from_secretkey_and_publickey')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_box_keypair_from_secretkey_and_publickey()
|
||||
* @param string $sk
|
||||
* @param string $pk
|
||||
* @return string
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function crypto_box_keypair_from_secretkey_and_publickey($sk, $pk)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_box_keypair_from_secretkey_and_publickey($sk, $pk);
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_box_open')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_box_open()
|
||||
* @param string $message
|
||||
* @param string $nonce
|
||||
* @param string $kp
|
||||
* @return string|bool
|
||||
*/
|
||||
function crypto_box_open($message, $nonce, $kp)
|
||||
{
|
||||
try {
|
||||
return ParagonIE_Sodium_Compat::crypto_box_open($message, $nonce, $kp);
|
||||
} catch (\TypeError $ex) {
|
||||
return false;
|
||||
} catch (\SodiumException $ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_box_publickey')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_box_publickey()
|
||||
* @param string $keypair
|
||||
* @return string
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function crypto_box_publickey($keypair)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_box_publickey($keypair);
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_box_publickey_from_secretkey')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_box_publickey_from_secretkey()
|
||||
* @param string $sk
|
||||
* @return string
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function crypto_box_publickey_from_secretkey($sk)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_box_publickey_from_secretkey($sk);
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_box_seal')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_box_seal_open()
|
||||
* @param string $message
|
||||
* @param string $publicKey
|
||||
* @return string
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function crypto_box_seal($message, $publicKey)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_box_seal($message, $publicKey);
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_box_seal_open')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_box_seal_open()
|
||||
* @param string $message
|
||||
* @param string $kp
|
||||
* @return string|bool
|
||||
*/
|
||||
function crypto_box_seal_open($message, $kp)
|
||||
{
|
||||
try {
|
||||
return ParagonIE_Sodium_Compat::crypto_box_seal_open($message, $kp);
|
||||
} catch (\TypeError $ex) {
|
||||
return false;
|
||||
} catch (\SodiumException $ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_box_secretkey')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_box_secretkey()
|
||||
* @param string $keypair
|
||||
* @return string
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function crypto_box_secretkey($keypair)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_box_secretkey($keypair);
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_generichash')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_generichash()
|
||||
* @param string $message
|
||||
* @param string|null $key
|
||||
* @param int $outLen
|
||||
* @return string
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function crypto_generichash($message, $key = null, $outLen = 32)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_generichash($message, $key, $outLen);
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_generichash_final')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_generichash_final()
|
||||
* @param string|null $ctx
|
||||
* @param int $outputLength
|
||||
* @return string
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function crypto_generichash_final(&$ctx, $outputLength = 32)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_generichash_final($ctx, $outputLength);
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_generichash_init')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_generichash_init()
|
||||
* @param string|null $key
|
||||
* @param int $outLen
|
||||
* @return string
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function crypto_generichash_init($key = null, $outLen = 32)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_generichash_init($key, $outLen);
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_generichash_update')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_generichash_update()
|
||||
* @param string|null $ctx
|
||||
* @param string $message
|
||||
* @return void
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function crypto_generichash_update(&$ctx, $message = '')
|
||||
{
|
||||
ParagonIE_Sodium_Compat::crypto_generichash_update($ctx, $message);
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_kx')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_kx()
|
||||
* @param string $my_secret
|
||||
* @param string $their_public
|
||||
* @param string $client_public
|
||||
* @param string $server_public
|
||||
* @return string
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function crypto_kx($my_secret, $their_public, $client_public, $server_public)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_kx(
|
||||
$my_secret,
|
||||
$their_public,
|
||||
$client_public,
|
||||
$server_public,
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_pwhash')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_pwhash()
|
||||
* @param int $outlen
|
||||
* @param string $passwd
|
||||
* @param string $salt
|
||||
* @param int $opslimit
|
||||
* @param int $memlimit
|
||||
* @return string
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function crypto_pwhash($outlen, $passwd, $salt, $opslimit, $memlimit)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_pwhash($outlen, $passwd, $salt, $opslimit, $memlimit);
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_pwhash_str')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_pwhash_str()
|
||||
* @param string $passwd
|
||||
* @param int $opslimit
|
||||
* @param int $memlimit
|
||||
* @return string
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function crypto_pwhash_str($passwd, $opslimit, $memlimit)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_pwhash_str($passwd, $opslimit, $memlimit);
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_pwhash_str_verify')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_pwhash_str_verify()
|
||||
* @param string $passwd
|
||||
* @param string $hash
|
||||
* @return bool
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function crypto_pwhash_str_verify($passwd, $hash)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_pwhash_str_verify($passwd, $hash);
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_pwhash_scryptsalsa208sha256')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_pwhash_scryptsalsa208sha256()
|
||||
* @param int $outlen
|
||||
* @param string $passwd
|
||||
* @param string $salt
|
||||
* @param int $opslimit
|
||||
* @param int $memlimit
|
||||
* @return string
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function crypto_pwhash_scryptsalsa208sha256($outlen, $passwd, $salt, $opslimit, $memlimit)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_pwhash_scryptsalsa208sha256($outlen, $passwd, $salt, $opslimit, $memlimit);
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_pwhash_scryptsalsa208sha256_str')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_pwhash_scryptsalsa208sha256_str()
|
||||
* @param string $passwd
|
||||
* @param int $opslimit
|
||||
* @param int $memlimit
|
||||
* @return string
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function crypto_pwhash_scryptsalsa208sha256_str($passwd, $opslimit, $memlimit)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_pwhash_scryptsalsa208sha256_str($passwd, $opslimit, $memlimit);
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_pwhash_scryptsalsa208sha256_str_verify')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_pwhash_scryptsalsa208sha256_str_verify()
|
||||
* @param string $passwd
|
||||
* @param string $hash
|
||||
* @return bool
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function crypto_pwhash_scryptsalsa208sha256_str_verify($passwd, $hash)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_pwhash_scryptsalsa208sha256_str_verify($passwd, $hash);
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_scalarmult')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_scalarmult()
|
||||
* @param string $n
|
||||
* @param string $p
|
||||
* @return string
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function crypto_scalarmult($n, $p)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_scalarmult($n, $p);
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_scalarmult_base')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_scalarmult_base()
|
||||
* @param string $n
|
||||
* @return string
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function crypto_scalarmult_base($n)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_scalarmult_base($n);
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_secretbox')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_secretbox()
|
||||
* @param string $message
|
||||
* @param string $nonce
|
||||
* @param string $key
|
||||
* @return string
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function crypto_secretbox($message, $nonce, $key)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_secretbox($message, $nonce, $key);
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_secretbox_open')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_secretbox_open()
|
||||
* @param string $message
|
||||
* @param string $nonce
|
||||
* @param string $key
|
||||
* @return string|bool
|
||||
*/
|
||||
function crypto_secretbox_open($message, $nonce, $key)
|
||||
{
|
||||
try {
|
||||
return ParagonIE_Sodium_Compat::crypto_secretbox_open($message, $nonce, $key);
|
||||
} catch (\TypeError $ex) {
|
||||
return false;
|
||||
} catch (\SodiumException $ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_shorthash')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_shorthash()
|
||||
* @param string $message
|
||||
* @param string $key
|
||||
* @return string
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function crypto_shorthash($message, $key = '')
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_shorthash($message, $key);
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_sign')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_sign()
|
||||
* @param string $message
|
||||
* @param string $sk
|
||||
* @return string
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function crypto_sign($message, $sk)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_sign($message, $sk);
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_sign_detached')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_sign_detached()
|
||||
* @param string $message
|
||||
* @param string $sk
|
||||
* @return string
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function crypto_sign_detached($message, $sk)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_sign_detached($message, $sk);
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_sign_keypair')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_sign_keypair()
|
||||
* @return string
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function crypto_sign_keypair()
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_sign_keypair();
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_sign_open')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_sign_open()
|
||||
* @param string $signedMessage
|
||||
* @param string $pk
|
||||
* @return string|bool
|
||||
*/
|
||||
function crypto_sign_open($signedMessage, $pk)
|
||||
{
|
||||
try {
|
||||
return ParagonIE_Sodium_Compat::crypto_sign_open($signedMessage, $pk);
|
||||
} catch (\TypeError $ex) {
|
||||
return false;
|
||||
} catch (\SodiumException $ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_sign_publickey')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_sign_publickey()
|
||||
* @param string $keypair
|
||||
* @return string
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function crypto_sign_publickey($keypair)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_sign_publickey($keypair);
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_sign_publickey_from_secretkey')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_sign_publickey_from_secretkey()
|
||||
* @param string $sk
|
||||
* @return string
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function crypto_sign_publickey_from_secretkey($sk)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_sign_publickey_from_secretkey($sk);
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_sign_secretkey')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_sign_secretkey()
|
||||
* @param string $keypair
|
||||
* @return string
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function crypto_sign_secretkey($keypair)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_sign_secretkey($keypair);
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_sign_seed_keypair')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_sign_seed_keypair()
|
||||
* @param string $seed
|
||||
* @return string
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function crypto_sign_seed_keypair($seed)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_sign_seed_keypair($seed);
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_sign_verify_detached')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_sign_verify_detached()
|
||||
* @param string $signature
|
||||
* @param string $message
|
||||
* @param string $pk
|
||||
* @return bool
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function crypto_sign_verify_detached($signature, $message, $pk)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_sign_verify_detached($signature, $message, $pk);
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_sign_ed25519_pk_to_curve25519')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_sign_ed25519_pk_to_curve25519()
|
||||
* @param string $pk
|
||||
* @return string
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function crypto_sign_ed25519_pk_to_curve25519($pk)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_sign_ed25519_pk_to_curve25519($pk);
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_sign_ed25519_sk_to_curve25519')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_sign_ed25519_sk_to_curve25519()
|
||||
* @param string $sk
|
||||
* @return string
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function crypto_sign_ed25519_sk_to_curve25519($sk)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_sign_ed25519_sk_to_curve25519($sk);
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_stream')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_stream()
|
||||
* @param int $len
|
||||
* @param string $nonce
|
||||
* @param string $key
|
||||
* @return string
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function crypto_stream($len, $nonce, $key)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_stream($len, $nonce, $key);
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\crypto_stream_xor')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_stream_xor()
|
||||
* @param string $message
|
||||
* @param string $nonce
|
||||
* @param string $key
|
||||
* @return string
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function crypto_stream_xor($message, $nonce, $key)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_stream_xor($message, $nonce, $key);
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\hex2bin')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::hex2bin()
|
||||
* @param string $string
|
||||
* @return string
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function hex2bin($string)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::hex2bin($string);
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\memcmp')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::memcmp()
|
||||
* @param string $a
|
||||
* @param string $b
|
||||
* @return int
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function memcmp($a, $b)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::memcmp($a, $b);
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\memzero')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::memzero()
|
||||
* @param string $str
|
||||
* @return void
|
||||
* @throws \SodiumException
|
||||
* @throws \TypeError
|
||||
*
|
||||
* @psalm-suppress MissingParamType
|
||||
* @psalm-suppress MissingReturnType
|
||||
* @psalm-suppress ReferenceConstraintViolation
|
||||
*/
|
||||
function memzero(&$str)
|
||||
{
|
||||
ParagonIE_Sodium_Compat::memzero($str);
|
||||
}
|
||||
}
|
||||
if (!is_callable('\\Sodium\\randombytes_buf')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::randombytes_buf()
|
||||
* @param int $amount
|
||||
* @return string
|
||||
* @throws \TypeError
|
||||
*/
|
||||
function randombytes_buf($amount)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::randombytes_buf($amount);
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_callable('\\Sodium\\randombytes_uniform')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::randombytes_uniform()
|
||||
* @param int $upperLimit
|
||||
* @return int
|
||||
* @throws \SodiumException
|
||||
* @throws \Error
|
||||
*/
|
||||
function randombytes_uniform($upperLimit)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::randombytes_uniform($upperLimit);
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_callable('\\Sodium\\randombytes_random16')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::randombytes_random16()
|
||||
* @return int
|
||||
*/
|
||||
function randombytes_random16()
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::randombytes_random16();
|
||||
}
|
||||
}
|
||||
|
||||
if (!defined('\\Sodium\\CRYPTO_AUTH_BYTES')) {
|
||||
require_once dirname(__FILE__) . '/constants.php';
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
|
||||
if (!is_callable('sodium_crypto_stream_xchacha20')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_stream_xchacha20()
|
||||
* @param int $len
|
||||
* @param string $nonce
|
||||
* @param string $key
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
* @throws TypeError
|
||||
*/
|
||||
function sodium_crypto_stream_xchacha20($len, $nonce, $key)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_stream_xchacha20($len, $nonce, $key, true);
|
||||
}
|
||||
}
|
||||
if (!is_callable('sodium_crypto_stream_xchacha20_keygen')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_stream_xchacha20_keygen()
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
function sodium_crypto_stream_xchacha20_keygen()
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_stream_xchacha20_keygen();
|
||||
}
|
||||
}
|
||||
if (!is_callable('sodium_crypto_stream_xchacha20_xor')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_stream_xchacha20_xor()
|
||||
* @param string $message
|
||||
* @param string $nonce
|
||||
* @param string $key
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
* @throws TypeError
|
||||
*/
|
||||
function sodium_crypto_stream_xchacha20_xor($message, $nonce, $key)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_stream_xchacha20_xor($message, $nonce, $key, true);
|
||||
}
|
||||
}
|
||||
if (!is_callable('sodium_crypto_stream_xchacha20_xor_ic')) {
|
||||
/**
|
||||
* @see ParagonIE_Sodium_Compat::crypto_stream_xchacha20_xor_ic()
|
||||
* @param string $message
|
||||
* @param string $nonce
|
||||
* @param int $counter
|
||||
* @param string $key
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
* @throws TypeError
|
||||
*/
|
||||
function sodium_crypto_stream_xchacha20_xor_ic($message, $nonce, $counter, $key)
|
||||
{
|
||||
return ParagonIE_Sodium_Compat::crypto_stream_xchacha20_xor_ic($message, $nonce, $counter, $key, true);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
namespace ParagonIE\Sodium;
|
||||
|
||||
class Compat extends \ParagonIE_Sodium_Compat
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
namespace ParagonIE\Sodium\Core;
|
||||
|
||||
class BLAKE2b extends \ParagonIE_Sodium_Core_BLAKE2b
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
namespace ParagonIE\Sodium\Core;
|
||||
|
||||
class ChaCha20 extends \ParagonIE_Sodium_Core_ChaCha20
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
namespace ParagonIE\Sodium\Core\ChaCha20;
|
||||
|
||||
class Ctx extends \ParagonIE_Sodium_Core_ChaCha20_Ctx
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
namespace ParagonIE\Sodium\Core\ChaCha20;
|
||||
|
||||
class IetfCtx extends \ParagonIE_Sodium_Core_ChaCha20_IetfCtx
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
namespace ParagonIE\Sodium\Core;
|
||||
|
||||
class Curve25519 extends \ParagonIE_Sodium_Core_Curve25519
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
namespace ParagonIE\Sodium\Core\Curve25519;
|
||||
|
||||
class Fe extends \ParagonIE_Sodium_Core_Curve25519_Fe
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
namespace ParagonIE\Sodium\Core\Curve25519\Ge;
|
||||
|
||||
class Cached extends \ParagonIE_Sodium_Core_Curve25519_Ge_Cached
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
namespace ParagonIE\Sodium\Core\Curve25519\Ge;
|
||||
|
||||
class P1p1 extends \ParagonIE_Sodium_Core_Curve25519_Ge_P1p1
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
namespace ParagonIE\Sodium\Core\Curve25519\Ge;
|
||||
|
||||
class P2 extends \ParagonIE_Sodium_Core_Curve25519_Ge_P2
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
namespace ParagonIE\Sodium\Core\Curve25519\Ge;
|
||||
|
||||
class P3 extends \ParagonIE_Sodium_Core_Curve25519_Ge_P3
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
namespace ParagonIE\Sodium\Core\Curve25519\Ge;
|
||||
|
||||
class Precomp extends \ParagonIE_Sodium_Core_Curve25519_Ge_Precomp
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
namespace ParagonIE\Sodium\Core\Curve25519;
|
||||
|
||||
class H extends \ParagonIE_Sodium_Core_Curve25519_H
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
namespace ParagonIE\Sodium\Core;
|
||||
|
||||
class Ed25519 extends \ParagonIE_Sodium_Core_Ed25519
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
namespace ParagonIE\Sodium\Core;
|
||||
|
||||
class HChaCha20 extends \ParagonIE_Sodium_Core_HChaCha20
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
namespace ParagonIE\Sodium\Core;
|
||||
|
||||
class HSalsa20 extends \ParagonIE_Sodium_Core_HSalsa20
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
namespace ParagonIE\Sodium\Core;
|
||||
|
||||
class Poly1305 extends \ParagonIE_Sodium_Core_Poly1305
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
namespace ParagonIE\Sodium\Core\Poly1305;
|
||||
|
||||
class State extends \ParagonIE_Sodium_Core_Poly1305_State
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
namespace ParagonIE\Sodium\Core;
|
||||
|
||||
class Salsa20 extends \ParagonIE_Sodium_Core_Salsa20
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
namespace ParagonIE\Sodium\Core;
|
||||
|
||||
class SipHash extends \ParagonIE_Sodium_Core_SipHash
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
namespace ParagonIE\Sodium\Core;
|
||||
|
||||
class Util extends \ParagonIE_Sodium_Core_Util
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
namespace ParagonIE\Sodium\Core;
|
||||
|
||||
class X25519 extends \ParagonIE_Sodium_Core_X25519
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
namespace ParagonIE\Sodium\Core;
|
||||
|
||||
class XChaCha20 extends \ParagonIE_Sodium_Core_XChaCha20
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
namespace ParagonIE\Sodium\Core;
|
||||
|
||||
class Xsalsa20 extends \ParagonIE_Sodium_Core_XSalsa20
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
namespace ParagonIE\Sodium;
|
||||
|
||||
class Crypto extends \ParagonIE_Sodium_Crypto
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
namespace ParagonIE\Sodium;
|
||||
|
||||
class File extends \ParagonIE_Sodium_File
|
||||
{
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,798 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
|
||||
if (class_exists('ParagonIE_Sodium_Core_BLAKE2b', false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class ParagonIE_Sodium_Core_BLAKE2b
|
||||
*
|
||||
* Based on the work of Devi Mandiri in devi/salt.
|
||||
*/
|
||||
abstract class ParagonIE_Sodium_Core_BLAKE2b extends ParagonIE_Sodium_Core_Util
|
||||
{
|
||||
/**
|
||||
* @var SplFixedArray
|
||||
*/
|
||||
protected static $iv;
|
||||
|
||||
/**
|
||||
* @var array<int, array<int, int>>
|
||||
*/
|
||||
protected static $sigma = array(
|
||||
array( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15),
|
||||
array( 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3),
|
||||
array( 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4),
|
||||
array( 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8),
|
||||
array( 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13),
|
||||
array( 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9),
|
||||
array( 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11),
|
||||
array( 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10),
|
||||
array( 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5),
|
||||
array( 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0),
|
||||
array( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15),
|
||||
array( 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3)
|
||||
);
|
||||
|
||||
const BLOCKBYTES = 128;
|
||||
const OUTBYTES = 64;
|
||||
const KEYBYTES = 64;
|
||||
|
||||
/**
|
||||
* Turn two 32-bit integers into a fixed array representing a 64-bit integer.
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param int $high
|
||||
* @param int $low
|
||||
* @return SplFixedArray
|
||||
* @psalm-suppress MixedAssignment
|
||||
*/
|
||||
public static function new64($high, $low)
|
||||
{
|
||||
if (PHP_INT_SIZE === 4) {
|
||||
throw new SodiumException("Error, use 32-bit");
|
||||
}
|
||||
$i64 = new SplFixedArray(2);
|
||||
$i64[0] = $high & 0xffffffff;
|
||||
$i64[1] = $low & 0xffffffff;
|
||||
return $i64;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an arbitrary number into an SplFixedArray of two 32-bit integers
|
||||
* that represents a 64-bit integer.
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param int $num
|
||||
* @return SplFixedArray
|
||||
*/
|
||||
protected static function to64($num)
|
||||
{
|
||||
list($hi, $lo) = self::numericTo64BitInteger($num);
|
||||
return self::new64($hi, $lo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds two 64-bit integers together, returning their sum as a SplFixedArray
|
||||
* containing two 32-bit integers (representing a 64-bit integer).
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param SplFixedArray $x
|
||||
* @param SplFixedArray $y
|
||||
* @return SplFixedArray
|
||||
* @psalm-suppress MixedArgument
|
||||
* @psalm-suppress MixedAssignment
|
||||
* @psalm-suppress MixedOperand
|
||||
*/
|
||||
protected static function add64($x, $y)
|
||||
{
|
||||
if (PHP_INT_SIZE === 4) {
|
||||
throw new SodiumException("Error, use 32-bit");
|
||||
}
|
||||
$l = ($x[1] + $y[1]) & 0xffffffff;
|
||||
return self::new64(
|
||||
(int) ($x[0] + $y[0] + (
|
||||
($l < $x[1]) ? 1 : 0
|
||||
)),
|
||||
(int) $l
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param SplFixedArray $x
|
||||
* @param SplFixedArray $y
|
||||
* @param SplFixedArray $z
|
||||
* @return SplFixedArray
|
||||
*/
|
||||
protected static function add364($x, $y, $z)
|
||||
{
|
||||
return self::add64($x, self::add64($y, $z));
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param SplFixedArray $x
|
||||
* @param SplFixedArray $y
|
||||
* @return SplFixedArray
|
||||
* @throws SodiumException
|
||||
* @throws TypeError
|
||||
*/
|
||||
protected static function xor64(SplFixedArray $x, SplFixedArray $y)
|
||||
{
|
||||
if (PHP_INT_SIZE === 4) {
|
||||
throw new SodiumException("Error, use 32-bit");
|
||||
}
|
||||
if (!is_numeric($x[0])) {
|
||||
throw new SodiumException('x[0] is not an integer');
|
||||
}
|
||||
if (!is_numeric($x[1])) {
|
||||
throw new SodiumException('x[1] is not an integer');
|
||||
}
|
||||
if (!is_numeric($y[0])) {
|
||||
throw new SodiumException('y[0] is not an integer');
|
||||
}
|
||||
if (!is_numeric($y[1])) {
|
||||
throw new SodiumException('y[1] is not an integer');
|
||||
}
|
||||
return self::new64(
|
||||
(int) (($x[0] ^ $y[0]) & 0xffffffff),
|
||||
(int) (($x[1] ^ $y[1]) & 0xffffffff)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param SplFixedArray $x
|
||||
* @param int $c
|
||||
* @return SplFixedArray
|
||||
* @psalm-suppress MixedAssignment
|
||||
*/
|
||||
public static function rotr64($x, $c)
|
||||
{
|
||||
if (PHP_INT_SIZE === 4) {
|
||||
throw new SodiumException("Error, use 32-bit");
|
||||
}
|
||||
if ($c >= 64) {
|
||||
$c %= 64;
|
||||
}
|
||||
if ($c >= 32) {
|
||||
/** @var int $tmp */
|
||||
$tmp = $x[0];
|
||||
$x[0] = $x[1];
|
||||
$x[1] = $tmp;
|
||||
$c -= 32;
|
||||
}
|
||||
if ($c === 0) {
|
||||
return $x;
|
||||
}
|
||||
|
||||
$l0 = 0;
|
||||
$c = 64 - $c;
|
||||
|
||||
/** @var int $c */
|
||||
if ($c < 32) {
|
||||
$h0 = ((int) ($x[0]) << $c) | (
|
||||
(
|
||||
(int) ($x[1]) & ((1 << $c) - 1)
|
||||
<<
|
||||
(32 - $c)
|
||||
) >> (32 - $c)
|
||||
);
|
||||
$l0 = (int) ($x[1]) << $c;
|
||||
} else {
|
||||
$h0 = (int) ($x[1]) << ($c - 32);
|
||||
}
|
||||
|
||||
$h1 = 0;
|
||||
$c1 = 64 - $c;
|
||||
|
||||
if ($c1 < 32) {
|
||||
$h1 = (int) ($x[0]) >> $c1;
|
||||
$l1 = ((int) ($x[1]) >> $c1) | ((int) ($x[0]) & ((1 << $c1) - 1)) << (32 - $c1);
|
||||
} else {
|
||||
$l1 = (int) ($x[0]) >> ($c1 - 32);
|
||||
}
|
||||
|
||||
return self::new64($h0 | $h1, $l0 | $l1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param SplFixedArray $x
|
||||
* @return int
|
||||
* @psalm-suppress MixedOperand
|
||||
*/
|
||||
protected static function flatten64($x)
|
||||
{
|
||||
return (int) ($x[0] * 4294967296 + $x[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param SplFixedArray $x
|
||||
* @param int $i
|
||||
* @return SplFixedArray
|
||||
* @psalm-suppress MixedArgument
|
||||
* @psalm-suppress MixedArrayOffset
|
||||
*/
|
||||
protected static function load64(SplFixedArray $x, $i)
|
||||
{
|
||||
/** @var int $l */
|
||||
$l = (int) ($x[$i])
|
||||
| ((int) ($x[$i+1]) << 8)
|
||||
| ((int) ($x[$i+2]) << 16)
|
||||
| ((int) ($x[$i+3]) << 24);
|
||||
/** @var int $h */
|
||||
$h = (int) ($x[$i+4])
|
||||
| ((int) ($x[$i+5]) << 8)
|
||||
| ((int) ($x[$i+6]) << 16)
|
||||
| ((int) ($x[$i+7]) << 24);
|
||||
return self::new64($h, $l);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param SplFixedArray $x
|
||||
* @param int $i
|
||||
* @param SplFixedArray $u
|
||||
* @return void
|
||||
* @psalm-suppress MixedAssignment
|
||||
*/
|
||||
protected static function store64(SplFixedArray $x, $i, SplFixedArray $u)
|
||||
{
|
||||
$maxLength = $x->getSize() - 1;
|
||||
for ($j = 0; $j < 8; ++$j) {
|
||||
/*
|
||||
[0, 1, 2, 3, 4, 5, 6, 7]
|
||||
... becomes ...
|
||||
[0, 0, 0, 0, 1, 1, 1, 1]
|
||||
*/
|
||||
/** @var int $uIdx */
|
||||
$uIdx = ((7 - $j) & 4) >> 2;
|
||||
$x[$i] = ((int) ($u[$uIdx]) & 0xff);
|
||||
if (++$i > $maxLength) {
|
||||
return;
|
||||
}
|
||||
/** @psalm-suppress MixedOperand */
|
||||
$u[$uIdx] >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This just sets the $iv static variable.
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function pseudoConstructor()
|
||||
{
|
||||
static $called = false;
|
||||
if ($called) {
|
||||
return;
|
||||
}
|
||||
self::$iv = new SplFixedArray(8);
|
||||
self::$iv[0] = self::new64(0x6a09e667, 0xf3bcc908);
|
||||
self::$iv[1] = self::new64(0xbb67ae85, 0x84caa73b);
|
||||
self::$iv[2] = self::new64(0x3c6ef372, 0xfe94f82b);
|
||||
self::$iv[3] = self::new64(0xa54ff53a, 0x5f1d36f1);
|
||||
self::$iv[4] = self::new64(0x510e527f, 0xade682d1);
|
||||
self::$iv[5] = self::new64(0x9b05688c, 0x2b3e6c1f);
|
||||
self::$iv[6] = self::new64(0x1f83d9ab, 0xfb41bd6b);
|
||||
self::$iv[7] = self::new64(0x5be0cd19, 0x137e2179);
|
||||
|
||||
$called = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a fresh BLAKE2 context.
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @return SplFixedArray
|
||||
* @psalm-suppress MixedAssignment
|
||||
* @psalm-suppress MixedArrayAccess
|
||||
* @psalm-suppress MixedArrayAssignment
|
||||
*/
|
||||
protected static function context()
|
||||
{
|
||||
$ctx = new SplFixedArray(6);
|
||||
$ctx[0] = new SplFixedArray(8); // h
|
||||
$ctx[1] = new SplFixedArray(2); // t
|
||||
$ctx[2] = new SplFixedArray(2); // f
|
||||
$ctx[3] = new SplFixedArray(256); // buf
|
||||
$ctx[4] = 0; // buflen
|
||||
$ctx[5] = 0; // last_node (uint8_t)
|
||||
|
||||
for ($i = 8; $i--;) {
|
||||
$ctx[0][$i] = self::$iv[$i];
|
||||
}
|
||||
for ($i = 256; $i--;) {
|
||||
$ctx[3][$i] = 0;
|
||||
}
|
||||
|
||||
$zero = self::new64(0, 0);
|
||||
$ctx[1][0] = $zero;
|
||||
$ctx[1][1] = $zero;
|
||||
$ctx[2][0] = $zero;
|
||||
$ctx[2][1] = $zero;
|
||||
|
||||
return $ctx;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param SplFixedArray $ctx
|
||||
* @param SplFixedArray $buf
|
||||
* @return void
|
||||
* @throws SodiumException
|
||||
* @throws TypeError
|
||||
* @psalm-suppress MixedArgument
|
||||
* @psalm-suppress MixedAssignment
|
||||
* @psalm-suppress MixedArrayAccess
|
||||
* @psalm-suppress MixedArrayAssignment
|
||||
* @psalm-suppress MixedArrayOffset
|
||||
*/
|
||||
protected static function compress(SplFixedArray $ctx, SplFixedArray $buf)
|
||||
{
|
||||
$m = new SplFixedArray(16);
|
||||
$v = new SplFixedArray(16);
|
||||
|
||||
for ($i = 16; $i--;) {
|
||||
$m[$i] = self::load64($buf, $i << 3);
|
||||
}
|
||||
|
||||
for ($i = 8; $i--;) {
|
||||
$v[$i] = $ctx[0][$i];
|
||||
}
|
||||
|
||||
$v[ 8] = self::$iv[0];
|
||||
$v[ 9] = self::$iv[1];
|
||||
$v[10] = self::$iv[2];
|
||||
$v[11] = self::$iv[3];
|
||||
|
||||
$v[12] = self::xor64($ctx[1][0], self::$iv[4]);
|
||||
$v[13] = self::xor64($ctx[1][1], self::$iv[5]);
|
||||
$v[14] = self::xor64($ctx[2][0], self::$iv[6]);
|
||||
$v[15] = self::xor64($ctx[2][1], self::$iv[7]);
|
||||
|
||||
for ($r = 0; $r < 12; ++$r) {
|
||||
$v = self::G($r, 0, 0, 4, 8, 12, $v, $m);
|
||||
$v = self::G($r, 1, 1, 5, 9, 13, $v, $m);
|
||||
$v = self::G($r, 2, 2, 6, 10, 14, $v, $m);
|
||||
$v = self::G($r, 3, 3, 7, 11, 15, $v, $m);
|
||||
$v = self::G($r, 4, 0, 5, 10, 15, $v, $m);
|
||||
$v = self::G($r, 5, 1, 6, 11, 12, $v, $m);
|
||||
$v = self::G($r, 6, 2, 7, 8, 13, $v, $m);
|
||||
$v = self::G($r, 7, 3, 4, 9, 14, $v, $m);
|
||||
}
|
||||
|
||||
for ($i = 8; $i--;) {
|
||||
$ctx[0][$i] = self::xor64(
|
||||
$ctx[0][$i], self::xor64($v[$i], $v[$i+8])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param int $r
|
||||
* @param int $i
|
||||
* @param int $a
|
||||
* @param int $b
|
||||
* @param int $c
|
||||
* @param int $d
|
||||
* @param SplFixedArray $v
|
||||
* @param SplFixedArray $m
|
||||
* @return SplFixedArray
|
||||
* @throws SodiumException
|
||||
* @throws TypeError
|
||||
* @psalm-suppress MixedArgument
|
||||
* @psalm-suppress MixedArrayOffset
|
||||
*/
|
||||
public static function G($r, $i, $a, $b, $c, $d, SplFixedArray $v, SplFixedArray $m)
|
||||
{
|
||||
$v[$a] = self::add364($v[$a], $v[$b], $m[self::$sigma[$r][$i << 1]]);
|
||||
$v[$d] = self::rotr64(self::xor64($v[$d], $v[$a]), 32);
|
||||
$v[$c] = self::add64($v[$c], $v[$d]);
|
||||
$v[$b] = self::rotr64(self::xor64($v[$b], $v[$c]), 24);
|
||||
$v[$a] = self::add364($v[$a], $v[$b], $m[self::$sigma[$r][($i << 1) + 1]]);
|
||||
$v[$d] = self::rotr64(self::xor64($v[$d], $v[$a]), 16);
|
||||
$v[$c] = self::add64($v[$c], $v[$d]);
|
||||
$v[$b] = self::rotr64(self::xor64($v[$b], $v[$c]), 63);
|
||||
return $v;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param SplFixedArray $ctx
|
||||
* @param int $inc
|
||||
* @return void
|
||||
* @throws SodiumException
|
||||
* @psalm-suppress MixedArgument
|
||||
* @psalm-suppress MixedArrayAccess
|
||||
* @psalm-suppress MixedArrayAssignment
|
||||
*/
|
||||
public static function increment_counter($ctx, $inc)
|
||||
{
|
||||
if ($inc < 0) {
|
||||
throw new SodiumException('Increasing by a negative number makes no sense.');
|
||||
}
|
||||
$t = self::to64($inc);
|
||||
# S->t is $ctx[1] in our implementation
|
||||
|
||||
# S->t[0] = ( uint64_t )( t >> 0 );
|
||||
$ctx[1][0] = self::add64($ctx[1][0], $t);
|
||||
|
||||
# S->t[1] += ( S->t[0] < inc );
|
||||
if (self::flatten64($ctx[1][0]) < $inc) {
|
||||
$ctx[1][1] = self::add64($ctx[1][1], self::to64(1));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param SplFixedArray $ctx
|
||||
* @param SplFixedArray $p
|
||||
* @param int $plen
|
||||
* @return void
|
||||
* @throws SodiumException
|
||||
* @throws TypeError
|
||||
* @psalm-suppress MixedArgument
|
||||
* @psalm-suppress MixedAssignment
|
||||
* @psalm-suppress MixedArrayAccess
|
||||
* @psalm-suppress MixedArrayAssignment
|
||||
* @psalm-suppress MixedArrayOffset
|
||||
* @psalm-suppress MixedOperand
|
||||
*/
|
||||
public static function update(SplFixedArray $ctx, SplFixedArray $p, $plen)
|
||||
{
|
||||
self::pseudoConstructor();
|
||||
|
||||
$offset = 0;
|
||||
while ($plen > 0) {
|
||||
$left = $ctx[4];
|
||||
$fill = 256 - $left;
|
||||
|
||||
if ($plen > $fill) {
|
||||
# memcpy( S->buf + left, in, fill ); /* Fill buffer */
|
||||
for ($i = $fill; $i--;) {
|
||||
$ctx[3][$i + $left] = $p[$i + $offset];
|
||||
}
|
||||
|
||||
# S->buflen += fill;
|
||||
$ctx[4] += $fill;
|
||||
|
||||
# blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES );
|
||||
self::increment_counter($ctx, 128);
|
||||
|
||||
# blake2b_compress( S, S->buf ); /* Compress */
|
||||
self::compress($ctx, $ctx[3]);
|
||||
|
||||
# memcpy( S->buf, S->buf + BLAKE2B_BLOCKBYTES, BLAKE2B_BLOCKBYTES ); /* Shift buffer left */
|
||||
for ($i = 128; $i--;) {
|
||||
$ctx[3][$i] = $ctx[3][$i + 128];
|
||||
}
|
||||
|
||||
# S->buflen -= BLAKE2B_BLOCKBYTES;
|
||||
$ctx[4] -= 128;
|
||||
|
||||
# in += fill;
|
||||
$offset += $fill;
|
||||
|
||||
# inlen -= fill;
|
||||
$plen -= $fill;
|
||||
} else {
|
||||
for ($i = $plen; $i--;) {
|
||||
$ctx[3][$i + $left] = $p[$i + $offset];
|
||||
}
|
||||
$ctx[4] += $plen;
|
||||
$offset += $plen;
|
||||
$plen -= $plen;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param SplFixedArray $ctx
|
||||
* @param SplFixedArray $out
|
||||
* @return SplFixedArray
|
||||
* @throws SodiumException
|
||||
* @throws TypeError
|
||||
* @psalm-suppress MixedArgument
|
||||
* @psalm-suppress MixedAssignment
|
||||
* @psalm-suppress MixedArrayAccess
|
||||
* @psalm-suppress MixedArrayAssignment
|
||||
* @psalm-suppress MixedArrayOffset
|
||||
* @psalm-suppress MixedOperand
|
||||
*/
|
||||
public static function finish(SplFixedArray $ctx, SplFixedArray $out)
|
||||
{
|
||||
self::pseudoConstructor();
|
||||
if ($ctx[4] > 128) {
|
||||
self::increment_counter($ctx, 128);
|
||||
self::compress($ctx, $ctx[3]);
|
||||
$ctx[4] -= 128;
|
||||
if ($ctx[4] > 128) {
|
||||
throw new SodiumException('Failed to assert that buflen <= 128 bytes');
|
||||
}
|
||||
for ($i = $ctx[4]; $i--;) {
|
||||
$ctx[3][$i] = $ctx[3][$i + 128];
|
||||
}
|
||||
}
|
||||
|
||||
self::increment_counter($ctx, $ctx[4]);
|
||||
$ctx[2][0] = self::new64(0xffffffff, 0xffffffff);
|
||||
|
||||
for ($i = 256 - $ctx[4]; $i--;) {
|
||||
$ctx[3][$i+$ctx[4]] = 0;
|
||||
}
|
||||
|
||||
self::compress($ctx, $ctx[3]);
|
||||
|
||||
$i = (int) (($out->getSize() - 1) / 8);
|
||||
for (; $i >= 0; --$i) {
|
||||
self::store64($out, $i << 3, $ctx[0][$i]);
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param SplFixedArray|null $key
|
||||
* @param int $outlen
|
||||
* @param SplFixedArray|null $salt
|
||||
* @param SplFixedArray|null $personal
|
||||
* @return SplFixedArray
|
||||
* @throws SodiumException
|
||||
* @throws TypeError
|
||||
* @psalm-suppress MixedArgument
|
||||
* @psalm-suppress MixedAssignment
|
||||
* @psalm-suppress MixedArrayAccess
|
||||
* @psalm-suppress MixedArrayAssignment
|
||||
* @psalm-suppress MixedArrayOffset
|
||||
*/
|
||||
public static function init(
|
||||
$key = null,
|
||||
$outlen = 64,
|
||||
$salt = null,
|
||||
$personal = null
|
||||
) {
|
||||
self::pseudoConstructor();
|
||||
$klen = 0;
|
||||
|
||||
if ($key !== null) {
|
||||
if (count($key) > 64) {
|
||||
throw new SodiumException('Invalid key size');
|
||||
}
|
||||
$klen = count($key);
|
||||
}
|
||||
|
||||
if ($outlen > 64) {
|
||||
throw new SodiumException('Invalid output size');
|
||||
}
|
||||
|
||||
$ctx = self::context();
|
||||
|
||||
$p = new SplFixedArray(64);
|
||||
// Zero our param buffer...
|
||||
for ($i = 64; --$i;) {
|
||||
$p[$i] = 0;
|
||||
}
|
||||
|
||||
$p[0] = $outlen; // digest_length
|
||||
$p[1] = $klen; // key_length
|
||||
$p[2] = 1; // fanout
|
||||
$p[3] = 1; // depth
|
||||
|
||||
if ($salt instanceof SplFixedArray) {
|
||||
// salt: [32] through [47]
|
||||
for ($i = 0; $i < 16; ++$i) {
|
||||
$p[32 + $i] = (int) $salt[$i];
|
||||
}
|
||||
}
|
||||
if ($personal instanceof SplFixedArray) {
|
||||
// personal: [48] through [63]
|
||||
for ($i = 0; $i < 16; ++$i) {
|
||||
$p[48 + $i] = (int) $personal[$i];
|
||||
}
|
||||
}
|
||||
|
||||
$ctx[0][0] = self::xor64(
|
||||
$ctx[0][0],
|
||||
self::load64($p, 0)
|
||||
);
|
||||
if ($salt instanceof SplFixedArray || $personal instanceof SplFixedArray) {
|
||||
// We need to do what blake2b_init_param() does:
|
||||
for ($i = 1; $i < 8; ++$i) {
|
||||
$ctx[0][$i] = self::xor64(
|
||||
$ctx[0][$i],
|
||||
self::load64($p, $i << 3)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ($klen > 0 && $key instanceof SplFixedArray) {
|
||||
$block = new SplFixedArray(128);
|
||||
for ($i = 128; $i--;) {
|
||||
$block[$i] = 0;
|
||||
}
|
||||
for ($i = $klen; $i--;) {
|
||||
$block[$i] = $key[$i];
|
||||
}
|
||||
self::update($ctx, $block, 128);
|
||||
$ctx[4] = 128;
|
||||
}
|
||||
|
||||
return $ctx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a string into an SplFixedArray of integers
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param string $str
|
||||
* @return SplFixedArray
|
||||
* @psalm-suppress MixedArgumentTypeCoercion
|
||||
*/
|
||||
public static function stringToSplFixedArray($str = '')
|
||||
{
|
||||
$values = unpack('C*', $str);
|
||||
return SplFixedArray::fromArray(array_values($values));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an SplFixedArray of integers into a string
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param SplFixedArray $a
|
||||
* @return string
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function SplFixedArrayToString(SplFixedArray $a)
|
||||
{
|
||||
/**
|
||||
* @var array<int, int|string> $arr
|
||||
*/
|
||||
$arr = $a->toArray();
|
||||
$c = $a->count();
|
||||
array_unshift($arr, str_repeat('C', $c));
|
||||
return (string) (call_user_func_array('pack', $arr));
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param SplFixedArray $ctx
|
||||
* @return string
|
||||
* @throws TypeError
|
||||
* @psalm-suppress MixedArgument
|
||||
* @psalm-suppress MixedAssignment
|
||||
* @psalm-suppress MixedArrayAccess
|
||||
* @psalm-suppress MixedArrayAssignment
|
||||
* @psalm-suppress MixedArrayOffset
|
||||
* @psalm-suppress MixedMethodCall
|
||||
*/
|
||||
public static function contextToString(SplFixedArray $ctx)
|
||||
{
|
||||
$str = '';
|
||||
/** @var array<int, array<int, int>> $ctxA */
|
||||
$ctxA = $ctx[0]->toArray();
|
||||
|
||||
# uint64_t h[8];
|
||||
for ($i = 0; $i < 8; ++$i) {
|
||||
$str .= self::store32_le($ctxA[$i][1]);
|
||||
$str .= self::store32_le($ctxA[$i][0]);
|
||||
}
|
||||
|
||||
# uint64_t t[2];
|
||||
# uint64_t f[2];
|
||||
for ($i = 1; $i < 3; ++$i) {
|
||||
$ctxA = $ctx[$i]->toArray();
|
||||
$str .= self::store32_le($ctxA[0][1]);
|
||||
$str .= self::store32_le($ctxA[0][0]);
|
||||
$str .= self::store32_le($ctxA[1][1]);
|
||||
$str .= self::store32_le($ctxA[1][0]);
|
||||
}
|
||||
|
||||
# uint8_t buf[2 * 128];
|
||||
$str .= self::SplFixedArrayToString($ctx[3]);
|
||||
|
||||
/** @var int $ctx4 */
|
||||
$ctx4 = (int) $ctx[4];
|
||||
|
||||
# size_t buflen;
|
||||
$str .= implode('', array(
|
||||
self::intToChr($ctx4 & 0xff),
|
||||
self::intToChr(($ctx4 >> 8) & 0xff),
|
||||
self::intToChr(($ctx4 >> 16) & 0xff),
|
||||
self::intToChr(($ctx4 >> 24) & 0xff),
|
||||
self::intToChr(($ctx4 >> 32) & 0xff),
|
||||
self::intToChr(($ctx4 >> 40) & 0xff),
|
||||
self::intToChr(($ctx4 >> 48) & 0xff),
|
||||
self::intToChr(($ctx4 >> 56) & 0xff)
|
||||
));
|
||||
# uint8_t last_node;
|
||||
return $str . self::intToChr($ctx[5]) . str_repeat("\x00", 23);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an SplFixedArray containing other SplFixedArray elements, from
|
||||
* a string (compatible with \Sodium\crypto_generichash_{init, update, final})
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param string $string
|
||||
* @return SplFixedArray
|
||||
* @throws SodiumException
|
||||
* @throws TypeError
|
||||
* @psalm-suppress MixedArrayAssignment
|
||||
*/
|
||||
public static function stringToContext($string)
|
||||
{
|
||||
$ctx = self::context();
|
||||
|
||||
# uint64_t h[8];
|
||||
for ($i = 0; $i < 8; ++$i) {
|
||||
$ctx[0][$i] = SplFixedArray::fromArray(
|
||||
array(
|
||||
self::load_4(
|
||||
self::substr($string, (($i << 3) + 4), 4)
|
||||
),
|
||||
self::load_4(
|
||||
self::substr($string, (($i << 3) + 0), 4)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
# uint64_t t[2];
|
||||
# uint64_t f[2];
|
||||
for ($i = 1; $i < 3; ++$i) {
|
||||
$ctx[$i][1] = SplFixedArray::fromArray(
|
||||
array(
|
||||
self::load_4(self::substr($string, 76 + (($i - 1) << 4), 4)),
|
||||
self::load_4(self::substr($string, 72 + (($i - 1) << 4), 4))
|
||||
)
|
||||
);
|
||||
$ctx[$i][0] = SplFixedArray::fromArray(
|
||||
array(
|
||||
self::load_4(self::substr($string, 68 + (($i - 1) << 4), 4)),
|
||||
self::load_4(self::substr($string, 64 + (($i - 1) << 4), 4))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
# uint8_t buf[2 * 128];
|
||||
$ctx[3] = self::stringToSplFixedArray(self::substr($string, 96, 256));
|
||||
|
||||
# uint8_t buf[2 * 128];
|
||||
$int = 0;
|
||||
for ($i = 0; $i < 8; ++$i) {
|
||||
$int |= self::chrToInt($string[352 + $i]) << ($i << 3);
|
||||
}
|
||||
$ctx[4] = $int;
|
||||
|
||||
return $ctx;
|
||||
}
|
||||
}
|
||||
@@ -1,249 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
|
||||
/**
|
||||
* Class ParagonIE_Sodium_Core_Base64
|
||||
*
|
||||
* Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
|
||||
* Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
|
||||
*/
|
||||
class ParagonIE_Sodium_Core_Base64_Original
|
||||
{
|
||||
// COPY ParagonIE_Sodium_Core_Base64_Common STARTING HERE
|
||||
/**
|
||||
* Encode into Base64
|
||||
*
|
||||
* Base64 character set "[A-Z][a-z][0-9]+/"
|
||||
*
|
||||
* @param string $src
|
||||
* @return string
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function encode($src)
|
||||
{
|
||||
return self::doEncode($src, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode into Base64, no = padding
|
||||
*
|
||||
* Base64 character set "[A-Z][a-z][0-9]+/"
|
||||
*
|
||||
* @param string $src
|
||||
* @return string
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function encodeUnpadded($src)
|
||||
{
|
||||
return self::doEncode($src, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $src
|
||||
* @param bool $pad Include = padding?
|
||||
* @return string
|
||||
* @throws TypeError
|
||||
*/
|
||||
protected static function doEncode($src, $pad = true)
|
||||
{
|
||||
$dest = '';
|
||||
$srcLen = ParagonIE_Sodium_Core_Util::strlen($src);
|
||||
// Main loop (no padding):
|
||||
for ($i = 0; $i + 3 <= $srcLen; $i += 3) {
|
||||
/** @var array<int, int> $chunk */
|
||||
$chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, 3));
|
||||
$b0 = $chunk[1];
|
||||
$b1 = $chunk[2];
|
||||
$b2 = $chunk[3];
|
||||
|
||||
$dest .=
|
||||
self::encode6Bits( $b0 >> 2 ) .
|
||||
self::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) .
|
||||
self::encode6Bits((($b1 << 2) | ($b2 >> 6)) & 63) .
|
||||
self::encode6Bits( $b2 & 63);
|
||||
}
|
||||
// The last chunk, which may have padding:
|
||||
if ($i < $srcLen) {
|
||||
/** @var array<int, int> $chunk */
|
||||
$chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, $srcLen - $i));
|
||||
$b0 = $chunk[1];
|
||||
if ($i + 1 < $srcLen) {
|
||||
$b1 = $chunk[2];
|
||||
$dest .=
|
||||
self::encode6Bits($b0 >> 2) .
|
||||
self::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) .
|
||||
self::encode6Bits(($b1 << 2) & 63);
|
||||
if ($pad) {
|
||||
$dest .= '=';
|
||||
}
|
||||
} else {
|
||||
$dest .=
|
||||
self::encode6Bits( $b0 >> 2) .
|
||||
self::encode6Bits(($b0 << 4) & 63);
|
||||
if ($pad) {
|
||||
$dest .= '==';
|
||||
}
|
||||
}
|
||||
}
|
||||
return $dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* decode from base64 into binary
|
||||
*
|
||||
* Base64 character set "./[A-Z][a-z][0-9]"
|
||||
*
|
||||
* @param string $src
|
||||
* @param bool $strictPadding
|
||||
* @return string
|
||||
* @throws RangeException
|
||||
* @throws TypeError
|
||||
* @psalm-suppress RedundantCondition
|
||||
*/
|
||||
public static function decode($src, $strictPadding = false)
|
||||
{
|
||||
// Remove padding
|
||||
$srcLen = ParagonIE_Sodium_Core_Util::strlen($src);
|
||||
if ($srcLen === 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ($strictPadding) {
|
||||
if (($srcLen & 3) === 0) {
|
||||
if ($src[$srcLen - 1] === '=') {
|
||||
$srcLen--;
|
||||
if ($src[$srcLen - 1] === '=') {
|
||||
$srcLen--;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (($srcLen & 3) === 1) {
|
||||
throw new RangeException(
|
||||
'Incorrect padding'
|
||||
);
|
||||
}
|
||||
if ($src[$srcLen - 1] === '=') {
|
||||
throw new RangeException(
|
||||
'Incorrect padding'
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$src = rtrim($src, '=');
|
||||
$srcLen = ParagonIE_Sodium_Core_Util::strlen($src);
|
||||
}
|
||||
|
||||
$err = 0;
|
||||
$dest = '';
|
||||
// Main loop (no padding):
|
||||
for ($i = 0; $i + 4 <= $srcLen; $i += 4) {
|
||||
/** @var array<int, int> $chunk */
|
||||
$chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, 4));
|
||||
$c0 = self::decode6Bits($chunk[1]);
|
||||
$c1 = self::decode6Bits($chunk[2]);
|
||||
$c2 = self::decode6Bits($chunk[3]);
|
||||
$c3 = self::decode6Bits($chunk[4]);
|
||||
|
||||
$dest .= pack(
|
||||
'CCC',
|
||||
((($c0 << 2) | ($c1 >> 4)) & 0xff),
|
||||
((($c1 << 4) | ($c2 >> 2)) & 0xff),
|
||||
((($c2 << 6) | $c3) & 0xff)
|
||||
);
|
||||
$err |= ($c0 | $c1 | $c2 | $c3) >> 8;
|
||||
}
|
||||
// The last chunk, which may have padding:
|
||||
if ($i < $srcLen) {
|
||||
/** @var array<int, int> $chunk */
|
||||
$chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, $srcLen - $i));
|
||||
$c0 = self::decode6Bits($chunk[1]);
|
||||
|
||||
if ($i + 2 < $srcLen) {
|
||||
$c1 = self::decode6Bits($chunk[2]);
|
||||
$c2 = self::decode6Bits($chunk[3]);
|
||||
$dest .= pack(
|
||||
'CC',
|
||||
((($c0 << 2) | ($c1 >> 4)) & 0xff),
|
||||
((($c1 << 4) | ($c2 >> 2)) & 0xff)
|
||||
);
|
||||
$err |= ($c0 | $c1 | $c2) >> 8;
|
||||
} elseif ($i + 1 < $srcLen) {
|
||||
$c1 = self::decode6Bits($chunk[2]);
|
||||
$dest .= pack(
|
||||
'C',
|
||||
((($c0 << 2) | ($c1 >> 4)) & 0xff)
|
||||
);
|
||||
$err |= ($c0 | $c1) >> 8;
|
||||
} elseif ($i < $srcLen && $strictPadding) {
|
||||
$err |= 1;
|
||||
}
|
||||
}
|
||||
/** @var bool $check */
|
||||
$check = ($err === 0);
|
||||
if (!$check) {
|
||||
throw new RangeException(
|
||||
'Base64::decode() only expects characters in the correct base64 alphabet'
|
||||
);
|
||||
}
|
||||
return $dest;
|
||||
}
|
||||
// COPY ParagonIE_Sodium_Core_Base64_Common ENDING HERE
|
||||
|
||||
/**
|
||||
* Uses bitwise operators instead of table-lookups to turn 6-bit integers
|
||||
* into 8-bit integers.
|
||||
*
|
||||
* Base64 character set:
|
||||
* [A-Z] [a-z] [0-9] + /
|
||||
* 0x41-0x5a, 0x61-0x7a, 0x30-0x39, 0x2b, 0x2f
|
||||
*
|
||||
* @param int $src
|
||||
* @return int
|
||||
*/
|
||||
protected static function decode6Bits($src)
|
||||
{
|
||||
$ret = -1;
|
||||
|
||||
// if ($src > 0x40 && $src < 0x5b) $ret += $src - 0x41 + 1; // -64
|
||||
$ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 64);
|
||||
|
||||
// if ($src > 0x60 && $src < 0x7b) $ret += $src - 0x61 + 26 + 1; // -70
|
||||
$ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 70);
|
||||
|
||||
// if ($src > 0x2f && $src < 0x3a) $ret += $src - 0x30 + 52 + 1; // 5
|
||||
$ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src + 5);
|
||||
|
||||
// if ($src == 0x2b) $ret += 62 + 1;
|
||||
$ret += (((0x2a - $src) & ($src - 0x2c)) >> 8) & 63;
|
||||
|
||||
// if ($src == 0x2f) ret += 63 + 1;
|
||||
$ret += (((0x2e - $src) & ($src - 0x30)) >> 8) & 64;
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses bitwise operators instead of table-lookups to turn 8-bit integers
|
||||
* into 6-bit integers.
|
||||
*
|
||||
* @param int $src
|
||||
* @return string
|
||||
*/
|
||||
protected static function encode6Bits($src)
|
||||
{
|
||||
$diff = 0x41;
|
||||
|
||||
// if ($src > 25) $diff += 0x61 - 0x41 - 26; // 6
|
||||
$diff += ((25 - $src) >> 8) & 6;
|
||||
|
||||
// if ($src > 51) $diff += 0x30 - 0x61 - 26; // -75
|
||||
$diff -= ((51 - $src) >> 8) & 75;
|
||||
|
||||
// if ($src > 61) $diff += 0x2b - 0x30 - 10; // -15
|
||||
$diff -= ((61 - $src) >> 8) & 15;
|
||||
|
||||
// if ($src > 62) $diff += 0x2f - 0x2b - 1; // 3
|
||||
$diff += ((62 - $src) >> 8) & 3;
|
||||
|
||||
return pack('C', $src + $diff);
|
||||
}
|
||||
}
|
||||
@@ -1,248 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
|
||||
/**
|
||||
* Class ParagonIE_Sodium_Core_Base64UrlSafe
|
||||
*
|
||||
* Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
|
||||
* Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
|
||||
*/
|
||||
class ParagonIE_Sodium_Core_Base64_UrlSafe
|
||||
{
|
||||
// COPY ParagonIE_Sodium_Core_Base64_Common STARTING HERE
|
||||
/**
|
||||
* Encode into Base64
|
||||
*
|
||||
* Base64 character set "[A-Z][a-z][0-9]+/"
|
||||
*
|
||||
* @param string $src
|
||||
* @return string
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function encode($src)
|
||||
{
|
||||
return self::doEncode($src, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode into Base64, no = padding
|
||||
*
|
||||
* Base64 character set "[A-Z][a-z][0-9]+/"
|
||||
*
|
||||
* @param string $src
|
||||
* @return string
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function encodeUnpadded($src)
|
||||
{
|
||||
return self::doEncode($src, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $src
|
||||
* @param bool $pad Include = padding?
|
||||
* @return string
|
||||
* @throws TypeError
|
||||
*/
|
||||
protected static function doEncode($src, $pad = true)
|
||||
{
|
||||
$dest = '';
|
||||
$srcLen = ParagonIE_Sodium_Core_Util::strlen($src);
|
||||
// Main loop (no padding):
|
||||
for ($i = 0; $i + 3 <= $srcLen; $i += 3) {
|
||||
/** @var array<int, int> $chunk */
|
||||
$chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, 3));
|
||||
$b0 = $chunk[1];
|
||||
$b1 = $chunk[2];
|
||||
$b2 = $chunk[3];
|
||||
|
||||
$dest .=
|
||||
self::encode6Bits( $b0 >> 2 ) .
|
||||
self::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) .
|
||||
self::encode6Bits((($b1 << 2) | ($b2 >> 6)) & 63) .
|
||||
self::encode6Bits( $b2 & 63);
|
||||
}
|
||||
// The last chunk, which may have padding:
|
||||
if ($i < $srcLen) {
|
||||
/** @var array<int, int> $chunk */
|
||||
$chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, $srcLen - $i));
|
||||
$b0 = $chunk[1];
|
||||
if ($i + 1 < $srcLen) {
|
||||
$b1 = $chunk[2];
|
||||
$dest .=
|
||||
self::encode6Bits($b0 >> 2) .
|
||||
self::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) .
|
||||
self::encode6Bits(($b1 << 2) & 63);
|
||||
if ($pad) {
|
||||
$dest .= '=';
|
||||
}
|
||||
} else {
|
||||
$dest .=
|
||||
self::encode6Bits( $b0 >> 2) .
|
||||
self::encode6Bits(($b0 << 4) & 63);
|
||||
if ($pad) {
|
||||
$dest .= '==';
|
||||
}
|
||||
}
|
||||
}
|
||||
return $dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* decode from base64 into binary
|
||||
*
|
||||
* Base64 character set "./[A-Z][a-z][0-9]"
|
||||
*
|
||||
* @param string $src
|
||||
* @param bool $strictPadding
|
||||
* @return string
|
||||
* @throws RangeException
|
||||
* @throws TypeError
|
||||
* @psalm-suppress RedundantCondition
|
||||
*/
|
||||
public static function decode($src, $strictPadding = false)
|
||||
{
|
||||
// Remove padding
|
||||
$srcLen = ParagonIE_Sodium_Core_Util::strlen($src);
|
||||
if ($srcLen === 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ($strictPadding) {
|
||||
if (($srcLen & 3) === 0) {
|
||||
if ($src[$srcLen - 1] === '=') {
|
||||
$srcLen--;
|
||||
if ($src[$srcLen - 1] === '=') {
|
||||
$srcLen--;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (($srcLen & 3) === 1) {
|
||||
throw new RangeException(
|
||||
'Incorrect padding'
|
||||
);
|
||||
}
|
||||
if ($src[$srcLen - 1] === '=') {
|
||||
throw new RangeException(
|
||||
'Incorrect padding'
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$src = rtrim($src, '=');
|
||||
$srcLen = ParagonIE_Sodium_Core_Util::strlen($src);
|
||||
}
|
||||
|
||||
$err = 0;
|
||||
$dest = '';
|
||||
// Main loop (no padding):
|
||||
for ($i = 0; $i + 4 <= $srcLen; $i += 4) {
|
||||
/** @var array<int, int> $chunk */
|
||||
$chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, 4));
|
||||
$c0 = self::decode6Bits($chunk[1]);
|
||||
$c1 = self::decode6Bits($chunk[2]);
|
||||
$c2 = self::decode6Bits($chunk[3]);
|
||||
$c3 = self::decode6Bits($chunk[4]);
|
||||
|
||||
$dest .= pack(
|
||||
'CCC',
|
||||
((($c0 << 2) | ($c1 >> 4)) & 0xff),
|
||||
((($c1 << 4) | ($c2 >> 2)) & 0xff),
|
||||
((($c2 << 6) | $c3) & 0xff)
|
||||
);
|
||||
$err |= ($c0 | $c1 | $c2 | $c3) >> 8;
|
||||
}
|
||||
// The last chunk, which may have padding:
|
||||
if ($i < $srcLen) {
|
||||
/** @var array<int, int> $chunk */
|
||||
$chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, $srcLen - $i));
|
||||
$c0 = self::decode6Bits($chunk[1]);
|
||||
|
||||
if ($i + 2 < $srcLen) {
|
||||
$c1 = self::decode6Bits($chunk[2]);
|
||||
$c2 = self::decode6Bits($chunk[3]);
|
||||
$dest .= pack(
|
||||
'CC',
|
||||
((($c0 << 2) | ($c1 >> 4)) & 0xff),
|
||||
((($c1 << 4) | ($c2 >> 2)) & 0xff)
|
||||
);
|
||||
$err |= ($c0 | $c1 | $c2) >> 8;
|
||||
} elseif ($i + 1 < $srcLen) {
|
||||
$c1 = self::decode6Bits($chunk[2]);
|
||||
$dest .= pack(
|
||||
'C',
|
||||
((($c0 << 2) | ($c1 >> 4)) & 0xff)
|
||||
);
|
||||
$err |= ($c0 | $c1) >> 8;
|
||||
} elseif ($i < $srcLen && $strictPadding) {
|
||||
$err |= 1;
|
||||
}
|
||||
}
|
||||
/** @var bool $check */
|
||||
$check = ($err === 0);
|
||||
if (!$check) {
|
||||
throw new RangeException(
|
||||
'Base64::decode() only expects characters in the correct base64 alphabet'
|
||||
);
|
||||
}
|
||||
return $dest;
|
||||
}
|
||||
// COPY ParagonIE_Sodium_Core_Base64_Common ENDING HERE
|
||||
/**
|
||||
* Uses bitwise operators instead of table-lookups to turn 6-bit integers
|
||||
* into 8-bit integers.
|
||||
*
|
||||
* Base64 character set:
|
||||
* [A-Z] [a-z] [0-9] + /
|
||||
* 0x41-0x5a, 0x61-0x7a, 0x30-0x39, 0x2b, 0x2f
|
||||
*
|
||||
* @param int $src
|
||||
* @return int
|
||||
*/
|
||||
protected static function decode6Bits($src)
|
||||
{
|
||||
$ret = -1;
|
||||
|
||||
// if ($src > 0x40 && $src < 0x5b) $ret += $src - 0x41 + 1; // -64
|
||||
$ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 64);
|
||||
|
||||
// if ($src > 0x60 && $src < 0x7b) $ret += $src - 0x61 + 26 + 1; // -70
|
||||
$ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 70);
|
||||
|
||||
// if ($src > 0x2f && $src < 0x3a) $ret += $src - 0x30 + 52 + 1; // 5
|
||||
$ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src + 5);
|
||||
|
||||
// if ($src == 0x2c) $ret += 62 + 1;
|
||||
$ret += (((0x2c - $src) & ($src - 0x2e)) >> 8) & 63;
|
||||
|
||||
// if ($src == 0x5f) ret += 63 + 1;
|
||||
$ret += (((0x5e - $src) & ($src - 0x60)) >> 8) & 64;
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses bitwise operators instead of table-lookups to turn 8-bit integers
|
||||
* into 6-bit integers.
|
||||
*
|
||||
* @param int $src
|
||||
* @return string
|
||||
*/
|
||||
protected static function encode6Bits($src)
|
||||
{
|
||||
$diff = 0x41;
|
||||
|
||||
// if ($src > 25) $diff += 0x61 - 0x41 - 26; // 6
|
||||
$diff += ((25 - $src) >> 8) & 6;
|
||||
|
||||
// if ($src > 51) $diff += 0x30 - 0x61 - 26; // -75
|
||||
$diff -= ((51 - $src) >> 8) & 75;
|
||||
|
||||
// if ($src > 61) $diff += 0x2d - 0x30 - 10; // -13
|
||||
$diff -= ((61 - $src) >> 8) & 13;
|
||||
|
||||
// if ($src > 62) $diff += 0x5f - 0x2b - 1; // 3
|
||||
$diff += ((62 - $src) >> 8) & 49;
|
||||
|
||||
return pack('C', $src + $diff);
|
||||
}
|
||||
}
|
||||
@@ -1,396 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
|
||||
if (class_exists('ParagonIE_Sodium_Core_ChaCha20', false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class ParagonIE_Sodium_Core_ChaCha20
|
||||
*/
|
||||
class ParagonIE_Sodium_Core_ChaCha20 extends ParagonIE_Sodium_Core_Util
|
||||
{
|
||||
/**
|
||||
* Bitwise left rotation
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param int $v
|
||||
* @param int $n
|
||||
* @return int
|
||||
*/
|
||||
public static function rotate($v, $n)
|
||||
{
|
||||
$v &= 0xffffffff;
|
||||
$n &= 31;
|
||||
return (int) (
|
||||
0xffffffff & (
|
||||
($v << $n)
|
||||
|
|
||||
($v >> (32 - $n))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The ChaCha20 quarter round function. Works on four 32-bit integers.
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param int $a
|
||||
* @param int $b
|
||||
* @param int $c
|
||||
* @param int $d
|
||||
* @return array<int, int>
|
||||
*/
|
||||
protected static function quarterRound($a, $b, $c, $d)
|
||||
{
|
||||
# a = PLUS(a,b); d = ROTATE(XOR(d,a),16);
|
||||
/** @var int $a */
|
||||
$a = ($a + $b) & 0xffffffff;
|
||||
$d = self::rotate($d ^ $a, 16);
|
||||
|
||||
# c = PLUS(c,d); b = ROTATE(XOR(b,c),12);
|
||||
/** @var int $c */
|
||||
$c = ($c + $d) & 0xffffffff;
|
||||
$b = self::rotate($b ^ $c, 12);
|
||||
|
||||
# a = PLUS(a,b); d = ROTATE(XOR(d,a), 8);
|
||||
/** @var int $a */
|
||||
$a = ($a + $b) & 0xffffffff;
|
||||
$d = self::rotate($d ^ $a, 8);
|
||||
|
||||
# c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);
|
||||
/** @var int $c */
|
||||
$c = ($c + $d) & 0xffffffff;
|
||||
$b = self::rotate($b ^ $c, 7);
|
||||
return array((int) $a, (int) $b, (int) $c, (int) $d);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param ParagonIE_Sodium_Core_ChaCha20_Ctx $ctx
|
||||
* @param string $message
|
||||
*
|
||||
* @return string
|
||||
* @throws TypeError
|
||||
* @throws SodiumException
|
||||
*/
|
||||
public static function encryptBytes(
|
||||
ParagonIE_Sodium_Core_ChaCha20_Ctx $ctx,
|
||||
$message = ''
|
||||
) {
|
||||
$bytes = self::strlen($message);
|
||||
|
||||
/*
|
||||
j0 = ctx->input[0];
|
||||
j1 = ctx->input[1];
|
||||
j2 = ctx->input[2];
|
||||
j3 = ctx->input[3];
|
||||
j4 = ctx->input[4];
|
||||
j5 = ctx->input[5];
|
||||
j6 = ctx->input[6];
|
||||
j7 = ctx->input[7];
|
||||
j8 = ctx->input[8];
|
||||
j9 = ctx->input[9];
|
||||
j10 = ctx->input[10];
|
||||
j11 = ctx->input[11];
|
||||
j12 = ctx->input[12];
|
||||
j13 = ctx->input[13];
|
||||
j14 = ctx->input[14];
|
||||
j15 = ctx->input[15];
|
||||
*/
|
||||
$j0 = (int) $ctx[0];
|
||||
$j1 = (int) $ctx[1];
|
||||
$j2 = (int) $ctx[2];
|
||||
$j3 = (int) $ctx[3];
|
||||
$j4 = (int) $ctx[4];
|
||||
$j5 = (int) $ctx[5];
|
||||
$j6 = (int) $ctx[6];
|
||||
$j7 = (int) $ctx[7];
|
||||
$j8 = (int) $ctx[8];
|
||||
$j9 = (int) $ctx[9];
|
||||
$j10 = (int) $ctx[10];
|
||||
$j11 = (int) $ctx[11];
|
||||
$j12 = (int) $ctx[12];
|
||||
$j13 = (int) $ctx[13];
|
||||
$j14 = (int) $ctx[14];
|
||||
$j15 = (int) $ctx[15];
|
||||
|
||||
$c = '';
|
||||
for (;;) {
|
||||
if ($bytes < 64) {
|
||||
$message .= str_repeat("\x00", 64 - $bytes);
|
||||
}
|
||||
|
||||
$x0 = (int) $j0;
|
||||
$x1 = (int) $j1;
|
||||
$x2 = (int) $j2;
|
||||
$x3 = (int) $j3;
|
||||
$x4 = (int) $j4;
|
||||
$x5 = (int) $j5;
|
||||
$x6 = (int) $j6;
|
||||
$x7 = (int) $j7;
|
||||
$x8 = (int) $j8;
|
||||
$x9 = (int) $j9;
|
||||
$x10 = (int) $j10;
|
||||
$x11 = (int) $j11;
|
||||
$x12 = (int) $j12;
|
||||
$x13 = (int) $j13;
|
||||
$x14 = (int) $j14;
|
||||
$x15 = (int) $j15;
|
||||
|
||||
# for (i = 20; i > 0; i -= 2) {
|
||||
for ($i = 20; $i > 0; $i -= 2) {
|
||||
# QUARTERROUND( x0, x4, x8, x12)
|
||||
list($x0, $x4, $x8, $x12) = self::quarterRound($x0, $x4, $x8, $x12);
|
||||
|
||||
# QUARTERROUND( x1, x5, x9, x13)
|
||||
list($x1, $x5, $x9, $x13) = self::quarterRound($x1, $x5, $x9, $x13);
|
||||
|
||||
# QUARTERROUND( x2, x6, x10, x14)
|
||||
list($x2, $x6, $x10, $x14) = self::quarterRound($x2, $x6, $x10, $x14);
|
||||
|
||||
# QUARTERROUND( x3, x7, x11, x15)
|
||||
list($x3, $x7, $x11, $x15) = self::quarterRound($x3, $x7, $x11, $x15);
|
||||
|
||||
# QUARTERROUND( x0, x5, x10, x15)
|
||||
list($x0, $x5, $x10, $x15) = self::quarterRound($x0, $x5, $x10, $x15);
|
||||
|
||||
# QUARTERROUND( x1, x6, x11, x12)
|
||||
list($x1, $x6, $x11, $x12) = self::quarterRound($x1, $x6, $x11, $x12);
|
||||
|
||||
# QUARTERROUND( x2, x7, x8, x13)
|
||||
list($x2, $x7, $x8, $x13) = self::quarterRound($x2, $x7, $x8, $x13);
|
||||
|
||||
# QUARTERROUND( x3, x4, x9, x14)
|
||||
list($x3, $x4, $x9, $x14) = self::quarterRound($x3, $x4, $x9, $x14);
|
||||
}
|
||||
/*
|
||||
x0 = PLUS(x0, j0);
|
||||
x1 = PLUS(x1, j1);
|
||||
x2 = PLUS(x2, j2);
|
||||
x3 = PLUS(x3, j3);
|
||||
x4 = PLUS(x4, j4);
|
||||
x5 = PLUS(x5, j5);
|
||||
x6 = PLUS(x6, j6);
|
||||
x7 = PLUS(x7, j7);
|
||||
x8 = PLUS(x8, j8);
|
||||
x9 = PLUS(x9, j9);
|
||||
x10 = PLUS(x10, j10);
|
||||
x11 = PLUS(x11, j11);
|
||||
x12 = PLUS(x12, j12);
|
||||
x13 = PLUS(x13, j13);
|
||||
x14 = PLUS(x14, j14);
|
||||
x15 = PLUS(x15, j15);
|
||||
*/
|
||||
/** @var int $x0 */
|
||||
$x0 = ($x0 & 0xffffffff) + $j0;
|
||||
/** @var int $x1 */
|
||||
$x1 = ($x1 & 0xffffffff) + $j1;
|
||||
/** @var int $x2 */
|
||||
$x2 = ($x2 & 0xffffffff) + $j2;
|
||||
/** @var int $x3 */
|
||||
$x3 = ($x3 & 0xffffffff) + $j3;
|
||||
/** @var int $x4 */
|
||||
$x4 = ($x4 & 0xffffffff) + $j4;
|
||||
/** @var int $x5 */
|
||||
$x5 = ($x5 & 0xffffffff) + $j5;
|
||||
/** @var int $x6 */
|
||||
$x6 = ($x6 & 0xffffffff) + $j6;
|
||||
/** @var int $x7 */
|
||||
$x7 = ($x7 & 0xffffffff) + $j7;
|
||||
/** @var int $x8 */
|
||||
$x8 = ($x8 & 0xffffffff) + $j8;
|
||||
/** @var int $x9 */
|
||||
$x9 = ($x9 & 0xffffffff) + $j9;
|
||||
/** @var int $x10 */
|
||||
$x10 = ($x10 & 0xffffffff) + $j10;
|
||||
/** @var int $x11 */
|
||||
$x11 = ($x11 & 0xffffffff) + $j11;
|
||||
/** @var int $x12 */
|
||||
$x12 = ($x12 & 0xffffffff) + $j12;
|
||||
/** @var int $x13 */
|
||||
$x13 = ($x13 & 0xffffffff) + $j13;
|
||||
/** @var int $x14 */
|
||||
$x14 = ($x14 & 0xffffffff) + $j14;
|
||||
/** @var int $x15 */
|
||||
$x15 = ($x15 & 0xffffffff) + $j15;
|
||||
|
||||
/*
|
||||
x0 = XOR(x0, LOAD32_LE(m + 0));
|
||||
x1 = XOR(x1, LOAD32_LE(m + 4));
|
||||
x2 = XOR(x2, LOAD32_LE(m + 8));
|
||||
x3 = XOR(x3, LOAD32_LE(m + 12));
|
||||
x4 = XOR(x4, LOAD32_LE(m + 16));
|
||||
x5 = XOR(x5, LOAD32_LE(m + 20));
|
||||
x6 = XOR(x6, LOAD32_LE(m + 24));
|
||||
x7 = XOR(x7, LOAD32_LE(m + 28));
|
||||
x8 = XOR(x8, LOAD32_LE(m + 32));
|
||||
x9 = XOR(x9, LOAD32_LE(m + 36));
|
||||
x10 = XOR(x10, LOAD32_LE(m + 40));
|
||||
x11 = XOR(x11, LOAD32_LE(m + 44));
|
||||
x12 = XOR(x12, LOAD32_LE(m + 48));
|
||||
x13 = XOR(x13, LOAD32_LE(m + 52));
|
||||
x14 = XOR(x14, LOAD32_LE(m + 56));
|
||||
x15 = XOR(x15, LOAD32_LE(m + 60));
|
||||
*/
|
||||
$x0 ^= self::load_4(self::substr($message, 0, 4));
|
||||
$x1 ^= self::load_4(self::substr($message, 4, 4));
|
||||
$x2 ^= self::load_4(self::substr($message, 8, 4));
|
||||
$x3 ^= self::load_4(self::substr($message, 12, 4));
|
||||
$x4 ^= self::load_4(self::substr($message, 16, 4));
|
||||
$x5 ^= self::load_4(self::substr($message, 20, 4));
|
||||
$x6 ^= self::load_4(self::substr($message, 24, 4));
|
||||
$x7 ^= self::load_4(self::substr($message, 28, 4));
|
||||
$x8 ^= self::load_4(self::substr($message, 32, 4));
|
||||
$x9 ^= self::load_4(self::substr($message, 36, 4));
|
||||
$x10 ^= self::load_4(self::substr($message, 40, 4));
|
||||
$x11 ^= self::load_4(self::substr($message, 44, 4));
|
||||
$x12 ^= self::load_4(self::substr($message, 48, 4));
|
||||
$x13 ^= self::load_4(self::substr($message, 52, 4));
|
||||
$x14 ^= self::load_4(self::substr($message, 56, 4));
|
||||
$x15 ^= self::load_4(self::substr($message, 60, 4));
|
||||
|
||||
/*
|
||||
j12 = PLUSONE(j12);
|
||||
if (!j12) {
|
||||
j13 = PLUSONE(j13);
|
||||
}
|
||||
*/
|
||||
++$j12;
|
||||
if ($j12 & 0xf0000000) {
|
||||
throw new SodiumException('Overflow');
|
||||
}
|
||||
|
||||
/*
|
||||
STORE32_LE(c + 0, x0);
|
||||
STORE32_LE(c + 4, x1);
|
||||
STORE32_LE(c + 8, x2);
|
||||
STORE32_LE(c + 12, x3);
|
||||
STORE32_LE(c + 16, x4);
|
||||
STORE32_LE(c + 20, x5);
|
||||
STORE32_LE(c + 24, x6);
|
||||
STORE32_LE(c + 28, x7);
|
||||
STORE32_LE(c + 32, x8);
|
||||
STORE32_LE(c + 36, x9);
|
||||
STORE32_LE(c + 40, x10);
|
||||
STORE32_LE(c + 44, x11);
|
||||
STORE32_LE(c + 48, x12);
|
||||
STORE32_LE(c + 52, x13);
|
||||
STORE32_LE(c + 56, x14);
|
||||
STORE32_LE(c + 60, x15);
|
||||
*/
|
||||
$block = self::store32_le((int) ($x0 & 0xffffffff)) .
|
||||
self::store32_le((int) ($x1 & 0xffffffff)) .
|
||||
self::store32_le((int) ($x2 & 0xffffffff)) .
|
||||
self::store32_le((int) ($x3 & 0xffffffff)) .
|
||||
self::store32_le((int) ($x4 & 0xffffffff)) .
|
||||
self::store32_le((int) ($x5 & 0xffffffff)) .
|
||||
self::store32_le((int) ($x6 & 0xffffffff)) .
|
||||
self::store32_le((int) ($x7 & 0xffffffff)) .
|
||||
self::store32_le((int) ($x8 & 0xffffffff)) .
|
||||
self::store32_le((int) ($x9 & 0xffffffff)) .
|
||||
self::store32_le((int) ($x10 & 0xffffffff)) .
|
||||
self::store32_le((int) ($x11 & 0xffffffff)) .
|
||||
self::store32_le((int) ($x12 & 0xffffffff)) .
|
||||
self::store32_le((int) ($x13 & 0xffffffff)) .
|
||||
self::store32_le((int) ($x14 & 0xffffffff)) .
|
||||
self::store32_le((int) ($x15 & 0xffffffff));
|
||||
|
||||
/* Partial block */
|
||||
if ($bytes < 64) {
|
||||
$c .= self::substr($block, 0, $bytes);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Full block */
|
||||
$c .= $block;
|
||||
$bytes -= 64;
|
||||
if ($bytes <= 0) {
|
||||
break;
|
||||
}
|
||||
$message = self::substr($message, 64);
|
||||
}
|
||||
/* end for(;;) loop */
|
||||
|
||||
$ctx[12] = $j12;
|
||||
$ctx[13] = $j13;
|
||||
return $c;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param int $len
|
||||
* @param string $nonce
|
||||
* @param string $key
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function stream($len = 64, $nonce = '', $key = '')
|
||||
{
|
||||
return self::encryptBytes(
|
||||
new ParagonIE_Sodium_Core_ChaCha20_Ctx($key, $nonce),
|
||||
str_repeat("\x00", $len)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param int $len
|
||||
* @param string $nonce
|
||||
* @param string $key
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function ietfStream($len, $nonce = '', $key = '')
|
||||
{
|
||||
return self::encryptBytes(
|
||||
new ParagonIE_Sodium_Core_ChaCha20_IetfCtx($key, $nonce),
|
||||
str_repeat("\x00", $len)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param string $message
|
||||
* @param string $nonce
|
||||
* @param string $key
|
||||
* @param string $ic
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function ietfStreamXorIc($message, $nonce = '', $key = '', $ic = '')
|
||||
{
|
||||
return self::encryptBytes(
|
||||
new ParagonIE_Sodium_Core_ChaCha20_IetfCtx($key, $nonce, $ic),
|
||||
$message
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param string $message
|
||||
* @param string $nonce
|
||||
* @param string $key
|
||||
* @param string $ic
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function streamXorIc($message, $nonce = '', $key = '', $ic = '')
|
||||
{
|
||||
return self::encryptBytes(
|
||||
new ParagonIE_Sodium_Core_ChaCha20_Ctx($key, $nonce, $ic),
|
||||
$message
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,124 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
|
||||
if (class_exists('ParagonIE_Sodium_Core_ChaCha20_Ctx', false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class ParagonIE_Sodium_Core_ChaCha20_Ctx
|
||||
*/
|
||||
class ParagonIE_Sodium_Core_ChaCha20_Ctx extends ParagonIE_Sodium_Core_Util implements ArrayAccess
|
||||
{
|
||||
/**
|
||||
* @var SplFixedArray internally, <int, int>
|
||||
*/
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* ParagonIE_Sodium_Core_ChaCha20_Ctx constructor.
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param string $key ChaCha20 key.
|
||||
* @param string $iv Initialization Vector (a.k.a. nonce).
|
||||
* @param string $counter The initial counter value.
|
||||
* Defaults to 8 0x00 bytes.
|
||||
* @throws InvalidArgumentException
|
||||
* @throws TypeError
|
||||
*/
|
||||
public function __construct($key = '', $iv = '', $counter = '')
|
||||
{
|
||||
if (self::strlen($key) !== 32) {
|
||||
throw new InvalidArgumentException('ChaCha20 expects a 256-bit key.');
|
||||
}
|
||||
if (self::strlen($iv) !== 8) {
|
||||
throw new InvalidArgumentException('ChaCha20 expects a 64-bit nonce.');
|
||||
}
|
||||
$this->container = new SplFixedArray(16);
|
||||
|
||||
/* "expand 32-byte k" as per ChaCha20 spec */
|
||||
$this->container[0] = 0x61707865;
|
||||
$this->container[1] = 0x3320646e;
|
||||
$this->container[2] = 0x79622d32;
|
||||
$this->container[3] = 0x6b206574;
|
||||
$this->container[4] = self::load_4(self::substr($key, 0, 4));
|
||||
$this->container[5] = self::load_4(self::substr($key, 4, 4));
|
||||
$this->container[6] = self::load_4(self::substr($key, 8, 4));
|
||||
$this->container[7] = self::load_4(self::substr($key, 12, 4));
|
||||
$this->container[8] = self::load_4(self::substr($key, 16, 4));
|
||||
$this->container[9] = self::load_4(self::substr($key, 20, 4));
|
||||
$this->container[10] = self::load_4(self::substr($key, 24, 4));
|
||||
$this->container[11] = self::load_4(self::substr($key, 28, 4));
|
||||
|
||||
if (empty($counter)) {
|
||||
$this->container[12] = 0;
|
||||
$this->container[13] = 0;
|
||||
} else {
|
||||
$this->container[12] = self::load_4(self::substr($counter, 0, 4));
|
||||
$this->container[13] = self::load_4(self::substr($counter, 4, 4));
|
||||
}
|
||||
$this->container[14] = self::load_4(self::substr($iv, 0, 4));
|
||||
$this->container[15] = self::load_4(self::substr($iv, 4, 4));
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param int $offset
|
||||
* @param int $value
|
||||
* @return void
|
||||
* @psalm-suppress MixedArrayOffset
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
if (!is_int($offset)) {
|
||||
throw new InvalidArgumentException('Expected an integer');
|
||||
}
|
||||
if (!is_int($value)) {
|
||||
throw new InvalidArgumentException('Expected an integer');
|
||||
}
|
||||
$this->container[$offset] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param int $offset
|
||||
* @return bool
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return isset($this->container[$offset]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param int $offset
|
||||
* @return void
|
||||
* @psalm-suppress MixedArrayOffset
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
unset($this->container[$offset]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param int $offset
|
||||
* @return mixed|null
|
||||
* @psalm-suppress MixedArrayOffset
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
return isset($this->container[$offset])
|
||||
? $this->container[$offset]
|
||||
: null;
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
|
||||
if (class_exists('ParagonIE_Sodium_Core_ChaCha20_IetfCtx', false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class ParagonIE_Sodium_Core_ChaCha20_IetfCtx
|
||||
*/
|
||||
class ParagonIE_Sodium_Core_ChaCha20_IetfCtx extends ParagonIE_Sodium_Core_ChaCha20_Ctx
|
||||
{
|
||||
/**
|
||||
* ParagonIE_Sodium_Core_ChaCha20_IetfCtx constructor.
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param string $key ChaCha20 key.
|
||||
* @param string $iv Initialization Vector (a.k.a. nonce).
|
||||
* @param string $counter The initial counter value.
|
||||
* Defaults to 4 0x00 bytes.
|
||||
* @throws InvalidArgumentException
|
||||
* @throws TypeError
|
||||
*/
|
||||
public function __construct($key = '', $iv = '', $counter = '')
|
||||
{
|
||||
if (self::strlen($iv) !== 12) {
|
||||
throw new InvalidArgumentException('ChaCha20 expects a 96-bit nonce in IETF mode.');
|
||||
}
|
||||
parent::__construct($key, self::substr($iv, 0, 8), $counter);
|
||||
|
||||
if (!empty($counter)) {
|
||||
$this->container[12] = self::load_4(self::substr($counter, 0, 4));
|
||||
}
|
||||
$this->container[13] = self::load_4(self::substr($iv, 0, 4));
|
||||
$this->container[14] = self::load_4(self::substr($iv, 4, 4));
|
||||
$this->container[15] = self::load_4(self::substr($iv, 8, 4));
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,128 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
|
||||
if (class_exists('ParagonIE_Sodium_Core_Curve25519_Fe', false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class ParagonIE_Sodium_Core_Curve25519_Fe
|
||||
*
|
||||
* This represents a Field Element
|
||||
*/
|
||||
class ParagonIE_Sodium_Core_Curve25519_Fe implements ArrayAccess
|
||||
{
|
||||
/**
|
||||
* @var array<int, int>
|
||||
*/
|
||||
protected $container = array();
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $size = 10;
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param array<int, int> $array
|
||||
* @param bool $save_indexes
|
||||
* @return self
|
||||
*/
|
||||
public static function fromArray($array, $save_indexes = null)
|
||||
{
|
||||
$count = count($array);
|
||||
if ($save_indexes) {
|
||||
$keys = array_keys($array);
|
||||
} else {
|
||||
$keys = range(0, $count - 1);
|
||||
}
|
||||
$array = array_values($array);
|
||||
/** @var array<int, int> $keys */
|
||||
|
||||
$obj = new ParagonIE_Sodium_Core_Curve25519_Fe();
|
||||
if ($save_indexes) {
|
||||
for ($i = 0; $i < $count; ++$i) {
|
||||
$obj->offsetSet($keys[$i], $array[$i]);
|
||||
}
|
||||
} else {
|
||||
for ($i = 0; $i < $count; ++$i) {
|
||||
$obj->offsetSet($i, $array[$i]);
|
||||
}
|
||||
}
|
||||
return $obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param int|null $offset
|
||||
* @param int $value
|
||||
* @return void
|
||||
* @psalm-suppress MixedArrayOffset
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
if (!is_int($value)) {
|
||||
throw new InvalidArgumentException('Expected an integer');
|
||||
}
|
||||
if (is_null($offset)) {
|
||||
$this->container[] = $value;
|
||||
} else {
|
||||
$this->container[$offset] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param int $offset
|
||||
* @return bool
|
||||
* @psalm-suppress MixedArrayOffset
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return isset($this->container[$offset]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param int $offset
|
||||
* @return void
|
||||
* @psalm-suppress MixedArrayOffset
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
unset($this->container[$offset]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param int $offset
|
||||
* @return int
|
||||
* @psalm-suppress MixedArrayOffset
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
if (!isset($this->container[$offset])) {
|
||||
$this->container[$offset] = 0;
|
||||
}
|
||||
return (int) ($this->container[$offset]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function __debugInfo()
|
||||
{
|
||||
return array(implode(', ', $this->container));
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
|
||||
|
||||
if (class_exists('ParagonIE_Sodium_Core_Curve25519_Ge_Cached', false)) {
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Class ParagonIE_Sodium_Core_Curve25519_Ge_Cached
|
||||
*/
|
||||
class ParagonIE_Sodium_Core_Curve25519_Ge_Cached
|
||||
{
|
||||
/**
|
||||
* @var ParagonIE_Sodium_Core_Curve25519_Fe
|
||||
*/
|
||||
public $YplusX;
|
||||
|
||||
/**
|
||||
* @var ParagonIE_Sodium_Core_Curve25519_Fe
|
||||
*/
|
||||
public $YminusX;
|
||||
|
||||
/**
|
||||
* @var ParagonIE_Sodium_Core_Curve25519_Fe
|
||||
*/
|
||||
public $Z;
|
||||
|
||||
/**
|
||||
* @var ParagonIE_Sodium_Core_Curve25519_Fe
|
||||
*/
|
||||
public $T2d;
|
||||
|
||||
/**
|
||||
* ParagonIE_Sodium_Core_Curve25519_Ge_Cached constructor.
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param ParagonIE_Sodium_Core_Curve25519_Fe|null $YplusX
|
||||
* @param ParagonIE_Sodium_Core_Curve25519_Fe|null $YminusX
|
||||
* @param ParagonIE_Sodium_Core_Curve25519_Fe|null $Z
|
||||
* @param ParagonIE_Sodium_Core_Curve25519_Fe|null $T2d
|
||||
*/
|
||||
public function __construct(
|
||||
ParagonIE_Sodium_Core_Curve25519_Fe $YplusX = null,
|
||||
ParagonIE_Sodium_Core_Curve25519_Fe $YminusX = null,
|
||||
ParagonIE_Sodium_Core_Curve25519_Fe $Z = null,
|
||||
ParagonIE_Sodium_Core_Curve25519_Fe $T2d = null
|
||||
) {
|
||||
if ($YplusX === null) {
|
||||
$YplusX = new ParagonIE_Sodium_Core_Curve25519_Fe();
|
||||
}
|
||||
$this->YplusX = $YplusX;
|
||||
if ($YminusX === null) {
|
||||
$YminusX = new ParagonIE_Sodium_Core_Curve25519_Fe();
|
||||
}
|
||||
$this->YminusX = $YminusX;
|
||||
if ($Z === null) {
|
||||
$Z = new ParagonIE_Sodium_Core_Curve25519_Fe();
|
||||
}
|
||||
$this->Z = $Z;
|
||||
if ($T2d === null) {
|
||||
$T2d = new ParagonIE_Sodium_Core_Curve25519_Fe();
|
||||
}
|
||||
$this->T2d = $T2d;
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
|
||||
if (class_exists('ParagonIE_Sodium_Core_Curve25519_Ge_P1p1', false)) {
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Class ParagonIE_Sodium_Core_Curve25519_Ge_P1p1
|
||||
*/
|
||||
class ParagonIE_Sodium_Core_Curve25519_Ge_P1p1
|
||||
{
|
||||
/**
|
||||
* @var ParagonIE_Sodium_Core_Curve25519_Fe
|
||||
*/
|
||||
public $X;
|
||||
|
||||
/**
|
||||
* @var ParagonIE_Sodium_Core_Curve25519_Fe
|
||||
*/
|
||||
public $Y;
|
||||
|
||||
/**
|
||||
* @var ParagonIE_Sodium_Core_Curve25519_Fe
|
||||
*/
|
||||
public $Z;
|
||||
|
||||
/**
|
||||
* @var ParagonIE_Sodium_Core_Curve25519_Fe
|
||||
*/
|
||||
public $T;
|
||||
|
||||
/**
|
||||
* ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 constructor.
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param ParagonIE_Sodium_Core_Curve25519_Fe|null $x
|
||||
* @param ParagonIE_Sodium_Core_Curve25519_Fe|null $y
|
||||
* @param ParagonIE_Sodium_Core_Curve25519_Fe|null $z
|
||||
* @param ParagonIE_Sodium_Core_Curve25519_Fe|null $t
|
||||
*/
|
||||
public function __construct(
|
||||
ParagonIE_Sodium_Core_Curve25519_Fe $x = null,
|
||||
ParagonIE_Sodium_Core_Curve25519_Fe $y = null,
|
||||
ParagonIE_Sodium_Core_Curve25519_Fe $z = null,
|
||||
ParagonIE_Sodium_Core_Curve25519_Fe $t = null
|
||||
) {
|
||||
if ($x === null) {
|
||||
$x = new ParagonIE_Sodium_Core_Curve25519_Fe();
|
||||
}
|
||||
$this->X = $x;
|
||||
if ($y === null) {
|
||||
$y = new ParagonIE_Sodium_Core_Curve25519_Fe();
|
||||
}
|
||||
$this->Y = $y;
|
||||
if ($z === null) {
|
||||
$z = new ParagonIE_Sodium_Core_Curve25519_Fe();
|
||||
}
|
||||
$this->Z = $z;
|
||||
if ($t === null) {
|
||||
$t = new ParagonIE_Sodium_Core_Curve25519_Fe();
|
||||
}
|
||||
$this->T = $t;
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
|
||||
if (class_exists('ParagonIE_Sodium_Core_Curve25519_Ge_P2', false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class ParagonIE_Sodium_Core_Curve25519_Ge_P2
|
||||
*/
|
||||
class ParagonIE_Sodium_Core_Curve25519_Ge_P2
|
||||
{
|
||||
/**
|
||||
* @var ParagonIE_Sodium_Core_Curve25519_Fe
|
||||
*/
|
||||
public $X;
|
||||
|
||||
/**
|
||||
* @var ParagonIE_Sodium_Core_Curve25519_Fe
|
||||
*/
|
||||
public $Y;
|
||||
|
||||
/**
|
||||
* @var ParagonIE_Sodium_Core_Curve25519_Fe
|
||||
*/
|
||||
public $Z;
|
||||
|
||||
/**
|
||||
* ParagonIE_Sodium_Core_Curve25519_Ge_P2 constructor.
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param ParagonIE_Sodium_Core_Curve25519_Fe|null $x
|
||||
* @param ParagonIE_Sodium_Core_Curve25519_Fe|null $y
|
||||
* @param ParagonIE_Sodium_Core_Curve25519_Fe|null $z
|
||||
*/
|
||||
public function __construct(
|
||||
ParagonIE_Sodium_Core_Curve25519_Fe $x = null,
|
||||
ParagonIE_Sodium_Core_Curve25519_Fe $y = null,
|
||||
ParagonIE_Sodium_Core_Curve25519_Fe $z = null
|
||||
) {
|
||||
if ($x === null) {
|
||||
$x = new ParagonIE_Sodium_Core_Curve25519_Fe();
|
||||
}
|
||||
$this->X = $x;
|
||||
if ($y === null) {
|
||||
$y = new ParagonIE_Sodium_Core_Curve25519_Fe();
|
||||
}
|
||||
$this->Y = $y;
|
||||
if ($z === null) {
|
||||
$z = new ParagonIE_Sodium_Core_Curve25519_Fe();
|
||||
}
|
||||
$this->Z = $z;
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
|
||||
if (class_exists('ParagonIE_Sodium_Core_Curve25519_Ge_P3', false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class ParagonIE_Sodium_Core_Curve25519_Ge_P3
|
||||
*/
|
||||
class ParagonIE_Sodium_Core_Curve25519_Ge_P3
|
||||
{
|
||||
/**
|
||||
* @var ParagonIE_Sodium_Core_Curve25519_Fe
|
||||
*/
|
||||
public $X;
|
||||
|
||||
/**
|
||||
* @var ParagonIE_Sodium_Core_Curve25519_Fe
|
||||
*/
|
||||
public $Y;
|
||||
|
||||
/**
|
||||
* @var ParagonIE_Sodium_Core_Curve25519_Fe
|
||||
*/
|
||||
public $Z;
|
||||
|
||||
/**
|
||||
* @var ParagonIE_Sodium_Core_Curve25519_Fe
|
||||
*/
|
||||
public $T;
|
||||
|
||||
/**
|
||||
* ParagonIE_Sodium_Core_Curve25519_Ge_P3 constructor.
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param ParagonIE_Sodium_Core_Curve25519_Fe|null $x
|
||||
* @param ParagonIE_Sodium_Core_Curve25519_Fe|null $y
|
||||
* @param ParagonIE_Sodium_Core_Curve25519_Fe|null $z
|
||||
* @param ParagonIE_Sodium_Core_Curve25519_Fe|null $t
|
||||
*/
|
||||
public function __construct(
|
||||
ParagonIE_Sodium_Core_Curve25519_Fe $x = null,
|
||||
ParagonIE_Sodium_Core_Curve25519_Fe $y = null,
|
||||
ParagonIE_Sodium_Core_Curve25519_Fe $z = null,
|
||||
ParagonIE_Sodium_Core_Curve25519_Fe $t = null
|
||||
) {
|
||||
if ($x === null) {
|
||||
$x = new ParagonIE_Sodium_Core_Curve25519_Fe();
|
||||
}
|
||||
$this->X = $x;
|
||||
if ($y === null) {
|
||||
$y = new ParagonIE_Sodium_Core_Curve25519_Fe();
|
||||
}
|
||||
$this->Y = $y;
|
||||
if ($z === null) {
|
||||
$z = new ParagonIE_Sodium_Core_Curve25519_Fe();
|
||||
}
|
||||
$this->Z = $z;
|
||||
if ($t === null) {
|
||||
$t = new ParagonIE_Sodium_Core_Curve25519_Fe();
|
||||
}
|
||||
$this->T = $t;
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
|
||||
if (class_exists('ParagonIE_Sodium_Core_Curve25519_Ge_Precomp', false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class ParagonIE_Sodium_Core_Curve25519_Ge_Precomp
|
||||
*/
|
||||
class ParagonIE_Sodium_Core_Curve25519_Ge_Precomp
|
||||
{
|
||||
/**
|
||||
* @var ParagonIE_Sodium_Core_Curve25519_Fe
|
||||
*/
|
||||
public $yplusx;
|
||||
|
||||
/**
|
||||
* @var ParagonIE_Sodium_Core_Curve25519_Fe
|
||||
*/
|
||||
public $yminusx;
|
||||
|
||||
/**
|
||||
* @var ParagonIE_Sodium_Core_Curve25519_Fe
|
||||
*/
|
||||
public $xy2d;
|
||||
|
||||
/**
|
||||
* ParagonIE_Sodium_Core_Curve25519_Ge_Precomp constructor.
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param ParagonIE_Sodium_Core_Curve25519_Fe $yplusx
|
||||
* @param ParagonIE_Sodium_Core_Curve25519_Fe $yminusx
|
||||
* @param ParagonIE_Sodium_Core_Curve25519_Fe $xy2d
|
||||
*/
|
||||
public function __construct(
|
||||
ParagonIE_Sodium_Core_Curve25519_Fe $yplusx = null,
|
||||
ParagonIE_Sodium_Core_Curve25519_Fe $yminusx = null,
|
||||
ParagonIE_Sodium_Core_Curve25519_Fe $xy2d = null
|
||||
) {
|
||||
if ($yplusx === null) {
|
||||
$yplusx = new ParagonIE_Sodium_Core_Curve25519_Fe();
|
||||
}
|
||||
$this->yplusx = $yplusx;
|
||||
if ($yminusx === null) {
|
||||
$yminusx = new ParagonIE_Sodium_Core_Curve25519_Fe();
|
||||
}
|
||||
$this->yminusx = $yminusx;
|
||||
if ($xy2d === null) {
|
||||
$xy2d = new ParagonIE_Sodium_Core_Curve25519_Fe();
|
||||
}
|
||||
$this->xy2d = $xy2d;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,555 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
|
||||
if (class_exists('ParagonIE_Sodium_Core_Ed25519', false)) {
|
||||
return;
|
||||
}
|
||||
if (!class_exists('ParagonIE_Sodium_Core_Curve25519', false)) {
|
||||
require_once dirname(__FILE__) . '/Curve25519.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Class ParagonIE_Sodium_Core_Ed25519
|
||||
*/
|
||||
abstract class ParagonIE_Sodium_Core_Ed25519 extends ParagonIE_Sodium_Core_Curve25519
|
||||
{
|
||||
const KEYPAIR_BYTES = 96;
|
||||
const SEED_BYTES = 32;
|
||||
const SCALAR_BYTES = 32;
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @return string (96 bytes)
|
||||
* @throws Exception
|
||||
* @throws SodiumException
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function keypair()
|
||||
{
|
||||
$seed = random_bytes(self::SEED_BYTES);
|
||||
$pk = '';
|
||||
$sk = '';
|
||||
self::seed_keypair($pk, $sk, $seed);
|
||||
return $sk . $pk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param string $pk
|
||||
* @param string $sk
|
||||
* @param string $seed
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function seed_keypair(&$pk, &$sk, $seed)
|
||||
{
|
||||
if (self::strlen($seed) !== self::SEED_BYTES) {
|
||||
throw new RangeException('crypto_sign keypair seed must be 32 bytes long');
|
||||
}
|
||||
|
||||
/** @var string $pk */
|
||||
$pk = self::publickey_from_secretkey($seed);
|
||||
$sk = $seed . $pk;
|
||||
return $sk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param string $keypair
|
||||
* @return string
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function secretkey($keypair)
|
||||
{
|
||||
if (self::strlen($keypair) !== self::KEYPAIR_BYTES) {
|
||||
throw new RangeException('crypto_sign keypair must be 96 bytes long');
|
||||
}
|
||||
return self::substr($keypair, 0, 64);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param string $keypair
|
||||
* @return string
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function publickey($keypair)
|
||||
{
|
||||
if (self::strlen($keypair) !== self::KEYPAIR_BYTES) {
|
||||
throw new RangeException('crypto_sign keypair must be 96 bytes long');
|
||||
}
|
||||
return self::substr($keypair, 64, 32);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param string $sk
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function publickey_from_secretkey($sk)
|
||||
{
|
||||
/** @var string $sk */
|
||||
$sk = hash('sha512', self::substr($sk, 0, 32), true);
|
||||
$sk[0] = self::intToChr(
|
||||
self::chrToInt($sk[0]) & 248
|
||||
);
|
||||
$sk[31] = self::intToChr(
|
||||
(self::chrToInt($sk[31]) & 63) | 64
|
||||
);
|
||||
return self::sk_to_pk($sk);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $pk
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function pk_to_curve25519($pk)
|
||||
{
|
||||
if (self::small_order($pk)) {
|
||||
throw new SodiumException('Public key is on a small order');
|
||||
}
|
||||
$A = self::ge_frombytes_negate_vartime(self::substr($pk, 0, 32));
|
||||
$p1 = self::ge_mul_l($A);
|
||||
if (!self::fe_isnonzero($p1->X)) {
|
||||
throw new SodiumException('Unexpected zero result');
|
||||
}
|
||||
|
||||
# fe_1(one_minus_y);
|
||||
# fe_sub(one_minus_y, one_minus_y, A.Y);
|
||||
# fe_invert(one_minus_y, one_minus_y);
|
||||
$one_minux_y = self::fe_invert(
|
||||
self::fe_sub(
|
||||
self::fe_1(),
|
||||
$A->Y
|
||||
)
|
||||
);
|
||||
|
||||
# fe_1(x);
|
||||
# fe_add(x, x, A.Y);
|
||||
# fe_mul(x, x, one_minus_y);
|
||||
$x = self::fe_mul(
|
||||
self::fe_add(self::fe_1(), $A->Y),
|
||||
$one_minux_y
|
||||
);
|
||||
|
||||
# fe_tobytes(curve25519_pk, x);
|
||||
return self::fe_tobytes($x);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param string $sk
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function sk_to_pk($sk)
|
||||
{
|
||||
return self::ge_p3_tobytes(
|
||||
self::ge_scalarmult_base(
|
||||
self::substr($sk, 0, 32)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param string $message
|
||||
* @param string $sk
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function sign($message, $sk)
|
||||
{
|
||||
/** @var string $signature */
|
||||
$signature = self::sign_detached($message, $sk);
|
||||
return $signature . $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param string $message A signed message
|
||||
* @param string $pk Public key
|
||||
* @return string Message (without signature)
|
||||
* @throws SodiumException
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function sign_open($message, $pk)
|
||||
{
|
||||
/** @var string $signature */
|
||||
$signature = self::substr($message, 0, 64);
|
||||
|
||||
/** @var string $message */
|
||||
$message = self::substr($message, 64);
|
||||
|
||||
if (self::verify_detached($signature, $message, $pk)) {
|
||||
return $message;
|
||||
}
|
||||
throw new SodiumException('Invalid signature');
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param string $message
|
||||
* @param string $sk
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function sign_detached($message, $sk)
|
||||
{
|
||||
# crypto_hash_sha512(az, sk, 32);
|
||||
$az = hash('sha512', self::substr($sk, 0, 32), true);
|
||||
|
||||
# az[0] &= 248;
|
||||
# az[31] &= 63;
|
||||
# az[31] |= 64;
|
||||
$az[0] = self::intToChr(self::chrToInt($az[0]) & 248);
|
||||
$az[31] = self::intToChr((self::chrToInt($az[31]) & 63) | 64);
|
||||
|
||||
# crypto_hash_sha512_init(&hs);
|
||||
# crypto_hash_sha512_update(&hs, az + 32, 32);
|
||||
# crypto_hash_sha512_update(&hs, m, mlen);
|
||||
# crypto_hash_sha512_final(&hs, nonce);
|
||||
$hs = hash_init('sha512');
|
||||
hash_update($hs, self::substr($az, 32, 32));
|
||||
hash_update($hs, $message);
|
||||
$nonceHash = hash_final($hs, true);
|
||||
|
||||
# memmove(sig + 32, sk + 32, 32);
|
||||
$pk = self::substr($sk, 32, 32);
|
||||
|
||||
# sc_reduce(nonce);
|
||||
# ge_scalarmult_base(&R, nonce);
|
||||
# ge_p3_tobytes(sig, &R);
|
||||
$nonce = self::sc_reduce($nonceHash) . self::substr($nonceHash, 32);
|
||||
$sig = self::ge_p3_tobytes(
|
||||
self::ge_scalarmult_base($nonce)
|
||||
);
|
||||
|
||||
# crypto_hash_sha512_init(&hs);
|
||||
# crypto_hash_sha512_update(&hs, sig, 64);
|
||||
# crypto_hash_sha512_update(&hs, m, mlen);
|
||||
# crypto_hash_sha512_final(&hs, hram);
|
||||
$hs = hash_init('sha512');
|
||||
hash_update($hs, self::substr($sig, 0, 32));
|
||||
hash_update($hs, self::substr($pk, 0, 32));
|
||||
hash_update($hs, $message);
|
||||
$hramHash = hash_final($hs, true);
|
||||
|
||||
# sc_reduce(hram);
|
||||
# sc_muladd(sig + 32, hram, az, nonce);
|
||||
$hram = self::sc_reduce($hramHash);
|
||||
$sigAfter = self::sc_muladd($hram, $az, $nonce);
|
||||
$sig = self::substr($sig, 0, 32) . self::substr($sigAfter, 0, 32);
|
||||
|
||||
try {
|
||||
ParagonIE_Sodium_Compat::memzero($az);
|
||||
} catch (SodiumException $ex) {
|
||||
$az = null;
|
||||
}
|
||||
return $sig;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param string $sig
|
||||
* @param string $message
|
||||
* @param string $pk
|
||||
* @return bool
|
||||
* @throws SodiumException
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function verify_detached($sig, $message, $pk)
|
||||
{
|
||||
if (self::strlen($sig) < 64) {
|
||||
throw new SodiumException('Signature is too short');
|
||||
}
|
||||
if ((self::chrToInt($sig[63]) & 240) && self::check_S_lt_L(self::substr($sig, 32, 32))) {
|
||||
throw new SodiumException('S < L - Invalid signature');
|
||||
}
|
||||
if (self::small_order($sig)) {
|
||||
throw new SodiumException('Signature is on too small of an order');
|
||||
}
|
||||
if ((self::chrToInt($sig[63]) & 224) !== 0) {
|
||||
throw new SodiumException('Invalid signature');
|
||||
}
|
||||
$d = 0;
|
||||
for ($i = 0; $i < 32; ++$i) {
|
||||
$d |= self::chrToInt($pk[$i]);
|
||||
}
|
||||
if ($d === 0) {
|
||||
throw new SodiumException('All zero public key');
|
||||
}
|
||||
|
||||
/** @var bool The original value of ParagonIE_Sodium_Compat::$fastMult */
|
||||
$orig = ParagonIE_Sodium_Compat::$fastMult;
|
||||
|
||||
// Set ParagonIE_Sodium_Compat::$fastMult to true to speed up verification.
|
||||
ParagonIE_Sodium_Compat::$fastMult = true;
|
||||
|
||||
/** @var ParagonIE_Sodium_Core_Curve25519_Ge_P3 $A */
|
||||
$A = self::ge_frombytes_negate_vartime($pk);
|
||||
|
||||
/** @var string $hDigest */
|
||||
$hDigest = hash(
|
||||
'sha512',
|
||||
self::substr($sig, 0, 32) .
|
||||
self::substr($pk, 0, 32) .
|
||||
$message,
|
||||
true
|
||||
);
|
||||
|
||||
/** @var string $h */
|
||||
$h = self::sc_reduce($hDigest) . self::substr($hDigest, 32);
|
||||
|
||||
/** @var ParagonIE_Sodium_Core_Curve25519_Ge_P2 $R */
|
||||
$R = self::ge_double_scalarmult_vartime(
|
||||
$h,
|
||||
$A,
|
||||
self::substr($sig, 32)
|
||||
);
|
||||
|
||||
/** @var string $rcheck */
|
||||
$rcheck = self::ge_tobytes($R);
|
||||
|
||||
// Reset ParagonIE_Sodium_Compat::$fastMult to what it was before.
|
||||
ParagonIE_Sodium_Compat::$fastMult = $orig;
|
||||
|
||||
return self::verify_32($rcheck, self::substr($sig, 0, 32));
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param string $S
|
||||
* @return bool
|
||||
* @throws SodiumException
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function check_S_lt_L($S)
|
||||
{
|
||||
if (self::strlen($S) < 32) {
|
||||
throw new SodiumException('Signature must be 32 bytes');
|
||||
}
|
||||
$L = array(
|
||||
0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
|
||||
0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10
|
||||
);
|
||||
$c = 0;
|
||||
$n = 1;
|
||||
$i = 32;
|
||||
|
||||
/** @var array<int, int> $L */
|
||||
do {
|
||||
--$i;
|
||||
$x = self::chrToInt($S[$i]);
|
||||
$c |= (
|
||||
(($x - $L[$i]) >> 8) & $n
|
||||
);
|
||||
$n &= (
|
||||
(($x ^ $L[$i]) - 1) >> 8
|
||||
);
|
||||
} while ($i !== 0);
|
||||
|
||||
return $c === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $R
|
||||
* @return bool
|
||||
* @throws SodiumException
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function small_order($R)
|
||||
{
|
||||
/** @var array<int, array<int, int>> $blocklist */
|
||||
$blocklist = array(
|
||||
/* 0 (order 4) */
|
||||
array(
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
),
|
||||
/* 1 (order 1) */
|
||||
array(
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
),
|
||||
/* 2707385501144840649318225287225658788936804267575313519463743609750303402022 (order 8) */
|
||||
array(
|
||||
0x26, 0xe8, 0x95, 0x8f, 0xc2, 0xb2, 0x27, 0xb0,
|
||||
0x45, 0xc3, 0xf4, 0x89, 0xf2, 0xef, 0x98, 0xf0,
|
||||
0xd5, 0xdf, 0xac, 0x05, 0xd3, 0xc6, 0x33, 0x39,
|
||||
0xb1, 0x38, 0x02, 0x88, 0x6d, 0x53, 0xfc, 0x05
|
||||
),
|
||||
/* 55188659117513257062467267217118295137698188065244968500265048394206261417927 (order 8) */
|
||||
array(
|
||||
0xc7, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f,
|
||||
0xba, 0x3c, 0x0b, 0x76, 0x0d, 0x10, 0x67, 0x0f,
|
||||
0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39, 0xcc, 0xc6,
|
||||
0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0x7a
|
||||
),
|
||||
/* p-1 (order 2) */
|
||||
array(
|
||||
0x13, 0xe8, 0x95, 0x8f, 0xc2, 0xb2, 0x27, 0xb0,
|
||||
0x45, 0xc3, 0xf4, 0x89, 0xf2, 0xef, 0x98, 0xf0,
|
||||
0xd5, 0xdf, 0xac, 0x05, 0xd3, 0xc6, 0x33, 0x39,
|
||||
0xb1, 0x38, 0x02, 0x88, 0x6d, 0x53, 0xfc, 0x85
|
||||
),
|
||||
/* p (order 4) */
|
||||
array(
|
||||
0xb4, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f,
|
||||
0xba, 0x3c, 0x0b, 0x76, 0x0d, 0x10, 0x67, 0x0f,
|
||||
0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39, 0xcc, 0xc6,
|
||||
0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0xfa
|
||||
),
|
||||
/* p+1 (order 1) */
|
||||
array(
|
||||
0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f
|
||||
),
|
||||
/* p+2707385501144840649318225287225658788936804267575313519463743609750303402022 (order 8) */
|
||||
array(
|
||||
0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f
|
||||
),
|
||||
/* p+55188659117513257062467267217118295137698188065244968500265048394206261417927 (order 8) */
|
||||
array(
|
||||
0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f
|
||||
),
|
||||
/* 2p-1 (order 2) */
|
||||
array(
|
||||
0xd9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
||||
),
|
||||
/* 2p (order 4) */
|
||||
array(
|
||||
0xda, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
||||
),
|
||||
/* 2p+1 (order 1) */
|
||||
array(
|
||||
0xdb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
||||
)
|
||||
);
|
||||
/** @var int $countBlocklist */
|
||||
$countBlocklist = count($blocklist);
|
||||
|
||||
for ($i = 0; $i < $countBlocklist; ++$i) {
|
||||
$c = 0;
|
||||
for ($j = 0; $j < 32; ++$j) {
|
||||
$c |= self::chrToInt($R[$j]) ^ (int) $blocklist[$i][$j];
|
||||
}
|
||||
if ($c === 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $s
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
*/
|
||||
public static function scalar_complement($s)
|
||||
{
|
||||
$t_ = self::L . str_repeat("\x00", 32);
|
||||
sodium_increment($t_);
|
||||
$s_ = $s . str_repeat("\x00", 32);
|
||||
ParagonIE_Sodium_Compat::sub($t_, $s_);
|
||||
return self::sc_reduce($t_);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
*/
|
||||
public static function scalar_random()
|
||||
{
|
||||
do {
|
||||
$r = ParagonIE_Sodium_Compat::randombytes_buf(self::SCALAR_BYTES);
|
||||
$r[self::SCALAR_BYTES - 1] = self::intToChr(
|
||||
self::chrToInt($r[self::SCALAR_BYTES - 1]) & 0x1f
|
||||
);
|
||||
} while (
|
||||
!self::check_S_lt_L($r) || ParagonIE_Sodium_Compat::is_zero($r)
|
||||
);
|
||||
return $r;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $s
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
*/
|
||||
public static function scalar_negate($s)
|
||||
{
|
||||
$t_ = self::L . str_repeat("\x00", 32) ;
|
||||
$s_ = $s . str_repeat("\x00", 32) ;
|
||||
ParagonIE_Sodium_Compat::sub($t_, $s_);
|
||||
return self::sc_reduce($t_);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $a
|
||||
* @param string $b
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
*/
|
||||
public static function scalar_add($a, $b)
|
||||
{
|
||||
$a_ = $a . str_repeat("\x00", 32);
|
||||
$b_ = $b . str_repeat("\x00", 32);
|
||||
ParagonIE_Sodium_Compat::add($a_, $b_);
|
||||
return self::sc_reduce($a_);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $x
|
||||
* @param string $y
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
*/
|
||||
public static function scalar_sub($x, $y)
|
||||
{
|
||||
$yn = self::scalar_negate($y);
|
||||
return self::scalar_add($x, $yn);
|
||||
}
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
|
||||
if (class_exists('ParagonIE_Sodium_Core_HChaCha20', false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class ParagonIE_Sodium_Core_HChaCha20
|
||||
*/
|
||||
class ParagonIE_Sodium_Core_HChaCha20 extends ParagonIE_Sodium_Core_ChaCha20
|
||||
{
|
||||
/**
|
||||
* @param string $in
|
||||
* @param string $key
|
||||
* @param string|null $c
|
||||
* @return string
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function hChaCha20($in = '', $key = '', $c = null)
|
||||
{
|
||||
$ctx = array();
|
||||
|
||||
if ($c === null) {
|
||||
$ctx[0] = 0x61707865;
|
||||
$ctx[1] = 0x3320646e;
|
||||
$ctx[2] = 0x79622d32;
|
||||
$ctx[3] = 0x6b206574;
|
||||
} else {
|
||||
$ctx[0] = self::load_4(self::substr($c, 0, 4));
|
||||
$ctx[1] = self::load_4(self::substr($c, 4, 4));
|
||||
$ctx[2] = self::load_4(self::substr($c, 8, 4));
|
||||
$ctx[3] = self::load_4(self::substr($c, 12, 4));
|
||||
}
|
||||
$ctx[4] = self::load_4(self::substr($key, 0, 4));
|
||||
$ctx[5] = self::load_4(self::substr($key, 4, 4));
|
||||
$ctx[6] = self::load_4(self::substr($key, 8, 4));
|
||||
$ctx[7] = self::load_4(self::substr($key, 12, 4));
|
||||
$ctx[8] = self::load_4(self::substr($key, 16, 4));
|
||||
$ctx[9] = self::load_4(self::substr($key, 20, 4));
|
||||
$ctx[10] = self::load_4(self::substr($key, 24, 4));
|
||||
$ctx[11] = self::load_4(self::substr($key, 28, 4));
|
||||
$ctx[12] = self::load_4(self::substr($in, 0, 4));
|
||||
$ctx[13] = self::load_4(self::substr($in, 4, 4));
|
||||
$ctx[14] = self::load_4(self::substr($in, 8, 4));
|
||||
$ctx[15] = self::load_4(self::substr($in, 12, 4));
|
||||
return self::hChaCha20Bytes($ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $ctx
|
||||
* @return string
|
||||
* @throws TypeError
|
||||
*/
|
||||
protected static function hChaCha20Bytes(array $ctx)
|
||||
{
|
||||
$x0 = (int) $ctx[0];
|
||||
$x1 = (int) $ctx[1];
|
||||
$x2 = (int) $ctx[2];
|
||||
$x3 = (int) $ctx[3];
|
||||
$x4 = (int) $ctx[4];
|
||||
$x5 = (int) $ctx[5];
|
||||
$x6 = (int) $ctx[6];
|
||||
$x7 = (int) $ctx[7];
|
||||
$x8 = (int) $ctx[8];
|
||||
$x9 = (int) $ctx[9];
|
||||
$x10 = (int) $ctx[10];
|
||||
$x11 = (int) $ctx[11];
|
||||
$x12 = (int) $ctx[12];
|
||||
$x13 = (int) $ctx[13];
|
||||
$x14 = (int) $ctx[14];
|
||||
$x15 = (int) $ctx[15];
|
||||
|
||||
for ($i = 0; $i < 10; ++$i) {
|
||||
# QUARTERROUND( x0, x4, x8, x12)
|
||||
list($x0, $x4, $x8, $x12) = self::quarterRound($x0, $x4, $x8, $x12);
|
||||
|
||||
# QUARTERROUND( x1, x5, x9, x13)
|
||||
list($x1, $x5, $x9, $x13) = self::quarterRound($x1, $x5, $x9, $x13);
|
||||
|
||||
# QUARTERROUND( x2, x6, x10, x14)
|
||||
list($x2, $x6, $x10, $x14) = self::quarterRound($x2, $x6, $x10, $x14);
|
||||
|
||||
# QUARTERROUND( x3, x7, x11, x15)
|
||||
list($x3, $x7, $x11, $x15) = self::quarterRound($x3, $x7, $x11, $x15);
|
||||
|
||||
# QUARTERROUND( x0, x5, x10, x15)
|
||||
list($x0, $x5, $x10, $x15) = self::quarterRound($x0, $x5, $x10, $x15);
|
||||
|
||||
# QUARTERROUND( x1, x6, x11, x12)
|
||||
list($x1, $x6, $x11, $x12) = self::quarterRound($x1, $x6, $x11, $x12);
|
||||
|
||||
# QUARTERROUND( x2, x7, x8, x13)
|
||||
list($x2, $x7, $x8, $x13) = self::quarterRound($x2, $x7, $x8, $x13);
|
||||
|
||||
# QUARTERROUND( x3, x4, x9, x14)
|
||||
list($x3, $x4, $x9, $x14) = self::quarterRound($x3, $x4, $x9, $x14);
|
||||
}
|
||||
|
||||
return self::store32_le((int) ($x0 & 0xffffffff)) .
|
||||
self::store32_le((int) ($x1 & 0xffffffff)) .
|
||||
self::store32_le((int) ($x2 & 0xffffffff)) .
|
||||
self::store32_le((int) ($x3 & 0xffffffff)) .
|
||||
self::store32_le((int) ($x12 & 0xffffffff)) .
|
||||
self::store32_le((int) ($x13 & 0xffffffff)) .
|
||||
self::store32_le((int) ($x14 & 0xffffffff)) .
|
||||
self::store32_le((int) ($x15 & 0xffffffff));
|
||||
}
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
|
||||
if (class_exists('ParagonIE_Sodium_Core_HSalsa20', false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class ParagonIE_Sodium_Core_HSalsa20
|
||||
*/
|
||||
abstract class ParagonIE_Sodium_Core_HSalsa20 extends ParagonIE_Sodium_Core_Salsa20
|
||||
{
|
||||
/**
|
||||
* Calculate an hsalsa20 hash of a single block
|
||||
*
|
||||
* HSalsa20 doesn't have a counter and will never be used for more than
|
||||
* one block (used to derive a subkey for xsalsa20).
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param string $in
|
||||
* @param string $k
|
||||
* @param string|null $c
|
||||
* @return string
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function hsalsa20($in, $k, $c = null)
|
||||
{
|
||||
if ($c === null) {
|
||||
$x0 = 0x61707865;
|
||||
$x5 = 0x3320646e;
|
||||
$x10 = 0x79622d32;
|
||||
$x15 = 0x6b206574;
|
||||
} else {
|
||||
$x0 = self::load_4(self::substr($c, 0, 4));
|
||||
$x5 = self::load_4(self::substr($c, 4, 4));
|
||||
$x10 = self::load_4(self::substr($c, 8, 4));
|
||||
$x15 = self::load_4(self::substr($c, 12, 4));
|
||||
}
|
||||
$x1 = self::load_4(self::substr($k, 0, 4));
|
||||
$x2 = self::load_4(self::substr($k, 4, 4));
|
||||
$x3 = self::load_4(self::substr($k, 8, 4));
|
||||
$x4 = self::load_4(self::substr($k, 12, 4));
|
||||
$x11 = self::load_4(self::substr($k, 16, 4));
|
||||
$x12 = self::load_4(self::substr($k, 20, 4));
|
||||
$x13 = self::load_4(self::substr($k, 24, 4));
|
||||
$x14 = self::load_4(self::substr($k, 28, 4));
|
||||
$x6 = self::load_4(self::substr($in, 0, 4));
|
||||
$x7 = self::load_4(self::substr($in, 4, 4));
|
||||
$x8 = self::load_4(self::substr($in, 8, 4));
|
||||
$x9 = self::load_4(self::substr($in, 12, 4));
|
||||
|
||||
for ($i = self::ROUNDS; $i > 0; $i -= 2) {
|
||||
$x4 ^= self::rotate($x0 + $x12, 7);
|
||||
$x8 ^= self::rotate($x4 + $x0, 9);
|
||||
$x12 ^= self::rotate($x8 + $x4, 13);
|
||||
$x0 ^= self::rotate($x12 + $x8, 18);
|
||||
$x9 ^= self::rotate($x5 + $x1, 7);
|
||||
$x13 ^= self::rotate($x9 + $x5, 9);
|
||||
$x1 ^= self::rotate($x13 + $x9, 13);
|
||||
$x5 ^= self::rotate($x1 + $x13, 18);
|
||||
$x14 ^= self::rotate($x10 + $x6, 7);
|
||||
$x2 ^= self::rotate($x14 + $x10, 9);
|
||||
$x6 ^= self::rotate($x2 + $x14, 13);
|
||||
$x10 ^= self::rotate($x6 + $x2, 18);
|
||||
$x3 ^= self::rotate($x15 + $x11, 7);
|
||||
$x7 ^= self::rotate($x3 + $x15, 9);
|
||||
$x11 ^= self::rotate($x7 + $x3, 13);
|
||||
$x15 ^= self::rotate($x11 + $x7, 18);
|
||||
$x1 ^= self::rotate($x0 + $x3, 7);
|
||||
$x2 ^= self::rotate($x1 + $x0, 9);
|
||||
$x3 ^= self::rotate($x2 + $x1, 13);
|
||||
$x0 ^= self::rotate($x3 + $x2, 18);
|
||||
$x6 ^= self::rotate($x5 + $x4, 7);
|
||||
$x7 ^= self::rotate($x6 + $x5, 9);
|
||||
$x4 ^= self::rotate($x7 + $x6, 13);
|
||||
$x5 ^= self::rotate($x4 + $x7, 18);
|
||||
$x11 ^= self::rotate($x10 + $x9, 7);
|
||||
$x8 ^= self::rotate($x11 + $x10, 9);
|
||||
$x9 ^= self::rotate($x8 + $x11, 13);
|
||||
$x10 ^= self::rotate($x9 + $x8, 18);
|
||||
$x12 ^= self::rotate($x15 + $x14, 7);
|
||||
$x13 ^= self::rotate($x12 + $x15, 9);
|
||||
$x14 ^= self::rotate($x13 + $x12, 13);
|
||||
$x15 ^= self::rotate($x14 + $x13, 18);
|
||||
}
|
||||
|
||||
return self::store32_le($x0) .
|
||||
self::store32_le($x5) .
|
||||
self::store32_le($x10) .
|
||||
self::store32_le($x15) .
|
||||
self::store32_le($x6) .
|
||||
self::store32_le($x7) .
|
||||
self::store32_le($x8) .
|
||||
self::store32_le($x9);
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
|
||||
if (class_exists('ParagonIE_Sodium_Core_Poly1305', false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class ParagonIE_Sodium_Core_Poly1305
|
||||
*/
|
||||
abstract class ParagonIE_Sodium_Core_Poly1305 extends ParagonIE_Sodium_Core_Util
|
||||
{
|
||||
const BLOCK_SIZE = 16;
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param string $m
|
||||
* @param string $key
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function onetimeauth($m, $key)
|
||||
{
|
||||
if (self::strlen($key) < 32) {
|
||||
throw new InvalidArgumentException(
|
||||
'Key must be 32 bytes long.'
|
||||
);
|
||||
}
|
||||
$state = new ParagonIE_Sodium_Core_Poly1305_State(
|
||||
self::substr($key, 0, 32)
|
||||
);
|
||||
return $state
|
||||
->update($m)
|
||||
->finish();
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param string $mac
|
||||
* @param string $m
|
||||
* @param string $key
|
||||
* @return bool
|
||||
* @throws SodiumException
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function onetimeauth_verify($mac, $m, $key)
|
||||
{
|
||||
if (self::strlen($key) < 32) {
|
||||
throw new InvalidArgumentException(
|
||||
'Key must be 32 bytes long.'
|
||||
);
|
||||
}
|
||||
$state = new ParagonIE_Sodium_Core_Poly1305_State(
|
||||
self::substr($key, 0, 32)
|
||||
);
|
||||
$calc = $state
|
||||
->update($m)
|
||||
->finish();
|
||||
return self::verify_16($calc, $mac);
|
||||
}
|
||||
}
|
||||
@@ -1,446 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
|
||||
if (class_exists('ParagonIE_Sodium_Core_Poly1305_State', false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class ParagonIE_Sodium_Core_Poly1305_State
|
||||
*/
|
||||
class ParagonIE_Sodium_Core_Poly1305_State extends ParagonIE_Sodium_Core_Util
|
||||
{
|
||||
/**
|
||||
* @var array<int, int>
|
||||
*/
|
||||
protected $buffer = array();
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $final = false;
|
||||
|
||||
/**
|
||||
* @var array<int, int>
|
||||
*/
|
||||
public $h;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $leftover = 0;
|
||||
|
||||
/**
|
||||
* @var int[]
|
||||
*/
|
||||
public $r;
|
||||
|
||||
/**
|
||||
* @var int[]
|
||||
*/
|
||||
public $pad;
|
||||
|
||||
/**
|
||||
* ParagonIE_Sodium_Core_Poly1305_State constructor.
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param string $key
|
||||
* @throws InvalidArgumentException
|
||||
* @throws TypeError
|
||||
*/
|
||||
public function __construct($key = '')
|
||||
{
|
||||
if (self::strlen($key) < 32) {
|
||||
throw new InvalidArgumentException(
|
||||
'Poly1305 requires a 32-byte key'
|
||||
);
|
||||
}
|
||||
/* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
|
||||
$this->r = array(
|
||||
(int) ((self::load_4(self::substr($key, 0, 4))) & 0x3ffffff),
|
||||
(int) ((self::load_4(self::substr($key, 3, 4)) >> 2) & 0x3ffff03),
|
||||
(int) ((self::load_4(self::substr($key, 6, 4)) >> 4) & 0x3ffc0ff),
|
||||
(int) ((self::load_4(self::substr($key, 9, 4)) >> 6) & 0x3f03fff),
|
||||
(int) ((self::load_4(self::substr($key, 12, 4)) >> 8) & 0x00fffff)
|
||||
);
|
||||
|
||||
/* h = 0 */
|
||||
$this->h = array(0, 0, 0, 0, 0);
|
||||
|
||||
/* save pad for later */
|
||||
$this->pad = array(
|
||||
self::load_4(self::substr($key, 16, 4)),
|
||||
self::load_4(self::substr($key, 20, 4)),
|
||||
self::load_4(self::substr($key, 24, 4)),
|
||||
self::load_4(self::substr($key, 28, 4)),
|
||||
);
|
||||
|
||||
$this->leftover = 0;
|
||||
$this->final = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Zero internal buffer upon destruction
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
$this->r[0] ^= $this->r[0];
|
||||
$this->r[1] ^= $this->r[1];
|
||||
$this->r[2] ^= $this->r[2];
|
||||
$this->r[3] ^= $this->r[3];
|
||||
$this->r[4] ^= $this->r[4];
|
||||
$this->h[0] ^= $this->h[0];
|
||||
$this->h[1] ^= $this->h[1];
|
||||
$this->h[2] ^= $this->h[2];
|
||||
$this->h[3] ^= $this->h[3];
|
||||
$this->h[4] ^= $this->h[4];
|
||||
$this->pad[0] ^= $this->pad[0];
|
||||
$this->pad[1] ^= $this->pad[1];
|
||||
$this->pad[2] ^= $this->pad[2];
|
||||
$this->pad[3] ^= $this->pad[3];
|
||||
$this->leftover = 0;
|
||||
$this->final = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param string $message
|
||||
* @return self
|
||||
* @throws SodiumException
|
||||
* @throws TypeError
|
||||
*/
|
||||
public function update($message = '')
|
||||
{
|
||||
$bytes = self::strlen($message);
|
||||
if ($bytes < 1) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
/* handle leftover */
|
||||
if ($this->leftover) {
|
||||
$want = ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE - $this->leftover;
|
||||
if ($want > $bytes) {
|
||||
$want = $bytes;
|
||||
}
|
||||
for ($i = 0; $i < $want; ++$i) {
|
||||
$mi = self::chrToInt($message[$i]);
|
||||
$this->buffer[$this->leftover + $i] = $mi;
|
||||
}
|
||||
// We snip off the leftmost bytes.
|
||||
$message = self::substr($message, $want);
|
||||
$bytes = self::strlen($message);
|
||||
$this->leftover += $want;
|
||||
if ($this->leftover < ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE) {
|
||||
// We still don't have enough to run $this->blocks()
|
||||
return $this;
|
||||
}
|
||||
|
||||
$this->blocks(
|
||||
self::intArrayToString($this->buffer),
|
||||
ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE
|
||||
);
|
||||
$this->leftover = 0;
|
||||
}
|
||||
|
||||
/* process full blocks */
|
||||
if ($bytes >= ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE) {
|
||||
/** @var int $want */
|
||||
$want = $bytes & ~(ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE - 1);
|
||||
if ($want >= ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE) {
|
||||
$block = self::substr($message, 0, $want);
|
||||
if (self::strlen($block) >= ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE) {
|
||||
$this->blocks($block, $want);
|
||||
$message = self::substr($message, $want);
|
||||
$bytes = self::strlen($message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* store leftover */
|
||||
if ($bytes) {
|
||||
for ($i = 0; $i < $bytes; ++$i) {
|
||||
$mi = self::chrToInt($message[$i]);
|
||||
$this->buffer[$this->leftover + $i] = $mi;
|
||||
}
|
||||
$this->leftover = (int) $this->leftover + $bytes;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param string $message
|
||||
* @param int $bytes
|
||||
* @return self
|
||||
* @throws TypeError
|
||||
*/
|
||||
public function blocks($message, $bytes)
|
||||
{
|
||||
if (self::strlen($message) < 16) {
|
||||
$message = str_pad($message, 16, "\x00", STR_PAD_RIGHT);
|
||||
}
|
||||
/** @var int $hibit */
|
||||
$hibit = $this->final ? 0 : 1 << 24; /* 1 << 128 */
|
||||
$r0 = (int) $this->r[0];
|
||||
$r1 = (int) $this->r[1];
|
||||
$r2 = (int) $this->r[2];
|
||||
$r3 = (int) $this->r[3];
|
||||
$r4 = (int) $this->r[4];
|
||||
|
||||
$s1 = self::mul($r1, 5, 3);
|
||||
$s2 = self::mul($r2, 5, 3);
|
||||
$s3 = self::mul($r3, 5, 3);
|
||||
$s4 = self::mul($r4, 5, 3);
|
||||
|
||||
$h0 = $this->h[0];
|
||||
$h1 = $this->h[1];
|
||||
$h2 = $this->h[2];
|
||||
$h3 = $this->h[3];
|
||||
$h4 = $this->h[4];
|
||||
|
||||
while ($bytes >= ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE) {
|
||||
/* h += m[i] */
|
||||
$h0 += self::load_4(self::substr($message, 0, 4)) & 0x3ffffff;
|
||||
$h1 += (self::load_4(self::substr($message, 3, 4)) >> 2) & 0x3ffffff;
|
||||
$h2 += (self::load_4(self::substr($message, 6, 4)) >> 4) & 0x3ffffff;
|
||||
$h3 += (self::load_4(self::substr($message, 9, 4)) >> 6) & 0x3ffffff;
|
||||
$h4 += (self::load_4(self::substr($message, 12, 4)) >> 8) | $hibit;
|
||||
|
||||
/* h *= r */
|
||||
$d0 = (
|
||||
self::mul($h0, $r0, 27) +
|
||||
self::mul($s4, $h1, 27) +
|
||||
self::mul($s3, $h2, 27) +
|
||||
self::mul($s2, $h3, 27) +
|
||||
self::mul($s1, $h4, 27)
|
||||
);
|
||||
|
||||
$d1 = (
|
||||
self::mul($h0, $r1, 27) +
|
||||
self::mul($h1, $r0, 27) +
|
||||
self::mul($s4, $h2, 27) +
|
||||
self::mul($s3, $h3, 27) +
|
||||
self::mul($s2, $h4, 27)
|
||||
);
|
||||
|
||||
$d2 = (
|
||||
self::mul($h0, $r2, 27) +
|
||||
self::mul($h1, $r1, 27) +
|
||||
self::mul($h2, $r0, 27) +
|
||||
self::mul($s4, $h3, 27) +
|
||||
self::mul($s3, $h4, 27)
|
||||
);
|
||||
|
||||
$d3 = (
|
||||
self::mul($h0, $r3, 27) +
|
||||
self::mul($h1, $r2, 27) +
|
||||
self::mul($h2, $r1, 27) +
|
||||
self::mul($h3, $r0, 27) +
|
||||
self::mul($s4, $h4, 27)
|
||||
);
|
||||
|
||||
$d4 = (
|
||||
self::mul($h0, $r4, 27) +
|
||||
self::mul($h1, $r3, 27) +
|
||||
self::mul($h2, $r2, 27) +
|
||||
self::mul($h3, $r1, 27) +
|
||||
self::mul($h4, $r0, 27)
|
||||
);
|
||||
|
||||
/* (partial) h %= p */
|
||||
/** @var int $c */
|
||||
$c = $d0 >> 26;
|
||||
/** @var int $h0 */
|
||||
$h0 = $d0 & 0x3ffffff;
|
||||
$d1 += $c;
|
||||
|
||||
/** @var int $c */
|
||||
$c = $d1 >> 26;
|
||||
/** @var int $h1 */
|
||||
$h1 = $d1 & 0x3ffffff;
|
||||
$d2 += $c;
|
||||
|
||||
/** @var int $c */
|
||||
$c = $d2 >> 26;
|
||||
/** @var int $h2 */
|
||||
$h2 = $d2 & 0x3ffffff;
|
||||
$d3 += $c;
|
||||
|
||||
/** @var int $c */
|
||||
$c = $d3 >> 26;
|
||||
/** @var int $h3 */
|
||||
$h3 = $d3 & 0x3ffffff;
|
||||
$d4 += $c;
|
||||
|
||||
/** @var int $c */
|
||||
$c = $d4 >> 26;
|
||||
/** @var int $h4 */
|
||||
$h4 = $d4 & 0x3ffffff;
|
||||
$h0 += (int) self::mul($c, 5, 3);
|
||||
|
||||
/** @var int $c */
|
||||
$c = $h0 >> 26;
|
||||
/** @var int $h0 */
|
||||
$h0 &= 0x3ffffff;
|
||||
$h1 += $c;
|
||||
|
||||
// Chop off the left 32 bytes.
|
||||
$message = self::substr(
|
||||
$message,
|
||||
ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE
|
||||
);
|
||||
$bytes -= ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE;
|
||||
}
|
||||
|
||||
$this->h = array(
|
||||
(int) ($h0 & 0xffffffff),
|
||||
(int) ($h1 & 0xffffffff),
|
||||
(int) ($h2 & 0xffffffff),
|
||||
(int) ($h3 & 0xffffffff),
|
||||
(int) ($h4 & 0xffffffff)
|
||||
);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @return string
|
||||
* @throws TypeError
|
||||
*/
|
||||
public function finish()
|
||||
{
|
||||
/* process the remaining block */
|
||||
if ($this->leftover) {
|
||||
$i = $this->leftover;
|
||||
$this->buffer[$i++] = 1;
|
||||
for (; $i < ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE; ++$i) {
|
||||
$this->buffer[$i] = 0;
|
||||
}
|
||||
$this->final = true;
|
||||
$this->blocks(
|
||||
self::substr(
|
||||
self::intArrayToString($this->buffer),
|
||||
0,
|
||||
ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE
|
||||
),
|
||||
ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE
|
||||
);
|
||||
}
|
||||
|
||||
$h0 = (int) $this->h[0];
|
||||
$h1 = (int) $this->h[1];
|
||||
$h2 = (int) $this->h[2];
|
||||
$h3 = (int) $this->h[3];
|
||||
$h4 = (int) $this->h[4];
|
||||
|
||||
/** @var int $c */
|
||||
$c = $h1 >> 26;
|
||||
/** @var int $h1 */
|
||||
$h1 &= 0x3ffffff;
|
||||
/** @var int $h2 */
|
||||
$h2 += $c;
|
||||
/** @var int $c */
|
||||
$c = $h2 >> 26;
|
||||
/** @var int $h2 */
|
||||
$h2 &= 0x3ffffff;
|
||||
$h3 += $c;
|
||||
/** @var int $c */
|
||||
$c = $h3 >> 26;
|
||||
$h3 &= 0x3ffffff;
|
||||
$h4 += $c;
|
||||
/** @var int $c */
|
||||
$c = $h4 >> 26;
|
||||
$h4 &= 0x3ffffff;
|
||||
/** @var int $h0 */
|
||||
$h0 += self::mul($c, 5, 3);
|
||||
/** @var int $c */
|
||||
$c = $h0 >> 26;
|
||||
/** @var int $h0 */
|
||||
$h0 &= 0x3ffffff;
|
||||
/** @var int $h1 */
|
||||
$h1 += $c;
|
||||
|
||||
/* compute h + -p */
|
||||
/** @var int $g0 */
|
||||
$g0 = $h0 + 5;
|
||||
/** @var int $c */
|
||||
$c = $g0 >> 26;
|
||||
/** @var int $g0 */
|
||||
$g0 &= 0x3ffffff;
|
||||
|
||||
/** @var int $g1 */
|
||||
$g1 = $h1 + $c;
|
||||
/** @var int $c */
|
||||
$c = $g1 >> 26;
|
||||
$g1 &= 0x3ffffff;
|
||||
|
||||
/** @var int $g2 */
|
||||
$g2 = $h2 + $c;
|
||||
/** @var int $c */
|
||||
$c = $g2 >> 26;
|
||||
/** @var int $g2 */
|
||||
$g2 &= 0x3ffffff;
|
||||
|
||||
/** @var int $g3 */
|
||||
$g3 = $h3 + $c;
|
||||
/** @var int $c */
|
||||
$c = $g3 >> 26;
|
||||
/** @var int $g3 */
|
||||
$g3 &= 0x3ffffff;
|
||||
|
||||
/** @var int $g4 */
|
||||
$g4 = ($h4 + $c - (1 << 26)) & 0xffffffff;
|
||||
|
||||
/* select h if h < p, or h + -p if h >= p */
|
||||
/** @var int $mask */
|
||||
$mask = ($g4 >> 31) - 1;
|
||||
|
||||
$g0 &= $mask;
|
||||
$g1 &= $mask;
|
||||
$g2 &= $mask;
|
||||
$g3 &= $mask;
|
||||
$g4 &= $mask;
|
||||
|
||||
/** @var int $mask */
|
||||
$mask = ~$mask & 0xffffffff;
|
||||
/** @var int $h0 */
|
||||
$h0 = ($h0 & $mask) | $g0;
|
||||
/** @var int $h1 */
|
||||
$h1 = ($h1 & $mask) | $g1;
|
||||
/** @var int $h2 */
|
||||
$h2 = ($h2 & $mask) | $g2;
|
||||
/** @var int $h3 */
|
||||
$h3 = ($h3 & $mask) | $g3;
|
||||
/** @var int $h4 */
|
||||
$h4 = ($h4 & $mask) | $g4;
|
||||
|
||||
/* h = h % (2^128) */
|
||||
/** @var int $h0 */
|
||||
$h0 = (($h0) | ($h1 << 26)) & 0xffffffff;
|
||||
/** @var int $h1 */
|
||||
$h1 = (($h1 >> 6) | ($h2 << 20)) & 0xffffffff;
|
||||
/** @var int $h2 */
|
||||
$h2 = (($h2 >> 12) | ($h3 << 14)) & 0xffffffff;
|
||||
/** @var int $h3 */
|
||||
$h3 = (($h3 >> 18) | ($h4 << 8)) & 0xffffffff;
|
||||
|
||||
/* mac = (h + pad) % (2^128) */
|
||||
$f = (int) ($h0 + $this->pad[0]);
|
||||
$h0 = (int) $f;
|
||||
$f = (int) ($h1 + $this->pad[1] + ($f >> 32));
|
||||
$h1 = (int) $f;
|
||||
$f = (int) ($h2 + $this->pad[2] + ($f >> 32));
|
||||
$h2 = (int) $f;
|
||||
$f = (int) ($h3 + $this->pad[3] + ($f >> 32));
|
||||
$h3 = (int) $f;
|
||||
|
||||
return self::store32_le($h0 & 0xffffffff) .
|
||||
self::store32_le($h1 & 0xffffffff) .
|
||||
self::store32_le($h2 & 0xffffffff) .
|
||||
self::store32_le($h3 & 0xffffffff);
|
||||
}
|
||||
}
|
||||
@@ -1,708 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
|
||||
/**
|
||||
* Class ParagonIE_Sodium_Core_Ristretto255
|
||||
*/
|
||||
class ParagonIE_Sodium_Core_Ristretto255 extends ParagonIE_Sodium_Core_Ed25519
|
||||
{
|
||||
const crypto_core_ristretto255_HASHBYTES = 64;
|
||||
const HASH_SC_L = 48;
|
||||
const CORE_H2C_SHA256 = 1;
|
||||
const CORE_H2C_SHA512 = 2;
|
||||
|
||||
/**
|
||||
* @param ParagonIE_Sodium_Core_Curve25519_Fe $f
|
||||
* @param int $b
|
||||
* @return ParagonIE_Sodium_Core_Curve25519_Fe
|
||||
*/
|
||||
public static function fe_cneg(ParagonIE_Sodium_Core_Curve25519_Fe $f, $b)
|
||||
{
|
||||
$negf = self::fe_neg($f);
|
||||
return self::fe_cmov($f, $negf, $b);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ParagonIE_Sodium_Core_Curve25519_Fe $f
|
||||
* @return ParagonIE_Sodium_Core_Curve25519_Fe
|
||||
* @throws SodiumException
|
||||
*/
|
||||
public static function fe_abs(ParagonIE_Sodium_Core_Curve25519_Fe $f)
|
||||
{
|
||||
return self::fe_cneg($f, self::fe_isnegative($f));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns 0 if this field element results in all NUL bytes.
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param ParagonIE_Sodium_Core_Curve25519_Fe $f
|
||||
* @return int
|
||||
* @throws SodiumException
|
||||
*/
|
||||
public static function fe_iszero(ParagonIE_Sodium_Core_Curve25519_Fe $f)
|
||||
{
|
||||
static $zero;
|
||||
if ($zero === null) {
|
||||
$zero = str_repeat("\x00", 32);
|
||||
}
|
||||
/** @var string $zero */
|
||||
$str = self::fe_tobytes($f);
|
||||
|
||||
$d = 0;
|
||||
for ($i = 0; $i < 32; ++$i) {
|
||||
$d |= self::chrToInt($str[$i]);
|
||||
}
|
||||
return (($d - 1) >> 31) & 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param ParagonIE_Sodium_Core_Curve25519_Fe $u
|
||||
* @param ParagonIE_Sodium_Core_Curve25519_Fe $v
|
||||
* @return array{x: ParagonIE_Sodium_Core_Curve25519_Fe, nonsquare: int}
|
||||
*
|
||||
* @throws SodiumException
|
||||
*/
|
||||
public static function ristretto255_sqrt_ratio_m1(
|
||||
ParagonIE_Sodium_Core_Curve25519_Fe $u,
|
||||
ParagonIE_Sodium_Core_Curve25519_Fe $v
|
||||
) {
|
||||
$sqrtm1 = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqrtm1);
|
||||
|
||||
$v3 = self::fe_mul(
|
||||
self::fe_sq($v),
|
||||
$v
|
||||
); /* v3 = v^3 */
|
||||
$x = self::fe_mul(
|
||||
self::fe_mul(
|
||||
self::fe_sq($v3),
|
||||
$u
|
||||
),
|
||||
$v
|
||||
); /* x = uv^7 */
|
||||
|
||||
$x = self::fe_mul(
|
||||
self::fe_mul(
|
||||
self::fe_pow22523($x), /* x = (uv^7)^((q-5)/8) */
|
||||
$v3
|
||||
),
|
||||
$u
|
||||
); /* x = uv^3(uv^7)^((q-5)/8) */
|
||||
|
||||
$vxx = self::fe_mul(
|
||||
self::fe_sq($x),
|
||||
$v
|
||||
); /* vx^2 */
|
||||
|
||||
$m_root_check = self::fe_sub($vxx, $u); /* vx^2-u */
|
||||
$p_root_check = self::fe_add($vxx, $u); /* vx^2+u */
|
||||
$f_root_check = self::fe_mul($u, $sqrtm1); /* u*sqrt(-1) */
|
||||
$f_root_check = self::fe_add($vxx, $f_root_check); /* vx^2+u*sqrt(-1) */
|
||||
|
||||
$has_m_root = self::fe_iszero($m_root_check);
|
||||
$has_p_root = self::fe_iszero($p_root_check);
|
||||
$has_f_root = self::fe_iszero($f_root_check);
|
||||
|
||||
$x_sqrtm1 = self::fe_mul($x, $sqrtm1); /* x*sqrt(-1) */
|
||||
|
||||
$x = self::fe_abs(
|
||||
self::fe_cmov($x, $x_sqrtm1, $has_p_root | $has_f_root)
|
||||
);
|
||||
return array(
|
||||
'x' => $x,
|
||||
'nonsquare' => $has_m_root | $has_p_root
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $s
|
||||
* @return int
|
||||
* @throws SodiumException
|
||||
*/
|
||||
public static function ristretto255_point_is_canonical($s)
|
||||
{
|
||||
$c = (self::chrToInt($s[31]) & 0x7f) ^ 0x7f;
|
||||
for ($i = 30; $i > 0; --$i) {
|
||||
$c |= self::chrToInt($s[$i]) ^ 0xff;
|
||||
}
|
||||
$c = ($c - 1) >> 8;
|
||||
$d = (0xed - 1 - self::chrToInt($s[0])) >> 8;
|
||||
$e = self::chrToInt($s[31]) >> 7;
|
||||
|
||||
return 1 - ((($c & $d) | $e | self::chrToInt($s[0])) & 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $s
|
||||
* @param bool $skipCanonicalCheck
|
||||
* @return array{h: ParagonIE_Sodium_Core_Curve25519_Ge_P3, res: int}
|
||||
* @throws SodiumException
|
||||
*/
|
||||
public static function ristretto255_frombytes($s, $skipCanonicalCheck = false)
|
||||
{
|
||||
if (!$skipCanonicalCheck) {
|
||||
if (!self::ristretto255_point_is_canonical($s)) {
|
||||
throw new SodiumException('S is not canonical');
|
||||
}
|
||||
}
|
||||
|
||||
$s_ = self::fe_frombytes($s);
|
||||
$ss = self::fe_sq($s_); /* ss = s^2 */
|
||||
|
||||
$u1 = self::fe_sub(self::fe_1(), $ss); /* u1 = 1-ss */
|
||||
$u1u1 = self::fe_sq($u1); /* u1u1 = u1^2 */
|
||||
|
||||
$u2 = self::fe_add(self::fe_1(), $ss); /* u2 = 1+ss */
|
||||
$u2u2 = self::fe_sq($u2); /* u2u2 = u2^2 */
|
||||
|
||||
$v = self::fe_mul(
|
||||
ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$d),
|
||||
$u1u1
|
||||
); /* v = d*u1^2 */
|
||||
$v = self::fe_neg($v); /* v = -d*u1^2 */
|
||||
$v = self::fe_sub($v, $u2u2); /* v = -(d*u1^2)-u2^2 */
|
||||
$v_u2u2 = self::fe_mul($v, $u2u2); /* v_u2u2 = v*u2^2 */
|
||||
|
||||
// fe25519_1(one);
|
||||
// notsquare = ristretto255_sqrt_ratio_m1(inv_sqrt, one, v_u2u2);
|
||||
$one = self::fe_1();
|
||||
$result = self::ristretto255_sqrt_ratio_m1($one, $v_u2u2);
|
||||
$inv_sqrt = $result['x'];
|
||||
$notsquare = $result['nonsquare'];
|
||||
|
||||
$h = new ParagonIE_Sodium_Core_Curve25519_Ge_P3();
|
||||
|
||||
$h->X = self::fe_mul($inv_sqrt, $u2);
|
||||
$h->Y = self::fe_mul(self::fe_mul($inv_sqrt, $h->X), $v);
|
||||
|
||||
$h->X = self::fe_mul($h->X, $s_);
|
||||
$h->X = self::fe_abs(
|
||||
self::fe_add($h->X, $h->X)
|
||||
);
|
||||
$h->Y = self::fe_mul($u1, $h->Y);
|
||||
$h->Z = self::fe_1();
|
||||
$h->T = self::fe_mul($h->X, $h->Y);
|
||||
|
||||
$res = - ((1 - $notsquare) | self::fe_isnegative($h->T) | self::fe_iszero($h->Y));
|
||||
return array('h' => $h, 'res' => $res);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $h
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
*/
|
||||
public static function ristretto255_p3_tobytes(ParagonIE_Sodium_Core_Curve25519_Ge_P3 $h)
|
||||
{
|
||||
$sqrtm1 = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqrtm1);
|
||||
$invsqrtamd = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$invsqrtamd);
|
||||
|
||||
$u1 = self::fe_add($h->Z, $h->Y); /* u1 = Z+Y */
|
||||
$zmy = self::fe_sub($h->Z, $h->Y); /* zmy = Z-Y */
|
||||
$u1 = self::fe_mul($u1, $zmy); /* u1 = (Z+Y)*(Z-Y) */
|
||||
$u2 = self::fe_mul($h->X, $h->Y); /* u2 = X*Y */
|
||||
|
||||
$u1_u2u2 = self::fe_mul(self::fe_sq($u2), $u1); /* u1_u2u2 = u1*u2^2 */
|
||||
$one = self::fe_1();
|
||||
|
||||
// fe25519_1(one);
|
||||
// (void) ristretto255_sqrt_ratio_m1(inv_sqrt, one, u1_u2u2);
|
||||
$result = self::ristretto255_sqrt_ratio_m1($one, $u1_u2u2);
|
||||
$inv_sqrt = $result['x'];
|
||||
|
||||
$den1 = self::fe_mul($inv_sqrt, $u1); /* den1 = inv_sqrt*u1 */
|
||||
$den2 = self::fe_mul($inv_sqrt, $u2); /* den2 = inv_sqrt*u2 */
|
||||
$z_inv = self::fe_mul($h->T, self::fe_mul($den1, $den2)); /* z_inv = den1*den2*T */
|
||||
|
||||
$ix = self::fe_mul($h->X, $sqrtm1); /* ix = X*sqrt(-1) */
|
||||
$iy = self::fe_mul($h->Y, $sqrtm1); /* iy = Y*sqrt(-1) */
|
||||
$eden = self::fe_mul($den1, $invsqrtamd);
|
||||
|
||||
$t_z_inv = self::fe_mul($h->T, $z_inv); /* t_z_inv = T*z_inv */
|
||||
$rotate = self::fe_isnegative($t_z_inv);
|
||||
|
||||
$x_ = self::fe_copy($h->X);
|
||||
$y_ = self::fe_copy($h->Y);
|
||||
$den_inv = self::fe_copy($den2);
|
||||
|
||||
$x_ = self::fe_cmov($x_, $iy, $rotate);
|
||||
$y_ = self::fe_cmov($y_, $ix, $rotate);
|
||||
$den_inv = self::fe_cmov($den_inv, $eden, $rotate);
|
||||
|
||||
$x_z_inv = self::fe_mul($x_, $z_inv);
|
||||
$y_ = self::fe_cneg($y_, self::fe_isnegative($x_z_inv));
|
||||
|
||||
|
||||
// fe25519_sub(s_, h->Z, y_);
|
||||
// fe25519_mul(s_, den_inv, s_);
|
||||
// fe25519_abs(s_, s_);
|
||||
// fe25519_tobytes(s, s_);
|
||||
return self::fe_tobytes(
|
||||
self::fe_abs(
|
||||
self::fe_mul(
|
||||
$den_inv,
|
||||
self::fe_sub($h->Z, $y_)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ParagonIE_Sodium_Core_Curve25519_Fe $t
|
||||
* @return ParagonIE_Sodium_Core_Curve25519_Ge_P3
|
||||
*
|
||||
* @throws SodiumException
|
||||
*/
|
||||
public static function ristretto255_elligator(ParagonIE_Sodium_Core_Curve25519_Fe $t)
|
||||
{
|
||||
$sqrtm1 = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqrtm1);
|
||||
$onemsqd = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$onemsqd);
|
||||
$d = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$d);
|
||||
$sqdmone = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqdmone);
|
||||
$sqrtadm1 = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqrtadm1);
|
||||
|
||||
$one = self::fe_1();
|
||||
$r = self::fe_mul($sqrtm1, self::fe_sq($t)); /* r = sqrt(-1)*t^2 */
|
||||
$u = self::fe_mul(self::fe_add($r, $one), $onemsqd); /* u = (r+1)*(1-d^2) */
|
||||
$c = self::fe_neg(self::fe_1()); /* c = -1 */
|
||||
$rpd = self::fe_add($r, $d); /* rpd = r+d */
|
||||
|
||||
$v = self::fe_mul(
|
||||
self::fe_sub(
|
||||
$c,
|
||||
self::fe_mul($r, $d)
|
||||
),
|
||||
$rpd
|
||||
); /* v = (c-r*d)*(r+d) */
|
||||
|
||||
$result = self::ristretto255_sqrt_ratio_m1($u, $v);
|
||||
$s = $result['x'];
|
||||
$wasnt_square = 1 - $result['nonsquare'];
|
||||
|
||||
$s_prime = self::fe_neg(
|
||||
self::fe_abs(
|
||||
self::fe_mul($s, $t)
|
||||
)
|
||||
); /* s_prime = -|s*t| */
|
||||
$s = self::fe_cmov($s, $s_prime, $wasnt_square);
|
||||
$c = self::fe_cmov($c, $r, $wasnt_square);
|
||||
|
||||
// fe25519_sub(n, r, one); /* n = r-1 */
|
||||
// fe25519_mul(n, n, c); /* n = c*(r-1) */
|
||||
// fe25519_mul(n, n, ed25519_sqdmone); /* n = c*(r-1)*(d-1)^2 */
|
||||
// fe25519_sub(n, n, v); /* n = c*(r-1)*(d-1)^2-v */
|
||||
$n = self::fe_sub(
|
||||
self::fe_mul(
|
||||
self::fe_mul(
|
||||
self::fe_sub($r, $one),
|
||||
$c
|
||||
),
|
||||
$sqdmone
|
||||
),
|
||||
$v
|
||||
); /* n = c*(r-1)*(d-1)^2-v */
|
||||
|
||||
$w0 = self::fe_mul(
|
||||
self::fe_add($s, $s),
|
||||
$v
|
||||
); /* w0 = 2s*v */
|
||||
|
||||
$w1 = self::fe_mul($n, $sqrtadm1); /* w1 = n*sqrt(ad-1) */
|
||||
$ss = self::fe_sq($s); /* ss = s^2 */
|
||||
$w2 = self::fe_sub($one, $ss); /* w2 = 1-s^2 */
|
||||
$w3 = self::fe_add($one, $ss); /* w3 = 1+s^2 */
|
||||
|
||||
return new ParagonIE_Sodium_Core_Curve25519_Ge_P3(
|
||||
self::fe_mul($w0, $w3),
|
||||
self::fe_mul($w2, $w1),
|
||||
self::fe_mul($w1, $w3),
|
||||
self::fe_mul($w0, $w2)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $h
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
*/
|
||||
public static function ristretto255_from_hash($h)
|
||||
{
|
||||
if (self::strlen($h) !== 64) {
|
||||
throw new SodiumException('Hash must be 64 bytes');
|
||||
}
|
||||
//fe25519_frombytes(r0, h);
|
||||
//fe25519_frombytes(r1, h + 32);
|
||||
$r0 = self::fe_frombytes(self::substr($h, 0, 32));
|
||||
$r1 = self::fe_frombytes(self::substr($h, 32, 32));
|
||||
|
||||
//ristretto255_elligator(&p0, r0);
|
||||
//ristretto255_elligator(&p1, r1);
|
||||
$p0 = self::ristretto255_elligator($r0);
|
||||
$p1 = self::ristretto255_elligator($r1);
|
||||
|
||||
//ge25519_p3_to_cached(&p1_cached, &p1);
|
||||
//ge25519_add_cached(&p_p1p1, &p0, &p1_cached);
|
||||
$p_p1p1 = self::ge_add(
|
||||
$p0,
|
||||
self::ge_p3_to_cached($p1)
|
||||
);
|
||||
|
||||
//ge25519_p1p1_to_p3(&p, &p_p1p1);
|
||||
//ristretto255_p3_tobytes(s, &p);
|
||||
return self::ristretto255_p3_tobytes(
|
||||
self::ge_p1p1_to_p3($p_p1p1)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $p
|
||||
* @return int
|
||||
* @throws SodiumException
|
||||
*/
|
||||
public static function is_valid_point($p)
|
||||
{
|
||||
$result = self::ristretto255_frombytes($p);
|
||||
if ($result['res'] !== 0) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $p
|
||||
* @param string $q
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
*/
|
||||
public static function ristretto255_add($p, $q)
|
||||
{
|
||||
$p_res = self::ristretto255_frombytes($p);
|
||||
$q_res = self::ristretto255_frombytes($q);
|
||||
if ($p_res['res'] !== 0 || $q_res['res'] !== 0) {
|
||||
throw new SodiumException('Could not add points');
|
||||
}
|
||||
$p_p3 = $p_res['h'];
|
||||
$q_p3 = $q_res['h'];
|
||||
$q_cached = self::ge_p3_to_cached($q_p3);
|
||||
$r_p1p1 = self::ge_add($p_p3, $q_cached);
|
||||
$r_p3 = self::ge_p1p1_to_p3($r_p1p1);
|
||||
return self::ristretto255_p3_tobytes($r_p3);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $p
|
||||
* @param string $q
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
*/
|
||||
public static function ristretto255_sub($p, $q)
|
||||
{
|
||||
$p_res = self::ristretto255_frombytes($p);
|
||||
$q_res = self::ristretto255_frombytes($q);
|
||||
if ($p_res['res'] !== 0 || $q_res['res'] !== 0) {
|
||||
throw new SodiumException('Could not add points');
|
||||
}
|
||||
$p_p3 = $p_res['h'];
|
||||
$q_p3 = $q_res['h'];
|
||||
$q_cached = self::ge_p3_to_cached($q_p3);
|
||||
$r_p1p1 = self::ge_sub($p_p3, $q_cached);
|
||||
$r_p3 = self::ge_p1p1_to_p3($r_p1p1);
|
||||
return self::ristretto255_p3_tobytes($r_p3);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param int $hLen
|
||||
* @param ?string $ctx
|
||||
* @param string $msg
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
* @psalm-suppress PossiblyInvalidArgument hash API
|
||||
*/
|
||||
protected static function h2c_string_to_hash_sha256($hLen, $ctx, $msg)
|
||||
{
|
||||
$h = array_fill(0, $hLen, 0);
|
||||
$ctx_len = !is_null($ctx) ? self::strlen($ctx) : 0;
|
||||
if ($hLen > 0xff) {
|
||||
throw new SodiumException('Hash must be less than 256 bytes');
|
||||
}
|
||||
|
||||
if ($ctx_len > 0xff) {
|
||||
$st = hash_init('sha256');
|
||||
self::hash_update($st, "H2C-OVERSIZE-DST-");
|
||||
self::hash_update($st, $ctx);
|
||||
$ctx = hash_final($st, true);
|
||||
$ctx_len = 32;
|
||||
}
|
||||
$t = array(0, $hLen, 0);
|
||||
$ux = str_repeat("\0", 64);
|
||||
$st = hash_init('sha256');
|
||||
self::hash_update($st, $ux);
|
||||
self::hash_update($st, $msg);
|
||||
self::hash_update($st, self::intArrayToString($t));
|
||||
self::hash_update($st, $ctx);
|
||||
self::hash_update($st, self::intToChr($ctx_len));
|
||||
$u0 = hash_final($st, true);
|
||||
|
||||
for ($i = 0; $i < $hLen; $i += 64) {
|
||||
$ux = self::xorStrings($ux, $u0);
|
||||
++$t[2];
|
||||
$st = hash_init('sha256');
|
||||
self::hash_update($st, $ux);
|
||||
self::hash_update($st, self::intToChr($t[2]));
|
||||
self::hash_update($st, $ctx);
|
||||
self::hash_update($st, self::intToChr($ctx_len));
|
||||
$ux = hash_final($st, true);
|
||||
$amount = min($hLen - $i, 64);
|
||||
for ($j = 0; $j < $amount; ++$j) {
|
||||
$h[$i + $j] = self::chrToInt($ux[$i]);
|
||||
}
|
||||
}
|
||||
return self::intArrayToString(array_slice($h, 0, $hLen));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $hLen
|
||||
* @param ?string $ctx
|
||||
* @param string $msg
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
* @psalm-suppress PossiblyInvalidArgument hash API
|
||||
*/
|
||||
protected static function h2c_string_to_hash_sha512($hLen, $ctx, $msg)
|
||||
{
|
||||
$h = array_fill(0, $hLen, 0);
|
||||
$ctx_len = !is_null($ctx) ? self::strlen($ctx) : 0;
|
||||
if ($hLen > 0xff) {
|
||||
throw new SodiumException('Hash must be less than 256 bytes');
|
||||
}
|
||||
|
||||
if ($ctx_len > 0xff) {
|
||||
$st = hash_init('sha256');
|
||||
self::hash_update($st, "H2C-OVERSIZE-DST-");
|
||||
self::hash_update($st, $ctx);
|
||||
$ctx = hash_final($st, true);
|
||||
$ctx_len = 32;
|
||||
}
|
||||
$t = array(0, $hLen, 0);
|
||||
$ux = str_repeat("\0", 128);
|
||||
$st = hash_init('sha512');
|
||||
self::hash_update($st, $ux);
|
||||
self::hash_update($st, $msg);
|
||||
self::hash_update($st, self::intArrayToString($t));
|
||||
self::hash_update($st, $ctx);
|
||||
self::hash_update($st, self::intToChr($ctx_len));
|
||||
$u0 = hash_final($st, true);
|
||||
|
||||
for ($i = 0; $i < $hLen; $i += 128) {
|
||||
$ux = self::xorStrings($ux, $u0);
|
||||
++$t[2];
|
||||
$st = hash_init('sha512');
|
||||
self::hash_update($st, $ux);
|
||||
self::hash_update($st, self::intToChr($t[2]));
|
||||
self::hash_update($st, $ctx);
|
||||
self::hash_update($st, self::intToChr($ctx_len));
|
||||
$ux = hash_final($st, true);
|
||||
$amount = min($hLen - $i, 128);
|
||||
for ($j = 0; $j < $amount; ++$j) {
|
||||
$h[$i + $j] = self::chrToInt($ux[$i]);
|
||||
}
|
||||
}
|
||||
return self::intArrayToString(array_slice($h, 0, $hLen));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $hLen
|
||||
* @param ?string $ctx
|
||||
* @param string $msg
|
||||
* @param int $hash_alg
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
*/
|
||||
public static function h2c_string_to_hash($hLen, $ctx, $msg, $hash_alg)
|
||||
{
|
||||
switch ($hash_alg) {
|
||||
case self::CORE_H2C_SHA256:
|
||||
return self::h2c_string_to_hash_sha256($hLen, $ctx, $msg);
|
||||
case self::CORE_H2C_SHA512:
|
||||
return self::h2c_string_to_hash_sha512($hLen, $ctx, $msg);
|
||||
default:
|
||||
throw new SodiumException('Invalid H2C hash algorithm');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ?string $ctx
|
||||
* @param string $msg
|
||||
* @param int $hash_alg
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
*/
|
||||
protected static function _string_to_element($ctx, $msg, $hash_alg)
|
||||
{
|
||||
return self::ristretto255_from_hash(
|
||||
self::h2c_string_to_hash(self::crypto_core_ristretto255_HASHBYTES, $ctx, $msg, $hash_alg)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function ristretto255_random()
|
||||
{
|
||||
return self::ristretto255_from_hash(
|
||||
ParagonIE_Sodium_Compat::randombytes_buf(self::crypto_core_ristretto255_HASHBYTES)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
*/
|
||||
public static function ristretto255_scalar_random()
|
||||
{
|
||||
return self::scalar_random();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $s
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
*/
|
||||
public static function ristretto255_scalar_complement($s)
|
||||
{
|
||||
return self::scalar_complement($s);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $s
|
||||
* @return string
|
||||
*/
|
||||
public static function ristretto255_scalar_invert($s)
|
||||
{
|
||||
return self::sc25519_invert($s);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $s
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
*/
|
||||
public static function ristretto255_scalar_negate($s)
|
||||
{
|
||||
return self::scalar_negate($s);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $x
|
||||
* @param string $y
|
||||
* @return string
|
||||
*/
|
||||
public static function ristretto255_scalar_add($x, $y)
|
||||
{
|
||||
return self::scalar_add($x, $y);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $x
|
||||
* @param string $y
|
||||
* @return string
|
||||
*/
|
||||
public static function ristretto255_scalar_sub($x, $y)
|
||||
{
|
||||
return self::scalar_sub($x, $y);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $x
|
||||
* @param string $y
|
||||
* @return string
|
||||
*/
|
||||
public static function ristretto255_scalar_mul($x, $y)
|
||||
{
|
||||
return self::sc25519_mul($x, $y);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $ctx
|
||||
* @param string $msg
|
||||
* @param int $hash_alg
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
*/
|
||||
public static function ristretto255_scalar_from_string($ctx, $msg, $hash_alg)
|
||||
{
|
||||
$h = array_fill(0, 64, 0);
|
||||
$h_be = self::stringToIntArray(
|
||||
self::h2c_string_to_hash(
|
||||
self::HASH_SC_L, $ctx, $msg, $hash_alg
|
||||
)
|
||||
);
|
||||
|
||||
for ($i = 0; $i < self::HASH_SC_L; ++$i) {
|
||||
$h[$i] = $h_be[self::HASH_SC_L - 1 - $i];
|
||||
}
|
||||
return self::ristretto255_scalar_reduce(self::intArrayToString($h));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $s
|
||||
* @return string
|
||||
*/
|
||||
public static function ristretto255_scalar_reduce($s)
|
||||
{
|
||||
return self::sc_reduce($s);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $n
|
||||
* @param string $p
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
*/
|
||||
public static function scalarmult_ristretto255($n, $p)
|
||||
{
|
||||
if (self::strlen($n) !== 32) {
|
||||
throw new SodiumException('Scalar must be 32 bytes, ' . self::strlen($p) . ' given.');
|
||||
}
|
||||
if (self::strlen($p) !== 32) {
|
||||
throw new SodiumException('Point must be 32 bytes, ' . self::strlen($p) . ' given.');
|
||||
}
|
||||
$result = self::ristretto255_frombytes($p);
|
||||
if ($result['res'] !== 0) {
|
||||
throw new SodiumException('Could not multiply points');
|
||||
}
|
||||
$P = $result['h'];
|
||||
|
||||
$t = self::stringToIntArray($n);
|
||||
$t[31] &= 0x7f;
|
||||
$Q = self::ge_scalarmult(self::intArrayToString($t), $P);
|
||||
$q = self::ristretto255_p3_tobytes($Q);
|
||||
if (ParagonIE_Sodium_Compat::is_zero($q)) {
|
||||
throw new SodiumException('An unknown error has occurred');
|
||||
}
|
||||
return $q;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $n
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
*/
|
||||
public static function scalarmult_ristretto255_base($n)
|
||||
{
|
||||
$t = self::stringToIntArray($n);
|
||||
$t[31] &= 0x7f;
|
||||
$Q = self::ge_scalarmult_base(self::intArrayToString($t));
|
||||
$q = self::ristretto255_p3_tobytes($Q);
|
||||
if (ParagonIE_Sodium_Compat::is_zero($q)) {
|
||||
throw new SodiumException('An unknown error has occurred');
|
||||
}
|
||||
return $q;
|
||||
}
|
||||
}
|
||||
@@ -1,274 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
|
||||
if (class_exists('ParagonIE_Sodium_Core_Salsa20', false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class ParagonIE_Sodium_Core_Salsa20
|
||||
*/
|
||||
abstract class ParagonIE_Sodium_Core_Salsa20 extends ParagonIE_Sodium_Core_Util
|
||||
{
|
||||
const ROUNDS = 20;
|
||||
|
||||
/**
|
||||
* Calculate an salsa20 hash of a single block
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param string $in
|
||||
* @param string $k
|
||||
* @param string|null $c
|
||||
* @return string
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function core_salsa20($in, $k, $c = null)
|
||||
{
|
||||
if (self::strlen($k) < 32) {
|
||||
throw new RangeException('Key must be 32 bytes long');
|
||||
}
|
||||
if ($c === null) {
|
||||
$j0 = $x0 = 0x61707865;
|
||||
$j5 = $x5 = 0x3320646e;
|
||||
$j10 = $x10 = 0x79622d32;
|
||||
$j15 = $x15 = 0x6b206574;
|
||||
} else {
|
||||
$j0 = $x0 = self::load_4(self::substr($c, 0, 4));
|
||||
$j5 = $x5 = self::load_4(self::substr($c, 4, 4));
|
||||
$j10 = $x10 = self::load_4(self::substr($c, 8, 4));
|
||||
$j15 = $x15 = self::load_4(self::substr($c, 12, 4));
|
||||
}
|
||||
$j1 = $x1 = self::load_4(self::substr($k, 0, 4));
|
||||
$j2 = $x2 = self::load_4(self::substr($k, 4, 4));
|
||||
$j3 = $x3 = self::load_4(self::substr($k, 8, 4));
|
||||
$j4 = $x4 = self::load_4(self::substr($k, 12, 4));
|
||||
$j6 = $x6 = self::load_4(self::substr($in, 0, 4));
|
||||
$j7 = $x7 = self::load_4(self::substr($in, 4, 4));
|
||||
$j8 = $x8 = self::load_4(self::substr($in, 8, 4));
|
||||
$j9 = $x9 = self::load_4(self::substr($in, 12, 4));
|
||||
$j11 = $x11 = self::load_4(self::substr($k, 16, 4));
|
||||
$j12 = $x12 = self::load_4(self::substr($k, 20, 4));
|
||||
$j13 = $x13 = self::load_4(self::substr($k, 24, 4));
|
||||
$j14 = $x14 = self::load_4(self::substr($k, 28, 4));
|
||||
|
||||
for ($i = self::ROUNDS; $i > 0; $i -= 2) {
|
||||
$x4 ^= self::rotate($x0 + $x12, 7);
|
||||
$x8 ^= self::rotate($x4 + $x0, 9);
|
||||
$x12 ^= self::rotate($x8 + $x4, 13);
|
||||
$x0 ^= self::rotate($x12 + $x8, 18);
|
||||
|
||||
$x9 ^= self::rotate($x5 + $x1, 7);
|
||||
$x13 ^= self::rotate($x9 + $x5, 9);
|
||||
$x1 ^= self::rotate($x13 + $x9, 13);
|
||||
$x5 ^= self::rotate($x1 + $x13, 18);
|
||||
|
||||
$x14 ^= self::rotate($x10 + $x6, 7);
|
||||
$x2 ^= self::rotate($x14 + $x10, 9);
|
||||
$x6 ^= self::rotate($x2 + $x14, 13);
|
||||
$x10 ^= self::rotate($x6 + $x2, 18);
|
||||
|
||||
$x3 ^= self::rotate($x15 + $x11, 7);
|
||||
$x7 ^= self::rotate($x3 + $x15, 9);
|
||||
$x11 ^= self::rotate($x7 + $x3, 13);
|
||||
$x15 ^= self::rotate($x11 + $x7, 18);
|
||||
|
||||
$x1 ^= self::rotate($x0 + $x3, 7);
|
||||
$x2 ^= self::rotate($x1 + $x0, 9);
|
||||
$x3 ^= self::rotate($x2 + $x1, 13);
|
||||
$x0 ^= self::rotate($x3 + $x2, 18);
|
||||
|
||||
$x6 ^= self::rotate($x5 + $x4, 7);
|
||||
$x7 ^= self::rotate($x6 + $x5, 9);
|
||||
$x4 ^= self::rotate($x7 + $x6, 13);
|
||||
$x5 ^= self::rotate($x4 + $x7, 18);
|
||||
|
||||
$x11 ^= self::rotate($x10 + $x9, 7);
|
||||
$x8 ^= self::rotate($x11 + $x10, 9);
|
||||
$x9 ^= self::rotate($x8 + $x11, 13);
|
||||
$x10 ^= self::rotate($x9 + $x8, 18);
|
||||
|
||||
$x12 ^= self::rotate($x15 + $x14, 7);
|
||||
$x13 ^= self::rotate($x12 + $x15, 9);
|
||||
$x14 ^= self::rotate($x13 + $x12, 13);
|
||||
$x15 ^= self::rotate($x14 + $x13, 18);
|
||||
}
|
||||
|
||||
$x0 += $j0;
|
||||
$x1 += $j1;
|
||||
$x2 += $j2;
|
||||
$x3 += $j3;
|
||||
$x4 += $j4;
|
||||
$x5 += $j5;
|
||||
$x6 += $j6;
|
||||
$x7 += $j7;
|
||||
$x8 += $j8;
|
||||
$x9 += $j9;
|
||||
$x10 += $j10;
|
||||
$x11 += $j11;
|
||||
$x12 += $j12;
|
||||
$x13 += $j13;
|
||||
$x14 += $j14;
|
||||
$x15 += $j15;
|
||||
|
||||
return self::store32_le($x0) .
|
||||
self::store32_le($x1) .
|
||||
self::store32_le($x2) .
|
||||
self::store32_le($x3) .
|
||||
self::store32_le($x4) .
|
||||
self::store32_le($x5) .
|
||||
self::store32_le($x6) .
|
||||
self::store32_le($x7) .
|
||||
self::store32_le($x8) .
|
||||
self::store32_le($x9) .
|
||||
self::store32_le($x10) .
|
||||
self::store32_le($x11) .
|
||||
self::store32_le($x12) .
|
||||
self::store32_le($x13) .
|
||||
self::store32_le($x14) .
|
||||
self::store32_le($x15);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param int $len
|
||||
* @param string $nonce
|
||||
* @param string $key
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function salsa20($len, $nonce, $key)
|
||||
{
|
||||
if (self::strlen($key) !== 32) {
|
||||
throw new RangeException('Key must be 32 bytes long');
|
||||
}
|
||||
$kcopy = '' . $key;
|
||||
$in = self::substr($nonce, 0, 8) . str_repeat("\0", 8);
|
||||
$c = '';
|
||||
while ($len >= 64) {
|
||||
$c .= self::core_salsa20($in, $kcopy, null);
|
||||
$u = 1;
|
||||
// Internal counter.
|
||||
for ($i = 8; $i < 16; ++$i) {
|
||||
$u += self::chrToInt($in[$i]);
|
||||
$in[$i] = self::intToChr($u & 0xff);
|
||||
$u >>= 8;
|
||||
}
|
||||
$len -= 64;
|
||||
}
|
||||
if ($len > 0) {
|
||||
$c .= self::substr(
|
||||
self::core_salsa20($in, $kcopy, null),
|
||||
0,
|
||||
$len
|
||||
);
|
||||
}
|
||||
try {
|
||||
ParagonIE_Sodium_Compat::memzero($kcopy);
|
||||
} catch (SodiumException $ex) {
|
||||
$kcopy = null;
|
||||
}
|
||||
return $c;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param string $m
|
||||
* @param string $n
|
||||
* @param int $ic
|
||||
* @param string $k
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function salsa20_xor_ic($m, $n, $ic, $k)
|
||||
{
|
||||
$mlen = self::strlen($m);
|
||||
if ($mlen < 1) {
|
||||
return '';
|
||||
}
|
||||
$kcopy = self::substr($k, 0, 32);
|
||||
$in = self::substr($n, 0, 8);
|
||||
// Initialize the counter
|
||||
$in .= ParagonIE_Sodium_Core_Util::store64_le($ic);
|
||||
|
||||
$c = '';
|
||||
while ($mlen >= 64) {
|
||||
$block = self::core_salsa20($in, $kcopy, null);
|
||||
$c .= self::xorStrings(
|
||||
self::substr($m, 0, 64),
|
||||
self::substr($block, 0, 64)
|
||||
);
|
||||
$u = 1;
|
||||
for ($i = 8; $i < 16; ++$i) {
|
||||
$u += self::chrToInt($in[$i]);
|
||||
$in[$i] = self::intToChr($u & 0xff);
|
||||
$u >>= 8;
|
||||
}
|
||||
|
||||
$mlen -= 64;
|
||||
$m = self::substr($m, 64);
|
||||
}
|
||||
|
||||
if ($mlen) {
|
||||
$block = self::core_salsa20($in, $kcopy, null);
|
||||
$c .= self::xorStrings(
|
||||
self::substr($m, 0, $mlen),
|
||||
self::substr($block, 0, $mlen)
|
||||
);
|
||||
}
|
||||
try {
|
||||
ParagonIE_Sodium_Compat::memzero($block);
|
||||
ParagonIE_Sodium_Compat::memzero($kcopy);
|
||||
} catch (SodiumException $ex) {
|
||||
$block = null;
|
||||
$kcopy = null;
|
||||
}
|
||||
|
||||
return $c;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param string $message
|
||||
* @param string $nonce
|
||||
* @param string $key
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function salsa20_xor($message, $nonce, $key)
|
||||
{
|
||||
return self::xorStrings(
|
||||
$message,
|
||||
self::salsa20(
|
||||
self::strlen($message),
|
||||
$nonce,
|
||||
$key
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param int $u
|
||||
* @param int $c
|
||||
* @return int
|
||||
*/
|
||||
public static function rotate($u, $c)
|
||||
{
|
||||
$u &= 0xffffffff;
|
||||
$c %= 32;
|
||||
return (int) (0xffffffff & (
|
||||
($u << $c)
|
||||
|
|
||||
($u >> (32 - $c))
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,164 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
|
||||
/**
|
||||
* Class ParagonIE_Sodium_Core_SecretStream_State
|
||||
*/
|
||||
class ParagonIE_Sodium_Core_SecretStream_State
|
||||
{
|
||||
/** @var string $key */
|
||||
protected $key;
|
||||
|
||||
/** @var int $counter */
|
||||
protected $counter;
|
||||
|
||||
/** @var string $nonce */
|
||||
protected $nonce;
|
||||
|
||||
/** @var string $_pad */
|
||||
protected $_pad;
|
||||
|
||||
/**
|
||||
* ParagonIE_Sodium_Core_SecretStream_State constructor.
|
||||
* @param string $key
|
||||
* @param string|null $nonce
|
||||
*/
|
||||
public function __construct($key, $nonce = null)
|
||||
{
|
||||
$this->key = $key;
|
||||
$this->counter = 1;
|
||||
if (is_null($nonce)) {
|
||||
$nonce = str_repeat("\0", 12);
|
||||
}
|
||||
$this->nonce = str_pad($nonce, 12, "\0", STR_PAD_RIGHT);;
|
||||
$this->_pad = str_repeat("\0", 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return self
|
||||
*/
|
||||
public function counterReset()
|
||||
{
|
||||
$this->counter = 1;
|
||||
$this->_pad = str_repeat("\0", 4);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getKey()
|
||||
{
|
||||
return $this->key;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getCounter()
|
||||
{
|
||||
return ParagonIE_Sodium_Core_Util::store32_le($this->counter);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getNonce()
|
||||
{
|
||||
if (!is_string($this->nonce)) {
|
||||
$this->nonce = str_repeat("\0", 12);
|
||||
}
|
||||
if (ParagonIE_Sodium_Core_Util::strlen($this->nonce) !== 12) {
|
||||
$this->nonce = str_pad($this->nonce, 12, "\0", STR_PAD_RIGHT);
|
||||
}
|
||||
return $this->nonce;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getCombinedNonce()
|
||||
{
|
||||
return $this->getCounter() .
|
||||
ParagonIE_Sodium_Core_Util::substr($this->getNonce(), 0, 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return self
|
||||
*/
|
||||
public function incrementCounter()
|
||||
{
|
||||
++$this->counter;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function needsRekey()
|
||||
{
|
||||
return ($this->counter & 0xffff) === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $newKeyAndNonce
|
||||
* @return self
|
||||
*/
|
||||
public function rekey($newKeyAndNonce)
|
||||
{
|
||||
$this->key = ParagonIE_Sodium_Core_Util::substr($newKeyAndNonce, 0, 32);
|
||||
$this->nonce = str_pad(
|
||||
ParagonIE_Sodium_Core_Util::substr($newKeyAndNonce, 32),
|
||||
12,
|
||||
"\0",
|
||||
STR_PAD_RIGHT
|
||||
);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $str
|
||||
* @return self
|
||||
*/
|
||||
public function xorNonce($str)
|
||||
{
|
||||
$this->nonce = ParagonIE_Sodium_Core_Util::xorStrings(
|
||||
$this->getNonce(),
|
||||
str_pad(
|
||||
ParagonIE_Sodium_Core_Util::substr($str, 0, 8),
|
||||
12,
|
||||
"\0",
|
||||
STR_PAD_RIGHT
|
||||
)
|
||||
);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @return self
|
||||
*/
|
||||
public static function fromString($string)
|
||||
{
|
||||
$state = new ParagonIE_Sodium_Core_SecretStream_State(
|
||||
ParagonIE_Sodium_Core_Util::substr($string, 0, 32)
|
||||
);
|
||||
$state->counter = ParagonIE_Sodium_Core_Util::load_4(
|
||||
ParagonIE_Sodium_Core_Util::substr($string, 32, 4)
|
||||
);
|
||||
$state->nonce = ParagonIE_Sodium_Core_Util::substr($string, 36, 12);
|
||||
$state->_pad = ParagonIE_Sodium_Core_Util::substr($string, 48, 8);
|
||||
return $state;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function toString()
|
||||
{
|
||||
return $this->key .
|
||||
$this->getCounter() .
|
||||
$this->nonce .
|
||||
$this->_pad;
|
||||
}
|
||||
}
|
||||
@@ -1,307 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
|
||||
if (class_exists('ParagonIE_Sodium_Core_SipHash', false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class ParagonIE_SodiumCompat_Core_SipHash
|
||||
*
|
||||
* Only uses 32-bit arithmetic, while the original SipHash used 64-bit integers
|
||||
*/
|
||||
class ParagonIE_Sodium_Core_SipHash extends ParagonIE_Sodium_Core_Util
|
||||
{
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param int[] $v
|
||||
* @return int[]
|
||||
*
|
||||
*/
|
||||
public static function sipRound(array $v)
|
||||
{
|
||||
# v0 += v1;
|
||||
list($v[0], $v[1]) = self::add(
|
||||
array($v[0], $v[1]),
|
||||
array($v[2], $v[3])
|
||||
);
|
||||
|
||||
# v1=ROTL(v1,13);
|
||||
list($v[2], $v[3]) = self::rotl_64((int) $v[2], (int) $v[3], 13);
|
||||
|
||||
# v1 ^= v0;
|
||||
$v[2] = (int) $v[2] ^ (int) $v[0];
|
||||
$v[3] = (int) $v[3] ^ (int) $v[1];
|
||||
|
||||
# v0=ROTL(v0,32);
|
||||
list($v[0], $v[1]) = self::rotl_64((int) $v[0], (int) $v[1], 32);
|
||||
|
||||
# v2 += v3;
|
||||
list($v[4], $v[5]) = self::add(
|
||||
array((int) $v[4], (int) $v[5]),
|
||||
array((int) $v[6], (int) $v[7])
|
||||
);
|
||||
|
||||
# v3=ROTL(v3,16);
|
||||
list($v[6], $v[7]) = self::rotl_64((int) $v[6], (int) $v[7], 16);
|
||||
|
||||
# v3 ^= v2;
|
||||
$v[6] = (int) $v[6] ^ (int) $v[4];
|
||||
$v[7] = (int) $v[7] ^ (int) $v[5];
|
||||
|
||||
# v0 += v3;
|
||||
list($v[0], $v[1]) = self::add(
|
||||
array((int) $v[0], (int) $v[1]),
|
||||
array((int) $v[6], (int) $v[7])
|
||||
);
|
||||
|
||||
# v3=ROTL(v3,21);
|
||||
list($v[6], $v[7]) = self::rotl_64((int) $v[6], (int) $v[7], 21);
|
||||
|
||||
# v3 ^= v0;
|
||||
$v[6] = (int) $v[6] ^ (int) $v[0];
|
||||
$v[7] = (int) $v[7] ^ (int) $v[1];
|
||||
|
||||
# v2 += v1;
|
||||
list($v[4], $v[5]) = self::add(
|
||||
array((int) $v[4], (int) $v[5]),
|
||||
array((int) $v[2], (int) $v[3])
|
||||
);
|
||||
|
||||
# v1=ROTL(v1,17);
|
||||
list($v[2], $v[3]) = self::rotl_64((int) $v[2], (int) $v[3], 17);
|
||||
|
||||
# v1 ^= v2;;
|
||||
$v[2] = (int) $v[2] ^ (int) $v[4];
|
||||
$v[3] = (int) $v[3] ^ (int) $v[5];
|
||||
|
||||
# v2=ROTL(v2,32)
|
||||
list($v[4], $v[5]) = self::rotl_64((int) $v[4], (int) $v[5], 32);
|
||||
|
||||
return $v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add two 32 bit integers representing a 64-bit integer.
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param int[] $a
|
||||
* @param int[] $b
|
||||
* @return array<int, mixed>
|
||||
*/
|
||||
public static function add(array $a, array $b)
|
||||
{
|
||||
/** @var int $x1 */
|
||||
$x1 = $a[1] + $b[1];
|
||||
/** @var int $c */
|
||||
$c = $x1 >> 32; // Carry if ($a + $b) > 0xffffffff
|
||||
/** @var int $x0 */
|
||||
$x0 = $a[0] + $b[0] + $c;
|
||||
return array(
|
||||
$x0 & 0xffffffff,
|
||||
$x1 & 0xffffffff
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param int $int0
|
||||
* @param int $int1
|
||||
* @param int $c
|
||||
* @return array<int, mixed>
|
||||
*/
|
||||
public static function rotl_64($int0, $int1, $c)
|
||||
{
|
||||
$int0 &= 0xffffffff;
|
||||
$int1 &= 0xffffffff;
|
||||
$c &= 63;
|
||||
if ($c === 32) {
|
||||
return array($int1, $int0);
|
||||
}
|
||||
if ($c > 31) {
|
||||
$tmp = $int1;
|
||||
$int1 = $int0;
|
||||
$int0 = $tmp;
|
||||
$c &= 31;
|
||||
}
|
||||
if ($c === 0) {
|
||||
return array($int0, $int1);
|
||||
}
|
||||
return array(
|
||||
0xffffffff & (
|
||||
($int0 << $c)
|
||||
|
|
||||
($int1 >> (32 - $c))
|
||||
),
|
||||
0xffffffff & (
|
||||
($int1 << $c)
|
||||
|
|
||||
($int0 >> (32 - $c))
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements Siphash-2-4 using only 32-bit numbers.
|
||||
*
|
||||
* When we split an int into two, the higher bits go to the lower index.
|
||||
* e.g. 0xDEADBEEFAB10C92D becomes [
|
||||
* 0 => 0xDEADBEEF,
|
||||
* 1 => 0xAB10C92D
|
||||
* ].
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param string $in
|
||||
* @param string $key
|
||||
* @return string
|
||||
* @throws SodiumException
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function sipHash24($in, $key)
|
||||
{
|
||||
$inlen = self::strlen($in);
|
||||
|
||||
# /* "somepseudorandomlygeneratedbytes" */
|
||||
# u64 v0 = 0x736f6d6570736575ULL;
|
||||
# u64 v1 = 0x646f72616e646f6dULL;
|
||||
# u64 v2 = 0x6c7967656e657261ULL;
|
||||
# u64 v3 = 0x7465646279746573ULL;
|
||||
$v = array(
|
||||
0x736f6d65, // 0
|
||||
0x70736575, // 1
|
||||
0x646f7261, // 2
|
||||
0x6e646f6d, // 3
|
||||
0x6c796765, // 4
|
||||
0x6e657261, // 5
|
||||
0x74656462, // 6
|
||||
0x79746573 // 7
|
||||
);
|
||||
// v0 => $v[0], $v[1]
|
||||
// v1 => $v[2], $v[3]
|
||||
// v2 => $v[4], $v[5]
|
||||
// v3 => $v[6], $v[7]
|
||||
|
||||
# u64 k0 = LOAD64_LE( k );
|
||||
# u64 k1 = LOAD64_LE( k + 8 );
|
||||
$k = array(
|
||||
self::load_4(self::substr($key, 4, 4)),
|
||||
self::load_4(self::substr($key, 0, 4)),
|
||||
self::load_4(self::substr($key, 12, 4)),
|
||||
self::load_4(self::substr($key, 8, 4))
|
||||
);
|
||||
// k0 => $k[0], $k[1]
|
||||
// k1 => $k[2], $k[3]
|
||||
|
||||
# b = ( ( u64 )inlen ) << 56;
|
||||
$b = array(
|
||||
$inlen << 24,
|
||||
0
|
||||
);
|
||||
// See docblock for why the 0th index gets the higher bits.
|
||||
|
||||
# v3 ^= k1;
|
||||
$v[6] ^= $k[2];
|
||||
$v[7] ^= $k[3];
|
||||
# v2 ^= k0;
|
||||
$v[4] ^= $k[0];
|
||||
$v[5] ^= $k[1];
|
||||
# v1 ^= k1;
|
||||
$v[2] ^= $k[2];
|
||||
$v[3] ^= $k[3];
|
||||
# v0 ^= k0;
|
||||
$v[0] ^= $k[0];
|
||||
$v[1] ^= $k[1];
|
||||
|
||||
$left = $inlen;
|
||||
# for ( ; in != end; in += 8 )
|
||||
while ($left >= 8) {
|
||||
# m = LOAD64_LE( in );
|
||||
$m = array(
|
||||
self::load_4(self::substr($in, 4, 4)),
|
||||
self::load_4(self::substr($in, 0, 4))
|
||||
);
|
||||
|
||||
# v3 ^= m;
|
||||
$v[6] ^= $m[0];
|
||||
$v[7] ^= $m[1];
|
||||
|
||||
# SIPROUND;
|
||||
# SIPROUND;
|
||||
$v = self::sipRound($v);
|
||||
$v = self::sipRound($v);
|
||||
|
||||
# v0 ^= m;
|
||||
$v[0] ^= $m[0];
|
||||
$v[1] ^= $m[1];
|
||||
|
||||
$in = self::substr($in, 8);
|
||||
$left -= 8;
|
||||
}
|
||||
|
||||
# switch( left )
|
||||
# {
|
||||
# case 7: b |= ( ( u64 )in[ 6] ) << 48;
|
||||
# case 6: b |= ( ( u64 )in[ 5] ) << 40;
|
||||
# case 5: b |= ( ( u64 )in[ 4] ) << 32;
|
||||
# case 4: b |= ( ( u64 )in[ 3] ) << 24;
|
||||
# case 3: b |= ( ( u64 )in[ 2] ) << 16;
|
||||
# case 2: b |= ( ( u64 )in[ 1] ) << 8;
|
||||
# case 1: b |= ( ( u64 )in[ 0] ); break;
|
||||
# case 0: break;
|
||||
# }
|
||||
switch ($left) {
|
||||
case 7:
|
||||
$b[0] |= self::chrToInt($in[6]) << 16;
|
||||
case 6:
|
||||
$b[0] |= self::chrToInt($in[5]) << 8;
|
||||
case 5:
|
||||
$b[0] |= self::chrToInt($in[4]);
|
||||
case 4:
|
||||
$b[1] |= self::chrToInt($in[3]) << 24;
|
||||
case 3:
|
||||
$b[1] |= self::chrToInt($in[2]) << 16;
|
||||
case 2:
|
||||
$b[1] |= self::chrToInt($in[1]) << 8;
|
||||
case 1:
|
||||
$b[1] |= self::chrToInt($in[0]);
|
||||
case 0:
|
||||
break;
|
||||
}
|
||||
// See docblock for why the 0th index gets the higher bits.
|
||||
|
||||
# v3 ^= b;
|
||||
$v[6] ^= $b[0];
|
||||
$v[7] ^= $b[1];
|
||||
|
||||
# SIPROUND;
|
||||
# SIPROUND;
|
||||
$v = self::sipRound($v);
|
||||
$v = self::sipRound($v);
|
||||
|
||||
# v0 ^= b;
|
||||
$v[0] ^= $b[0];
|
||||
$v[1] ^= $b[1];
|
||||
|
||||
// Flip the lower 8 bits of v2 which is ($v[4], $v[5]) in our implementation
|
||||
# v2 ^= 0xff;
|
||||
$v[5] ^= 0xff;
|
||||
|
||||
# SIPROUND;
|
||||
# SIPROUND;
|
||||
# SIPROUND;
|
||||
# SIPROUND;
|
||||
$v = self::sipRound($v);
|
||||
$v = self::sipRound($v);
|
||||
$v = self::sipRound($v);
|
||||
$v = self::sipRound($v);
|
||||
|
||||
# b = v0 ^ v1 ^ v2 ^ v3;
|
||||
# STORE64_LE( out, b );
|
||||
return self::store32_le($v[1] ^ $v[3] ^ $v[5] ^ $v[7]) .
|
||||
self::store32_le($v[0] ^ $v[2] ^ $v[4] ^ $v[6]);
|
||||
}
|
||||
}
|
||||
@@ -1,948 +0,0 @@
|
||||
<?php
|
||||
// phpcs:ignoreFile -- compatibility library for PHP 5-7.1
|
||||
|
||||
if (class_exists('ParagonIE_Sodium_Core_Util', false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class ParagonIE_Sodium_Core_Util
|
||||
*/
|
||||
abstract class ParagonIE_Sodium_Core_Util
|
||||
{
|
||||
/**
|
||||
* @param int $integer
|
||||
* @param int $size (16, 32, 64)
|
||||
* @return int
|
||||
*/
|
||||
public static function abs($integer, $size = 0)
|
||||
{
|
||||
/** @var int $realSize */
|
||||
$realSize = (PHP_INT_SIZE << 3) - 1;
|
||||
if ($size) {
|
||||
--$size;
|
||||
} else {
|
||||
/** @var int $size */
|
||||
$size = $realSize;
|
||||
}
|
||||
|
||||
$negative = -(($integer >> $size) & 1);
|
||||
return (int) (
|
||||
($integer ^ $negative)
|
||||
+
|
||||
(($negative >> $realSize) & 1)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a binary string into a hexadecimal string without cache-timing
|
||||
* leaks
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param string $binaryString (raw binary)
|
||||
* @return string
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function bin2hex($binaryString)
|
||||
{
|
||||
/* Type checks: */
|
||||
if (!is_string($binaryString)) {
|
||||
throw new TypeError('Argument 1 must be a string, ' . gettype($binaryString) . ' given.');
|
||||
}
|
||||
|
||||
$hex = '';
|
||||
$len = self::strlen($binaryString);
|
||||
for ($i = 0; $i < $len; ++$i) {
|
||||
/** @var array<int, int> $chunk */
|
||||
$chunk = unpack('C', $binaryString[$i]);
|
||||
/** @var int $c */
|
||||
$c = $chunk[1] & 0xf;
|
||||
/** @var int $b */
|
||||
$b = $chunk[1] >> 4;
|
||||
$hex .= pack(
|
||||
'CC',
|
||||
(87 + $b + ((($b - 10) >> 8) & ~38)),
|
||||
(87 + $c + ((($c - 10) >> 8) & ~38))
|
||||
);
|
||||
}
|
||||
return $hex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a binary string into a hexadecimal string without cache-timing
|
||||
* leaks, returning uppercase letters (as per RFC 4648)
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param string $bin_string (raw binary)
|
||||
* @return string
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function bin2hexUpper($bin_string)
|
||||
{
|
||||
$hex = '';
|
||||
$len = self::strlen($bin_string);
|
||||
for ($i = 0; $i < $len; ++$i) {
|
||||
/** @var array<int, int> $chunk */
|
||||
$chunk = unpack('C', $bin_string[$i]);
|
||||
/**
|
||||
* Lower 16 bits
|
||||
*
|
||||
* @var int $c
|
||||
*/
|
||||
$c = $chunk[1] & 0xf;
|
||||
|
||||
/**
|
||||
* Upper 16 bits
|
||||
* @var int $b
|
||||
*/
|
||||
$b = $chunk[1] >> 4;
|
||||
|
||||
/**
|
||||
* Use pack() and binary operators to turn the two integers
|
||||
* into hexadecimal characters. We don't use chr() here, because
|
||||
* it uses a lookup table internally and we want to avoid
|
||||
* cache-timing side-channels.
|
||||
*/
|
||||
$hex .= pack(
|
||||
'CC',
|
||||
(55 + $b + ((($b - 10) >> 8) & ~6)),
|
||||
(55 + $c + ((($c - 10) >> 8) & ~6))
|
||||
);
|
||||
}
|
||||
return $hex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cache-timing-safe variant of ord()
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param string $chr
|
||||
* @return int
|
||||
* @throws SodiumException
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function chrToInt($chr)
|
||||
{
|
||||
/* Type checks: */
|
||||
if (!is_string($chr)) {
|
||||
throw new TypeError('Argument 1 must be a string, ' . gettype($chr) . ' given.');
|
||||
}
|
||||
if (self::strlen($chr) !== 1) {
|
||||
throw new SodiumException('chrToInt() expects a string that is exactly 1 character long');
|
||||
}
|
||||
/** @var array<int, int> $chunk */
|
||||
$chunk = unpack('C', $chr);
|
||||
return (int) ($chunk[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two strings.
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param string $left
|
||||
* @param string $right
|
||||
* @param int $len
|
||||
* @return int
|
||||
* @throws SodiumException
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function compare($left, $right, $len = null)
|
||||
{
|
||||
$leftLen = self::strlen($left);
|
||||
$rightLen = self::strlen($right);
|
||||
if ($len === null) {
|
||||
$len = max($leftLen, $rightLen);
|
||||
$left = str_pad($left, $len, "\x00", STR_PAD_RIGHT);
|
||||
$right = str_pad($right, $len, "\x00", STR_PAD_RIGHT);
|
||||
}
|
||||
|
||||
$gt = 0;
|
||||
$eq = 1;
|
||||
$i = $len;
|
||||
while ($i !== 0) {
|
||||
--$i;
|
||||
$gt |= ((self::chrToInt($right[$i]) - self::chrToInt($left[$i])) >> 8) & $eq;
|
||||
$eq &= ((self::chrToInt($right[$i]) ^ self::chrToInt($left[$i])) - 1) >> 8;
|
||||
}
|
||||
return ($gt + $gt + $eq) - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* If a variable does not match a given type, throw a TypeError.
|
||||
*
|
||||
* @param mixed $mixedVar
|
||||
* @param string $type
|
||||
* @param int $argumentIndex
|
||||
* @throws TypeError
|
||||
* @throws SodiumException
|
||||
* @return void
|
||||
*/
|
||||
public static function declareScalarType(&$mixedVar = null, $type = 'void', $argumentIndex = 0)
|
||||
{
|
||||
if (func_num_args() === 0) {
|
||||
/* Tautology, by default */
|
||||
return;
|
||||
}
|
||||
if (func_num_args() === 1) {
|
||||
throw new TypeError('Declared void, but passed a variable');
|
||||
}
|
||||
$realType = strtolower(gettype($mixedVar));
|
||||
$type = strtolower($type);
|
||||
switch ($type) {
|
||||
case 'null':
|
||||
if ($mixedVar !== null) {
|
||||
throw new TypeError('Argument ' . $argumentIndex . ' must be null, ' . $realType . ' given.');
|
||||
}
|
||||
break;
|
||||
case 'integer':
|
||||
case 'int':
|
||||
$allow = array('int', 'integer');
|
||||
if (!in_array($type, $allow)) {
|
||||
throw new TypeError('Argument ' . $argumentIndex . ' must be an integer, ' . $realType . ' given.');
|
||||
}
|
||||
$mixedVar = (int) $mixedVar;
|
||||
break;
|
||||
case 'boolean':
|
||||
case 'bool':
|
||||
$allow = array('bool', 'boolean');
|
||||
if (!in_array($type, $allow)) {
|
||||
throw new TypeError('Argument ' . $argumentIndex . ' must be a boolean, ' . $realType . ' given.');
|
||||
}
|
||||
$mixedVar = (bool) $mixedVar;
|
||||
break;
|
||||
case 'string':
|
||||
if (!is_string($mixedVar)) {
|
||||
throw new TypeError('Argument ' . $argumentIndex . ' must be a string, ' . $realType . ' given.');
|
||||
}
|
||||
$mixedVar = (string) $mixedVar;
|
||||
break;
|
||||
case 'decimal':
|
||||
case 'double':
|
||||
case 'float':
|
||||
$allow = array('decimal', 'double', 'float');
|
||||
if (!in_array($type, $allow)) {
|
||||
throw new TypeError('Argument ' . $argumentIndex . ' must be a float, ' . $realType . ' given.');
|
||||
}
|
||||
$mixedVar = (float) $mixedVar;
|
||||
break;
|
||||
case 'object':
|
||||
if (!is_object($mixedVar)) {
|
||||
throw new TypeError('Argument ' . $argumentIndex . ' must be an object, ' . $realType . ' given.');
|
||||
}
|
||||
break;
|
||||
case 'array':
|
||||
if (!is_array($mixedVar)) {
|
||||
if (is_object($mixedVar)) {
|
||||
if ($mixedVar instanceof ArrayAccess) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new TypeError('Argument ' . $argumentIndex . ' must be an array, ' . $realType . ' given.');
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new SodiumException('Unknown type (' . $realType .') does not match expect type (' . $type . ')');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate whether or not two strings are equal (in constant-time)
|
||||
*
|
||||
* @param string $left
|
||||
* @param string $right
|
||||
* @return bool
|
||||
* @throws SodiumException
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function hashEquals($left, $right)
|
||||
{
|
||||
/* Type checks: */
|
||||
if (!is_string($left)) {
|
||||
throw new TypeError('Argument 1 must be a string, ' . gettype($left) . ' given.');
|
||||
}
|
||||
if (!is_string($right)) {
|
||||
throw new TypeError('Argument 2 must be a string, ' . gettype($right) . ' given.');
|
||||
}
|
||||
|
||||
if (is_callable('hash_equals')) {
|
||||
return hash_equals($left, $right);
|
||||
}
|
||||
$d = 0;
|
||||
/** @var int $len */
|
||||
$len = self::strlen($left);
|
||||
if ($len !== self::strlen($right)) {
|
||||
return false;
|
||||
}
|
||||
for ($i = 0; $i < $len; ++$i) {
|
||||
$d |= self::chrToInt($left[$i]) ^ self::chrToInt($right[$i]);
|
||||
}
|
||||
|
||||
if ($d !== 0) {
|
||||
return false;
|
||||
}
|
||||
return $left === $right;
|
||||
}
|
||||
|
||||
/**
|
||||
* Catch hash_update() failures and throw instead of silently proceeding
|
||||
*
|
||||
* @param HashContext|resource &$hs
|
||||
* @param string $data
|
||||
* @return void
|
||||
* @throws SodiumException
|
||||
* @psalm-suppress PossiblyInvalidArgument
|
||||
*/
|
||||
protected static function hash_update(&$hs, $data)
|
||||
{
|
||||
if (!hash_update($hs, $data)) {
|
||||
throw new SodiumException('hash_update() failed');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a hexadecimal string into a binary string without cache-timing
|
||||
* leaks
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param string $hexString
|
||||
* @param string $ignore
|
||||
* @param bool $strictPadding
|
||||
* @return string (raw binary)
|
||||
* @throws RangeException
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function hex2bin($hexString, $ignore = '', $strictPadding = false)
|
||||
{
|
||||
/* Type checks: */
|
||||
if (!is_string($hexString)) {
|
||||
throw new TypeError('Argument 1 must be a string, ' . gettype($hexString) . ' given.');
|
||||
}
|
||||
if (!is_string($ignore)) {
|
||||
throw new TypeError('Argument 2 must be a string, ' . gettype($hexString) . ' given.');
|
||||
}
|
||||
|
||||
$hex_pos = 0;
|
||||
$bin = '';
|
||||
$c_acc = 0;
|
||||
$hex_len = self::strlen($hexString);
|
||||
$state = 0;
|
||||
if (($hex_len & 1) !== 0) {
|
||||
if ($strictPadding) {
|
||||
throw new RangeException(
|
||||
'Expected an even number of hexadecimal characters'
|
||||
);
|
||||
} else {
|
||||
$hexString = '0' . $hexString;
|
||||
++$hex_len;
|
||||
}
|
||||
}
|
||||
|
||||
$chunk = unpack('C*', $hexString);
|
||||
while ($hex_pos < $hex_len) {
|
||||
++$hex_pos;
|
||||
/** @var int $c */
|
||||
$c = $chunk[$hex_pos];
|
||||
$c_num = $c ^ 48;
|
||||
$c_num0 = ($c_num - 10) >> 8;
|
||||
$c_alpha = ($c & ~32) - 55;
|
||||
$c_alpha0 = (($c_alpha - 10) ^ ($c_alpha - 16)) >> 8;
|
||||
if (($c_num0 | $c_alpha0) === 0) {
|
||||
if ($ignore && $state === 0 && strpos($ignore, self::intToChr($c)) !== false) {
|
||||
continue;
|
||||
}
|
||||
throw new RangeException(
|
||||
'hex2bin() only expects hexadecimal characters'
|
||||
);
|
||||
}
|
||||
$c_val = ($c_num0 & $c_num) | ($c_alpha & $c_alpha0);
|
||||
if ($state === 0) {
|
||||
$c_acc = $c_val * 16;
|
||||
} else {
|
||||
$bin .= pack('C', $c_acc | $c_val);
|
||||
}
|
||||
$state ^= 1;
|
||||
}
|
||||
return $bin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn an array of integers into a string
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param array<int, int> $ints
|
||||
* @return string
|
||||
*/
|
||||
public static function intArrayToString(array $ints)
|
||||
{
|
||||
$args = $ints;
|
||||
foreach ($args as $i => $v) {
|
||||
$args[$i] = (int) ($v & 0xff);
|
||||
}
|
||||
array_unshift($args, str_repeat('C', count($ints)));
|
||||
return (string) (call_user_func_array('pack', $args));
|
||||
}
|
||||
|
||||
/**
|
||||
* Cache-timing-safe variant of ord()
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param int $int
|
||||
* @return string
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function intToChr($int)
|
||||
{
|
||||
return pack('C', $int);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a 3 character substring into an integer
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param string $string
|
||||
* @return int
|
||||
* @throws RangeException
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function load_3($string)
|
||||
{
|
||||
/* Type checks: */
|
||||
if (!is_string($string)) {
|
||||
throw new TypeError('Argument 1 must be a string, ' . gettype($string) . ' given.');
|
||||
}
|
||||
|
||||
/* Input validation: */
|
||||
if (self::strlen($string) < 3) {
|
||||
throw new RangeException(
|
||||
'String must be 3 bytes or more; ' . self::strlen($string) . ' given.'
|
||||
);
|
||||
}
|
||||
/** @var array<int, int> $unpacked */
|
||||
$unpacked = unpack('V', $string . "\0");
|
||||
return (int) ($unpacked[1] & 0xffffff);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a 4 character substring into an integer
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param string $string
|
||||
* @return int
|
||||
* @throws RangeException
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function load_4($string)
|
||||
{
|
||||
/* Type checks: */
|
||||
if (!is_string($string)) {
|
||||
throw new TypeError('Argument 1 must be a string, ' . gettype($string) . ' given.');
|
||||
}
|
||||
|
||||
/* Input validation: */
|
||||
if (self::strlen($string) < 4) {
|
||||
throw new RangeException(
|
||||
'String must be 4 bytes or more; ' . self::strlen($string) . ' given.'
|
||||
);
|
||||
}
|
||||
/** @var array<int, int> $unpacked */
|
||||
$unpacked = unpack('V', $string);
|
||||
return (int) $unpacked[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a 8 character substring into an integer
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param string $string
|
||||
* @return int
|
||||
* @throws RangeException
|
||||
* @throws SodiumException
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function load64_le($string)
|
||||
{
|
||||
/* Type checks: */
|
||||
if (!is_string($string)) {
|
||||
throw new TypeError('Argument 1 must be a string, ' . gettype($string) . ' given.');
|
||||
}
|
||||
|
||||
/* Input validation: */
|
||||
if (self::strlen($string) < 4) {
|
||||
throw new RangeException(
|
||||
'String must be 4 bytes or more; ' . self::strlen($string) . ' given.'
|
||||
);
|
||||
}
|
||||
if (PHP_VERSION_ID >= 50603 && PHP_INT_SIZE === 8) {
|
||||
/** @var array<int, int> $unpacked */
|
||||
$unpacked = unpack('P', $string);
|
||||
return (int) $unpacked[1];
|
||||
}
|
||||
|
||||
/** @var int $result */
|
||||
$result = (self::chrToInt($string[0]) & 0xff);
|
||||
$result |= (self::chrToInt($string[1]) & 0xff) << 8;
|
||||
$result |= (self::chrToInt($string[2]) & 0xff) << 16;
|
||||
$result |= (self::chrToInt($string[3]) & 0xff) << 24;
|
||||
$result |= (self::chrToInt($string[4]) & 0xff) << 32;
|
||||
$result |= (self::chrToInt($string[5]) & 0xff) << 40;
|
||||
$result |= (self::chrToInt($string[6]) & 0xff) << 48;
|
||||
$result |= (self::chrToInt($string[7]) & 0xff) << 56;
|
||||
return (int) $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param string $left
|
||||
* @param string $right
|
||||
* @return int
|
||||
* @throws SodiumException
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function memcmp($left, $right)
|
||||
{
|
||||
if (self::hashEquals($left, $right)) {
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiply two integers in constant-time
|
||||
*
|
||||
* Micro-architecture timing side-channels caused by how your CPU
|
||||
* implements multiplication are best prevented by never using the
|
||||
* multiplication operators and ensuring that our code always takes
|
||||
* the same number of operations to complete, regardless of the values
|
||||
* of $a and $b.
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param int $a
|
||||
* @param int $b
|
||||
* @param int $size Limits the number of operations (useful for small,
|
||||
* constant operands)
|
||||
* @return int
|
||||
*/
|
||||
public static function mul($a, $b, $size = 0)
|
||||
{
|
||||
if (ParagonIE_Sodium_Compat::$fastMult) {
|
||||
return (int) ($a * $b);
|
||||
}
|
||||
|
||||
static $defaultSize = null;
|
||||
/** @var int $defaultSize */
|
||||
if (!$defaultSize) {
|
||||
/** @var int $defaultSize */
|
||||
$defaultSize = (PHP_INT_SIZE << 3) - 1;
|
||||
}
|
||||
if ($size < 1) {
|
||||
/** @var int $size */
|
||||
$size = $defaultSize;
|
||||
}
|
||||
/** @var int $size */
|
||||
|
||||
$c = 0;
|
||||
|
||||
/**
|
||||
* Mask is either -1 or 0.
|
||||
*
|
||||
* -1 in binary looks like 0x1111 ... 1111
|
||||
* 0 in binary looks like 0x0000 ... 0000
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
$mask = -(($b >> ((int) $defaultSize)) & 1);
|
||||
|
||||
/**
|
||||
* Ensure $b is a positive integer, without creating
|
||||
* a branching side-channel
|
||||
*
|
||||
* @var int $b
|
||||
*/
|
||||
$b = ($b & ~$mask) | ($mask & -$b);
|
||||
|
||||
/**
|
||||
* Unless $size is provided:
|
||||
*
|
||||
* This loop always runs 32 times when PHP_INT_SIZE is 4.
|
||||
* This loop always runs 64 times when PHP_INT_SIZE is 8.
|
||||
*/
|
||||
for ($i = $size; $i >= 0; --$i) {
|
||||
$c += (int) ($a & -($b & 1));
|
||||
$a <<= 1;
|
||||
$b >>= 1;
|
||||
}
|
||||
$c = (int) @($c & -1);
|
||||
|
||||
/**
|
||||
* If $b was negative, we then apply the same value to $c here.
|
||||
* It doesn't matter much if $a was negative; the $c += above would
|
||||
* have produced a negative integer to begin with. But a negative $b
|
||||
* makes $b >>= 1 never return 0, so we would end up with incorrect
|
||||
* results.
|
||||
*
|
||||
* The end result is what we'd expect from integer multiplication.
|
||||
*/
|
||||
return (int) (($c & ~$mask) | ($mask & -$c));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert any arbitrary numbers into two 32-bit integers that represent
|
||||
* a 64-bit integer.
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param int|float $num
|
||||
* @return array<int, int>
|
||||
*/
|
||||
public static function numericTo64BitInteger($num)
|
||||
{
|
||||
$high = 0;
|
||||
/** @var int $low */
|
||||
if (PHP_INT_SIZE === 4) {
|
||||
$low = (int) $num;
|
||||
} else {
|
||||
$low = $num & 0xffffffff;
|
||||
}
|
||||
|
||||
if ((+(abs($num))) >= 1) {
|
||||
if ($num > 0) {
|
||||
/** @var int $high */
|
||||
$high = min((+(floor($num/4294967296))), 4294967295);
|
||||
} else {
|
||||
/** @var int $high */
|
||||
$high = ~~((+(ceil(($num - (+((~~($num)))))/4294967296))));
|
||||
}
|
||||
}
|
||||
return array((int) $high, (int) $low);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a 24-bit integer into a string, treating it as big-endian.
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param int $int
|
||||
* @return string
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function store_3($int)
|
||||
{
|
||||
/* Type checks: */
|
||||
if (!is_int($int)) {
|
||||
if (is_numeric($int)) {
|
||||
$int = (int) $int;
|
||||
} else {
|
||||
throw new TypeError('Argument 1 must be an integer, ' . gettype($int) . ' given.');
|
||||
}
|
||||
}
|
||||
/** @var string $packed */
|
||||
$packed = pack('N', $int);
|
||||
return self::substr($packed, 1, 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a 32-bit integer into a string, treating it as little-endian.
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param int $int
|
||||
* @return string
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function store32_le($int)
|
||||
{
|
||||
/* Type checks: */
|
||||
if (!is_int($int)) {
|
||||
if (is_numeric($int)) {
|
||||
$int = (int) $int;
|
||||
} else {
|
||||
throw new TypeError('Argument 1 must be an integer, ' . gettype($int) . ' given.');
|
||||
}
|
||||
}
|
||||
|
||||
/** @var string $packed */
|
||||
$packed = pack('V', $int);
|
||||
return $packed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a 32-bit integer into a string, treating it as big-endian.
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param int $int
|
||||
* @return string
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function store_4($int)
|
||||
{
|
||||
/* Type checks: */
|
||||
if (!is_int($int)) {
|
||||
if (is_numeric($int)) {
|
||||
$int = (int) $int;
|
||||
} else {
|
||||
throw new TypeError('Argument 1 must be an integer, ' . gettype($int) . ' given.');
|
||||
}
|
||||
}
|
||||
|
||||
/** @var string $packed */
|
||||
$packed = pack('N', $int);
|
||||
return $packed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a 64-bit integer as an string, treating it as little-endian.
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param int $int
|
||||
* @return string
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function store64_le($int)
|
||||
{
|
||||
/* Type checks: */
|
||||
if (!is_int($int)) {
|
||||
if (is_numeric($int)) {
|
||||
$int = (int) $int;
|
||||
} else {
|
||||
throw new TypeError('Argument 1 must be an integer, ' . gettype($int) . ' given.');
|
||||
}
|
||||
}
|
||||
|
||||
if (PHP_INT_SIZE === 8) {
|
||||
if (PHP_VERSION_ID >= 50603) {
|
||||
/** @var string $packed */
|
||||
$packed = pack('P', $int);
|
||||
return $packed;
|
||||
}
|
||||
return self::intToChr($int & 0xff) .
|
||||
self::intToChr(($int >> 8) & 0xff) .
|
||||
self::intToChr(($int >> 16) & 0xff) .
|
||||
self::intToChr(($int >> 24) & 0xff) .
|
||||
self::intToChr(($int >> 32) & 0xff) .
|
||||
self::intToChr(($int >> 40) & 0xff) .
|
||||
self::intToChr(($int >> 48) & 0xff) .
|
||||
self::intToChr(($int >> 56) & 0xff);
|
||||
}
|
||||
if ($int > PHP_INT_MAX) {
|
||||
list($hiB, $int) = self::numericTo64BitInteger($int);
|
||||
} else {
|
||||
$hiB = 0;
|
||||
}
|
||||
return
|
||||
self::intToChr(($int ) & 0xff) .
|
||||
self::intToChr(($int >> 8) & 0xff) .
|
||||
self::intToChr(($int >> 16) & 0xff) .
|
||||
self::intToChr(($int >> 24) & 0xff) .
|
||||
self::intToChr($hiB & 0xff) .
|
||||
self::intToChr(($hiB >> 8) & 0xff) .
|
||||
self::intToChr(($hiB >> 16) & 0xff) .
|
||||
self::intToChr(($hiB >> 24) & 0xff);
|
||||
}
|
||||
|
||||
/**
|
||||
* Safe string length
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @ref mbstring.func_overload
|
||||
*
|
||||
* @param string $str
|
||||
* @return int
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function strlen($str)
|
||||
{
|
||||
/* Type checks: */
|
||||
if (!is_string($str)) {
|
||||
throw new TypeError('String expected');
|
||||
}
|
||||
|
||||
return (int) (
|
||||
self::isMbStringOverride()
|
||||
? mb_strlen($str, '8bit')
|
||||
: strlen($str)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn a string into an array of integers
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param string $string
|
||||
* @return array<int, int>
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function stringToIntArray($string)
|
||||
{
|
||||
if (!is_string($string)) {
|
||||
throw new TypeError('String expected');
|
||||
}
|
||||
/**
|
||||
* @var array<int, int>
|
||||
*/
|
||||
$values = array_values(
|
||||
unpack('C*', $string)
|
||||
);
|
||||
return $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Safe substring
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @ref mbstring.func_overload
|
||||
*
|
||||
* @param string $str
|
||||
* @param int $start
|
||||
* @param int $length
|
||||
* @return string
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function substr($str, $start = 0, $length = null)
|
||||
{
|
||||
/* Type checks: */
|
||||
if (!is_string($str)) {
|
||||
throw new TypeError('String expected');
|
||||
}
|
||||
|
||||
if ($length === 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (self::isMbStringOverride()) {
|
||||
if (PHP_VERSION_ID < 50400 && $length === null) {
|
||||
$length = self::strlen($str);
|
||||
}
|
||||
$sub = (string) mb_substr($str, $start, $length, '8bit');
|
||||
} elseif ($length === null) {
|
||||
$sub = (string) substr($str, $start);
|
||||
} else {
|
||||
$sub = (string) substr($str, $start, $length);
|
||||
}
|
||||
if ($sub !== '') {
|
||||
return $sub;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare a 16-character byte string in constant time.
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param string $a
|
||||
* @param string $b
|
||||
* @return bool
|
||||
* @throws SodiumException
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function verify_16($a, $b)
|
||||
{
|
||||
/* Type checks: */
|
||||
if (!is_string($a)) {
|
||||
throw new TypeError('String expected');
|
||||
}
|
||||
if (!is_string($b)) {
|
||||
throw new TypeError('String expected');
|
||||
}
|
||||
return self::hashEquals(
|
||||
self::substr($a, 0, 16),
|
||||
self::substr($b, 0, 16)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare a 32-character byte string in constant time.
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param string $a
|
||||
* @param string $b
|
||||
* @return bool
|
||||
* @throws SodiumException
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function verify_32($a, $b)
|
||||
{
|
||||
/* Type checks: */
|
||||
if (!is_string($a)) {
|
||||
throw new TypeError('String expected');
|
||||
}
|
||||
if (!is_string($b)) {
|
||||
throw new TypeError('String expected');
|
||||
}
|
||||
return self::hashEquals(
|
||||
self::substr($a, 0, 32),
|
||||
self::substr($b, 0, 32)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate $a ^ $b for two strings.
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* @param string $a
|
||||
* @param string $b
|
||||
* @return string
|
||||
* @throws TypeError
|
||||
*/
|
||||
public static function xorStrings($a, $b)
|
||||
{
|
||||
/* Type checks: */
|
||||
if (!is_string($a)) {
|
||||
throw new TypeError('Argument 1 must be a string');
|
||||
}
|
||||
if (!is_string($b)) {
|
||||
throw new TypeError('Argument 2 must be a string');
|
||||
}
|
||||
|
||||
return (string) ($a ^ $b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not mbstring.func_overload is in effect.
|
||||
*
|
||||
* @internal You should not use this directly from another application
|
||||
*
|
||||
* Note: MB_OVERLOAD_STRING === 2, but we don't reference the constant
|
||||
* (for nuisance-free PHP 8 support)
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected static function isMbStringOverride()
|
||||
{
|
||||
static $mbstring = null;
|
||||
|
||||
if ($mbstring === null) {
|
||||
if (!defined('MB_OVERLOAD_STRING')) {
|
||||
$mbstring = false;
|
||||
return $mbstring;
|
||||
}
|
||||
$mbstring = extension_loaded('mbstring')
|
||||
&& defined('MB_OVERLOAD_STRING')
|
||||
&&
|
||||
((int) (ini_get('mbstring.func_overload')) & 2);
|
||||
// MB_OVERLOAD_STRING === 2
|
||||
}
|
||||
/** @var bool $mbstring */
|
||||
|
||||
return $mbstring;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user