Skip to content

Commit

Permalink
Add element xenc:DHKeyValue
Browse files Browse the repository at this point in the history
  • Loading branch information
tvdijen committed Nov 28, 2024
1 parent ff5cbf0 commit 5e49436
Show file tree
Hide file tree
Showing 5 changed files with 324 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/XML/element.registry.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
'AgreementMethod' => '\SimpleSAML\XMLSecurity\XML\xenc\AgreementMethod',
'CipherData' => '\SimpleSAML\XMLSecurity\XML\xenc\CipherData',
'CipherReference' => '\SimpleSAML\XMLSecurity\XML\xenc\CipherReference',
// 'DHKeyValue' => '\SimpleSAML\XMLSecurity\XML\xenc\DHKeyValue',
'DHKeyValue' => '\SimpleSAML\XMLSecurity\XML\xenc\DHKeyValue',
'EncryptedData' => '\SimpleSAML\XMLSecurity\XML\xenc\EncryptedData',
'EncryptedKey' => '\SimpleSAML\XMLSecurity\XML\xenc\EncryptedKey',
'EncryptionProperties' => '\SimpleSAML\XMLSecurity\XML\xenc\EncryptionProperties',
Expand Down
188 changes: 188 additions & 0 deletions src/XML/xenc/AbstractDHKeyValueType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
<?php

declare(strict_types=1);

namespace SimpleSAML\XMLSecurity\XML\xenc;

use DOMElement;
use SimpleSAML\Assert\Assert;
use SimpleSAML\XML\Exception\InvalidDOMElementException;
use SimpleSAML\XML\Exception\MissingElementException;
use SimpleSAML\XML\Exception\SchemaViolationException;
use SimpleSAML\XML\Exception\TooManyElementsException;

use function array_pop;

