Skip to content

Commit 446cbf3

Browse files
authored
Add element registry (#55)
* Add element registry * Leverage new getChildElementsFromXML * Fix phpstan-issues * Fix
1 parent 1007102 commit 446cbf3

17 files changed

+136
-153
lines changed

codecov.yml

+2
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,5 @@ comment:
1616
branches: null
1717
github_checks:
1818
annotations: false
19+
ignore:
20+
- 'src/XML/element.registry.php'

composer.json

+5-4
Original file line numberDiff line numberDiff line change
@@ -42,18 +42,19 @@
4242
"ext-pcre": "*",
4343
"ext-spl": "*",
4444

45-
"simplesamlphp/assert": "^1.1",
46-
"simplesamlphp/xml-common": "^1.15"
45+
"simplesamlphp/assert": "^1.3",
46+
"simplesamlphp/xml-common": "^1.18"
4747
},
4848
"require-dev": {
49-
"simplesamlphp/simplesamlphp-test-framework": "^1.5"
49+
"simplesamlphp/simplesamlphp-test-framework": "^1.7"
5050
},
5151
"config": {
5252
"allow-plugins": {
5353
"composer/package-versions-deprecated": true,
5454
"dealerdirect/phpcodesniffer-composer-installer": true,
55+
"phpstan/extension-installer": true,
5556
"simplesamlphp/composer-module-installer": true,
56-
"phpstan/extension-installer": true
57+
"simplesamlphp/composer-xmlprovider-installer": true
5758
}
5859
}
5960
}

src/XML/EncryptableElementTrait.php

+3-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,9 @@ public function encrypt(EncryptionAlgorithmInterface $encryptor): EncryptedData
6666

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

69-
$factory = new EncryptionAlgorithmFactory($this->getBlacklistedAlgorithms() ?? EncryptionAlgorithmFactory::DEFAULT_BLACKLIST);
69+
$factory = new EncryptionAlgorithmFactory(
70+
$this->getBlacklistedAlgorithms() ?? EncryptionAlgorithmFactory::DEFAULT_BLACKLIST,
71+
);
7072
$encryptor = $factory->getAlgorithm($this->blockCipherAlgId, $sessionKey);
7173
$encryptor->setBackend($this->getEncryptionBackend());
7274
}

src/XML/EncryptedElementTrait.php

+3-1
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,9 @@ protected function decryptData(EncryptionAlgorithmInterface $decryptor): string
131131
$encryptedKey = $this->getEncryptedKey();
132132
$decryptionKey = $encryptedKey->decrypt($decryptor);
133133

134-
$factory = new EncryptionAlgorithmFactory($this->getBlacklistedAlgorithms() ?? EncryptionAlgorithmFactory::DEFAULT_BLACKLIST);
134+
$factory = new EncryptionAlgorithmFactory(
135+
$this->getBlacklistedAlgorithms() ?? EncryptionAlgorithmFactory::DEFAULT_BLACKLIST,
136+
);
135137
$decryptor = $factory->getAlgorithm($encMethod->getAlgorithm(), new SymmetricKey($decryptionKey));
136138
$decryptor->setBackend($this->getEncryptionBackend());
137139
}

