Skip to content

Commit 3163047

Browse files
authored
Import EncryptedElementTrait from saml2-library
1 parent cb6d983 commit 3163047

1 file changed

Lines changed: 195 additions & 0 deletions

File tree

src/XML/EncryptedElementTrait.php

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SimpleSAML\XMLSecurity\XML;
6+
7+
use DOMElement;
8+
use SimpleSAML\Assert\Assert;
9+
use SimpleSAML\XML\AbstractXMLElement;
10+
use SimpleSAML\XML\Exception\InvalidDOMElementException;
11+
use SimpleSAML\XMLSecurity\XML\xenc\EncryptedData;
12+
use SimpleSAML\XMLSecurity\XML\xenc\EncryptedKey;
13+
use SimpleSAML\XMLSecurity\XMLSecEnc;
14+
use SimpleSAML\XMLSecurity\XMLSecurityKey;
15+
16+
/**
17+
* Trait aggregating functionality for encrypted elements.
18+
*
19+
* @package simplesamlphp/saml2
20+
*/
21+
trait EncryptedElementTrait
22+
{
23+
/**
24+
* The current encrypted ID.
25+
*
26+
* @var \SimpleSAML\XMLSecurity\XML\xenc\EncryptedData
27+
* @psalm-suppress PropertyNotSetInConstructor
28+
*/
29+
protected EncryptedData $encryptedData;
30+
31+
/**
32+
* A list of encrypted keys.
33+
*
34+
* @var \SimpleSAML\XMLSecurity\XML\xenc\EncryptedKey[]
35+
*/
36+
protected array $encryptedKeys = [];
37+
38+
39+
/**
40+
* Constructor for encrypted elements.
41+
*
42+
* @param \SimpleSAML\XMLSecurity\XML\xenc\EncryptedData $encryptedData The EncryptedData object.
43+
* @param \SimpleSAML\XMLSecurity\XML\xenc\EncryptedKey[] $encryptedKeys An array of zero or more EncryptedKey objects.
44+
*/
45+
public function __construct(EncryptedData $encryptedData, array $encryptedKeys)
46+
{
47+
$this->setEncryptedData($encryptedData);
48+
$this->setEncryptedKeys($encryptedKeys);
49+
}
50+
51+
52+
/**
53+
* Get the EncryptedData object.
54+
*
55+
* @return \SimpleSAML\XMLSecurity\XML\xenc\EncryptedData
56+
*/
57+
public function getEncryptedData(): EncryptedData
58+
{
59+
return $this->encryptedData;
60+
}
61+
62+
63+
/**
64+
* @param \SimpleSAML\XMLSecurity\XML\xenc\EncryptedData $encryptedData
65+
*/
66+
protected function setEncryptedData(EncryptedData $encryptedData): void
67+
{
68+
$this->encryptedData = $encryptedData;
69+
}
70+
71+
72+
/**
73+
* Get the array of EncryptedKey objects
74+
*
75+
* @return \SimpleSAML\XMLSecurity\XML\xenc\EncryptedKey[]
76+
*/
77+
public function getEncryptedKeys(): array
78+
{
79+
return $this->encryptedKeys;
80+
}
81+
82+
83+
/**
84+
* @param \SimpleSAML\XMLSecurity\XML\xenc\EncryptedKey[] $encryptedKeys
85+
*/
86+
protected function setEncryptedKeys(array $encryptedKeys): void
87+
{
88+
Assert::allIsInstanceOf(
89+
$encryptedKeys,
90+
EncryptedKey::class,
91+
'All encrypted keys in <' . $this->getQualifiedName() . '> must be an instance of EncryptedKey.'
92+
);
93+
94+
$this->encryptedKeys = $encryptedKeys;
95+
}
96+
97+
98+
/**
99+
* Create an encrypted element from a given unencrypted element and a key.
100+
*
101+
* @param \SimpleSAML\XML\AbstractXMLElement $element
102+
* @param \SimpleSAML\XMLSecurity\XMLSecurityKey $key
103+
*
104+
* @return \SimpleSAML\XMLSecurity\XML\EncryptedElementInterface
105+
* @throws \Exception
106+
*/
107+
public static function fromUnencryptedElement(
108+
AbstractXMLElement $element,
109+
XMLSecurityKey $key
110+
): EncryptedElementInterface {
111+
$xml = $element->toXML();
112+
113+
$enc = new XMLSecEnc();
114+
$enc->setNode($xml);
115+
$enc->type = XMLSecEnc::Element;
116+
117+
switch ($key->type) {
118+
case XMLSecurityKey::TRIPLEDES_CBC:
119+
case XMLSecurityKey::AES128_CBC:
120+
case XMLSecurityKey::AES192_CBC:
121+
case XMLSecurityKey::AES256_CBC:
122+
case XMLSecurityKey::AES128_GCM:
123+
case XMLSecurityKey::AES192_GCM:
124+
case XMLSecurityKey::AES256_GCM:
125+
$symmetricKey = $key;
126+
break;
127+
128+
case XMLSecurityKey::RSA_1_5:
129+
case XMLSecurityKey::RSA_SHA1:
130+
case XMLSecurityKey::RSA_SHA256:
131+
case XMLSecurityKey::RSA_SHA384:
132+
case XMLSecurityKey::RSA_SHA512:
133+
case XMLSecurityKey::RSA_OAEP:
134+
case XMLSecurityKey::RSA_OAEP_MGF1P:
135+
$symmetricKey = new XMLSecurityKey(XMLSecurityKey::AES128_CBC);
136+
$symmetricKey->generateSessionKey();
137+
138+
$enc->encryptKey($key, $symmetricKey);
139+
140+
break;
141+
142+
default:
143+
throw new \Exception('Unknown key type for encryption: ' . $key->type);
144+
}
145+
146+
$dom = $enc->encryptNode($symmetricKey);
147+
/** @var \SimpleSAML\XMLSecurity\XML\xenc\EncryptedData $encData */
148+
$encData = EncryptedData::fromXML($dom);
149+
return new static($encData, []);
150+
}
151+
152+
153+
/**
154+
* @inheritDoc
155+
* @return \SimpleSAML\XMLSecurity\XML\EncryptedElementInterface
156+
*
157+
* @throws \SimpleSAML\XML\Exception\InvalidDOMElementException if the qualified name of the supplied element is wrong
158+
*/
159+
public static function fromXML(DOMElement $xml): object
160+
{
161+
Assert::same($xml->localName, AbstractXMLElement::getClassName(static::class), InvalidDOMElementException::class);
162+
Assert::same($xml->namespaceURI, static::NS, InvalidDOMElementException::class);
163+
164+
$ed = EncryptedData::getChildrenOfClass($xml);
165+
Assert::count($ed, 1, 'No more or less than one EncryptedData element allowed in ' .
166+
AbstractXMLElement::getClassName(static::class) . '.');
167+
168+
$ek = EncryptedKey::getChildrenOfClass($xml);
169+
170+
return new static($ed[0], $ek);
171+
}
172+
173+
174+
/**
175+
* @inheritDoc
176+
*/
177+
public function toXML(DOMElement $parent = null): DOMElement
178+
{
179+
$e = $this->instantiateParentElement($parent);
180+
181+
$this->encryptedData->toXML($e);
182+
183+
foreach ($this->encryptedKeys as $key) {
184+
$key->toXML($e);
185+
}
186+
187+
return $e;
188+
}
189+
190+
191+
abstract public function instantiateParentElement(DOMElement $parent = null): DOMElement;
192+
193+
194+
abstract public function getQualifiedName(): string;
195+
}

0 commit comments

Comments
 (0)