Skip to content

Commit 7a7d261

Browse files
committed
Add element xenc:DHKeyValue
1 parent ff5cbf0 commit 7a7d261

File tree

5 files changed

+324
-1
lines changed

5 files changed

+324
-1
lines changed

src/XML/element.registry.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
'AgreementMethod' => '\SimpleSAML\XMLSecurity\XML\xenc\AgreementMethod',
4747
'CipherData' => '\SimpleSAML\XMLSecurity\XML\xenc\CipherData',
4848
'CipherReference' => '\SimpleSAML\XMLSecurity\XML\xenc\CipherReference',
49-
// 'DHKeyValue' => '\SimpleSAML\XMLSecurity\XML\xenc\DHKeyValue',
49+
'DHKeyValue' => '\SimpleSAML\XMLSecurity\XML\xenc\DHKeyValue',
5050
'EncryptedData' => '\SimpleSAML\XMLSecurity\XML\xenc\EncryptedData',
5151
'EncryptedKey' => '\SimpleSAML\XMLSecurity\XML\xenc\EncryptedKey',
5252
'EncryptionProperties' => '\SimpleSAML\XMLSecurity\XML\xenc\EncryptionProperties',
+188
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SimpleSAML\XMLSecurity\XML\xenc;
6+
7+
use DOMElement;
8+
use SimpleSAML\Assert\Assert;
9+
use SimpleSAML\XML\Exception\InvalidDOMElementException;
10+
use SimpleSAML\XML\Exception\MissingElementException;
11+
use SimpleSAML\XML\Exception\SchemaViolationException;
12+
use SimpleSAML\XML\Exception\TooManyElementsException;
13+
14+
use function array_pop;
15+
16+
/**
17+
* A class implementing the xenc:AbstractDHKeyValueType element.
18+
*
19+
* @package simplesamlphp/xml-security
20+
*/
21+
abstract class AbstractDHKeyValueType extends AbstractXencElement
22+
{
23+
/**
24+
* DHKeyValueType constructor.
25+
*
26+
* @param \SimpleSAML\XMLSecurity\XML\xenc\XencPublic $xencPublic
27+
* @param \SimpleSAML\XMLSecurity\XML\xenc\P|null $p
28+
* @param \SimpleSAML\XMLSecurity\XML\xenc\Q|null $q
29+
* @param \SimpleSAML\XMLSecurity\XML\xenc\Generator|null $generator
30+
* @param \SimpleSAML\XMLSecurity\XML\xenc\Seed|null $seed
31+
* @param \SimpleSAML\XMLSecurity\XML\xenc\PgenCounter|null $pgenCounter
32+
*/
33+
final public function __construct(
34+
protected XencPublic $xencPublic,
35+
protected ?P $p = null,
36+
protected ?Q $q = null,
37+
protected ?Generator $generator = null,
38+
protected ?Seed $seed = null,
39+
protected ?PgenCounter $pgenCounter = null,
40+
) {
41+
if ($p !== null || $q !== null || $generator !== null) {
42+
Assert::allNotNull([$p, $q, $generator], SchemaViolationException::class);
43+
} else {
44+
Assert::allNull([$p, $q, $generator], SchemaViolationException::class);
45+
}
46+
47+
if ($seed !== null || $pgenCounter !== null) {
48+
Assert::allNotNull([$seed, $pgenCounter], SchemaViolationException::class);
49+
} else {
50+
Assert::allNull([$seed, $pgenCounter], SchemaViolationException::class);
51+
}
52+
}
53+
54+
55+
/**
56+
* Get the Public.
57+
*
58+
* @return \SimpleSAML\XMLSecurity\XML\xenc\XencPublic
59+
*/
60+
public function getPublic(): XencPublic
61+
{
62+
return $this->xencPublic;
63+
}
64+
65+
66+
/**
67+
* Get the P.
68+
*
69+
* @return \SimpleSAML\XMLSecurity\XML\xenc\P|null
70+
*/
71+
public function getP(): ?P
72+
{
73+
return $this->p;
74+
}
75+
76+
77+
/**
78+
* Get the Q.
79+
*
80+
* @return \SimpleSAML\XMLSecurity\XML\xenc\Q|null
81+
*/
82+
public function getQ(): ?Q
83+
{
84+
return $this->q;
85+
}
86+
87+
88+
/**
89+
* Get the Generator.
90+
*
91+
* @return \SimpleSAML\XMLSecurity\XML\xenc\Generator|null
92+
*/
93+
public function getGenerator(): ?Generator
94+
{
95+
return $this->generator;
96+
}
97+
98+
99+
/**
100+
* Get the Seed.
101+
*
102+
* @return \SimpleSAML\XMLSecurity\XML\xenc\Seed|null
103+
*/
104+
public function getSeed(): ?Seed
105+
{
106+
return $this->seed;
107+
}
108+
109+
110+
/**
111+
* Get the PgenCounter.
112+
*
113+
* @return \SimpleSAML\XMLSecurity\XML\xenc\PgenCounter|null
114+
*/
115+
public function getPgenCounter(): ?PgenCounter
116+
{
117+
return $this->pgenCounter;
118+
}
119+
120+
121+
/**
122+
* Initialize an DHKeyValue object from an existing XML.
123+
*
124+
* @param \DOMElement $xml
125+
* @return static
126+
*
127+
* @throws \SimpleSAML\XML\Exception\InvalidDOMElementException
128+
* if the qualified name of the supplied element is wrong
129+
* @throws \SimpleSAML\XML\Exception\MissingAttributeException
130+
* if the supplied element is missing one of the mandatory attributes
131+
* @throws \SimpleSAML\XML\Exception\TooManyElementsException
132+
* if too many child-elements of a type are specified
133+
*/
134+
public static function fromXML(DOMElement $xml): static
135+
{
136+
Assert::same($xml->localName, 'DHKeyValue', InvalidDOMElementException::class);
137+
Assert::same($xml->namespaceURI, static::NS, InvalidDOMElementException::class);
138+
139+
$xencPublic = XencPublic::getChildrenOfClass($xml);
140+
Assert::minCount($xencPublic, 1, MissingElementException::class);
141+
Assert::maxCount($xencPublic, 1, TooManyElementsException::class);
142+
143+
$p = P::getChildrenOfClass($xml);
144+
Assert::maxCount($p, 1, TooManyElementsException::class);
145+
146+
$q = Q::getChildrenOfClass($xml);
147+
Assert::maxCount($q, 1, TooManyElementsException::class);
148+
149+
$generator = Generator::getChildrenOfClass($xml);
150+
Assert::maxCount($generator, 1, TooManyElementsException::class);
151+
152+
$seed = Seed::getChildrenOfClass($xml);
153+
Assert::maxCount($seed, 1, TooManyElementsException::class);
154+
155+
$pgenCounter = PgenCounter::getChildrenOfClass($xml);
156+
Assert::maxCount($pgenCounter, 1, TooManyElementsException::class);
157+
158+
return new static(
159+
array_pop($xencPublic),
160+
array_pop($p),
161+
array_pop($q),
162+
array_pop($generator),
163+
array_pop($seed),
164+
array_pop($pgenCounter),
165+
);
166+
}
167+
168+
169+
/**
170+
* Convert this DHKeyValue object to XML.
171+
*
172+
* @param \DOMElement|null $parent The element we should append this DHKeyValue to.
173+
* @return \DOMElement
174+
*/
175+
public function toXML(DOMElement $parent = null): DOMElement
176+
{
177+
$e = $this->instantiateParentElement($parent);
178+
179+
$this->getP()?->toXML($e);
180+
$this->getQ()?->toXML($e);
181+
$this->getGenerator()?->toXML($e);
182+
$this->getPublic()->toXML($e);
183+
$this->getSeed()?->toXML($e);
184+
$this->getPgenCounter()?->toXML($e);
185+
186+
return $e;
187+
}
188+
}

