Skip to content

Commit

Permalink
Add element registry (#55)
Browse files Browse the repository at this point in the history
* Add element registry

* Leverage new getChildElementsFromXML

* Fix phpstan-issues

* Fix
  • Loading branch information
tvdijen authored Sep 13, 2024
1 parent 1007102 commit 446cbf3
Show file tree
Hide file tree
Showing 17 changed files with 136 additions and 153 deletions.
2 changes: 2 additions & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,5 @@ comment:
branches: null
github_checks:
annotations: false
ignore:
- 'src/XML/element.registry.php'
9 changes: 5 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,19 @@
"ext-pcre": "*",
"ext-spl": "*",

"simplesamlphp/assert": "^1.1",
"simplesamlphp/xml-common": "^1.15"
"simplesamlphp/assert": "^1.3",
"simplesamlphp/xml-common": "^1.18"
},
"require-dev": {
"simplesamlphp/simplesamlphp-test-framework": "^1.5"
"simplesamlphp/simplesamlphp-test-framework": "^1.7"
},
"config": {
"allow-plugins": {
"composer/package-versions-deprecated": true,
"dealerdirect/phpcodesniffer-composer-installer": true,
"phpstan/extension-installer": true,
"simplesamlphp/composer-module-installer": true,
"phpstan/extension-installer": true
"simplesamlphp/composer-xmlprovider-installer": true
}
}
}
4 changes: 3 additions & 1 deletion src/XML/EncryptableElementTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@ public function encrypt(EncryptionAlgorithmInterface $encryptor): EncryptedData

$keyInfo = new KeyInfo([$encryptedKey]);

$factory = new EncryptionAlgorithmFactory($this->getBlacklistedAlgorithms() ?? EncryptionAlgorithmFactory::DEFAULT_BLACKLIST);
$factory = new EncryptionAlgorithmFactory(
$this->getBlacklistedAlgorithms() ?? EncryptionAlgorithmFactory::DEFAULT_BLACKLIST,
);
$encryptor = $factory->getAlgorithm($this->blockCipherAlgId, $sessionKey);
$encryptor->setBackend($this->getEncryptionBackend());
}
Expand Down
4 changes: 3 additions & 1 deletion src/XML/EncryptedElementTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,9 @@ protected function decryptData(EncryptionAlgorithmInterface $decryptor): string
$encryptedKey = $this->getEncryptedKey();
$decryptionKey = $encryptedKey->decrypt($decryptor);

$factory = new EncryptionAlgorithmFactory($this->getBlacklistedAlgorithms() ?? EncryptionAlgorithmFactory::DEFAULT_BLACKLIST);
$factory = new EncryptionAlgorithmFactory(
$this->getBlacklistedAlgorithms() ?? EncryptionAlgorithmFactory::DEFAULT_BLACKLIST,
);
$decryptor = $factory->getAlgorithm($encMethod->getAlgorithm(), new SymmetricKey($decryptionKey));
$decryptor->setBackend($this->getEncryptionBackend());
}
Expand Down
3 changes: 2 additions & 1 deletion src/XML/SignedElementTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,8 @@ private function verifyInternal(SignatureAlgorithmInterface $verifier): SignedEl
if (
$verifier?->verify(
$c14nSignedInfo, // the canonicalized ds:SignedInfo element (plaintext)
base64_decode($this->getSignature()->getSignatureValue()->getRawContent(), true), // the actual signature
// the actual signature
base64_decode($this->getSignature()->getSignatureValue()->getRawContent(), true),
)
) {
/*
Expand Down
13 changes: 2 additions & 11 deletions src/XML/ds/DigestMethod.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

use DOMElement;
use SimpleSAML\Assert\Assert;
use SimpleSAML\XML\Chunk;
use SimpleSAML\XML\Exception\InvalidDOMElementException;
use SimpleSAML\XML\Exception\SchemaViolationException;
use SimpleSAML\XML\ExtendableElementTrait;
Expand All @@ -29,7 +28,7 @@ final class DigestMethod extends AbstractDsElement
* Initialize a DigestMethod element.
*
* @param string $Algorithm
* @param \SimpleSAML\XML\Chunk[] $elements
* @param list<\SimpleSAML\XML\SerializableElementInterface> $elements
*/
public function __construct(
protected string $Algorithm,
Expand Down Expand Up @@ -73,15 +72,7 @@ public static function fromXML(DOMElement $xml): static
Assert::same($xml->namespaceURI, DigestMethod::NS, InvalidDOMElementException::class);

$Algorithm = DigestMethod::getAttribute($xml, 'Algorithm');

$elements = [];
foreach ($xml->childNodes as $elt) {
if (!($elt instanceof DOMElement)) {
continue;
}

$elements[] = new Chunk($elt);
}
$elements = self::getChildElementsFromXML($xml);

return new static($Algorithm, $elements);
}
Expand Down
18 changes: 1 addition & 17 deletions src/XML/ds/DsObject.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

use DOMElement;
use SimpleSAML\Assert\Assert;
use SimpleSAML\XML\Chunk;
use SimpleSAML\XML\Exception\InvalidDOMElementException;
use SimpleSAML\XML\ExtendableElementTrait;
use SimpleSAML\XML\XsNamespace as NS;
Expand Down Expand Up @@ -112,22 +111,7 @@ public static function fromXML(DOMElement $xml): static
$Id = DsObject::getOptionalAttribute($xml, 'Id', null);
$MimeType = DsObject::getOptionalAttribute($xml, 'MimeType', null);
$Encoding = DsObject::getOptionalAttribute($xml, 'Encoding', null);

$elements = [];
foreach ($xml->childNodes as $elt) {
if (!($elt instanceof DOMElement)) {
// @TODO: support mixed content
continue;
} elseif ($elt->namespaceURI === self::NS) {
$elements[] = match ($elt->localName) {
'SignatureProperties' => SignatureProperties::fromXML($elt),
'Manifest' => Manifest::fromXML($elt),
default => new Chunk($elt),
};
}

$elements[] = new Chunk($elt);
}
$elements = self::getChildElementsFromXML($xml);

return new static($Id, $MimeType, $Encoding, $elements);
}
Expand Down
105 changes: 44 additions & 61 deletions src/XML/ds/KeyInfo.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,12 @@

