Skip to content

Commit 2c5d0a2

Browse files
committed
Add ds:PGPData element
1 parent 6f5c6f9 commit 2c5d0a2

16 files changed

+292
-8
lines changed

src/XML/ds/AbstractKeyInfoType.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ abstract class AbstractKeyInfoType extends AbstractDsElement
3535
* \SimpleSAML\XMLSecurity\XML\ds\KeyValue|
3636
* \SimpleSAML\XMLSecurity\XML\ds\RetrievalMethod|
3737
* \SimpleSAML\XMLSecurity\XML\ds\X509Data|
38+
* \SimpleSAML\XMLSecurity\XML\ds\PGPData|
3839
* \SimpleSAML\XML\SerializableElementInterface
3940
* )[] $info
4041
* @param string|null $Id
@@ -64,7 +65,7 @@ final public function __construct(
6465
if ($item instanceof AbstractDsElement) {
6566
Assert::isInstanceOfAny(
6667
$item,
67-
[KeyName::class, KeyValue::class, RetrievalMethod::class, X509Data::class],
68+
[KeyName::class, KeyValue::class, RetrievalMethod::class, X509Data::class, PGPData::class],
6869
SchemaViolationException::class,
6970
);
7071
}

src/XML/ds/AbstractPGPDataType.php

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SimpleSAML\XMLSecurity\XML\ds;
6+
7+
use DOMElement;
8+
use SimpleSAML\Assert\Assert;
9+
use SimpleSAML\XML\Exception\InvalidDOMElementException;
10+
use SimpleSAML\XML\Exception\SchemaViolationException;
11+
use SimpleSAML\XML\Exception\TooManyElementsException;
12+
use SimpleSAML\XML\ExtendableElementTrait;
13+
use SimpleSAML\XML\XsNamespace as NS;
14+
use SimpleSAML\XMLSecurity\XML\ds\AbstractDsElement;
15+
16+
use function array_pop;
17+
18+
/**
19+
* Abstract class representing the PGPDataType.
20+
*
21+
* @package simplesamlphp/xml-security
22+
*/
23+
abstract class AbstractPGPDataType extends AbstractDsElement
24+
{
25+
use ExtendableElementTrait;
26+
27+
/** @var \SimpleSAML\XML\XsNamespace */
28+
public const XS_ANY_ELT_NAMESPACE = NS::OTHER;
29+
30+
31+
/**
32+
* Initialize a PGPData element.
33+
*
34+
* @param \SimpleSAML\XMLSecurity\XML\ds\PGPKeyID|null $pgpKeyId
35+
* @param \SimpleSAML\XMLSecurity\XML\ds\PGPKeyPacket|null $pgpKeyPacket
36+
* @param array<\SimpleSAML\XML\SerializableElementInterface> $children
37+
*/
38+
final public function __construct(
39+
protected ?PGPKeyID $pgpKeyId = null,
40+
protected ?PGPKeyPacket $pgpKeyPacket = null,
41+
array $children = [],
42+
) {
43+
if ($pgpKeyId === null && $pgpKeyPacket === null) {
44+
throw new SchemaViolationException("ds:PGPKeyID and ds:PGPKeyPacket can't both be null.");
45+
}
46+
47+
$this->setElements($children);
48+
}
49+
50+
51+
/**
52+
* Collect the value of the PGPKeyID-property
53+
*
54+
* @return \SimpleSAML\XMLSecurity\XML\ds\PGPKeyID|null
55+
*/
56+
public function getPGPKeyID(): ?PGPKeyID
57+
{
58+
return $this->pgpKeyId;
59+
}
60+
61+
62+
/**
63+
* Collect the value of the PGPKeyPacket-property
64+
*
65+
* @return \SimpleSAML\XMLSecurity\XML\ds\PGPKeyPacket|null
66+
*/
67+
public function getPGPKeyPacket(): ?PGPKeyPacket
68+
{
69+
return $this->pgpKeyPacket;
70+
}
71+
72+
73+
/**
74+
* Convert XML into a PGPData
75+
*
76+
* @param \DOMElement $xml The XML element we should load
77+
* @return static
78+
*
79+
* @throws \SimpleSAML\XML\Exception\InvalidDOMElementException
80+
* If the qualified name of the supplied element is wrong
81+
*/
82+
public static function fromXML(DOMElement $xml): static
83+
{
84+
Assert::same($xml->localName, static::getLocalName(), InvalidDOMElementException::class);
85+
Assert::same($xml->namespaceURI, static::NS, InvalidDOMElementException::class);
86+
87+
$pgpKeyId = PGPKeyID::getChildrenOfClass($xml);
88+
Assert::maxCount($pgpKeyId, 1, TooManyElementsException::class);
89+
90+
$pgpKeyPacket = PGPKeyPacket::getChildrenOfClass($xml);
91+
Assert::maxCount($pgpKeyPacket, 1, TooManyElementsException::class);
92+
93+
return new static(
94+
array_pop($pgpKeyId),
95+
array_pop($pgpKeyPacket),
96+
self::getChildElementsFromXML($xml),
97+
);
98+
}
99+
100+
101+
/**
102+
* Convert this PGPData to XML.
103+
*
104+
* @param \DOMElement|null $parent The element we should append this PGPData to.
105+
* @return \DOMElement
106+
*/
107+
public function toXML(DOMElement $parent = null): DOMElement
108+
{
109+
$e = $this->instantiateParentElement($parent);
110+
111+
$this->getPGPKeyId()?->toXML($e);
112+
$this->getPGPKeyPacket()?->toXML($e);
113+
114+
foreach ($this->getElements() as $elt) {
115+
$elt->toXML($e);
116+
}
117+
118+
return $e;
119+
}
120+
}

src/XML/ds/KeyInfo.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public static function fromXML(DOMElement $xml): static
3737
$keyValue = KeyValue::getChildrenOfClass($xml);
3838
$retrievalMethod = RetrievalMethod::getChildrenOfClass($xml);
3939
$x509Data = X509Data::getChildrenOfClass($xml);
40-
//$pgpData = PGPData::getChildrenOfClass($xml);
40+
$pgpData = PGPData::getChildrenOfClass($xml);
4141
//$spkiData = SPKIData::getChildrenOfClass($xml);
4242
$mgmtData = MgmtData::getChildrenOfClass($xml);
4343
$other = self::getChildElementsFromXML($xml);
@@ -47,7 +47,7 @@ public static function fromXML(DOMElement $xml): static
4747
$keyValue,
4848
$retrievalMethod,
4949
$x509Data,
50-
//$pgpData,
50+
$pgpData,
5151
//$spkiData,
5252
$mgmtData,
5353
$other,

src/XML/ds/PGPData.php

Lines changed: 14 additions & 0 deletions
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\ds;
6+
7+
/**
8+
* Class representing a ds:PGPData element.
9+
*
10+
* @package simplesaml/xml-security
11+
*/
12+
final class PGPData extends AbstractPGPDataType
13+
{
14+
}

src/XML/element.registry.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
'Manifest' => '\SimpleSAML\XMLSecurity\XML\ds\Manifest',
1515
'MgmtData' => '\SimpleSAML\XMLSecurity\XML\ds\MgmtData',
1616
'Object' => '\SimpleSAML\XMLSecurity\XML\ds\DsObject',
17-
// 'PGPData' => '\SimpleSAML\XMLSecurity\XML\ds\PGPData',
17+
'PGPData' => '\SimpleSAML\XMLSecurity\XML\ds\PGPData',
1818
'Reference' => '\SimpleSAML\XMLSecurity\XML\ds\Reference',
1919
'RetrievalMethod' => '\SimpleSAML\XMLSecurity\XML\ds\RetrievalMethod',
2020
'RSAKeyValue' => '\SimpleSAML\XMLSecurity\XML\ds\RSAKeyValue',

src/XML/xenc/OriginatorKeyInfo.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use SimpleSAML\XMLSecurity\XML\ds\KeyName;
1313
use SimpleSAML\XMLSecurity\XML\ds\KeyValue;
1414
use SimpleSAML\XMLSecurity\XML\ds\MgmtData;
15+
use SimpleSAML\XMLSecurity\XML\ds\PGPData;
1516
use SimpleSAML\XMLSecurity\XML\ds\RetrievalMethod;
1617
use SimpleSAML\XMLSecurity\XML\ds\X509Data;
1718

@@ -51,7 +52,7 @@ public static function fromXML(DOMElement $xml): static
5152
$keyValue = KeyValue::getChildrenOfClass($xml);
5253
$retrievalMethod = RetrievalMethod::getChildrenOfClass($xml);
5354
$x509Data = X509Data::getChildrenOfClass($xml);
54-
//$pgpData = PGPData::getChildrenOfClass($xml);
55+
$pgpData = PGPData::getChildrenOfClass($xml);
5556
//$spkiData = SPKIData::getChildrenOfClass($xml);
5657
$mgmtData = MgmtData::getChildrenOfClass($xml);
5758
$other = self::getChildElementsFromXML($xml);
@@ -61,7 +62,7 @@ public static function fromXML(DOMElement $xml): static
6162
$keyValue,
6263
$retrievalMethod,
6364
$x509Data,
64-
//$pgpData,
65+
$pgpData,
6566
//$spkiData,
6667
$mgmtData,
6768
$other,

src/XML/xenc/RecipientKeyInfo.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use SimpleSAML\XMLSecurity\XML\ds\KeyName;
1313
use SimpleSAML\XMLSecurity\XML\ds\KeyValue;
1414
use SimpleSAML\XMLSecurity\XML\ds\MgmtData;
15+
use SimpleSAML\XMLSecurity\XML\ds\PGPData;
1516
use SimpleSAML\XMLSecurity\XML\ds\RetrievalMethod;
1617
use SimpleSAML\XMLSecurity\XML\ds\X509Data;
1718

@@ -51,7 +52,7 @@ public static function fromXML(DOMElement $xml): static
5152
$keyValue = KeyValue::getChildrenOfClass($xml);
5253
$retrievalMethod = RetrievalMethod::getChildrenOfClass($xml);
5354
$x509Data = X509Data::getChildrenOfClass($xml);
54-
//$pgpData = PGPData::getChildrenOfClass($xml);
55+
$pgpData = PGPData::getChildrenOfClass($xml);
5556
//$spkiData = SPKIData::getChildrenOfClass($xml);
5657
$mgmtData = MgmtData::getChildrenOfClass($xml);
5758
$other = self::getChildElementsFromXML($xml);
@@ -61,7 +62,7 @@ public static function fromXML(DOMElement $xml): static
6162
$keyValue,
6263
$retrievalMethod,
6364
$x509Data,
64-
//$pgpData,
65+
$pgpData,
6566
//$spkiData,
6667
$mgmtData,
6768
$other,

tests/XML/ds/KeyInfoTest.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,13 @@
1616
use SimpleSAML\XMLSecurity\XML\ds\AbstractKeyInfoType;
1717
use SimpleSAML\XMLSecurity\XML\ds\KeyInfo;
1818
use SimpleSAML\XMLSecurity\XML\ds\KeyName;
19+
use SimpleSAML\XMLSecurity\XML\ds\PGPData;
20+
use SimpleSAML\XMLSecurity\XML\ds\PGPKeyID;
21+
use SimpleSAML\XMLSecurity\XML\ds\PGPKeyPacket;
1922
use SimpleSAML\XMLSecurity\XML\ds\X509Certificate;
2023
use SimpleSAML\XMLSecurity\XML\ds\X509Data;
2124
use SimpleSAML\XMLSecurity\XML\ds\X509SubjectName;
25+
use SimpleSAML\XMLSecurity\XML\xenc\P;
2226

2327
use function dirname;
2428
use function openssl_x509_parse;
@@ -96,6 +100,11 @@ public function testMarshalling(): void
96100
new X509SubjectName(self::$certData['name']),
97101
],
98102
),
103+
new PGPData(
104+
new PGPKeyID('GpM7'),
105+
new PGPKeyPacket('GpM8'),
106+
[new P('/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI=')],
107+
),
99108
new Chunk(DOMDocumentFactory::fromString(
100109
'<ssp:Chunk xmlns:ssp="urn:x-simplesamlphp:namespace">some</ssp:Chunk>',
101110
)->documentElement),