/**
* A class implementing the xenc:AbstractDHKeyValueType element.
*
* @package simplesamlphp/xml-security
*/
abstract class AbstractDHKeyValueType extends AbstractXencElement
{
/**
* DHKeyValueType constructor.
*
* @param \SimpleSAML\XMLSecurity\XML\xenc\XencPublic $xencPublic
* @param \SimpleSAML\XMLSecurity\XML\xenc\P|null $p
* @param \SimpleSAML\XMLSecurity\XML\xenc\Q|null $q
* @param \SimpleSAML\XMLSecurity\XML\xenc\Generator|null $generator
* @param \SimpleSAML\XMLSecurity\XML\xenc\Seed|null $seed
* @param \SimpleSAML\XMLSecurity\XML\xenc\PgenCounter|null $pgenCounter
*/
final public function __construct(
protected XencPublic $xencPublic,
protected ?P $p = null,
protected ?Q $q = null,
protected ?Generator $generator = null,
protected ?Seed $seed = null,
protected ?PgenCounter $pgenCounter = null,
) {
if ($p !== null || $q !== null || $generator !== null) {
Assert::allNotNull([$p, $q, $generator], SchemaViolationException::class);
} else {
Assert::allNull([$p, $q, $generator], SchemaViolationException::class);
}

if ($seed !== null || $pgenCounter !== null) {
Assert::allNotNull([$seed, $pgenCounter], SchemaViolationException::class);
} else {
Assert::allNull([$seed, $pgenCounter], SchemaViolationException::class);
}
}


/**
* Get the Public.
*
* @return \SimpleSAML\XMLSecurity\XML\xenc\XencPublic
*/
public function getPublic(): XencPublic
{
return $this->xencPublic;
}


/**
* Get the P.
*
* @return \SimpleSAML\XMLSecurity\XML\xenc\P|null
*/
public function getP(): ?P
{
return $this->p;
}


/**
* Get the Q.
*
* @return \SimpleSAML\XMLSecurity\XML\xenc\Q|null
*/
public function getQ(): ?Q
{
return $this->q;
}


/**
* Get the Generator.
*
* @return \SimpleSAML\XMLSecurity\XML\xenc\Generator|null
*/
public function getGenerator(): ?Generator
{
return $this->generator;
}


/**
* Get the Seed.
*
* @return \SimpleSAML\XMLSecurity\XML\xenc\Seed|null
*/
public function getSeed(): ?Seed
{
return $this->seed;
}


/**
* Get the PgenCounter.
*
* @return \SimpleSAML\XMLSecurity\XML\xenc\PgenCounter|null
*/
public function getPgenCounter(): ?PgenCounter
{
return $this->pgenCounter;
}


/**
* Initialize an DHKeyValue object from an existing XML.
*
* @param \DOMElement $xml
* @return static
*
* @throws \SimpleSAML\XML\Exception\InvalidDOMElementException
* if the qualified name of the supplied element is wrong
* @throws \SimpleSAML\XML\Exception\MissingAttributeException
* if the supplied element is missing one of the mandatory attributes
* @throws \SimpleSAML\XML\Exception\TooManyElementsException
* if too many child-elements of a type are specified
*/
public static function fromXML(DOMElement $xml): static
{
Assert::same($xml->localName, 'DHKeyValue', InvalidDOMElementException::class);
Assert::same($xml->namespaceURI, static::NS, InvalidDOMElementException::class);

$xencPublic = XencPublic::getChildrenOfClass($xml);
Assert::minCount($xencPublic, 1, MissingElementException::class);
Assert::maxCount($xencPublic, 1, TooManyElementsException::class);

$p = P::getChildrenOfClass($xml);
Assert::maxCount($p, 1, TooManyElementsException::class);

$q = Q::getChildrenOfClass($xml);
Assert::maxCount($q, 1, TooManyElementsException::class);

$generator = Generator::getChildrenOfClass($xml);
Assert::maxCount($generator, 1, TooManyElementsException::class);

$seed = Seed::getChildrenOfClass($xml);
Assert::maxCount($seed, 1, TooManyElementsException::class);

$pgenCounter = PgenCounter::getChildrenOfClass($xml);
Assert::maxCount($pgenCounter, 1, TooManyElementsException::class);

return new static(
array_pop($xencPublic),
array_pop($p),
array_pop($q),
array_pop($generator),
array_pop($seed),
array_pop($pgenCounter),
);
}


/**
* Convert this DHKeyValue object to XML.
*
* @param \DOMElement|null $parent The element we should append this DHKeyValue to.
* @return \DOMElement
*/
public function toXML(DOMElement $parent = null): DOMElement
{
$e = $this->instantiateParentElement($parent);

$this->getP()?->toXML($e);
$this->getQ()?->toXML($e);
$this->getGenerator()?->toXML($e);
$this->getPublic()->toXML($e);
$this->getSeed()?->toXML($e);
$this->getPgenCounter()?->toXML($e);

return $e;
}
}
14 changes: 14 additions & 0 deletions src/XML/xenc/DHKeyValue.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

declare(strict_types=1);

namespace SimpleSAML\XMLSecurity\XML\xenc;

/**
* A class implementing the xenc:DHKeyValue element.
*
* @package simplesamlphp/xml-security
*/
final class DHKeyValue extends AbstractDHKeyValueType
{
}
113 changes: 113 additions & 0 deletions tests/XML/xenc/DHKeyValueTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
<?php

declare(strict_types=1);

namespace SimpleSAML\XMLSecurity\Test\XML\xenc;

use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\TestCase;
use SimpleSAML\XML\DOMDocumentFactory;
use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait;
use SimpleSAML\XML\TestUtils\SerializableElementTestTrait;
use SimpleSAML\XMLSecurity\Utils\XPath;
use SimpleSAML\XMLSecurity\XML\xenc\AbstractDHKeyValueType;
use SimpleSAML\XMLSecurity\XML\xenc\AbstractXencElement;
use SimpleSAML\XMLSecurity\XML\xenc\DHKeyValue;
use SimpleSAML\XMLSecurity\XML\xenc\Generator;
use SimpleSAML\XMLSecurity\XML\xenc\P;
use SimpleSAML\XMLSecurity\XML\xenc\PgenCounter;
use SimpleSAML\XMLSecurity\XML\xenc\Q;
use SimpleSAML\XMLSecurity\XML\xenc\Seed;
use SimpleSAML\XMLSecurity\XML\xenc\XencPublic;

use function dirname;
use function strval;