use DOMElement;
use SimpleSAML\Assert\Assert;
use SimpleSAML\XML\Chunk;
use SimpleSAML\XML\Exception\InvalidDOMElementException;
use SimpleSAML\XML\ExtendableElementTrait;
use SimpleSAML\XML\SerializableElementInterface;
use SimpleSAML\XML\XsNamespace as NS;
use SimpleSAML\XMLSecurity\Constants as C;
use SimpleSAML\XMLSecurity\Exception\InvalidArgumentException;
use SimpleSAML\XMLSecurity\XML\dsig11\KeyInfoReference;
use SimpleSAML\XMLSecurity\XML\xenc\EncryptedData;
use SimpleSAML\XMLSecurity\XML\xenc\EncryptedKey;

/**
* Class representing a ds:KeyInfo element.
Expand All @@ -21,11 +20,16 @@
*/
final class KeyInfo extends AbstractDsElement
{
use ExtendableElementTrait;

/** @var \SimpleSAML\XML\XsNamespace */
public const XS_ANY_ELT_NAMESPACE = NS::OTHER;


/**
* Initialize a KeyInfo element.
*
* @param (
* \SimpleSAML\XML\SerializableElementInterface|
* \SimpleSAML\XMLSecurity\XML\ds\KeyName|
* \SimpleSAML\XMLSecurity\XML\ds\KeyValue|
* \SimpleSAML\XMLSecurity\XML\ds\RetrievalMethod|
Expand All @@ -34,29 +38,26 @@ final class KeyInfo extends AbstractDsElement
* \SimpleSAML\XMLSecurity\XML\xenc\EncryptedData|
* \SimpleSAML\XMLSecurity\XML\xenc\EncryptedKey
* )[] $info
* @param \SimpleSAML\XML\SerializableElementInterface[] $children
* @param string|null $Id
*/
public function __construct(
protected array $info,
array $children = [],
protected ?string $Id = null,
) {
Assert::notEmpty($info, 'ds:KeyInfo cannot be empty', InvalidArgumentException::class);
Assert::maxCount($info, C::UNBOUNDED_LIMIT);
Assert::allIsInstanceOfAny(
$info,
[
Chunk::class,
KeyName::class,
KeyValue::class,
RetrievalMethod::class,
X509Data::class,
EncryptedData::class,
EncryptedKey::class,
],
'KeyInfo can only contain instances of KeyName, X509Data, EncryptedKey or Chunk.',
$combi = array_merge($info, $children);

Assert::notEmpty($combi, 'ds:KeyInfo cannot be empty', InvalidArgumentException::class);
Assert::maxCount($combi, C::UNBOUNDED_LIMIT);
Assert::allIsInstanceOf(
$combi,
SerializableElementInterface::class,
InvalidArgumentException::class,
);
Assert::nullOrValidNCName($Id);

$this->setElements($children);
}


Expand All @@ -74,20 +75,11 @@ public function getId(): ?string
/**
* Collect the value of the info-property
*
* @return (
* \SimpleSAML\XML\SerializableElementInterface|
* \SimpleSAML\XMLSecurity\XML\ds\KeyName|
* \SimpleSAML\XMLSecurity\XML\ds\KeyValue|
* \SimpleSAML\XMLSecurity\XML\ds\RetrievalMethod|
* \SimpleSAML\XMLSecurity\XML\ds\X509Data|
* \SimpleSAML\XMLSecurity\XML\dsig11\KeyInfoReference|
* \SimpleSAML\XMLSecurity\XML\xenc\EncryptedData|
* \SimpleSAML\XMLSecurity\XML\xenc\EncryptedKey
* )[]
* @return list<\SimpleSAML\XML\SerializableElementInterface>
*/
public function getInfo(): array
{
return $this->info;
return array_merge($this->info, $this->getElements());
}


Expand All @@ -106,36 +98,27 @@ public static function fromXML(DOMElement $xml): static
Assert::same($xml->namespaceURI, KeyInfo::NS, InvalidDOMElementException::class);

$Id = self::getOptionalAttribute($xml, 'Id', null);
$info = [];

foreach ($xml->childNodes as $n) {
if (!($n instanceof DOMElement)) {
continue;
} elseif ($n->namespaceURI === C::NS_XDSIG) {
$info[] = match ($n->localName) {
'KeyName' => KeyName::fromXML($n),
'KeyValue' => KeyValue::fromXML($n),
'RetrievalMethod' => RetrievalMethod::fromXML($n),
'X509Data' => X509Data::fromXML($n),
default => new Chunk($n),
};
} elseif ($n->namespaceURI === C::NS_XDSIG11) {
$info[] = match ($n->localName) {
'KeyInfoReference' => KeyInfoReference::fromXML($n),
default => new Chunk($n),
};
} elseif ($n->namespaceURI === C::NS_XENC) {
$info[] = match ($n->localName) {
'EncryptedData' => EncryptedData::fromXML($n),
'EncryptedKey' => EncryptedKey::fromXML($n),
default => new Chunk($n),
};
} else {
$info[] = new Chunk($n);
}
}

return new static($info, $Id);
$keyName = KeyName::getChildrenOfClass($xml);
$keyValue = KeyValue::getChildrenOfClass($xml);
$retrievalMethod = RetrievalMethod::getChildrenOfClass($xml);
$x509Data = X509Data::getChildrenOfClass($xml);
//$pgpData = PGPData::getChildrenOfClass($xml);
//$spkiData = SPKIData::getChildrenOfClass($xml);
//$mgmtData = MgmtData::getChildrenOfClass($xml);

$info = array_merge(
$keyName,
$keyValue,
$retrievalMethod,
$x509Data,
//$pgpdata,
//$spkidata,
//$mgmtdata,
);

$children = self::getChildElementsFromXML($xml);
return new static($info, $children, $Id);
}


Expand All @@ -153,8 +136,8 @@ public function toXML(DOMElement $parent = null): DOMElement
$e->setAttribute('Id', $this->getId());
}