tests/XML/ds/PGPDataTest.php

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SimpleSAML\XMLSecurity\Test\XML\ds;
6+
7+
use PHPUnit\Framework\Attributes\CoversClass;
8+
use PHPUnit\Framework\TestCase;
9+
use SimpleSAML\XML\DOMDocumentFactory;
10+
use SimpleSAML\XML\Exception\SchemaViolationException;
11+
use SimpleSAML\XML\TestUtils\SchemaValidationTestTrait;
12+
use SimpleSAML\XML\TestUtils\SerializableElementTestTrait;
13+
use SimpleSAML\XMLSecurity\XML\ds\AbstractDsElement;
14+
use SimpleSAML\XMLSecurity\XML\ds\AbstractPGPDataType;
15+
use SimpleSAML\XMLSecurity\XML\ds\PGPData;
16+
use SimpleSAML\XMLSecurity\XML\ds\PGPKeyID;
17+
use SimpleSAML\XMLSecurity\XML\ds\PGPKeyPacket;
18+
use SimpleSAML\XMLSecurity\XML\xenc\P;
19+
20+
use function dirname;
21+
use function strval;
22+
23+
/**
24+
* Class \SimpleSAML\XMLSecurity\Test\XML\ds\PGPDataTest
25+
*
26+
* @package simplesamlphp/xml-security
27+
*/
28+
#[CoversClass(AbstractDsElement::class)]
29+
#[CoversClass(AbstractPGPDataType::class)]
30+
#[CoversClass(PGPData::class)]
31+
final class PGPDataTest extends TestCase
32+
{
33+
use SchemaValidationTestTrait;
34+
use SerializableElementTestTrait;
35+
36+
/**
37+
*/
38+
public static function setUpBeforeClass(): void
39+
{
40+
self::$testedClass = PGPData::class;
41+
42+
self::$schemaFile = dirname(__FILE__, 4) . '/resources/schemas/xmldsig1-schema.xsd';
43+
44+
self::$xmlRepresentation = DOMDocumentFactory::fromFile(
45+
dirname(__FILE__, 3) . '/resources/xml/ds_PGPData.xml',
46+
);
47+
}
48+
49+
50+
/**
51+
*/
52+
public function testMarshalling(): void
53+
{
54+
$pgpKeyId = new PGPKeyID('GpM7');
55+
$pgpKeyPacket = new PGPKeyPacket('GpM8');
56+
$p = new P('/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI=');
57+
58+
$pgpData = new PGPData($pgpKeyId, $pgpKeyPacket, [$p]);
59+
60+
$this->assertEquals(
61+
self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement),
62+
strval($pgpData),
63+
);
64+
}
65+
66+
67+
/**
68+
*/
69+
public function testMarshallingBothIdAndPacketNullThrowsException(): void
70+
{
71+
$this->expectException(SchemaViolationException::class);
72+
73+
new PGPData(null, null, []);
74+
}
75+
76+
77+
/**
78+
*/
79+
public function testMarshallingReferenceElementOrdering(): void
80+
{
81+
$pgpKeyId = new PGPKeyID('GpM7');
82+
$pgpKeyPacket = new PGPKeyPacket('GpM8');
83+
$p = new P('/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI=');
84+
85+
$pgpData = new PGPData($pgpKeyId, $pgpKeyPacket, [$p]);
86+
87+
$pgpDataElement = $pgpData->toXML();
88+
/** @var \DOMElement[] $children */
89+
$children = $pgpDataElement->childNodes;
90+
91+
$this->assertEquals('ds:PGPKeyID', $children[0]->tagName);
92+
$this->assertEquals('ds:PGPKeyPacket', $children[1]->tagName);
93+
$this->assertEquals('xenc:P', $children[2]->tagName);
94+
}
95+
}

