mirror of
https://git.friendi.ca/friendica/friendica-addons.git
synced 2025-07-09 01:48:48 +00:00
Add SAML addon.
This commit is contained in:
parent
f04493b5bb
commit
4b3b79c894
62 changed files with 16277 additions and 0 deletions
228
saml/vendor/robrichards/xmlseclibs/CHANGELOG.txt
vendored
Normal file
228
saml/vendor/robrichards/xmlseclibs/CHANGELOG.txt
vendored
Normal file
|
@ -0,0 +1,228 @@
|
|||
xmlseclibs.php
|
||||
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||
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
saml/vendor/robrichards/xmlseclibs/LICENSE
vendored
Normal file
31
saml/vendor/robrichards/xmlseclibs/LICENSE
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
Copyright (c) 2007-2019, 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
saml/vendor/robrichards/xmlseclibs/README.md
vendored
Normal file
85
saml/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
saml/vendor/robrichards/xmlseclibs/composer.json
vendored
Normal file
21
saml/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": "*"
|
||||
}
|
||||
}
|
44
saml/vendor/robrichards/xmlseclibs/src/Utils/XPath.php
vendored
Normal file
44
saml/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
saml/vendor/robrichards/xmlseclibs/src/XMLSecEnc.php
vendored
Normal file
511
saml/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-2020, 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-2020 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", " "), "", $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
saml/vendor/robrichards/xmlseclibs/src/XMLSecurityDSig.php
vendored
Normal file
1162
saml/vendor/robrichards/xmlseclibs/src/XMLSecurityDSig.php
vendored
Normal file
File diff suppressed because it is too large
Load diff
813
saml/vendor/robrichards/xmlseclibs/src/XMLSecurityKey.php
vendored
Normal file
813
saml/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-2020, 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-2020 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
saml/vendor/robrichards/xmlseclibs/xmlseclibs.php
vendored
Normal file
47
saml/vendor/robrichards/xmlseclibs/xmlseclibs.php
vendored
Normal file
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
/**
|
||||
* xmlseclibs.php
|
||||
*
|
||||
* Copyright (c) 2007-2020, 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-2020 Robert Richards <rrichards@cdatazone.org>
|
||||
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
|
||||
* @version 3.1.1
|
||||
*/
|
||||
|
||||
$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';
|
Loading…
Add table
Add a link
Reference in a new issue