src/XML/SignedElementTrait.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,8 @@ private function verifyInternal(SignatureAlgorithmInterface $verifier): SignedEl
198198
if (
199199
$verifier?->verify(
200200
$c14nSignedInfo, // the canonicalized ds:SignedInfo element (plaintext)
201-
base64_decode($this->getSignature()->getSignatureValue()->getRawContent(), true), // the actual signature
201+
// the actual signature
202+
base64_decode($this->getSignature()->getSignatureValue()->getRawContent(), true),
202203
)
203204
) {
204205
/*

src/XML/ds/DigestMethod.php

+2-11
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
use DOMElement;
88
use SimpleSAML\Assert\Assert;
9-
use SimpleSAML\XML\Chunk;
109
use SimpleSAML\XML\Exception\InvalidDOMElementException;
1110
use SimpleSAML\XML\Exception\SchemaViolationException;
1211
use SimpleSAML\XML\ExtendableElementTrait;
@@ -29,7 +28,7 @@ final class DigestMethod extends AbstractDsElement
2928
* Initialize a DigestMethod element.
3029
*
3130
* @param string $Algorithm
32-
* @param \SimpleSAML\XML\Chunk[] $elements
31+
* @param list<\SimpleSAML\XML\SerializableElementInterface> $elements
3332
*/
3433
public function __construct(
3534
protected string $Algorithm,
@@ -73,15 +72,7 @@ public static function fromXML(DOMElement $xml): static
7372
Assert::same($xml->namespaceURI, DigestMethod::NS, InvalidDOMElementException::class);
7473

7574
$Algorithm = DigestMethod::getAttribute($xml, 'Algorithm');
76-
77-
$elements = [];
78-
foreach ($xml->childNodes as $elt) {
79-
if (!($elt instanceof DOMElement)) {
80-
continue;
81-
}
82-
83-
$elements[] = new Chunk($elt);
84-
}
75+
$elements = self::getChildElementsFromXML($xml);
8576

8677
return new static($Algorithm, $elements);
8778
}

src/XML/ds/DsObject.php

+1-17
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
use DOMElement;
88
use SimpleSAML\Assert\Assert;
9-
use SimpleSAML\XML\Chunk;
109
use SimpleSAML\XML\Exception\InvalidDOMElementException;
1110
use SimpleSAML\XML\ExtendableElementTrait;
1211
use SimpleSAML\XML\XsNamespace as NS;
@@ -112,22 +111,7 @@ public static function fromXML(DOMElement $xml): static
112111
$Id = DsObject::getOptionalAttribute($xml, 'Id', null);
113112
$MimeType = DsObject::getOptionalAttribute($xml, 'MimeType', null);
114113
$Encoding = DsObject::getOptionalAttribute($xml, 'Encoding', null);
115-
116-
$elements = [];
117-
foreach ($xml->childNodes as $elt) {
118-
if (!($elt instanceof DOMElement)) {
119-
// @TODO: support mixed content
120-
continue;
121-
} elseif ($elt->namespaceURI === self::NS) {
122-
$elements[] = match ($elt->localName) {
123-
'SignatureProperties' => SignatureProperties::fromXML($elt),
124-
'Manifest' => Manifest::fromXML($elt),
125-
default => new Chunk($elt),
126-
};
127-
}
128-
129-
$elements[] = new Chunk($elt);
130-
}
114+
$elements = self::getChildElementsFromXML($xml);
131115

132116
return new static($Id, $MimeType, $Encoding, $elements);
133117
}

src/XML/ds/KeyInfo.php

+44-61
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,12 @@
66

77
use DOMElement;
88
use SimpleSAML\Assert\Assert;
9-
use SimpleSAML\XML\Chunk;
109
use SimpleSAML\XML\Exception\InvalidDOMElementException;
10+
use SimpleSAML\XML\ExtendableElementTrait;
11+
use SimpleSAML\XML\SerializableElementInterface;
12+
use SimpleSAML\XML\XsNamespace as NS;
1113
use SimpleSAML\XMLSecurity\Constants as C;
1214
use SimpleSAML\XMLSecurity\Exception\InvalidArgumentException;
13-
use SimpleSAML\XMLSecurity\XML\dsig11\KeyInfoReference;
14-
use SimpleSAML\XMLSecurity\XML\xenc\EncryptedData;
15-
use SimpleSAML\XMLSecurity\XML\xenc\EncryptedKey;
1615

