first commit
This commit is contained in:
23
composer.json
Normal file
23
composer.json
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"name": "claudecio/axiumes",
|
||||||
|
"description": "Framework PHP para geração, assinatura e validação de XMLs do eSocial",
|
||||||
|
"type": "library",
|
||||||
|
"require": {
|
||||||
|
"php": "^8.1",
|
||||||
|
"ext-dom": "*",
|
||||||
|
"robrichards/xmlseclibs": "^3.1.3"
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"AxiumES\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Claudecio",
|
||||||
|
"email": "contato@claudecio.is-a.dev"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"minimum-stability": "stable",
|
||||||
|
"license": "MIT"
|
||||||
|
}
|
||||||
64
composer.lock
generated
Normal file
64
composer.lock
generated
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
{
|
||||||
|
"_readme": [
|
||||||
|
"This file locks the dependencies of your project to a known state",
|
||||||
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
|
"This file is @generated automatically"
|
||||||
|
],
|
||||||
|
"content-hash": "c89e950e55c22c7df6a2121757156126",
|
||||||
|
"packages": [
|
||||||
|
{
|
||||||
|
"name": "robrichards/xmlseclibs",
|
||||||
|
"version": "3.1.3",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/robrichards/xmlseclibs.git",
|
||||||
|
"reference": "2bdfd742624d739dfadbd415f00181b4a77aaf07"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/robrichards/xmlseclibs/zipball/2bdfd742624d739dfadbd415f00181b4a77aaf07",
|
||||||
|
"reference": "2bdfd742624d739dfadbd415f00181b4a77aaf07",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-openssl": "*",
|
||||||
|
"php": ">= 5.4"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"RobRichards\\XMLSecLibs\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"BSD-3-Clause"
|
||||||
|
],
|
||||||
|
"description": "A PHP library for XML Security",
|
||||||
|
"homepage": "https://github.com/robrichards/xmlseclibs",
|
||||||
|
"keywords": [
|
||||||
|
"security",
|
||||||
|
"signature",
|
||||||
|
"xml",
|
||||||
|
"xmldsig"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/robrichards/xmlseclibs/issues",
|
||||||
|
"source": "https://github.com/robrichards/xmlseclibs/tree/3.1.3"
|
||||||
|
},
|
||||||
|
"time": "2024-11-20T21:13:56+00:00"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"packages-dev": [],
|
||||||
|
"aliases": [],
|
||||||
|
"minimum-stability": "stable",
|
||||||
|
"stability-flags": {},
|
||||||
|
"prefer-stable": false,
|
||||||
|
"prefer-lowest": false,
|
||||||
|
"platform": {
|
||||||
|
"php": "^8.1",
|
||||||
|
"ext-dom": "*"
|
||||||
|
},
|
||||||
|
"platform-dev": {},
|
||||||
|
"plugin-api-version": "2.6.0"
|
||||||
|
}
|
||||||
22
vendor/autoload.php
vendored
Normal file
22
vendor/autoload.php
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload.php @generated by Composer
|
||||||
|
|
||||||
|
if (PHP_VERSION_ID < 50600) {
|
||||||
|
if (!headers_sent()) {
|
||||||
|
header('HTTP/1.1 500 Internal Server Error');
|
||||||
|
}
|
||||||
|
$err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
|
||||||
|
if (!ini_get('display_errors')) {
|
||||||
|
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
|
||||||
|
fwrite(STDERR, $err);
|
||||||
|
} elseif (!headers_sent()) {
|
||||||
|
echo $err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new RuntimeException($err);
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once __DIR__ . '/composer/autoload_real.php';
|
||||||
|
|
||||||
|
return ComposerAutoloaderInitc89e950e55c22c7df6a2121757156126::getLoader();
|
||||||
579
vendor/composer/ClassLoader.php
vendored
Normal file
579
vendor/composer/ClassLoader.php
vendored
Normal file
@@ -0,0 +1,579 @@
|
|||||||
|
<?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
|
||||||
|
{
|
||||||
|
/** @var \Closure(string):void */
|
||||||
|
private static $includeFile;
|
||||||
|
|
||||||
|
/** @var string|null */
|
||||||
|
private $vendorDir;
|
||||||
|
|
||||||
|
// PSR-4
|
||||||
|
/**
|
||||||
|
* @var array<string, array<string, int>>
|
||||||
|
*/
|
||||||
|
private $prefixLengthsPsr4 = array();
|
||||||
|
/**
|
||||||
|
* @var array<string, list<string>>
|
||||||
|
*/
|
||||||
|
private $prefixDirsPsr4 = array();
|
||||||
|
/**
|
||||||
|
* @var list<string>
|
||||||
|
*/
|
||||||
|
private $fallbackDirsPsr4 = array();
|
||||||
|
|
||||||
|
// PSR-0
|
||||||
|
/**
|
||||||
|
* List of PSR-0 prefixes
|
||||||
|
*
|
||||||
|
* Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2')))
|
||||||
|
*
|
||||||
|
* @var array<string, array<string, list<string>>>
|
||||||
|
*/
|
||||||
|
private $prefixesPsr0 = array();
|
||||||
|
/**
|
||||||
|
* @var list<string>
|
||||||
|
*/
|
||||||
|
private $fallbackDirsPsr0 = array();
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
private $useIncludePath = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array<string, string>
|
||||||
|
*/
|
||||||
|
private $classMap = array();
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
private $classMapAuthoritative = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array<string, bool>
|
||||||
|
*/
|
||||||
|
private $missingClasses = array();
|
||||||
|
|
||||||
|
/** @var string|null */
|
||||||
|
private $apcuPrefix;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array<string, self>
|
||||||
|
*/
|
||||||
|
private static $registeredLoaders = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string|null $vendorDir
|
||||||
|
*/
|
||||||
|
public function __construct($vendorDir = null)
|
||||||
|
{
|
||||||
|
$this->vendorDir = $vendorDir;
|
||||||
|
self::initializeIncludeClosure();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, list<string>>
|
||||||
|
*/
|
||||||
|
public function getPrefixes()
|
||||||
|
{
|
||||||
|
if (!empty($this->prefixesPsr0)) {
|
||||||
|
return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
|
||||||
|
}
|
||||||
|
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, list<string>>
|
||||||
|
*/
|
||||||
|
public function getPrefixesPsr4()
|
||||||
|
{
|
||||||
|
return $this->prefixDirsPsr4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return list<string>
|
||||||
|
*/
|
||||||
|
public function getFallbackDirs()
|
||||||
|
{
|
||||||
|
return $this->fallbackDirsPsr0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return list<string>
|
||||||
|
*/
|
||||||
|
public function getFallbackDirsPsr4()
|
||||||
|
{
|
||||||
|
return $this->fallbackDirsPsr4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, string> Array of classname => path
|
||||||
|
*/
|
||||||
|
public function getClassMap()
|
||||||
|
{
|
||||||
|
return $this->classMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<string, string> $classMap Class to filename map
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
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 list<string>|string $paths The PSR-0 root directories
|
||||||
|
* @param bool $prepend Whether to prepend the directories
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function add($prefix, $paths, $prepend = false)
|
||||||
|
{
|
||||||
|
$paths = (array) $paths;
|
||||||
|
if (!$prefix) {
|
||||||
|
if ($prepend) {
|
||||||
|
$this->fallbackDirsPsr0 = array_merge(
|
||||||
|
$paths,
|
||||||
|
$this->fallbackDirsPsr0
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$this->fallbackDirsPsr0 = array_merge(
|
||||||
|
$this->fallbackDirsPsr0,
|
||||||
|
$paths
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$first = $prefix[0];
|
||||||
|
if (!isset($this->prefixesPsr0[$first][$prefix])) {
|
||||||
|
$this->prefixesPsr0[$first][$prefix] = $paths;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ($prepend) {
|
||||||
|
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||||
|
$paths,
|
||||||
|
$this->prefixesPsr0[$first][$prefix]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||||
|
$this->prefixesPsr0[$first][$prefix],
|
||||||
|
$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 list<string>|string $paths The PSR-4 base directories
|
||||||
|
* @param bool $prepend Whether to prepend the directories
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function addPsr4($prefix, $paths, $prepend = false)
|
||||||
|
{
|
||||||
|
$paths = (array) $paths;
|
||||||
|
if (!$prefix) {
|
||||||
|
// Register directories for the root namespace.
|
||||||
|
if ($prepend) {
|
||||||
|
$this->fallbackDirsPsr4 = array_merge(
|
||||||
|
$paths,
|
||||||
|
$this->fallbackDirsPsr4
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$this->fallbackDirsPsr4 = array_merge(
|
||||||
|
$this->fallbackDirsPsr4,
|
||||||
|
$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] = $paths;
|
||||||
|
} elseif ($prepend) {
|
||||||
|
// Prepend directories for an already registered namespace.
|
||||||
|
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||||
|
$paths,
|
||||||
|
$this->prefixDirsPsr4[$prefix]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Append directories for an already registered namespace.
|
||||||
|
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||||
|
$this->prefixDirsPsr4[$prefix],
|
||||||
|
$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 list<string>|string $paths The PSR-0 base directories
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
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 list<string>|string $paths The PSR-4 base directories
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
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.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
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 = self::$includeFile;
|
||||||
|
$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 keyed by their corresponding vendor directories.
|
||||||
|
*
|
||||||
|
* @return array<string, self>
|
||||||
|
*/
|
||||||
|
public static function getRegisteredLoaders()
|
||||||
|
{
|
||||||
|
return self::$registeredLoaders;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $class
|
||||||
|
* @param string $ext
|
||||||
|
* @return string|false
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private static function initializeIncludeClosure()
|
||||||
|
{
|
||||||
|
if (self::$includeFile !== null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scope isolated include.
|
||||||
|
*
|
||||||
|
* Prevents access to $this/self from included files.
|
||||||
|
*
|
||||||
|
* @param string $file
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
self::$includeFile = \Closure::bind(static function($file) {
|
||||||
|
include $file;
|
||||||
|
}, null, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
380
vendor/composer/InstalledVersions.php
vendored
Normal file
380
vendor/composer/InstalledVersions.php
vendored
Normal file
@@ -0,0 +1,380 @@
|
|||||||
|
<?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 its presence, you can require `composer-runtime-api ^2.0`
|
||||||
|
*
|
||||||
|
* @final
|
||||||
|
*/
|
||||||
|
class InstalledVersions
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string|null if set (by reflection by Composer), this should be set to the path where this class is being copied to
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
private static $selfDir = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var mixed[]|null
|
||||||
|
* @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
|
||||||
|
*/
|
||||||
|
private static $installed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool|null
|
||||||
|
*/
|
||||||
|
private static $canGetVendors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array[]
|
||||||
|
* @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||||
|
*/
|
||||||
|
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 || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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((string) $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, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
|
||||||
|
*/
|
||||||
|
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, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: 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, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: 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, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data
|
||||||
|
*/
|
||||||
|
public static function reload($data)
|
||||||
|
{
|
||||||
|
self::$installed = $data;
|
||||||
|
self::$installedByVendor = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private static function getSelfDir()
|
||||||
|
{
|
||||||
|
if (self::$selfDir === null) {
|
||||||
|
self::$selfDir = strtr(__DIR__, '\\', '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$selfDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array[]
|
||||||
|
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||||
|
*/
|
||||||
|
private static function getInstalled()
|
||||||
|
{
|
||||||
|
if (null === self::$canGetVendors) {
|
||||||
|
self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
|
||||||
|
}
|
||||||
|
|
||||||
|
$installed = array();
|
||||||
|
$copiedLocalDir = false;
|
||||||
|
|
||||||
|
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')) {
|
||||||
|
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
|
||||||
|
$required = require $vendorDir.'/composer/installed.php';
|
||||||
|
self::$installedByVendor[$vendorDir] = $required;
|
||||||
|
$installed[] = $required;
|
||||||
|
if (strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
|
||||||
|
self::$installed = $required;
|
||||||
|
$copiedLocalDir = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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') {
|
||||||
|
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
|
||||||
|
$required = require __DIR__ . '/installed.php';
|
||||||
|
self::$installed = $required;
|
||||||
|
} else {
|
||||||
|
self::$installed = array();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self::$installed !== array() && !$copiedLocalDir) {
|
||||||
|
$installed[] = self::$installed;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $installed;
|
||||||
|
}
|
||||||
|
}
|
||||||
19
vendor/composer/LICENSE
vendored
Normal file
19
vendor/composer/LICENSE
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
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.
|
||||||
10
vendor/composer/autoload_classmap.php
vendored
Normal file
10
vendor/composer/autoload_classmap.php
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_classmap.php @generated by Composer
|
||||||
|
|
||||||
|
$vendorDir = dirname(__DIR__);
|
||||||
|
$baseDir = dirname($vendorDir);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
|
||||||
|
);
|
||||||
9
vendor/composer/autoload_namespaces.php
vendored
Normal file
9
vendor/composer/autoload_namespaces.php
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_namespaces.php @generated by Composer
|
||||||
|
|
||||||
|
$vendorDir = dirname(__DIR__);
|
||||||
|
$baseDir = dirname($vendorDir);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
);
|
||||||
11
vendor/composer/autoload_psr4.php
vendored
Normal file
11
vendor/composer/autoload_psr4.php
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_psr4.php @generated by Composer
|
||||||
|
|
||||||
|
$vendorDir = dirname(__DIR__);
|
||||||
|
$baseDir = dirname($vendorDir);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'RobRichards\\XMLSecLibs\\' => array($vendorDir . '/robrichards/xmlseclibs/src'),
|
||||||
|
'AxiumES\\' => array($baseDir . '/src'),
|
||||||
|
);
|
||||||
38
vendor/composer/autoload_real.php
vendored
Normal file
38
vendor/composer/autoload_real.php
vendored
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_real.php @generated by Composer
|
||||||
|
|
||||||
|
class ComposerAutoloaderInitc89e950e55c22c7df6a2121757156126
|
||||||
|
{
|
||||||
|
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('ComposerAutoloaderInitc89e950e55c22c7df6a2121757156126', 'loadClassLoader'), true, true);
|
||||||
|
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
|
||||||
|
spl_autoload_unregister(array('ComposerAutoloaderInitc89e950e55c22c7df6a2121757156126', 'loadClassLoader'));
|
||||||
|
|
||||||
|
require __DIR__ . '/autoload_static.php';
|
||||||
|
call_user_func(\Composer\Autoload\ComposerStaticInitc89e950e55c22c7df6a2121757156126::getInitializer($loader));
|
||||||
|
|
||||||
|
$loader->register(true);
|
||||||
|
|
||||||
|
return $loader;
|
||||||
|
}
|
||||||
|
}
|
||||||
44
vendor/composer/autoload_static.php
vendored
Normal file
44
vendor/composer/autoload_static.php
vendored
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_static.php @generated by Composer
|
||||||
|
|
||||||
|
namespace Composer\Autoload;
|
||||||
|
|
||||||
|
class ComposerStaticInitc89e950e55c22c7df6a2121757156126
|
||||||
|
{
|
||||||
|
public static $prefixLengthsPsr4 = array (
|
||||||
|
'R' =>
|
||||||
|
array (
|
||||||
|
'RobRichards\\XMLSecLibs\\' => 23,
|
||||||
|
),
|
||||||
|
'A' =>
|
||||||
|
array (
|
||||||
|
'AxiumES\\' => 8,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
public static $prefixDirsPsr4 = array (
|
||||||
|
'RobRichards\\XMLSecLibs\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/robrichards/xmlseclibs/src',
|
||||||
|
),
|
||||||
|
'AxiumES\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/../..' . '/src',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
public static $classMap = array (
|
||||||
|
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
|
||||||
|
);
|
||||||
|
|
||||||
|
public static function getInitializer(ClassLoader $loader)
|
||||||
|
{
|
||||||
|
return \Closure::bind(function () use ($loader) {
|
||||||
|
$loader->prefixLengthsPsr4 = ComposerStaticInitc89e950e55c22c7df6a2121757156126::$prefixLengthsPsr4;
|
||||||
|
$loader->prefixDirsPsr4 = ComposerStaticInitc89e950e55c22c7df6a2121757156126::$prefixDirsPsr4;
|
||||||
|
$loader->classMap = ComposerStaticInitc89e950e55c22c7df6a2121757156126::$classMap;
|
||||||
|
|
||||||
|
}, null, ClassLoader::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
51
vendor/composer/installed.json
vendored
Normal file
51
vendor/composer/installed.json
vendored
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
{
|
||||||
|
"packages": [
|
||||||
|
{
|
||||||
|
"name": "robrichards/xmlseclibs",
|
||||||
|
"version": "3.1.3",
|
||||||
|
"version_normalized": "3.1.3.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/robrichards/xmlseclibs.git",
|
||||||
|
"reference": "2bdfd742624d739dfadbd415f00181b4a77aaf07"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/robrichards/xmlseclibs/zipball/2bdfd742624d739dfadbd415f00181b4a77aaf07",
|
||||||
|
"reference": "2bdfd742624d739dfadbd415f00181b4a77aaf07",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-openssl": "*",
|
||||||
|
"php": ">= 5.4"
|
||||||
|
},
|
||||||
|
"time": "2024-11-20T21:13:56+00:00",
|
||||||
|
"type": "library",
|
||||||
|
"installation-source": "dist",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"RobRichards\\XMLSecLibs\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"BSD-3-Clause"
|
||||||
|
],
|
||||||
|
"description": "A PHP library for XML Security",
|
||||||
|
"homepage": "https://github.com/robrichards/xmlseclibs",
|
||||||
|
"keywords": [
|
||||||
|
"security",
|
||||||
|
"signature",
|
||||||
|
"xml",
|
||||||
|
"xmldsig"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/robrichards/xmlseclibs/issues",
|
||||||
|
"source": "https://github.com/robrichards/xmlseclibs/tree/3.1.3"
|
||||||
|
},
|
||||||
|
"install-path": "../robrichards/xmlseclibs"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"dev-package-names": []
|
||||||
|
}
|
||||||
32
vendor/composer/installed.php
vendored
Normal file
32
vendor/composer/installed.php
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<?php return array(
|
||||||
|
'root' => array(
|
||||||
|
'name' => 'claudecio/axiumes',
|
||||||
|
'pretty_version' => '1.0.0+no-version-set',
|
||||||
|
'version' => '1.0.0.0',
|
||||||
|
'reference' => null,
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../../',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev' => true,
|
||||||
|
),
|
||||||
|
'versions' => array(
|
||||||
|
'claudecio/axiumes' => array(
|
||||||
|
'pretty_version' => '1.0.0+no-version-set',
|
||||||
|
'version' => '1.0.0.0',
|
||||||
|
'reference' => null,
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../../',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'robrichards/xmlseclibs' => array(
|
||||||
|
'pretty_version' => '3.1.3',
|
||||||
|
'version' => '3.1.3.0',
|
||||||
|
'reference' => '2bdfd742624d739dfadbd415f00181b4a77aaf07',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../robrichards/xmlseclibs',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
26
vendor/composer/platform_check.php
vendored
Normal file
26
vendor/composer/platform_check.php
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// platform_check.php @generated by Composer
|
||||||
|
|
||||||
|
$issues = array();
|
||||||
|
|
||||||
|
if (!(PHP_VERSION_ID >= 80100)) {
|
||||||
|
$issues[] = 'Your Composer dependencies require a PHP version ">= 8.1.0". 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
|
||||||
|
);
|
||||||
|
}
|
||||||
112
vendor/robrichards/xmlseclibs/.github/workflows/ci.yml
vendored
Normal file
112
vendor/robrichards/xmlseclibs/.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
name: Tests
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
tests-legacy:
|
||||||
|
name: PHP ${{ matrix.php-versions }} Tests
|
||||||
|
runs-on: ${{ matrix.operating-system }}
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
operating-system: ['ubuntu-latest']
|
||||||
|
php-versions: ['5.4', '5.5', '5.6']
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: shivammathur/setup-php@v2
|
||||||
|
with:
|
||||||
|
php-version: ${{ matrix.php-versions }}
|
||||||
|
extensions: openssl
|
||||||
|
tools: phpunit:4.8
|
||||||
|
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: phpunit --coverage-clover clover.xml tests
|
||||||
|
|
||||||
|
- uses: codecov/codecov-action@v2
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.CODECOV_TOKEN }}
|
||||||
|
files: ./clover.xml
|
||||||
|
|
||||||
|
tests-older:
|
||||||
|
name: PHP ${{ matrix.php-versions }} Tests
|
||||||
|
runs-on: ${{ matrix.operating-system }}
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
operating-system: ['ubuntu-latest']
|
||||||
|
php-versions: ['7.0', '7.1']
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: shivammathur/setup-php@v2
|
||||||
|
with:
|
||||||
|
php-version: ${{ matrix.php-versions }}
|
||||||
|
extensions: openssl
|
||||||
|
tools: phpunit:6.5
|
||||||
|
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: phpunit --coverage-clover clover.xml tests
|
||||||
|
|
||||||
|
- uses: codecov/codecov-action@v2
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.CODECOV_TOKEN }}
|
||||||
|
files: ./clover.xml
|
||||||
|
|
||||||
|
tests-old:
|
||||||
|
name: PHP ${{ matrix.php-versions }} Tests
|
||||||
|
runs-on: ${{ matrix.operating-system }}
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
operating-system: ['ubuntu-latest']
|
||||||
|
php-versions: ['7.2', '7.3', '7.4']
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: shivammathur/setup-php@v2
|
||||||
|
with:
|
||||||
|
php-version: ${{ matrix.php-versions }}
|
||||||
|
extensions: openssl
|
||||||
|
tools: phpunit:8.5
|
||||||
|
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: phpunit --coverage-clover clover.xml tests
|
||||||
|
|
||||||
|
- uses: codecov/codecov-action@v2
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.CODECOV_TOKEN }}
|
||||||
|
files: ./clover.xml
|
||||||
|
|
||||||
|
tests:
|
||||||
|
name: PHP ${{ matrix.php-versions }} Tests
|
||||||
|
runs-on: ${{ matrix.operating-system }}
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
operating-system: ['ubuntu-latest']
|
||||||
|
php-versions: ['8.0', '8.1']
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: shivammathur/setup-php@v2
|
||||||
|
with:
|
||||||
|
php-version: ${{ matrix.php-versions }}
|
||||||
|
extensions: openssl
|
||||||
|
tools: phpunit/phpunit:9.5
|
||||||
|
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: phpunit --coverage-clover clover.xml tests
|
||||||
|
|
||||||
|
- uses: codecov/codecov-action@v2
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.CODECOV_TOKEN }}
|
||||||
|
files: ./clover.xml
|
||||||
238
vendor/robrichards/xmlseclibs/CHANGELOG.txt
vendored
Normal file
238
vendor/robrichards/xmlseclibs/CHANGELOG.txt
vendored
Normal file
@@ -0,0 +1,238 @@
|
|||||||
|
xmlseclibs.php
|
||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||
|
20, Nov 2024, 3.1.3
|
||||||
|
Bug Fixes:
|
||||||
|
- remove loadKey check due to BC issues
|
||||||
|
|
||||||
|
20, Nov 2024, 3.1.2
|
||||||
|
Improvements:
|
||||||
|
- Add tab to list of whitespace values to remove from cert. refs #252
|
||||||
|
- loadKey should check return value for openssl_get_privatekey (sammarshallou)
|
||||||
|
- Switch to GitHub actions (SharkMachine)
|
||||||
|
|
||||||
|
05, Sep 2020, 3.1.1
|
||||||
|
Features:
|
||||||
|
- Support OAEP (iggyvolz)
|
||||||
|
|
||||||
|
Bug Fixes:
|
||||||
|
- Fix AES128 (iggyvolz)
|
||||||
|
|
||||||
|
Improvements:
|
||||||
|
- Fix tests for older PHP
|
||||||
|
|
||||||
|
22, Apr 2020, 3.1.0
|
||||||
|
Features:
|
||||||
|
- Support AES-GCM. Requires PHP 7.1. (François Kooman)
|
||||||
|
|
||||||
|
Improvements:
|
||||||
|
- Fix Travis tests for older PHP versions.
|
||||||
|
- Use DOMElement interface to fix some IDEs reporting documentation errors
|
||||||
|
|
||||||
|
Bug Fixes:
|
||||||
|
- FIX missing InclusiveNamespaces PrefixList from Java + Apache WSS4J. (njake)
|
||||||
|
|
||||||
|
06, Nov 2019, 3.0.4
|
||||||
|
Security Improvements:
|
||||||
|
- Insure only a single SignedInfo element exists within a signature during
|
||||||
|
verification. Refs CVE-2019-3465.
|
||||||
|
Bug Fixes:
|
||||||
|
- Fix variable casing.
|
||||||
|
|
||||||
|
15, Nov 2018, 3.0.3
|
||||||
|
Bug Fixes:
|
||||||
|
- Fix casing of class name. (Willem Stuursma-Ruwen)
|
||||||
|
- Fix Xpath casing. (Tim van Dijen)
|
||||||
|
|
||||||
|
Improvements:
|
||||||
|
- Make PCRE2 compliant. (Stefan Winter)
|
||||||
|
- Add PHP 7.3 support. (Stefan Winter)
|
||||||
|
|
||||||
|
27, Sep 2018, 3.0.2
|
||||||
|
Security Improvements:
|
||||||
|
- OpenSSL is now a requirement rather than suggestion. (Slaven Bacelic)
|
||||||
|
- Filter input to avoid XPath injection. (Jaime Pérez)
|
||||||
|
|
||||||
|
Bug Fixes:
|
||||||
|
- Fix missing parentheses (Tim van Dijen)
|
||||||
|
|
||||||
|
Improvements:
|
||||||
|
- Use strict comparison operator to compare digest values. (Jaime Pérez)
|
||||||
|
- Remove call to file_get_contents that doesn't even work. (Jaime Pérez)
|
||||||
|
- Document potentially dangerous return value behaviour. (Thijs Kinkhorst)
|
||||||
|
|
||||||
|
31, Aug 2017, 3.0.1
|
||||||
|
Bug Fixes:
|
||||||
|
- Fixed missing () in function call. (Dennis Væversted)
|
||||||
|
|
||||||
|
Improvements:
|
||||||
|
- Add OneLogin to supported software.
|
||||||
|
- Add .gitattributes to remove unneeded files. (Filippo Tessarotto)
|
||||||
|
- Fix bug in example code. (Dan Church)
|
||||||
|
- Travis: add PHP 7.1, move hhvm to allowed failures. (Thijs Kinkhorst)
|
||||||
|
- Drop failing extract-win-cert test (Thijs Kinkhorst). (Thijs Kinkhorst)
|
||||||
|
- Add comments to warn about return values of verify(). (Thijs Kinkhorst)
|
||||||
|
- Fix tests to properly check return code of verify(). (Thijs Kinkhorst)
|
||||||
|
- Restore support for PHP >= 5.4. (Jaime Pérez)
|
||||||
|
|
||||||
|
25, May 2017, 3.0.0
|
||||||
|
Improvements:
|
||||||
|
- Remove use of mcrypt (skymeyer)
|
||||||
|
|
||||||
|
08, Sep 2016, 2.0.1
|
||||||
|
Bug Fixes:
|
||||||
|
- Strip whitespace characters when parsing X509Certificate. fixes #84
|
||||||
|
(klemen.bratec)
|
||||||
|
- Certificate 'subject' values can be arrays. fixes #80 (Andreas Stangl)
|
||||||
|
- HHVM signing node with ID attribute w/out namespace regenerates ID value.
|
||||||
|
fixes #88 (Milos Tomic)
|
||||||
|
|
||||||
|
Improvements:
|
||||||
|
- Fix typos and add some PHPDoc Blocks. (gfaust-qb)
|
||||||
|
- Update lightSAML link. (Milos Tomic)
|
||||||
|
- Update copyright dates.
|
||||||
|
|
||||||
|
31, Jul 2015, 2.0.0
|
||||||
|
Features:
|
||||||
|
- Namespace support. Classes now in the RobRichards\XMLSecLibs\ namespace.
|
||||||
|
|
||||||
|
Improvements:
|
||||||
|
- Dropped support for PHP 5.2
|
||||||
|
|
||||||
|
31, Jul 2015, 1.4.1
|
||||||
|
Bug Fixes:
|
||||||
|
- Allow for large digest values that may have line breaks. fixes #62
|
||||||
|
|
||||||
|
Features:
|
||||||
|
- Support for locating specific signature when multiple exist in
|
||||||
|
document. (griga3k)
|
||||||
|
|
||||||
|
Improvements:
|
||||||
|
- Add optional argument to XMLSecurityDSig to define the prefix to be used,
|
||||||
|
also allowing for null to use no prefix, for the dsig namespace. fixes #13
|
||||||
|
- Code cleanup
|
||||||
|
- Depreciated XMLSecurityDSig::generate_GUID for XMLSecurityDSig::generateGUID
|
||||||
|
|
||||||
|
23, Jun 2015, 1.4.0
|
||||||
|
Features:
|
||||||
|
- Support for PSR-0 standard.
|
||||||
|
- Support for X509SubjectName. (Milos Tomic)
|
||||||
|
- Add HMAC-SHA1 support.
|
||||||
|
|
||||||
|
Improvements:
|
||||||
|
- Add how to install to README. (Bernardo Vieira da Silva)
|
||||||
|
- Code cleanup. (Jaime Pérez)
|
||||||
|
- Normalilze tests. (Hidde Wieringa)
|
||||||
|
- Add basic usage to README. (Hidde Wieringa)
|
||||||
|
|
||||||
|
21, May 2015, 1.3.2
|
||||||
|
Bug Fixes:
|
||||||
|
- Fix Undefined variable notice. (dpieper85)
|
||||||
|
- Fix typo when setting MimeType attribute. (Eugene OZ)
|
||||||
|
- Fix validateReference() with enveloping signatures
|
||||||
|
|
||||||
|
Features:
|
||||||
|
- canonicalizeData performance optimization. (Jaime Pérez)
|
||||||
|
- Add composer support (Maks3w)
|
||||||
|
|
||||||
|
19, Jun 2013, 1.3.1
|
||||||
|
Features:
|
||||||
|
- return encrypted node from XMLSecEnc::encryptNode() when replace is set to
|
||||||
|
false. (Olav)
|
||||||
|
- Add support for RSA SHA384 and RSA_SHA512 and SHA384 digest. (Jaime Prez)
|
||||||
|
- Add options parameter to the add cert methods.
|
||||||
|
- Add optional issuerSerial creation with cert
|
||||||
|
|
||||||
|
Bug Fixes:
|
||||||
|
- Fix persisted Id when namespaced. (Koen Thomeer)
|
||||||
|
|
||||||
|
Improvements:
|
||||||
|
- Add LICENSE file
|
||||||
|
- Convert CHANGELOG.txt to UTF-8
|
||||||
|
|
||||||
|
26, Sep 2011, 1.3.0
|
||||||
|
Features:
|
||||||
|
- Add param to append sig to node when signing. Fixes a problem when using
|
||||||
|
inclusive canonicalization to append a signature within a namespaced subtree.
|
||||||
|
ex. $objDSig->sign($objKey, $appendToNode);
|
||||||
|
- Add ability to encrypt by reference
|
||||||
|
- Add support for refences within an encrypted key
|
||||||
|
- Add thumbprint generation capability (XMLSecurityKey->getX509Thumbprint() and
|
||||||
|
XMLSecurityKey::getRawThumbprint($cert))
|
||||||
|
- Return signature element node from XMLSecurityDSig::insertSignature() and
|
||||||
|
XMLSecurityDSig::appendSignature() methods
|
||||||
|
- Support for <ds:RetrievalMethod> with simple URI Id reference.
|
||||||
|
- Add XMLSecurityKey::getSymmetricKeySize() method (Olav)
|
||||||
|
- Add XMLSecEnc::getCipherValue() method (Olav)
|
||||||
|
- Improve XMLSecurityKey:generateSessionKey() logic (Olav)
|
||||||
|
|
||||||
|
Bug Fixes:
|
||||||
|
- Change split() to explode() as split is now depreciated
|
||||||
|
- ds:References using empty or simple URI Id reference should never include
|
||||||
|
comments in canonicalized data.
|
||||||
|
- Make sure that the elements in EncryptedData are emitted in the correct
|
||||||
|
sequence.
|
||||||
|
|
||||||
|
11 Jan 2010, 1.2.2
|
||||||
|
Features:
|
||||||
|
- Add support XPath support when creating signature. Provides support for
|
||||||
|
working with EBXML documents.
|
||||||
|
- Add reference option to force creation of URI attribute. For use
|
||||||
|
when adding a DOM Document where by default no URI attribute is added.
|
||||||
|
- Add support for RSA-SHA256
|
||||||
|
|
||||||
|
Bug Fixes:
|
||||||
|
- fix bug #5: createDOMDocumentFragment() in decryptNode when data is node
|
||||||
|
content (patch by Francois Wang)
|
||||||
|
|
||||||
|
|
||||||
|
08 Jul 2008, 1.2.1
|
||||||
|
Features:
|
||||||
|
- Attempt to use mhash when hash extension is not present. (Alfredo Cubitos).
|
||||||
|
- Add fallback to built-in sha1 if both hash and mhash are not available and
|
||||||
|
throw error for other for other missing hashes. (patch by Olav Morken).
|
||||||
|
- Add getX509Certificate method to retrieve the x509 cert used for Key.
|
||||||
|
(patch by Olav Morken).
|
||||||
|
- Add getValidatedNodes method to retrieve the elements signed by the
|
||||||
|
signature. (patch by Olav Morken).
|
||||||
|
- Add insertSignature method for precision signature insertion. Merge
|
||||||
|
functionality from appendSignature in the process. (Olav Morken, Rob).
|
||||||
|
- Finally add some tests
|
||||||
|
|
||||||
|
Bug Fixes:
|
||||||
|
- Fix canonicalization for Document node when using PHP < 5.2.
|
||||||
|
- Add padding for RSA_SHA1. (patch by Olav Morken).
|
||||||
|
|
||||||
|
|
||||||
|
27 Nov 2007, 1.2.0
|
||||||
|
Features:
|
||||||
|
- New addReference/List option (overwrite). Boolean flag indicating if URI
|
||||||
|
value should be overwritten if already existing within document.
|
||||||
|
Default is TRUE to maintain BC.
|
||||||
|
|
||||||
|
18 Nov 2007, 1.1.2
|
||||||
|
Bug Fixes:
|
||||||
|
- Remove closing PHP tag to fix extra whitespace characters from being output
|
||||||
|
|
||||||
|
11 Nov 2007, 1.1.1
|
||||||
|
Features:
|
||||||
|
- Add getRefNodeID() and getRefIDs() methods missed in previous release.
|
||||||
|
Provide functionality to find URIs of existing reference nodes.
|
||||||
|
Required by simpleSAMLphp project
|
||||||
|
|
||||||
|
Bug Fixes:
|
||||||
|
- Remove erroneous whitespace causing issues under certain circumastances.
|
||||||
|
|
||||||
|
18 Oct 2007, 1.1.0
|
||||||
|
Features:
|
||||||
|
- Enable creation of enveloping signature. This allows the creation of
|
||||||
|
managed information cards.
|
||||||
|
- Add addObject method for enveloping signatures.
|
||||||
|
- Add staticGet509XCerts method. Chained certificates within a PEM file can
|
||||||
|
now be added within the X509Data node.
|
||||||
|
- Add xpath support within transformations
|
||||||
|
- Add InclusiveNamespaces prefix list support within exclusive transformations.
|
||||||
|
|
||||||
|
Bug Fixes:
|
||||||
|
- Initialize random number generator for mcrypt_create_iv. (Joan Cornadó).
|
||||||
|
- Fix an interoperability issue with .NET when encrypting data in CBC mode.
|
||||||
|
(Joan Cornadó).
|
||||||
31
vendor/robrichards/xmlseclibs/LICENSE
vendored
Normal file
31
vendor/robrichards/xmlseclibs/LICENSE
vendored
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
Copyright (c) 2007-2024, Robert Richards <rrichards@cdatazone.org>.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in
|
||||||
|
the documentation and/or other materials provided with the
|
||||||
|
distribution.
|
||||||
|
|
||||||
|
* Neither the name of Robert Richards nor the names of his
|
||||||
|
contributors may be used to endorse or promote products derived
|
||||||
|
from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
85
vendor/robrichards/xmlseclibs/README.md
vendored
Normal file
85
vendor/robrichards/xmlseclibs/README.md
vendored
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
#xmlseclibs
|
||||||
|
|
||||||
|
xmlseclibs is a library written in PHP for working with XML Encryption and Signatures.
|
||||||
|
|
||||||
|
The author of xmlseclibs is Rob Richards.
|
||||||
|
|
||||||
|
# Branches
|
||||||
|
Master is currently the only actively maintained branch.
|
||||||
|
* master/3.1: Added AES-GCM support requiring 7.1+
|
||||||
|
* 3.0: Removes mcrypt usage requiring 5.4+ (5.6.24+ recommended for security reasons)
|
||||||
|
* 2.0: Contains namespace support requiring 5.3+
|
||||||
|
* 1.4: Contains auto-loader support while also maintaining backwards compatiblity with the older 1.3 version using the xmlseclibs.php file. Supports PHP 5.2+
|
||||||
|
|
||||||
|
# Requirements
|
||||||
|
|
||||||
|
xmlseclibs requires PHP version 5.4 or greater. **5.6.24+ recommended for security reasons**
|
||||||
|
|
||||||
|
|
||||||
|
## How to Install
|
||||||
|
|
||||||
|
Install with [`composer.phar`](http://getcomposer.org).
|
||||||
|
|
||||||
|
```sh
|
||||||
|
php composer.phar require "robrichards/xmlseclibs"
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Use cases
|
||||||
|
|
||||||
|
xmlseclibs is being used in many different software.
|
||||||
|
|
||||||
|
* [SimpleSAMLPHP](https://github.com/simplesamlphp/simplesamlphp)
|
||||||
|
* [LightSAML](https://github.com/lightsaml/lightsaml)
|
||||||
|
* [OneLogin](https://github.com/onelogin/php-saml)
|
||||||
|
|
||||||
|
## Basic usage
|
||||||
|
|
||||||
|
The example below shows basic usage of xmlseclibs, with a SHA-256 signature.
|
||||||
|
|
||||||
|
```php
|
||||||
|
use RobRichards\XMLSecLibs\XMLSecurityDSig;
|
||||||
|
use RobRichards\XMLSecLibs\XMLSecurityKey;
|
||||||
|
|
||||||
|
// Load the XML to be signed
|
||||||
|
$doc = new DOMDocument();
|
||||||
|
$doc->load('./path/to/file/tobesigned.xml');
|
||||||
|
|
||||||
|
// Create a new Security object
|
||||||
|
$objDSig = new XMLSecurityDSig();
|
||||||
|
// Use the c14n exclusive canonicalization
|
||||||
|
$objDSig->setCanonicalMethod(XMLSecurityDSig::EXC_C14N);
|
||||||
|
// Sign using SHA-256
|
||||||
|
$objDSig->addReference(
|
||||||
|
$doc,
|
||||||
|
XMLSecurityDSig::SHA256,
|
||||||
|
array('http://www.w3.org/2000/09/xmldsig#enveloped-signature')
|
||||||
|
);
|
||||||
|
|
||||||
|
// Create a new (private) Security key
|
||||||
|
$objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA256, array('type'=>'private'));
|
||||||
|
/*
|
||||||
|
If key has a passphrase, set it using
|
||||||
|
$objKey->passphrase = '<passphrase>';
|
||||||
|
*/
|
||||||
|
// Load the private key
|
||||||
|
$objKey->loadKey('./path/to/privatekey.pem', TRUE);
|
||||||
|
|
||||||
|
// Sign the XML file
|
||||||
|
$objDSig->sign($objKey);
|
||||||
|
|
||||||
|
// Add the associated public key to the signature
|
||||||
|
$objDSig->add509Cert(file_get_contents('./path/to/file/mycert.pem'));
|
||||||
|
|
||||||
|
// Append the signature to the XML
|
||||||
|
$objDSig->appendSignature($doc->documentElement);
|
||||||
|
// Save the signed XML
|
||||||
|
$doc->save('./path/to/signed.xml');
|
||||||
|
```
|
||||||
|
|
||||||
|
## How to Contribute
|
||||||
|
|
||||||
|
* [Open Issues](https://github.com/robrichards/xmlseclibs/issues)
|
||||||
|
* [Open Pull Requests](https://github.com/robrichards/xmlseclibs/pulls)
|
||||||
|
|
||||||
|
Mailing List: https://groups.google.com/forum/#!forum/xmlseclibs
|
||||||
21
vendor/robrichards/xmlseclibs/composer.json
vendored
Normal file
21
vendor/robrichards/xmlseclibs/composer.json
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"name": "robrichards/xmlseclibs",
|
||||||
|
"description": "A PHP library for XML Security",
|
||||||
|
"license": "BSD-3-Clause",
|
||||||
|
"keywords": [
|
||||||
|
"xml",
|
||||||
|
"xmldsig",
|
||||||
|
"signature",
|
||||||
|
"security"
|
||||||
|
],
|
||||||
|
"homepage": "https://github.com/robrichards/xmlseclibs",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"RobRichards\\XMLSecLibs\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">= 5.4",
|
||||||
|
"ext-openssl": "*"
|
||||||
|
}
|
||||||
|
}
|
||||||
7
vendor/robrichards/xmlseclibs/phpunit.xml
vendored
Normal file
7
vendor/robrichards/xmlseclibs/phpunit.xml
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/6.5/phpunit.xsd">
|
||||||
|
<filter>
|
||||||
|
<whitelist addUncoveredFilesFromWhitelist="false">
|
||||||
|
<directory suffix=".php">src</directory>
|
||||||
|
</whitelist>
|
||||||
|
</filter>
|
||||||
|
</phpunit>
|
||||||
44
vendor/robrichards/xmlseclibs/src/Utils/XPath.php
vendored
Normal file
44
vendor/robrichards/xmlseclibs/src/Utils/XPath.php
vendored
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace RobRichards\XMLSecLibs\Utils;
|
||||||
|
|
||||||
|
class XPath
|
||||||
|
{
|
||||||
|
const ALPHANUMERIC = '\w\d';
|
||||||
|
const NUMERIC = '\d';
|
||||||
|
const LETTERS = '\w';
|
||||||
|
const EXTENDED_ALPHANUMERIC = '\w\d\s\-_:\.';
|
||||||
|
|
||||||
|
const SINGLE_QUOTE = '\'';
|
||||||
|
const DOUBLE_QUOTE = '"';
|
||||||
|
const ALL_QUOTES = '[\'"]';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter an attribute value for save inclusion in an XPath query.
|
||||||
|
*
|
||||||
|
* @param string $value The value to filter.
|
||||||
|
* @param string $quotes The quotes used to delimit the value in the XPath query.
|
||||||
|
*
|
||||||
|
* @return string The filtered attribute value.
|
||||||
|
*/
|
||||||
|
public static function filterAttrValue($value, $quotes = self::ALL_QUOTES)
|
||||||
|
{
|
||||||
|
return preg_replace('#'.$quotes.'#', '', $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter an attribute name for save inclusion in an XPath query.
|
||||||
|
*
|
||||||
|
* @param string $name The attribute name to filter.
|
||||||
|
* @param mixed $allow The set of characters to allow. Can be one of the constants provided by this class, or a
|
||||||
|
* custom regex excluding the '#' character (used as delimiter).
|
||||||
|
*
|
||||||
|
* @return string The filtered attribute name.
|
||||||
|
*/
|
||||||
|
public static function filterAttrName($name, $allow = self::EXTENDED_ALPHANUMERIC)
|
||||||
|
{
|
||||||
|
return preg_replace('#[^'.$allow.']#', '', $name);
|
||||||
|
}
|
||||||
|
}
|
||||||
511
vendor/robrichards/xmlseclibs/src/XMLSecEnc.php
vendored
Normal file
511
vendor/robrichards/xmlseclibs/src/XMLSecEnc.php
vendored
Normal file
@@ -0,0 +1,511 @@
|
|||||||
|
<?php
|
||||||
|
namespace RobRichards\XMLSecLibs;
|
||||||
|
|
||||||
|
use DOMDocument;
|
||||||
|
use DOMElement;
|
||||||
|
use DOMNode;
|
||||||
|
use DOMXPath;
|
||||||
|
use Exception;
|
||||||
|
use RobRichards\XMLSecLibs\Utils\XPath as XPath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlseclibs.php
|
||||||
|
*
|
||||||
|
* Copyright (c) 2007-2024, Robert Richards <rrichards@cdatazone.org>.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name of Robert Richards nor the names of his
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* @author Robert Richards <rrichards@cdatazone.org>
|
||||||
|
* @copyright 2007-2024 Robert Richards <rrichards@cdatazone.org>
|
||||||
|
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
|
||||||
|
*/
|
||||||
|
|
||||||
|
class XMLSecEnc
|
||||||
|
{
|
||||||
|
const template = "<xenc:EncryptedData xmlns:xenc='http://www.w3.org/2001/04/xmlenc#'>
|
||||||
|
<xenc:CipherData>
|
||||||
|
<xenc:CipherValue></xenc:CipherValue>
|
||||||
|
</xenc:CipherData>
|
||||||
|
</xenc:EncryptedData>";
|
||||||
|
|
||||||
|
const Element = 'http://www.w3.org/2001/04/xmlenc#Element';
|
||||||
|
const Content = 'http://www.w3.org/2001/04/xmlenc#Content';
|
||||||
|
const URI = 3;
|
||||||
|
const XMLENCNS = 'http://www.w3.org/2001/04/xmlenc#';
|
||||||
|
|
||||||
|
/** @var null|DOMDocument */
|
||||||
|
private $encdoc = null;
|
||||||
|
|
||||||
|
/** @var null|DOMNode */
|
||||||
|
private $rawNode = null;
|
||||||
|
|
||||||
|
/** @var null|string */
|
||||||
|
public $type = null;
|
||||||
|
|
||||||
|
/** @var null|DOMElement */
|
||||||
|
public $encKey = null;
|
||||||
|
|
||||||
|
/** @var array */
|
||||||
|
private $references = array();
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->_resetTemplate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function _resetTemplate()
|
||||||
|
{
|
||||||
|
$this->encdoc = new DOMDocument();
|
||||||
|
$this->encdoc->loadXML(self::template);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $name
|
||||||
|
* @param DOMNode $node
|
||||||
|
* @param string $type
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function addReference($name, $node, $type)
|
||||||
|
{
|
||||||
|
if (! $node instanceOf DOMNode) {
|
||||||
|
throw new Exception('$node is not of type DOMNode');
|
||||||
|
}
|
||||||
|
$curencdoc = $this->encdoc;
|
||||||
|
$this->_resetTemplate();
|
||||||
|
$encdoc = $this->encdoc;
|
||||||
|
$this->encdoc = $curencdoc;
|
||||||
|
$refuri = XMLSecurityDSig::generateGUID();
|
||||||
|
$element = $encdoc->documentElement;
|
||||||
|
$element->setAttribute("Id", $refuri);
|
||||||
|
$this->references[$name] = array("node" => $node, "type" => $type, "encnode" => $encdoc, "refuri" => $refuri);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param DOMNode $node
|
||||||
|
*/
|
||||||
|
public function setNode($node)
|
||||||
|
{
|
||||||
|
$this->rawNode = $node;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypt the selected node with the given key.
|
||||||
|
*
|
||||||
|
* @param XMLSecurityKey $objKey The encryption key and algorithm.
|
||||||
|
* @param bool $replace Whether the encrypted node should be replaced in the original tree. Default is true.
|
||||||
|
* @throws Exception
|
||||||
|
*
|
||||||
|
* @return DOMElement The <xenc:EncryptedData>-element.
|
||||||
|
*/
|
||||||
|
public function encryptNode($objKey, $replace = true)
|
||||||
|
{
|
||||||
|
$data = '';
|
||||||
|
if (empty($this->rawNode)) {
|
||||||
|
throw new Exception('Node to encrypt has not been set');
|
||||||
|
}
|
||||||
|
if (! $objKey instanceof XMLSecurityKey) {
|
||||||
|
throw new Exception('Invalid Key');
|
||||||
|
}
|
||||||
|
$doc = $this->rawNode->ownerDocument;
|
||||||
|
$xPath = new DOMXPath($this->encdoc);
|
||||||
|
$objList = $xPath->query('/xenc:EncryptedData/xenc:CipherData/xenc:CipherValue');
|
||||||
|
$cipherValue = $objList->item(0);
|
||||||
|
if ($cipherValue == null) {
|
||||||
|
throw new Exception('Error locating CipherValue element within template');
|
||||||
|
}
|
||||||
|
switch ($this->type) {
|
||||||
|
case (self::Element):
|
||||||
|
$data = $doc->saveXML($this->rawNode);
|
||||||
|
$this->encdoc->documentElement->setAttribute('Type', self::Element);
|
||||||
|
break;
|
||||||
|
case (self::Content):
|
||||||
|
$children = $this->rawNode->childNodes;
|
||||||
|
foreach ($children AS $child) {
|
||||||
|
$data .= $doc->saveXML($child);
|
||||||
|
}
|
||||||
|
$this->encdoc->documentElement->setAttribute('Type', self::Content);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Exception('Type is currently not supported');
|
||||||
|
}
|
||||||
|
|
||||||
|
$encMethod = $this->encdoc->documentElement->appendChild($this->encdoc->createElementNS(self::XMLENCNS, 'xenc:EncryptionMethod'));
|
||||||
|
$encMethod->setAttribute('Algorithm', $objKey->getAlgorithm());
|
||||||
|
$cipherValue->parentNode->parentNode->insertBefore($encMethod, $cipherValue->parentNode->parentNode->firstChild);
|
||||||
|
|
||||||
|
$strEncrypt = base64_encode($objKey->encryptData($data));
|
||||||
|
$value = $this->encdoc->createTextNode($strEncrypt);
|
||||||
|
$cipherValue->appendChild($value);
|
||||||
|
|
||||||
|
if ($replace) {
|
||||||
|
switch ($this->type) {
|
||||||
|
case (self::Element):
|
||||||
|
if ($this->rawNode->nodeType == XML_DOCUMENT_NODE) {
|
||||||
|
return $this->encdoc;
|
||||||
|
}
|
||||||
|
$importEnc = $this->rawNode->ownerDocument->importNode($this->encdoc->documentElement, true);
|
||||||
|
$this->rawNode->parentNode->replaceChild($importEnc, $this->rawNode);
|
||||||
|
return $importEnc;
|
||||||
|
case (self::Content):
|
||||||
|
$importEnc = $this->rawNode->ownerDocument->importNode($this->encdoc->documentElement, true);
|
||||||
|
while ($this->rawNode->firstChild) {
|
||||||
|
$this->rawNode->removeChild($this->rawNode->firstChild);
|
||||||
|
}
|
||||||
|
$this->rawNode->appendChild($importEnc);
|
||||||
|
return $importEnc;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return $this->encdoc->documentElement;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param XMLSecurityKey $objKey
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function encryptReferences($objKey)
|
||||||
|
{
|
||||||
|
$curRawNode = $this->rawNode;
|
||||||
|
$curType = $this->type;
|
||||||
|
foreach ($this->references AS $name => $reference) {
|
||||||
|
$this->encdoc = $reference["encnode"];
|
||||||
|
$this->rawNode = $reference["node"];
|
||||||
|
$this->type = $reference["type"];
|
||||||
|
try {
|
||||||
|
$encNode = $this->encryptNode($objKey);
|
||||||
|
$this->references[$name]["encnode"] = $encNode;
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$this->rawNode = $curRawNode;
|
||||||
|
$this->type = $curType;
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->rawNode = $curRawNode;
|
||||||
|
$this->type = $curType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the CipherValue text from this encrypted node.
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
* @return string|null The Ciphervalue text, or null if no CipherValue is found.
|
||||||
|
*/
|
||||||
|
public function getCipherValue()
|
||||||
|
{
|
||||||
|
if (empty($this->rawNode)) {
|
||||||
|
throw new Exception('Node to decrypt has not been set');
|
||||||
|
}
|
||||||
|
|
||||||
|
$doc = $this->rawNode->ownerDocument;
|
||||||
|
$xPath = new DOMXPath($doc);
|
||||||
|
$xPath->registerNamespace('xmlencr', self::XMLENCNS);
|
||||||
|
/* Only handles embedded content right now and not a reference */
|
||||||
|
$query = "./xmlencr:CipherData/xmlencr:CipherValue";
|
||||||
|
$nodeset = $xPath->query($query, $this->rawNode);
|
||||||
|
$node = $nodeset->item(0);
|
||||||
|
|
||||||
|
if (!$node) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return base64_decode($node->nodeValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decrypt this encrypted node.
|
||||||
|
*
|
||||||
|
* The behaviour of this function depends on the value of $replace.
|
||||||
|
* If $replace is false, we will return the decrypted data as a string.
|
||||||
|
* If $replace is true, we will insert the decrypted element(s) into the
|
||||||
|
* document, and return the decrypted element(s).
|
||||||
|
*
|
||||||
|
* @param XMLSecurityKey $objKey The decryption key that should be used when decrypting the node.
|
||||||
|
* @param boolean $replace Whether we should replace the encrypted node in the XML document with the decrypted data. The default is true.
|
||||||
|
*
|
||||||
|
* @return string|DOMElement The decrypted data.
|
||||||
|
*/
|
||||||
|
public function decryptNode($objKey, $replace=true)
|
||||||
|
{
|
||||||
|
if (! $objKey instanceof XMLSecurityKey) {
|
||||||
|
throw new Exception('Invalid Key');
|
||||||
|
}
|
||||||
|
|
||||||
|
$encryptedData = $this->getCipherValue();
|
||||||
|
if ($encryptedData) {
|
||||||
|
$decrypted = $objKey->decryptData($encryptedData);
|
||||||
|
if ($replace) {
|
||||||
|
switch ($this->type) {
|
||||||
|
case (self::Element):
|
||||||
|
$newdoc = new DOMDocument();
|
||||||
|
$newdoc->loadXML($decrypted);
|
||||||
|
if ($this->rawNode->nodeType == XML_DOCUMENT_NODE) {
|
||||||
|
return $newdoc;
|
||||||
|
}
|
||||||
|
$importEnc = $this->rawNode->ownerDocument->importNode($newdoc->documentElement, true);
|
||||||
|
$this->rawNode->parentNode->replaceChild($importEnc, $this->rawNode);
|
||||||
|
return $importEnc;
|
||||||
|
case (self::Content):
|
||||||
|
if ($this->rawNode->nodeType == XML_DOCUMENT_NODE) {
|
||||||
|
$doc = $this->rawNode;
|
||||||
|
} else {
|
||||||
|
$doc = $this->rawNode->ownerDocument;
|
||||||
|
}
|
||||||
|
$newFrag = $doc->createDocumentFragment();
|
||||||
|
$newFrag->appendXML($decrypted);
|
||||||
|
$parent = $this->rawNode->parentNode;
|
||||||
|
$parent->replaceChild($newFrag, $this->rawNode);
|
||||||
|
return $parent;
|
||||||
|
default:
|
||||||
|
return $decrypted;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return $decrypted;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Exception("Cannot locate encrypted data");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypt the XMLSecurityKey
|
||||||
|
*
|
||||||
|
* @param XMLSecurityKey $srcKey
|
||||||
|
* @param XMLSecurityKey $rawKey
|
||||||
|
* @param bool $append
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function encryptKey($srcKey, $rawKey, $append=true)
|
||||||
|
{
|
||||||
|
if ((! $srcKey instanceof XMLSecurityKey) || (! $rawKey instanceof XMLSecurityKey)) {
|
||||||
|
throw new Exception('Invalid Key');
|
||||||
|
}
|
||||||
|
$strEncKey = base64_encode($srcKey->encryptData($rawKey->key));
|
||||||
|
$root = $this->encdoc->documentElement;
|
||||||
|
$encKey = $this->encdoc->createElementNS(self::XMLENCNS, 'xenc:EncryptedKey');
|
||||||
|
if ($append) {
|
||||||
|
$keyInfo = $root->insertBefore($this->encdoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'dsig:KeyInfo'), $root->firstChild);
|
||||||
|
$keyInfo->appendChild($encKey);
|
||||||
|
} else {
|
||||||
|
$this->encKey = $encKey;
|
||||||
|
}
|
||||||
|
$encMethod = $encKey->appendChild($this->encdoc->createElementNS(self::XMLENCNS, 'xenc:EncryptionMethod'));
|
||||||
|
$encMethod->setAttribute('Algorithm', $srcKey->getAlgorith());
|
||||||
|
if (! empty($srcKey->name)) {
|
||||||
|
$keyInfo = $encKey->appendChild($this->encdoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'dsig:KeyInfo'));
|
||||||
|
$keyInfo->appendChild($this->encdoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'dsig:KeyName', $srcKey->name));
|
||||||
|
}
|
||||||
|
$cipherData = $encKey->appendChild($this->encdoc->createElementNS(self::XMLENCNS, 'xenc:CipherData'));
|
||||||
|
$cipherData->appendChild($this->encdoc->createElementNS(self::XMLENCNS, 'xenc:CipherValue', $strEncKey));
|
||||||
|
if (is_array($this->references) && count($this->references) > 0) {
|
||||||
|
$refList = $encKey->appendChild($this->encdoc->createElementNS(self::XMLENCNS, 'xenc:ReferenceList'));
|
||||||
|
foreach ($this->references AS $name => $reference) {
|
||||||
|
$refuri = $reference["refuri"];
|
||||||
|
$dataRef = $refList->appendChild($this->encdoc->createElementNS(self::XMLENCNS, 'xenc:DataReference'));
|
||||||
|
$dataRef->setAttribute("URI", '#' . $refuri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param XMLSecurityKey $encKey
|
||||||
|
* @return DOMElement|string
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function decryptKey($encKey)
|
||||||
|
{
|
||||||
|
if (! $encKey->isEncrypted) {
|
||||||
|
throw new Exception("Key is not Encrypted");
|
||||||
|
}
|
||||||
|
if (empty($encKey->key)) {
|
||||||
|
throw new Exception("Key is missing data to perform the decryption");
|
||||||
|
}
|
||||||
|
return $this->decryptNode($encKey, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param DOMDocument $element
|
||||||
|
* @return DOMNode|null
|
||||||
|
*/
|
||||||
|
public function locateEncryptedData($element)
|
||||||
|
{
|
||||||
|
if ($element instanceof DOMDocument) {
|
||||||
|
$doc = $element;
|
||||||
|
} else {
|
||||||
|
$doc = $element->ownerDocument;
|
||||||
|
}
|
||||||
|
if ($doc) {
|
||||||
|
$xpath = new DOMXPath($doc);
|
||||||
|
$query = "//*[local-name()='EncryptedData' and namespace-uri()='".self::XMLENCNS."']";
|
||||||
|
$nodeset = $xpath->query($query);
|
||||||
|
return $nodeset->item(0);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the key from the DOM
|
||||||
|
* @param null|DOMNode $node
|
||||||
|
* @return null|XMLSecurityKey
|
||||||
|
*/
|
||||||
|
public function locateKey($node=null)
|
||||||
|
{
|
||||||
|
if (empty($node)) {
|
||||||
|
$node = $this->rawNode;
|
||||||
|
}
|
||||||
|
if (! $node instanceof DOMNode) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if ($doc = $node->ownerDocument) {
|
||||||
|
$xpath = new DOMXPath($doc);
|
||||||
|
$xpath->registerNamespace('xmlsecenc', self::XMLENCNS);
|
||||||
|
$query = ".//xmlsecenc:EncryptionMethod";
|
||||||
|
$nodeset = $xpath->query($query, $node);
|
||||||
|
if ($encmeth = $nodeset->item(0)) {
|
||||||
|
$attrAlgorithm = $encmeth->getAttribute("Algorithm");
|
||||||
|
try {
|
||||||
|
$objKey = new XMLSecurityKey($attrAlgorithm, array('type' => 'private'));
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return $objKey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param null|XMLSecurityKey $objBaseKey
|
||||||
|
* @param null|DOMNode $node
|
||||||
|
* @return null|XMLSecurityKey
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static function staticLocateKeyInfo($objBaseKey=null, $node=null)
|
||||||
|
{
|
||||||
|
if (empty($node) || (! $node instanceof DOMNode)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
$doc = $node->ownerDocument;
|
||||||
|
if (!$doc) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$xpath = new DOMXPath($doc);
|
||||||
|
$xpath->registerNamespace('xmlsecenc', self::XMLENCNS);
|
||||||
|
$xpath->registerNamespace('xmlsecdsig', XMLSecurityDSig::XMLDSIGNS);
|
||||||
|
$query = "./xmlsecdsig:KeyInfo";
|
||||||
|
$nodeset = $xpath->query($query, $node);
|
||||||
|
$encmeth = $nodeset->item(0);
|
||||||
|
if (!$encmeth) {
|
||||||
|
/* No KeyInfo in EncryptedData / EncryptedKey. */
|
||||||
|
return $objBaseKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($encmeth->childNodes AS $child) {
|
||||||
|
switch ($child->localName) {
|
||||||
|
case 'KeyName':
|
||||||
|
if (! empty($objBaseKey)) {
|
||||||
|
$objBaseKey->name = $child->nodeValue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'KeyValue':
|
||||||
|
foreach ($child->childNodes AS $keyval) {
|
||||||
|
switch ($keyval->localName) {
|
||||||
|
case 'DSAKeyValue':
|
||||||
|
throw new Exception("DSAKeyValue currently not supported");
|
||||||
|
case 'RSAKeyValue':
|
||||||
|
$modulus = null;
|
||||||
|
$exponent = null;
|
||||||
|
if ($modulusNode = $keyval->getElementsByTagName('Modulus')->item(0)) {
|
||||||
|
$modulus = base64_decode($modulusNode->nodeValue);
|
||||||
|
}
|
||||||
|
if ($exponentNode = $keyval->getElementsByTagName('Exponent')->item(0)) {
|
||||||
|
$exponent = base64_decode($exponentNode->nodeValue);
|
||||||
|
}
|
||||||
|
if (empty($modulus) || empty($exponent)) {
|
||||||
|
throw new Exception("Missing Modulus or Exponent");
|
||||||
|
}
|
||||||
|
$publicKey = XMLSecurityKey::convertRSA($modulus, $exponent);
|
||||||
|
$objBaseKey->loadKey($publicKey);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'RetrievalMethod':
|
||||||
|
$type = $child->getAttribute('Type');
|
||||||
|
if ($type !== 'http://www.w3.org/2001/04/xmlenc#EncryptedKey') {
|
||||||
|
/* Unsupported key type. */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$uri = $child->getAttribute('URI');
|
||||||
|
if ($uri[0] !== '#') {
|
||||||
|
/* URI not a reference - unsupported. */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$id = substr($uri, 1);
|
||||||
|
|
||||||
|
$query = '//xmlsecenc:EncryptedKey[@Id="'.XPath::filterAttrValue($id, XPath::DOUBLE_QUOTE).'"]';
|
||||||
|
$keyElement = $xpath->query($query)->item(0);
|
||||||
|
if (!$keyElement) {
|
||||||
|
throw new Exception("Unable to locate EncryptedKey with @Id='$id'.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return XMLSecurityKey::fromEncryptedKeyElement($keyElement);
|
||||||
|
case 'EncryptedKey':
|
||||||
|
return XMLSecurityKey::fromEncryptedKeyElement($child);
|
||||||
|
case 'X509Data':
|
||||||
|
if ($x509certNodes = $child->getElementsByTagName('X509Certificate')) {
|
||||||
|
if ($x509certNodes->length > 0) {
|
||||||
|
$x509cert = $x509certNodes->item(0)->textContent;
|
||||||
|
$x509cert = str_replace(array("\r", "\n", " ", "\t"), "", $x509cert);
|
||||||
|
$x509cert = "-----BEGIN CERTIFICATE-----\n".chunk_split($x509cert, 64, "\n")."-----END CERTIFICATE-----\n";
|
||||||
|
$objBaseKey->loadKey($x509cert, false, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $objBaseKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param null|XMLSecurityKey $objBaseKey
|
||||||
|
* @param null|DOMNode $node
|
||||||
|
* @return null|XMLSecurityKey
|
||||||
|
*/
|
||||||
|
public function locateKeyInfo($objBaseKey=null, $node=null)
|
||||||
|
{
|
||||||
|
if (empty($node)) {
|
||||||
|
$node = $this->rawNode;
|
||||||
|
}
|
||||||
|
return self::staticLocateKeyInfo($objBaseKey, $node);
|
||||||
|
}
|
||||||
|
}
|
||||||
1162
vendor/robrichards/xmlseclibs/src/XMLSecurityDSig.php
vendored
Normal file
1162
vendor/robrichards/xmlseclibs/src/XMLSecurityDSig.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
813
vendor/robrichards/xmlseclibs/src/XMLSecurityKey.php
vendored
Normal file
813
vendor/robrichards/xmlseclibs/src/XMLSecurityKey.php
vendored
Normal file
@@ -0,0 +1,813 @@
|
|||||||
|
<?php
|
||||||
|
namespace RobRichards\XMLSecLibs;
|
||||||
|
|
||||||
|
use DOMElement;
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlseclibs.php
|
||||||
|
*
|
||||||
|
* Copyright (c) 2007-2024, Robert Richards <rrichards@cdatazone.org>.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name of Robert Richards nor the names of his
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* @author Robert Richards <rrichards@cdatazone.org>
|
||||||
|
* @copyright 2007-2024 Robert Richards <rrichards@cdatazone.org>
|
||||||
|
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
|
||||||
|
*/
|
||||||
|
|
||||||
|
class XMLSecurityKey
|
||||||
|
{
|
||||||
|
const TRIPLEDES_CBC = 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc';
|
||||||
|
const AES128_CBC = 'http://www.w3.org/2001/04/xmlenc#aes128-cbc';
|
||||||
|
const AES192_CBC = 'http://www.w3.org/2001/04/xmlenc#aes192-cbc';
|
||||||
|
const AES256_CBC = 'http://www.w3.org/2001/04/xmlenc#aes256-cbc';
|
||||||
|
const AES128_GCM = 'http://www.w3.org/2009/xmlenc11#aes128-gcm';
|
||||||
|
const AES192_GCM = 'http://www.w3.org/2009/xmlenc11#aes192-gcm';
|
||||||
|
const AES256_GCM = 'http://www.w3.org/2009/xmlenc11#aes256-gcm';
|
||||||
|
const RSA_1_5 = 'http://www.w3.org/2001/04/xmlenc#rsa-1_5';
|
||||||
|
const RSA_OAEP_MGF1P = 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p';
|
||||||
|
const RSA_OAEP = 'http://www.w3.org/2009/xmlenc11#rsa-oaep';
|
||||||
|
const DSA_SHA1 = 'http://www.w3.org/2000/09/xmldsig#dsa-sha1';
|
||||||
|
const RSA_SHA1 = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1';
|
||||||
|
const RSA_SHA256 = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256';
|
||||||
|
const RSA_SHA384 = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha384';
|
||||||
|
const RSA_SHA512 = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha512';
|
||||||
|
const HMAC_SHA1 = 'http://www.w3.org/2000/09/xmldsig#hmac-sha1';
|
||||||
|
const AUTHTAG_LENGTH = 16;
|
||||||
|
|
||||||
|
/** @var array */
|
||||||
|
private $cryptParams = array();
|
||||||
|
|
||||||
|
/** @var int|string */
|
||||||
|
public $type = 0;
|
||||||
|
|
||||||
|
/** @var mixed|null */
|
||||||
|
public $key = null;
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
public $passphrase = "";
|
||||||
|
|
||||||
|
/** @var string|null */
|
||||||
|
public $iv = null;
|
||||||
|
|
||||||
|
/** @var string|null */
|
||||||
|
public $name = null;
|
||||||
|
|
||||||
|
/** @var mixed|null */
|
||||||
|
public $keyChain = null;
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
public $isEncrypted = false;
|
||||||
|
|
||||||
|
/** @var XMLSecEnc|null */
|
||||||
|
public $encryptedCtx = null;
|
||||||
|
|
||||||
|
/** @var mixed|null */
|
||||||
|
public $guid = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This variable contains the certificate as a string if this key represents an X509-certificate.
|
||||||
|
* If this key doesn't represent a certificate, this will be null.
|
||||||
|
* @var string|null
|
||||||
|
*/
|
||||||
|
private $x509Certificate = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This variable contains the certificate thumbprint if we have loaded an X509-certificate.
|
||||||
|
* @var string|null
|
||||||
|
*/
|
||||||
|
private $X509Thumbprint = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $type
|
||||||
|
* @param null|array $params
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function __construct($type, $params=null)
|
||||||
|
{
|
||||||
|
switch ($type) {
|
||||||
|
case (self::TRIPLEDES_CBC):
|
||||||
|
$this->cryptParams['library'] = 'openssl';
|
||||||
|
$this->cryptParams['cipher'] = 'des-ede3-cbc';
|
||||||
|
$this->cryptParams['type'] = 'symmetric';
|
||||||
|
$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc';
|
||||||
|
$this->cryptParams['keysize'] = 24;
|
||||||
|
$this->cryptParams['blocksize'] = 8;
|
||||||
|
break;
|
||||||
|
case (self::AES128_CBC):
|
||||||
|
$this->cryptParams['library'] = 'openssl';
|
||||||
|
$this->cryptParams['cipher'] = 'aes-128-cbc';
|
||||||
|
$this->cryptParams['type'] = 'symmetric';
|
||||||
|
$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#aes128-cbc';
|
||||||
|
$this->cryptParams['keysize'] = 16;
|
||||||
|
$this->cryptParams['blocksize'] = 16;
|
||||||
|
break;
|
||||||
|
case (self::AES192_CBC):
|
||||||
|
$this->cryptParams['library'] = 'openssl';
|
||||||
|
$this->cryptParams['cipher'] = 'aes-192-cbc';
|
||||||
|
$this->cryptParams['type'] = 'symmetric';
|
||||||
|
$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#aes192-cbc';
|
||||||
|
$this->cryptParams['keysize'] = 24;
|
||||||
|
$this->cryptParams['blocksize'] = 16;
|
||||||
|
break;
|
||||||
|
case (self::AES256_CBC):
|
||||||
|
$this->cryptParams['library'] = 'openssl';
|
||||||
|
$this->cryptParams['cipher'] = 'aes-256-cbc';
|
||||||
|
$this->cryptParams['type'] = 'symmetric';
|
||||||
|
$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#aes256-cbc';
|
||||||
|
$this->cryptParams['keysize'] = 32;
|
||||||
|
$this->cryptParams['blocksize'] = 16;
|
||||||
|
break;
|
||||||
|
case (self::AES128_GCM):
|
||||||
|
$this->cryptParams['library'] = 'openssl';
|
||||||
|
$this->cryptParams['cipher'] = 'aes-128-gcm';
|
||||||
|
$this->cryptParams['type'] = 'symmetric';
|
||||||
|
$this->cryptParams['method'] = 'http://www.w3.org/2009/xmlenc11#aes128-gcm';
|
||||||
|
$this->cryptParams['keysize'] = 16;
|
||||||
|
$this->cryptParams['blocksize'] = 16;
|
||||||
|
break;
|
||||||
|
case (self::AES192_GCM):
|
||||||
|
$this->cryptParams['library'] = 'openssl';
|
||||||
|
$this->cryptParams['cipher'] = 'aes-192-gcm';
|
||||||
|
$this->cryptParams['type'] = 'symmetric';
|
||||||
|
$this->cryptParams['method'] = 'http://www.w3.org/2009/xmlenc11#aes192-gcm';
|
||||||
|
$this->cryptParams['keysize'] = 24;
|
||||||
|
$this->cryptParams['blocksize'] = 16;
|
||||||
|
break;
|
||||||
|
case (self::AES256_GCM):
|
||||||
|
$this->cryptParams['library'] = 'openssl';
|
||||||
|
$this->cryptParams['cipher'] = 'aes-256-gcm';
|
||||||
|
$this->cryptParams['type'] = 'symmetric';
|
||||||
|
$this->cryptParams['method'] = 'http://www.w3.org/2009/xmlenc11#aes256-gcm';
|
||||||
|
$this->cryptParams['keysize'] = 32;
|
||||||
|
$this->cryptParams['blocksize'] = 16;
|
||||||
|
break;
|
||||||
|
case (self::RSA_1_5):
|
||||||
|
$this->cryptParams['library'] = 'openssl';
|
||||||
|
$this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING;
|
||||||
|
$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#rsa-1_5';
|
||||||
|
if (is_array($params) && ! empty($params['type'])) {
|
||||||
|
if ($params['type'] == 'public' || $params['type'] == 'private') {
|
||||||
|
$this->cryptParams['type'] = $params['type'];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Exception('Certificate "type" (private/public) must be passed via parameters');
|
||||||
|
case (self::RSA_OAEP_MGF1P):
|
||||||
|
$this->cryptParams['library'] = 'openssl';
|
||||||
|
$this->cryptParams['padding'] = OPENSSL_PKCS1_OAEP_PADDING;
|
||||||
|
$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p';
|
||||||
|
$this->cryptParams['hash'] = null;
|
||||||
|
if (is_array($params) && ! empty($params['type'])) {
|
||||||
|
if ($params['type'] == 'public' || $params['type'] == 'private') {
|
||||||
|
$this->cryptParams['type'] = $params['type'];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Exception('Certificate "type" (private/public) must be passed via parameters');
|
||||||
|
case (self::RSA_OAEP):
|
||||||
|
$this->cryptParams['library'] = 'openssl';
|
||||||
|
$this->cryptParams['padding'] = OPENSSL_PKCS1_OAEP_PADDING;
|
||||||
|
$this->cryptParams['method'] = 'http://www.w3.org/2009/xmlenc11#rsa-oaep';
|
||||||
|
$this->cryptParams['hash'] = 'http://www.w3.org/2009/xmlenc11#mgf1sha1';
|
||||||
|
if (is_array($params) && ! empty($params['type'])) {
|
||||||
|
if ($params['type'] == 'public' || $params['type'] == 'private') {
|
||||||
|
$this->cryptParams['type'] = $params['type'];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Exception('Certificate "type" (private/public) must be passed via parameters');
|
||||||
|
case (self::RSA_SHA1):
|
||||||
|
$this->cryptParams['library'] = 'openssl';
|
||||||
|
$this->cryptParams['method'] = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1';
|
||||||
|
$this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING;
|
||||||
|
if (is_array($params) && ! empty($params['type'])) {
|
||||||
|
if ($params['type'] == 'public' || $params['type'] == 'private') {
|
||||||
|
$this->cryptParams['type'] = $params['type'];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Exception('Certificate "type" (private/public) must be passed via parameters');
|
||||||
|
case (self::RSA_SHA256):
|
||||||
|
$this->cryptParams['library'] = 'openssl';
|
||||||
|
$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256';
|
||||||
|
$this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING;
|
||||||
|
$this->cryptParams['digest'] = 'SHA256';
|
||||||
|
if (is_array($params) && ! empty($params['type'])) {
|
||||||
|
if ($params['type'] == 'public' || $params['type'] == 'private') {
|
||||||
|
$this->cryptParams['type'] = $params['type'];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Exception('Certificate "type" (private/public) must be passed via parameters');
|
||||||
|
case (self::RSA_SHA384):
|
||||||
|
$this->cryptParams['library'] = 'openssl';
|
||||||
|
$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha384';
|
||||||
|
$this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING;
|
||||||
|
$this->cryptParams['digest'] = 'SHA384';
|
||||||
|
if (is_array($params) && ! empty($params['type'])) {
|
||||||
|
if ($params['type'] == 'public' || $params['type'] == 'private') {
|
||||||
|
$this->cryptParams['type'] = $params['type'];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Exception('Certificate "type" (private/public) must be passed via parameters');
|
||||||
|
case (self::RSA_SHA512):
|
||||||
|
$this->cryptParams['library'] = 'openssl';
|
||||||
|
$this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha512';
|
||||||
|
$this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING;
|
||||||
|
$this->cryptParams['digest'] = 'SHA512';
|
||||||
|
if (is_array($params) && ! empty($params['type'])) {
|
||||||
|
if ($params['type'] == 'public' || $params['type'] == 'private') {
|
||||||
|
$this->cryptParams['type'] = $params['type'];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Exception('Certificate "type" (private/public) must be passed via parameters');
|
||||||
|
case (self::HMAC_SHA1):
|
||||||
|
$this->cryptParams['library'] = $type;
|
||||||
|
$this->cryptParams['method'] = 'http://www.w3.org/2000/09/xmldsig#hmac-sha1';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Exception('Invalid Key Type');
|
||||||
|
}
|
||||||
|
$this->type = $type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the key size for the symmetric encryption algorithm..
|
||||||
|
*
|
||||||
|
* If the key size is unknown, or this isn't a symmetric encryption algorithm,
|
||||||
|
* null is returned.
|
||||||
|
*
|
||||||
|
* @return int|null The number of bytes in the key.
|
||||||
|
*/
|
||||||
|
public function getSymmetricKeySize()
|
||||||
|
{
|
||||||
|
if (! isset($this->cryptParams['keysize'])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return $this->cryptParams['keysize'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a session key using the openssl-extension.
|
||||||
|
* In case of using DES3-CBC the key is checked for a proper parity bits set.
|
||||||
|
* @return string
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function generateSessionKey()
|
||||||
|
{
|
||||||
|
if (!isset($this->cryptParams['keysize'])) {
|
||||||
|
throw new Exception('Unknown key size for type "' . $this->type . '".');
|
||||||
|
}
|
||||||
|
$keysize = $this->cryptParams['keysize'];
|
||||||
|
|
||||||
|
$key = openssl_random_pseudo_bytes($keysize);
|
||||||
|
|
||||||
|
if ($this->type === self::TRIPLEDES_CBC) {
|
||||||
|
/* Make sure that the generated key has the proper parity bits set.
|
||||||
|
* Mcrypt doesn't care about the parity bits, but others may care.
|
||||||
|
*/
|
||||||
|
for ($i = 0; $i < strlen($key); $i++) {
|
||||||
|
$byte = ord($key[$i]) & 0xfe;
|
||||||
|
$parity = 1;
|
||||||
|
for ($j = 1; $j < 8; $j++) {
|
||||||
|
$parity ^= ($byte >> $j) & 1;
|
||||||
|
}
|
||||||
|
$byte |= $parity;
|
||||||
|
$key[$i] = chr($byte);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->key = $key;
|
||||||
|
return $key;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the raw thumbprint of a certificate
|
||||||
|
*
|
||||||
|
* @param string $cert
|
||||||
|
* @return null|string
|
||||||
|
*/
|
||||||
|
public static function getRawThumbprint($cert)
|
||||||
|
{
|
||||||
|
|
||||||
|
$arCert = explode("\n", $cert);
|
||||||
|
$data = '';
|
||||||
|
$inData = false;
|
||||||
|
|
||||||
|
foreach ($arCert AS $curData) {
|
||||||
|
if (! $inData) {
|
||||||
|
if (strncmp($curData, '-----BEGIN CERTIFICATE', 22) == 0) {
|
||||||
|
$inData = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (strncmp($curData, '-----END CERTIFICATE', 20) == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$data .= trim($curData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! empty($data)) {
|
||||||
|
return strtolower(sha1(base64_decode($data)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the given key, or - with isFile set true - the key from the keyfile.
|
||||||
|
*
|
||||||
|
* @param string $key
|
||||||
|
* @param bool $isFile
|
||||||
|
* @param bool $isCert
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function loadKey($key, $isFile=false, $isCert = false)
|
||||||
|
{
|
||||||
|
if ($isFile) {
|
||||||
|
$this->key = file_get_contents($key);
|
||||||
|
} else {
|
||||||
|
$this->key = $key;
|
||||||
|
}
|
||||||
|
if ($isCert) {
|
||||||
|
$this->key = openssl_x509_read($this->key);
|
||||||
|
openssl_x509_export($this->key, $str_cert);
|
||||||
|
$this->x509Certificate = $str_cert;
|
||||||
|
$this->key = $str_cert;
|
||||||
|
} else {
|
||||||
|
$this->x509Certificate = null;
|
||||||
|
}
|
||||||
|
if ($this->cryptParams['library'] == 'openssl') {
|
||||||
|
switch ($this->cryptParams['type']) {
|
||||||
|
case 'public':
|
||||||
|
if ($isCert) {
|
||||||
|
/* Load the thumbprint if this is an X509 certificate. */
|
||||||
|
$this->X509Thumbprint = self::getRawThumbprint($this->key);
|
||||||
|
}
|
||||||
|
$this->key = openssl_get_publickey($this->key);
|
||||||
|
if (! $this->key) {
|
||||||
|
throw new Exception('Unable to extract public key');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'private':
|
||||||
|
$this->key = openssl_get_privatekey($this->key, $this->passphrase);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case'symmetric':
|
||||||
|
if (strlen($this->key) < $this->cryptParams['keysize']) {
|
||||||
|
throw new Exception('Key must contain at least '.$this->cryptParams['keysize'].' characters for this cipher, contains '.strlen($this->key));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new Exception('Unknown type');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ISO 10126 Padding
|
||||||
|
*
|
||||||
|
* @param string $data
|
||||||
|
* @param integer $blockSize
|
||||||
|
* @throws Exception
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function padISO10126($data, $blockSize)
|
||||||
|
{
|
||||||
|
if ($blockSize > 256) {
|
||||||
|
throw new Exception('Block size higher than 256 not allowed');
|
||||||
|
}
|
||||||
|
$padChr = $blockSize - (strlen($data) % $blockSize);
|
||||||
|
$pattern = chr($padChr);
|
||||||
|
return $data . str_repeat($pattern, $padChr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove ISO 10126 Padding
|
||||||
|
*
|
||||||
|
* @param string $data
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function unpadISO10126($data)
|
||||||
|
{
|
||||||
|
$padChr = substr($data, -1);
|
||||||
|
$padLen = ord($padChr);
|
||||||
|
return substr($data, 0, -$padLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypts the given data (string) using the openssl-extension
|
||||||
|
*
|
||||||
|
* @param string $data
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function encryptSymmetric($data)
|
||||||
|
{
|
||||||
|
$this->iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($this->cryptParams['cipher']));
|
||||||
|
$authTag = null;
|
||||||
|
if(in_array($this->cryptParams['cipher'], ['aes-128-gcm', 'aes-192-gcm', 'aes-256-gcm'])) {
|
||||||
|
if (version_compare(PHP_VERSION, '7.1.0') < 0) {
|
||||||
|
throw new Exception('PHP 7.1.0 is required to use AES GCM algorithms');
|
||||||
|
}
|
||||||
|
$authTag = openssl_random_pseudo_bytes(self::AUTHTAG_LENGTH);
|
||||||
|
$encrypted = openssl_encrypt($data, $this->cryptParams['cipher'], $this->key, OPENSSL_RAW_DATA, $this->iv, $authTag);
|
||||||
|
} else {
|
||||||
|
$data = $this->padISO10126($data, $this->cryptParams['blocksize']);
|
||||||
|
$encrypted = openssl_encrypt($data, $this->cryptParams['cipher'], $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $this->iv);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false === $encrypted) {
|
||||||
|
throw new Exception('Failure encrypting Data (openssl symmetric) - ' . openssl_error_string());
|
||||||
|
}
|
||||||
|
return $this->iv . $encrypted . $authTag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decrypts the given data (string) using the openssl-extension
|
||||||
|
*
|
||||||
|
* @param string $data
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function decryptSymmetric($data)
|
||||||
|
{
|
||||||
|
$iv_length = openssl_cipher_iv_length($this->cryptParams['cipher']);
|
||||||
|
$this->iv = substr($data, 0, $iv_length);
|
||||||
|
$data = substr($data, $iv_length);
|
||||||
|
$authTag = null;
|
||||||
|
if(in_array($this->cryptParams['cipher'], ['aes-128-gcm', 'aes-192-gcm', 'aes-256-gcm'])) {
|
||||||
|
if (version_compare(PHP_VERSION, '7.1.0') < 0) {
|
||||||
|
throw new Exception('PHP 7.1.0 is required to use AES GCM algorithms');
|
||||||
|
}
|
||||||
|
// obtain and remove the authentication tag
|
||||||
|
$offset = 0 - self::AUTHTAG_LENGTH;
|
||||||
|
$authTag = substr($data, $offset);
|
||||||
|
$data = substr($data, 0, $offset);
|
||||||
|
$decrypted = openssl_decrypt($data, $this->cryptParams['cipher'], $this->key, OPENSSL_RAW_DATA, $this->iv, $authTag);
|
||||||
|
} else {
|
||||||
|
$decrypted = openssl_decrypt($data, $this->cryptParams['cipher'], $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $this->iv);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false === $decrypted) {
|
||||||
|
throw new Exception('Failure decrypting Data (openssl symmetric) - ' . openssl_error_string());
|
||||||
|
}
|
||||||
|
return null !== $authTag ? $decrypted : $this->unpadISO10126($decrypted);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypts the given public data (string) using the openssl-extension
|
||||||
|
*
|
||||||
|
* @param string $data
|
||||||
|
* @return string
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
private function encryptPublic($data)
|
||||||
|
{
|
||||||
|
if (! openssl_public_encrypt($data, $encrypted, $this->key, $this->cryptParams['padding'])) {
|
||||||
|
throw new Exception('Failure encrypting Data (openssl public) - ' . openssl_error_string());
|
||||||
|
}
|
||||||
|
return $encrypted;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decrypts the given public data (string) using the openssl-extension
|
||||||
|
*
|
||||||
|
* @param string $data
|
||||||
|
* @return string
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
private function decryptPublic($data)
|
||||||
|
{
|
||||||
|
if (! openssl_public_decrypt($data, $decrypted, $this->key, $this->cryptParams['padding'])) {
|
||||||
|
throw new Exception('Failure decrypting Data (openssl public) - ' . openssl_error_string());
|
||||||
|
}
|
||||||
|
return $decrypted;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypts the given private data (string) using the openssl-extension
|
||||||
|
*
|
||||||
|
* @param string $data
|
||||||
|
* @return string
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
private function encryptPrivate($data)
|
||||||
|
{
|
||||||
|
if (! openssl_private_encrypt($data, $encrypted, $this->key, $this->cryptParams['padding'])) {
|
||||||
|
throw new Exception('Failure encrypting Data (openssl private) - ' . openssl_error_string());
|
||||||
|
}
|
||||||
|
return $encrypted;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decrypts the given private data (string) using the openssl-extension
|
||||||
|
*
|
||||||
|
* @param string $data
|
||||||
|
* @return string
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
private function decryptPrivate($data)
|
||||||
|
{
|
||||||
|
if (! openssl_private_decrypt($data, $decrypted, $this->key, $this->cryptParams['padding'])) {
|
||||||
|
throw new Exception('Failure decrypting Data (openssl private) - ' . openssl_error_string());
|
||||||
|
}
|
||||||
|
return $decrypted;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signs the given data (string) using the openssl-extension
|
||||||
|
*
|
||||||
|
* @param string $data
|
||||||
|
* @return string
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
private function signOpenSSL($data)
|
||||||
|
{
|
||||||
|
$algo = OPENSSL_ALGO_SHA1;
|
||||||
|
if (! empty($this->cryptParams['digest'])) {
|
||||||
|
$algo = $this->cryptParams['digest'];
|
||||||
|
}
|
||||||
|
if (! openssl_sign($data, $signature, $this->key, $algo)) {
|
||||||
|
throw new Exception('Failure Signing Data: ' . openssl_error_string() . ' - ' . $algo);
|
||||||
|
}
|
||||||
|
return $signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies the given data (string) belonging to the given signature using the openssl-extension
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* 1 on succesful signature verification,
|
||||||
|
* 0 when signature verification failed,
|
||||||
|
* -1 if an error occurred during processing.
|
||||||
|
*
|
||||||
|
* NOTE: be very careful when checking the return value, because in PHP,
|
||||||
|
* -1 will be cast to True when in boolean context. So always check the
|
||||||
|
* return value in a strictly typed way, e.g. "$obj->verify(...) === 1".
|
||||||
|
*
|
||||||
|
* @param string $data
|
||||||
|
* @param string $signature
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
private function verifyOpenSSL($data, $signature)
|
||||||
|
{
|
||||||
|
$algo = OPENSSL_ALGO_SHA1;
|
||||||
|
if (! empty($this->cryptParams['digest'])) {
|
||||||
|
$algo = $this->cryptParams['digest'];
|
||||||
|
}
|
||||||
|
return openssl_verify($data, $signature, $this->key, $algo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypts the given data (string) using the regarding php-extension, depending on the library assigned to algorithm in the contructor.
|
||||||
|
*
|
||||||
|
* @param string $data
|
||||||
|
* @return mixed|string
|
||||||
|
*/
|
||||||
|
public function encryptData($data)
|
||||||
|
{
|
||||||
|
if ($this->cryptParams['library'] === 'openssl') {
|
||||||
|
switch ($this->cryptParams['type']) {
|
||||||
|
case 'symmetric':
|
||||||
|
return $this->encryptSymmetric($data);
|
||||||
|
case 'public':
|
||||||
|
return $this->encryptPublic($data);
|
||||||
|
case 'private':
|
||||||
|
return $this->encryptPrivate($data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decrypts the given data (string) using the regarding php-extension, depending on the library assigned to algorithm in the contructor.
|
||||||
|
*
|
||||||
|
* @param string $data
|
||||||
|
* @return mixed|string
|
||||||
|
*/
|
||||||
|
public function decryptData($data)
|
||||||
|
{
|
||||||
|
if ($this->cryptParams['library'] === 'openssl') {
|
||||||
|
switch ($this->cryptParams['type']) {
|
||||||
|
case 'symmetric':
|
||||||
|
return $this->decryptSymmetric($data);
|
||||||
|
case 'public':
|
||||||
|
return $this->decryptPublic($data);
|
||||||
|
case 'private':
|
||||||
|
return $this->decryptPrivate($data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signs the data (string) using the extension assigned to the type in the constructor.
|
||||||
|
*
|
||||||
|
* @param string $data
|
||||||
|
* @return mixed|string
|
||||||
|
*/
|
||||||
|
public function signData($data)
|
||||||
|
{
|
||||||
|
switch ($this->cryptParams['library']) {
|
||||||
|
case 'openssl':
|
||||||
|
return $this->signOpenSSL($data);
|
||||||
|
case (self::HMAC_SHA1):
|
||||||
|
return hash_hmac("sha1", $data, $this->key, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies the data (string) against the given signature using the extension assigned to the type in the constructor.
|
||||||
|
*
|
||||||
|
* Returns in case of openSSL:
|
||||||
|
* 1 on succesful signature verification,
|
||||||
|
* 0 when signature verification failed,
|
||||||
|
* -1 if an error occurred during processing.
|
||||||
|
*
|
||||||
|
* NOTE: be very careful when checking the return value, because in PHP,
|
||||||
|
* -1 will be cast to True when in boolean context. So always check the
|
||||||
|
* return value in a strictly typed way, e.g. "$obj->verify(...) === 1".
|
||||||
|
*
|
||||||
|
* @param string $data
|
||||||
|
* @param string $signature
|
||||||
|
* @return bool|int
|
||||||
|
*/
|
||||||
|
public function verifySignature($data, $signature)
|
||||||
|
{
|
||||||
|
switch ($this->cryptParams['library']) {
|
||||||
|
case 'openssl':
|
||||||
|
return $this->verifyOpenSSL($data, $signature);
|
||||||
|
case (self::HMAC_SHA1):
|
||||||
|
$expectedSignature = hash_hmac("sha1", $data, $this->key, true);
|
||||||
|
return strcmp($signature, $expectedSignature) == 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
* @see getAlgorithm()
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getAlgorith()
|
||||||
|
{
|
||||||
|
return $this->getAlgorithm();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getAlgorithm()
|
||||||
|
{
|
||||||
|
return $this->cryptParams['method'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param int $type
|
||||||
|
* @param string $string
|
||||||
|
* @return null|string
|
||||||
|
*/
|
||||||
|
public static function makeAsnSegment($type, $string)
|
||||||
|
{
|
||||||
|
switch ($type) {
|
||||||
|
case 0x02:
|
||||||
|
if (ord($string) > 0x7f)
|
||||||
|
$string = chr(0).$string;
|
||||||
|
break;
|
||||||
|
case 0x03:
|
||||||
|
$string = chr(0).$string;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$length = strlen($string);
|
||||||
|
|
||||||
|
if ($length < 128) {
|
||||||
|
$output = sprintf("%c%c%s", $type, $length, $string);
|
||||||
|
} else if ($length < 0x0100) {
|
||||||
|
$output = sprintf("%c%c%c%s", $type, 0x81, $length, $string);
|
||||||
|
} else if ($length < 0x010000) {
|
||||||
|
$output = sprintf("%c%c%c%c%s", $type, 0x82, $length / 0x0100, $length % 0x0100, $string);
|
||||||
|
} else {
|
||||||
|
$output = null;
|
||||||
|
}
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Hint: Modulus and Exponent must already be base64 decoded
|
||||||
|
* @param string $modulus
|
||||||
|
* @param string $exponent
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function convertRSA($modulus, $exponent)
|
||||||
|
{
|
||||||
|
/* make an ASN publicKeyInfo */
|
||||||
|
$exponentEncoding = self::makeAsnSegment(0x02, $exponent);
|
||||||
|
$modulusEncoding = self::makeAsnSegment(0x02, $modulus);
|
||||||
|
$sequenceEncoding = self::makeAsnSegment(0x30, $modulusEncoding.$exponentEncoding);
|
||||||
|
$bitstringEncoding = self::makeAsnSegment(0x03, $sequenceEncoding);
|
||||||
|
$rsaAlgorithmIdentifier = pack("H*", "300D06092A864886F70D0101010500");
|
||||||
|
$publicKeyInfo = self::makeAsnSegment(0x30, $rsaAlgorithmIdentifier.$bitstringEncoding);
|
||||||
|
|
||||||
|
/* encode the publicKeyInfo in base64 and add PEM brackets */
|
||||||
|
$publicKeyInfoBase64 = base64_encode($publicKeyInfo);
|
||||||
|
$encoding = "-----BEGIN PUBLIC KEY-----\n";
|
||||||
|
$offset = 0;
|
||||||
|
while ($segment = substr($publicKeyInfoBase64, $offset, 64)) {
|
||||||
|
$encoding = $encoding.$segment."\n";
|
||||||
|
$offset += 64;
|
||||||
|
}
|
||||||
|
return $encoding."-----END PUBLIC KEY-----\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mixed $parent
|
||||||
|
*/
|
||||||
|
public function serializeKey($parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the X509 certificate this key represents.
|
||||||
|
*
|
||||||
|
* Will return the X509 certificate in PEM-format if this key represents
|
||||||
|
* an X509 certificate.
|
||||||
|
*
|
||||||
|
* @return string The X509 certificate or null if this key doesn't represent an X509-certificate.
|
||||||
|
*/
|
||||||
|
public function getX509Certificate()
|
||||||
|
{
|
||||||
|
return $this->x509Certificate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the thumbprint of this X509 certificate.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* The thumbprint as a lowercase 40-character hexadecimal number, or null
|
||||||
|
* if this isn't a X509 certificate.
|
||||||
|
*
|
||||||
|
* @return string Lowercase 40-character hexadecimal number of thumbprint
|
||||||
|
*/
|
||||||
|
public function getX509Thumbprint()
|
||||||
|
{
|
||||||
|
return $this->X509Thumbprint;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create key from an EncryptedKey-element.
|
||||||
|
*
|
||||||
|
* @param DOMElement $element The EncryptedKey-element.
|
||||||
|
* @throws Exception
|
||||||
|
*
|
||||||
|
* @return XMLSecurityKey The new key.
|
||||||
|
*/
|
||||||
|
public static function fromEncryptedKeyElement(DOMElement $element)
|
||||||
|
{
|
||||||
|
|
||||||
|
$objenc = new XMLSecEnc();
|
||||||
|
$objenc->setNode($element);
|
||||||
|
if (! $objKey = $objenc->locateKey()) {
|
||||||
|
throw new Exception("Unable to locate algorithm for this Encrypted Key");
|
||||||
|
}
|
||||||
|
$objKey->isEncrypted = true;
|
||||||
|
$objKey->encryptedCtx = $objenc;
|
||||||
|
XMLSecEnc::staticLocateKeyInfo($objKey, $element);
|
||||||
|
return $objKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
47
vendor/robrichards/xmlseclibs/xmlseclibs.php
vendored
Normal file
47
vendor/robrichards/xmlseclibs/xmlseclibs.php
vendored
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* xmlseclibs.php
|
||||||
|
*
|
||||||
|
* Copyright (c) 2007-2024, Robert Richards <rrichards@cdatazone.org>.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name of Robert Richards nor the names of his
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* @author Robert Richards <rrichards@cdatazone.org>
|
||||||
|
* @copyright 2007-2024 Robert Richards <rrichards@cdatazone.org>
|
||||||
|
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
|
||||||
|
* @version 3.1.3
|
||||||
|
*/
|
||||||
|
|
||||||
|
$xmlseclibs_srcdir = dirname(__FILE__) . '/src/';
|
||||||
|
require $xmlseclibs_srcdir . '/XMLSecurityKey.php';
|
||||||
|
require $xmlseclibs_srcdir . '/XMLSecurityDSig.php';
|
||||||
|
require $xmlseclibs_srcdir . '/XMLSecEnc.php';
|
||||||
|
require $xmlseclibs_srcdir . '/Utils/XPath.php';
|
||||||
Reference in New Issue
Block a user