foreach ($this->getInfo() as $n) {
$n->toXML($e);
foreach ($this->getInfo() as $elt) {
$elt->toXML($e);
}

return $e;
Expand Down
10 changes: 1 addition & 9 deletions src/XML/ds/KeyValue.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

use DOMElement;
use SimpleSAML\Assert\Assert;
use SimpleSAML\XML\Chunk;
use SimpleSAML\XML\ElementInterface;
use SimpleSAML\XML\Exception\InvalidDOMElementException;
use SimpleSAML\XML\Exception\SchemaViolationException;
Expand Down Expand Up @@ -83,14 +82,7 @@ public static function fromXML(DOMElement $xml): static
TooManyElementsException::class,
);

$elements = [];
foreach ($xml->childNodes as $element) {
if (!($element instanceof DOMElement) || $element->namespaceURI === KeyValue::NS) {
continue;
}

$elements[] = new Chunk($element);
}
$elements = self::getChildElementsFromXML($xml);
Assert::maxCount(
$elements,
1,
Expand Down
11 changes: 1 addition & 10 deletions src/XML/ds/SignatureProperty.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

use DOMElement;
use SimpleSAML\Assert\Assert;
use SimpleSAML\XML\Chunk;
use SimpleSAML\XML\Exception\InvalidDOMElementException;
use SimpleSAML\XML\Exception\MissingElementException;
use SimpleSAML\XML\Exception\SchemaViolationException;
Expand Down Expand Up @@ -81,15 +80,7 @@ public static function fromXML(DOMElement $xml): static
$Target = self::getAttribute($xml, 'Target');
$Id = self::getOptionalAttribute($xml, 'Id', null);

$children = [];
foreach ($xml->childNodes as $child) {
if (!($child instanceof DOMElement)) {
continue;
}

$children[] = new Chunk($child);
}

$children = self::getChildElementsFromXML($xml);
Assert::minCount(
$children,
1,
Expand Down
Loading

0 comments on commit 446cbf3

Please sign in to comment.