tests/XML/xenc/OriginatorKeyInfoTest.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,14 @@
1414
use SimpleSAML\XMLSecurity\XML\ds\AbstractDsElement;
1515
use SimpleSAML\XMLSecurity\XML\ds\AbstractKeyInfoType;
1616
use SimpleSAML\XMLSecurity\XML\ds\KeyName;
17+
use SimpleSAML\XMLSecurity\XML\ds\PGPData;
18+
use SimpleSAML\XMLSecurity\XML\ds\PGPKeyID;
19+
use SimpleSAML\XMLSecurity\XML\ds\PGPKeyPacket;
1720
use SimpleSAML\XMLSecurity\XML\ds\X509Certificate;
1821
use SimpleSAML\XMLSecurity\XML\ds\X509Data;
1922
use SimpleSAML\XMLSecurity\XML\ds\X509SubjectName;
2023
use SimpleSAML\XMLSecurity\XML\xenc\OriginatorKeyInfo;
24+
use SimpleSAML\XMLSecurity\XML\xenc\P;
2125

2226
use function dirname;
2327
use function openssl_x509_parse;
@@ -92,6 +96,11 @@ public function testMarshalling(): void
9296
new X509SubjectName(self::$certData['name']),
9397
],
9498
),
99+
new PGPData(
100+
new PGPKeyID('GpM7'),
101+
new PGPKeyPacket('GpM8'),
102+
[new P('/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI=')],
103+
),
95104
new Chunk(DOMDocumentFactory::fromString(
96105
'<ssp:Chunk xmlns:ssp="urn:x-simplesamlphp:namespace">some</ssp:Chunk>',
97106
)->documentElement),

0 commit comments

Comments
 (0)