src/XML/xenc/DHKeyValue.php

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SimpleSAML\XMLSecurity\XML\xenc;
6+
7+
/**
8+
* A class implementing the xenc:DHKeyValue element.
9+
*
10+
* @package simplesamlphp/xml-security
11+
*/
12+
final class DHKeyValue extends AbstractDHKeyValueType
13+
{
14+
}

tests/XML/xenc/DHKeyValueTest.php

+113
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SimpleSAML\XMLSecurity\Test\XML\xenc;
6+
7+
use PHPUnit\Framework\Attributes\CoversClass;
8+
use PHPUnit\Framework\TestCase;
9+
use SimpleSAML\XML\DOMDocumentFactory;
10+
use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait;
11+
use SimpleSAML\XML\TestUtils\SerializableElementTestTrait;
12+
use SimpleSAML\XMLSecurity\Utils\XPath;
13+
use SimpleSAML\XMLSecurity\XML\xenc\AbstractDHKeyValueType;
14+
use SimpleSAML\XMLSecurity\XML\xenc\AbstractXencElement;
15+
use SimpleSAML\XMLSecurity\XML\xenc\DHKeyValue;
16+
use SimpleSAML\XMLSecurity\XML\xenc\Generator;
17+
use SimpleSAML\XMLSecurity\XML\xenc\P;
18+
use SimpleSAML\XMLSecurity\XML\xenc\PgenCounter;
19+
use SimpleSAML\XMLSecurity\XML\xenc\Q;
20+
use SimpleSAML\XMLSecurity\XML\xenc\Seed;
21+
use SimpleSAML\XMLSecurity\XML\xenc\XencPublic;
22+
23+
use function dirname;
24+
use function strval;
25+
26+
/**
27+
* Class \SimpleSAML\XMLSecurity\Test\XML\xenc\DHKeyValueTest
28+
*
29+
* @covers \SimpleSAML\XMLSecurity\XML\xenc\AbstractXencElement
30+
* @covers \SimpleSAML\XMLSecurity\XML\xenc\AbstractDHKeyValueType
31+
* @covers \SimpleSAML\XMLSecurity\XML\xenc\DHKeyValue
32+
*
33+
* @package simplesamlphp/xml-security
34+
*/
35+
#[CoversClass(AbstractXencElement::class)]
36+
#[CoversClass(AbstractDHKeyValueType::class)]
37+
#[CoversClass(DHKeyValue::class)]
38+
final class DHKeyValueTest extends TestCase
39+
{
40+
use SchemaValidationTestTrait;
41+
use SerializableElementTestTrait;
42+
43+
/**
44+
*/
45+
public static function setUpBeforeClass(): void
46+
{
47+
self::$testedClass = DHKeyValue::class;
48+
49+
self::$schemaFile = dirname(__FILE__, 4) . '/resources/schemas/xenc-schema.xsd';
50+
51+
self::$xmlRepresentation = DOMDocumentFactory::fromFile(
52+
dirname(__FILE__, 3) . '/resources/xml/xenc_DHKeyValue.xml',
53+
);
54+
}
55+
56+
57+
/**
58+
*/
59+
public function testMarshalling(): void
60+
{
61+
$xencPublic = new XencPublic('/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI=');
62+
$p = new P('/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI=');
63+
$q = new Q('/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI=');
64+
$generator = new Generator('/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI=');
65+
$seed = new Seed('/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI=');
66+
$pgenCounter = new PgenCounter('/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI=');
67+
68+
$dhKeyValue = new DHKeyValue($xencPublic, $p, $q, $generator, $seed, $pgenCounter);
69+
70+
$this->assertEquals(
71+
self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement),
72+
strval($dhKeyValue),
73+
);
74+
}
75+
/**
76+
*/
77+
public function testMarshallingElementOrder(): void
78+
{
79+
$xencPublic = new XencPublic('/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI=');
80+
$p = new P('/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI=');
81+
$q = new Q('/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI=');
82+
$generator = new Generator('/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI=');
83+
$seed = new Seed('/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI=');
84+
$pgenCounter = new PgenCounter('/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI=');
85+
86+
$dhKeyValue = new DHKeyValue($xencPublic, $p, $q, $generator, $seed, $pgenCounter);
87+
88+
// Marshall it to a \DOMElement
89+
$dhKeyValueElement = $dhKeyValue->toXML();
90+
91+
$xpCache = XPath::getXPath($dhKeyValueElement);
92+
93+
// Test for an P
94+
/** @var \DOMElement[] $pElements */
95+
$pElements = XPath::xpQuery($dhKeyValueElement, './xenc:P', $xpCache);
96+
$this->assertCount(1, $pElements);
97+
98+
// Test ordering of DHKeyValue contents
99+
/** @var \DOMElement[] $dhKeyValueElements */
100+
$dhKeyValueElements = XPath::xpQuery(
101+
$dhKeyValueElement,
102+
'./xenc:P/following-sibling::*',
103+
$xpCache,
104+
);
105+
106+
$this->assertCount(5, $dhKeyValueElements);
107+
$this->assertEquals('xenc:Q', $dhKeyValueElements[0]->tagName);
108+
$this->assertEquals('xenc:Generator', $dhKeyValueElements[1]->tagName);
109+
$this->assertEquals('xenc:Public', $dhKeyValueElements[2]->tagName);
110+
$this->assertEquals('xenc:seed', $dhKeyValueElements[3]->tagName);
111+
$this->assertEquals('xenc:pgenCounter', $dhKeyValueElements[4]->tagName);
112+
}
113+
}
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<xenc:DHKeyValue xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
2+
<xenc:P>/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI=</xenc:P>
3+
<xenc:Q>/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI=</xenc:Q>
4+
<xenc:Generator>/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI=</xenc:Generator>
5+
<xenc:Public>/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI=</xenc:Public>
6+
<xenc:seed>/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI=</xenc:seed>
7+
<xenc:pgenCounter>/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI=</xenc:pgenCounter>
8+
</xenc:DHKeyValue>

0 commit comments

Comments
 (0)