/**
* Class \SimpleSAML\XMLSecurity\Test\XML\xenc\DHKeyValueTest
*
* @covers \SimpleSAML\XMLSecurity\XML\xenc\AbstractXencElement
* @covers \SimpleSAML\XMLSecurity\XML\xenc\AbstractDHKeyValueType
* @covers \SimpleSAML\XMLSecurity\XML\xenc\DHKeyValue
*
* @package simplesamlphp/xml-security
*/
#[CoversClass(AbstractXencElement::class)]
#[CoversClass(AbstractDHKeyValueType::class)]
#[CoversClass(DHKeyValue::class)]
final class DHKeyValueTest extends TestCase
{
use SchemaValidationTestTrait;
use SerializableElementTestTrait;

/**
*/
public static function setUpBeforeClass(): void
{
self::$testedClass = DHKeyValue::class;

self::$schemaFile = dirname(__FILE__, 4) . '/resources/schemas/xenc-schema.xsd';

self::$xmlRepresentation = DOMDocumentFactory::fromFile(
dirname(__FILE__, 3) . '/resources/xml/xenc_DHKeyValue.xml',
);
}


/**
*/
public function testMarshalling(): void
{
$xencPublic = new XencPublic('/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI=');
$p = new P('/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI=');
$q = new Q('/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI=');
$generator = new Generator('/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI=');
$seed = new Seed('/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI=');
$pgenCounter = new PgenCounter('/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI=');

$dhKeyValue = new DHKeyValue($xencPublic, $p, $q, $generator, $seed, $pgenCounter);

$this->assertEquals(
self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement),
strval($dhKeyValue),
);
}
/**
*/
public function testMarshallingElementOrder(): void
{
$xencPublic = new XencPublic('/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI=');
$p = new P('/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI=');
$q = new Q('/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI=');
$generator = new Generator('/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI=');
$seed = new Seed('/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI=');
$pgenCounter = new PgenCounter('/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI=');

$dhKeyValue = new DHKeyValue($xencPublic, $p, $q, $generator, $seed, $pgenCounter);

// Marshall it to a \DOMElement
$dhKeyValueElement = $dhKeyValue->toXML();

$xpCache = XPath::getXPath($dhKeyValueElement);

// Test for an P
/** @var \DOMElement[] $kaNonceElements */
$pElements = XPath::xpQuery($dhKeyValueElement, './xenc:P', $xpCache);

Check failure on line 95 in tests/XML/xenc/DHKeyValueTest.php

View workflow job for this annotation

GitHub Actions / Quality control

Variable $kaNonceElements in PHPDoc tag @var does not match assigned variable $pElements.

Check failure on line 95 in tests/XML/xenc/DHKeyValueTest.php

View workflow job for this annotation

GitHub Actions / Quality control

Variable $kaNonceElements in PHPDoc tag @var does not match assigned variable $pElements.
$this->assertCount(1, $pElements);

// Test ordering of DHKeyValue contents
/** @var \DOMElement[] $dhKeyValueElements */
$dhKeyValueElements = XPath::xpQuery(
$dhKeyValueElement,
'./xenc:P/following-sibling::*',
$xpCache,
);

$this->assertCount(5, $dhKeyValueElements);
$this->assertEquals('xenc:Q', $dhKeyValueElements[0]->tagName);
$this->assertEquals('xenc:Generator', $dhKeyValueElements[1]->tagName);
$this->assertEquals('xenc:Public', $dhKeyValueElements[2]->tagName);
$this->assertEquals('xenc:seed', $dhKeyValueElements[3]->tagName);
$this->assertEquals('xenc:pgenCounter', $dhKeyValueElements[4]->tagName);
}
}
8 changes: 8 additions & 0 deletions tests/resources/xml/xenc_DHKeyValue.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<xenc:DHKeyValue xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
<xenc:P>/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI=</xenc:P>
<xenc:Q>/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI=</xenc:Q>
<xenc:Generator>/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI=</xenc:Generator>
<xenc:Public>/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI=</xenc:Public>
<xenc:seed>/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI=</xenc:seed>
<xenc:pgenCounter>/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI=</xenc:pgenCounter>
</xenc:DHKeyValue>

0 comments on commit 5e49436

Please sign in to comment.