1716
/**
1817
* Class representing a ds:KeyInfo element.
@@ -21,11 +20,16 @@
2120
*/
2221
final class KeyInfo extends AbstractDsElement
2322
{
23+
use ExtendableElementTrait;
24+
25+
/** @var \SimpleSAML\XML\XsNamespace */
26+
public const XS_ANY_ELT_NAMESPACE = NS::OTHER;
27+
28+
2429
/**
2530
* Initialize a KeyInfo element.
2631
*
2732
* @param (
28-
* \SimpleSAML\XML\SerializableElementInterface|
2933
* \SimpleSAML\XMLSecurity\XML\ds\KeyName|
3034
* \SimpleSAML\XMLSecurity\XML\ds\KeyValue|
3135
* \SimpleSAML\XMLSecurity\XML\ds\RetrievalMethod|
@@ -34,29 +38,26 @@ final class KeyInfo extends AbstractDsElement
3438
* \SimpleSAML\XMLSecurity\XML\xenc\EncryptedData|
3539
* \SimpleSAML\XMLSecurity\XML\xenc\EncryptedKey
3640
* )[] $info
41+
* @param \SimpleSAML\XML\SerializableElementInterface[] $children
3742
* @param string|null $Id
3843
*/
3944
public function __construct(
4045
protected array $info,
46+
array $children = [],
4147
protected ?string $Id = null,
4248
) {
43-
Assert::notEmpty($info, 'ds:KeyInfo cannot be empty', InvalidArgumentException::class);
44-
Assert::maxCount($info, C::UNBOUNDED_LIMIT);
45-
Assert::allIsInstanceOfAny(
46-
$info,
47-
[
48-
Chunk::class,
49-
KeyName::class,
50-
KeyValue::class,
51-
RetrievalMethod::class,
52-
X509Data::class,
53-
EncryptedData::class,
54-
EncryptedKey::class,
55-
],
56-
'KeyInfo can only contain instances of KeyName, X509Data, EncryptedKey or Chunk.',
49+
$combi = array_merge($info, $children);
50+
51+
Assert::notEmpty($combi, 'ds:KeyInfo cannot be empty', InvalidArgumentException::class);
52+
Assert::maxCount($combi, C::UNBOUNDED_LIMIT);
53+
Assert::allIsInstanceOf(
54+
$combi,
55+
SerializableElementInterface::class,
5756
InvalidArgumentException::class,
5857
);
5958
Assert::nullOrValidNCName($Id);
59+
60+
$this->setElements($children);
6061
}
6162

6263

@@ -74,20 +75,11 @@ public function getId(): ?string
7475
/**
7576
* Collect the value of the info-property
7677
*
77-
* @return (
78-
* \SimpleSAML\XML\SerializableElementInterface|
79-
* \SimpleSAML\XMLSecurity\XML\ds\KeyName|
80-
* \SimpleSAML\XMLSecurity\XML\ds\KeyValue|
81-
* \SimpleSAML\XMLSecurity\XML\ds\RetrievalMethod|
82-
* \SimpleSAML\XMLSecurity\XML\ds\X509Data|
83-
* \SimpleSAML\XMLSecurity\XML\dsig11\KeyInfoReference|
84-
* \SimpleSAML\XMLSecurity\XML\xenc\EncryptedData|
85-
* \SimpleSAML\XMLSecurity\XML\xenc\EncryptedKey
86-
* )[]
78+
* @return list<\SimpleSAML\XML\SerializableElementInterface>
8779
*/
8880
public function getInfo(): array
8981
{
90-
return $this->info;
82+
return array_merge($this->info, $this->getElements());
9183
}
9284

9385

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

108100
$Id = self::getOptionalAttribute($xml, 'Id', null);
109-
$info = [];
110-
111-
foreach ($xml->childNodes as $n) {
112-
if (!($n instanceof DOMElement)) {
113-
continue;
114-
} elseif ($n->namespaceURI === C::NS_XDSIG) {
115-
$info[] = match ($n->localName) {
116-
'KeyName' => KeyName::fromXML($n),
117-
'KeyValue' => KeyValue::fromXML($n),
118-
'RetrievalMethod' => RetrievalMethod::fromXML($n),
119-
'X509Data' => X509Data::fromXML($n),
120-
default => new Chunk($n),
121-
};
122-
} elseif ($n->namespaceURI === C::NS_XDSIG11) {
123-
$info[] = match ($n->localName) {
124-
'KeyInfoReference' => KeyInfoReference::fromXML($n),
125-
default => new Chunk($n),
126-
};
127-
} elseif ($n->namespaceURI === C::NS_XENC) {
128-
$info[] = match ($n->localName) {
129-
'EncryptedData' => EncryptedData::fromXML($n),
130-
'EncryptedKey' => EncryptedKey::fromXML($n),
131-
default => new Chunk($n),
132-
};
133-
} else {
134-
$info[] = new Chunk($n);
135-
}
136-
}
137101

138-
return new static($info, $Id);
102+
$keyName = KeyName::getChildrenOfClass($xml);
103+
$keyValue = KeyValue::getChildrenOfClass($xml);
104+
$retrievalMethod = RetrievalMethod::getChildrenOfClass($xml);
105+
$x509Data = X509Data::getChildrenOfClass($xml);
106+
//$pgpData = PGPData::getChildrenOfClass($xml);
107+
//$spkiData = SPKIData::getChildrenOfClass($xml);
108+
//$mgmtData = MgmtData::getChildrenOfClass($xml);
109+
110+
$info = array_merge(
111+
$keyName,
112+
$keyValue,
113+
$retrievalMethod,
114+
$x509Data,
115+
//$pgpdata,
116+
//$spkidata,
117+
//$mgmtdata,
118+
);
119+
120+
$children = self::getChildElementsFromXML($xml);
121+
return new static($info, $children, $Id);
139122
}
140123

141124

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

156-
foreach ($this->getInfo() as $n) {
157-
$n->toXML($e);
139+
foreach ($this->getInfo() as $elt) {
140+
$elt->toXML($e);
158141
}
159142

160143
return $e;

src/XML/ds/KeyValue.php

+1-9
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
use DOMElement;
88
use SimpleSAML\Assert\Assert;
9-
use SimpleSAML\XML\Chunk;
109
use SimpleSAML\XML\ElementInterface;
1110
use SimpleSAML\XML\Exception\InvalidDOMElementException;
1211
use SimpleSAML\XML\Exception\SchemaViolationException;
@@ -83,14 +82,7 @@ public static function fromXML(DOMElement $xml): static
8382
TooManyElementsException::class,
8483
);
8584

86-
$elements = [];
87-
foreach ($xml->childNodes as $element) {
88-
if (!($element instanceof DOMElement) || $element->namespaceURI === KeyValue::NS) {
89-
continue;
90-
}
91-
92-
$elements[] = new Chunk($element);
93-
}
85+
$elements = self::getChildElementsFromXML($xml);
9486
Assert::maxCount(
9587
$elements,
9688
1,

src/XML/ds/SignatureProperty.php

+1-10
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
use DOMElement;
88
use SimpleSAML\Assert\Assert;
9-
use SimpleSAML\XML\Chunk;
109
use SimpleSAML\XML\Exception\InvalidDOMElementException;
1110
use SimpleSAML\XML\Exception\MissingElementException;
1211
use SimpleSAML\XML\Exception\SchemaViolationException;
@@ -81,15 +80,7 @@ public static function fromXML(DOMElement $xml): static
8180
$Target = self::getAttribute($xml, 'Target');
8281
$Id = self::getOptionalAttribute($xml, 'Id', null);
8382

84-
$children = [];
85-
foreach ($xml->childNodes as $child) {
86-
if (!($child instanceof DOMElement)) {
87-
continue;
88-
}
89-
90-
$children[] = new Chunk($child);
91-
}
92-
83+
$children = self::getChildElementsFromXML($xml);
9384
Assert::minCount(
9485
$children,
9586
1,

0 commit comments

Comments
 (0)