Passed
Pull Request — master (#26)
by Jaime Pérez
02:00
created

EncryptedKey::setReferenceList()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 3
rs 10
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\XMLSecurity\Alg\Encryption\EncryptionAlgorithmInterface;
11
use SimpleSAML\XMLSecurity\Exception\InvalidArgumentException;
12
use SimpleSAML\XMLSecurity\Key\AbstractKey;
13
use SimpleSAML\XMLSecurity\XML\ds\KeyInfo;
14
15
/**
16
 * Class representing an encrypted key.
17
 *
18
 * @package simplesamlphp/xml-security
19
 */
20
class EncryptedKey extends AbstractEncryptedType
21
{
22
    /** @var \SimpleSAML\XMLSecurity\XML\xenc\CarriedKeyName|null */
23
    protected ?CarriedKeyName $carriedKeyName;
24
25
    /** @var string|null */
26
    protected ?string $recipient;
27
28
    /** @var \SimpleSAML\XMLSecurity\XML\xenc\ReferenceList|null */
29
    protected ?ReferenceList $referenceList;
30
31
32
    /**
33
     * EncryptedKey constructor.
34
     *
35
     * @param \SimpleSAML\XMLSecurity\XML\xenc\CipherData $cipherData The CipherData object of this EncryptedData.
36
     * @param string|null $id The Id attribute of this object. Optional.
37
     * @param string|null $type The Type attribute of this object. Optional.
38
     * @param string|null $mimeType The MimeType attribute of this object. Optional.
39
     * @param string|null $encoding The Encoding attribute of this object. Optional.
40
     * @param string|null $recipient The Recipient attribute of this object. Optional.
41
     * @param \SimpleSAML\XMLSecurity\XML\xenc\CarriedKeyName|null $carriedKeyName
42
     *   The value of the CarriedKeyName element of this EncryptedData.
43
     * @param \SimpleSAML\XMLSecurity\XML\xenc\EncryptionMethod|null $encryptionMethod
44
     *   The EncryptionMethod object of this EncryptedData. Optional.
45
     * @param \SimpleSAML\XMLSecurity\XML\ds\KeyInfo|null $keyInfo The KeyInfo object of this EncryptedData. Optional.
46
     * @param \SimpleSAML\XMLSecurity\XML\xenc\ReferenceList|null $referenceList
47
     *   The ReferenceList object of this EncryptedData. Optional.
48
     */
49
    public function __construct(
50
        CipherData $cipherData,
51
        ?string $id = null,
52
        ?string $type = null,
53
        ?string $mimeType = null,
54
        ?string $encoding = null,
55
        ?string $recipient = null,
56
        ?CarriedKeyName $carriedKeyName = null,
57
        ?EncryptionMethod $encryptionMethod = null,
58
        ?KeyInfo $keyInfo = null,
59
        ?ReferenceList $referenceList = null
60
    ) {
61
        parent::__construct($cipherData, $id, $type, $mimeType, $encoding, $encryptionMethod, $keyInfo);
62
        $this->setRecipient($recipient);
63
        $this->setReferenceList($referenceList);
64
        $this->setCarriedKeyName($carriedKeyName);
65
    }
66
67
68
    /**
69
     * Get the value of the CarriedKeyName property.
70
     *
71
     * @return \SimpleSAML\XMLSecurity\XML\xenc\CarriedKeyName|null
72
     */
73
    public function getCarriedKeyName(): ?CarriedKeyName
74
    {
75
        return $this->carriedKeyName;
76
    }
77
78
79
    /**
80
     * @param \SimpleSAML\XMLSecurity\XML\xenc\CarriedKeyName|null $carriedKeyName
81
     */
82
    protected function setCarriedKeyName(?CarriedKeyName $carriedKeyName): void
83
    {
84
        $this->carriedKeyName = $carriedKeyName;
85
    }
86
87
88
    /**
89
     * Get the value of the Recipient attribute.
90
     *
91
     * @return string|null
92
     */
93
    public function getRecipient(): ?string
94
    {
95
        return $this->recipient;
96
    }
97
98
99
    /**
100
     * @param string|null $recipient
101
     */
102
    protected function setRecipient(?string $recipient): void
103
    {
104
        $this->recipient = $recipient;
105
    }
106
107
108
    /**
109
     * Get the ReferenceList object.
110
     *
111
     * @return \SimpleSAML\XMLSecurity\XML\xenc\ReferenceList|null
112
     */
113
    public function getReferenceList(): ?ReferenceList
114
    {
115
        return $this->referenceList;
116
    }
117
118
119
    /**
120
     * @param \SimpleSAML\XMLSecurity\XML\xenc\ReferenceList|null $referenceList
121
     */
122
    protected function setReferenceList(?ReferenceList $referenceList): void
123
    {
124
        $this->referenceList = $referenceList;
125
    }
126
127
128
    /**
129
     * @param \SimpleSAML\XMLSecurity\Alg\Encryption\EncryptionAlgorithmInterface $decryptor The decryptor to use
130
     * to decrypt the key.
131
     *
132
     * @return string The decrypted key.
133
     */
134
    public function decrypt(EncryptionAlgorithmInterface $decryptor): string
135
    {
136
        Assert::notNull(
137
            $this->getCipherData()->getCipherValue(),
138
            'Decrypting keys by reference is not supported.',
139
            InvalidArgumentException::class
0 ignored issues
show
Unused Code introduced by
The call to SimpleSAML\Assert\Assert::notNull() has too many arguments starting with SimpleSAML\XMLSecurity\E...rgumentException::class. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

139
        Assert::/** @scrutinizer ignore-call */ 
140
                notNull(

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
140
        );
141
142
        Assert::eq(
143
            $decryptor->getAlgorithmId(),
144
            $this->getEncryptionMethod()->getAlgorithm(),
145
            'Decryptor algorithm does not match algorithm used.',
146
            InvalidArgumentException::class
0 ignored issues
show
Unused Code introduced by
The call to SimpleSAML\Assert\Assert::eq() has too many arguments starting with SimpleSAML\XMLSecurity\E...rgumentException::class. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

146
        Assert::/** @scrutinizer ignore-call */ 
147
                eq(

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
147
        );
148
149
        return $decryptor->decrypt(base64_decode($this->getCipherData()->getCipherValue()->getContent()));
150
    }
151
152
153
    /**
154
     * Create an EncryptedKey by encrypting a given key.
155
     *
156
     * @param \SimpleSAML\XMLSecurity\Key\AbstractKey $keyToEncrypt The key to encrypt.
157
     * @param \SimpleSAML\XMLSecurity\Alg\Encryption\EncryptionAlgorithmInterface $encryptor The encryptor to use.
158
     * @param \SimpleSAML\XMLSecurity\XML\xenc\EncryptionMethod|null $encryptionMethod
159
     *   The EncryptionMethod object of this EncryptedData. Optional.
160
     * @param string|null $id The Id attribute of this object. Optional.
161
     * @param string|null $type The Type attribute of this object. Optional.
162
     * @param string|null $mimeType The MimeType attribute of this object. Optional.
163
     * @param string|null $encoding The Encoding attribute of this object. Optional.
164
     * @param string|null $recipient The Recipient attribute of this object. Optional.
165
     * @param \SimpleSAML\XMLSecurity\XML\xenc\CarriedKeyName|null $carriedKeyName
166
     *   The value of the CarriedKeyName element of this EncryptedData.
167
     * @param \SimpleSAML\XMLSecurity\XML\ds\KeyInfo|null $keyInfo The KeyInfo object of this EncryptedData. Optional.
168
     * @param \SimpleSAML\XMLSecurity\XML\xenc\ReferenceList|null $referenceList
169
     *   The ReferenceList object of this EncryptedData. Optional.
170
     *
171
     * @return EncryptedKey The new EncryptedKey object.
172
     */
173
    public static function fromKey(
174
        AbstractKey $keyToEncrypt,
175
        EncryptionAlgorithmInterface $encryptor,
176
        EncryptionMethod $encryptionMethod,
177
        ?string $id = null,
178
        ?string $type = null,
179
        ?string $mimeType = null,
180
        ?string $encoding = null,
181
        ?string $recipient = null,
182
        ?CarriedKeyName $carriedKeyName = null,
183
        ?KeyInfo $keyInfo = null,
184
        ?ReferenceList $referenceList = null
185
    ): EncryptedKey {
186
        Assert::eq(
187
            $encryptor->getAlgorithmId(),
188
            $encryptionMethod->getAlgorithm(),
189
            'Encryptor algorithm and encryption method do not match.',
190
            InvalidArgumentException::class
0 ignored issues
show
Unused Code introduced by
The call to SimpleSAML\Assert\Assert::eq() has too many arguments starting with SimpleSAML\XMLSecurity\E...rgumentException::class. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

190
        Assert::/** @scrutinizer ignore-call */ 
191
                eq(

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
191
        );
192
193
        return new self(
194
            new CipherData(
195
                new CipherValue(
196
                    base64_encode(
197
                        $encryptor->encrypt($keyToEncrypt->get())
198
                    )
199
                )
200
            ),
201
            $id,
202
            $type,
203
            $mimeType,
204
            $encoding,
205
            $recipient,
206
            $carriedKeyName,
207
            $encryptionMethod,
208
            $keyInfo,
209
            $referenceList
210
        );
211
    }
212
213
214
    /**
215
     * @inheritDoc
216
     *
217
     * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException
218
     *   If the qualified name of the supplied element is wrong
219
     */
220
    public static function fromXML(DOMElement $xml): object
221
    {
222
        Assert::same($xml->localName, 'EncryptedKey', InvalidDOMElementException::class);
223
        Assert::same($xml->namespaceURI, EncryptedKey::NS, InvalidDOMElementException::class);
224
225
        $cipherData = CipherData::getChildrenOfClass($xml);
226
        Assert::count($cipherData, 1, 'No or more than one CipherData element found in <xenc:EncryptedKey>.');
227
228
        $encryptionMethod = EncryptionMethod::getChildrenOfClass($xml);
229
        Assert::maxCount(
230
            $encryptionMethod,
231
            1,
232
            'No more than one EncryptionMethod element allowed in <xenc:EncryptedKey>.'
233
        );
234
235
        $keyInfo = KeyInfo::getChildrenOfClass($xml);
236
        Assert::maxCount($keyInfo, 1, 'No more than one KeyInfo element allowed in <xenc:EncryptedKey>.');
237
238
        $referenceLists = ReferenceList::getChildrenOfClass($xml);
239
        Assert::maxCount($keyInfo, 1, 'Only one ReferenceList element allowed in <xenc:EncryptedKey>.');
240
241
        $carriedKeyNames = CarriedKeyName::getChildrenOfClass($xml);
242
        Assert::maxCount($carriedKeyNames, 1, 'Only one CarriedKeyName element allowed in <xenc:EncryptedKey>.');
243
244
        return new self(
245
            $cipherData[0],
246
            self::getAttribute($xml, 'Id', null),
247
            self::getAttribute($xml, 'Type', null),
248
            self::getAttribute($xml, 'MimeType', null),
249
            self::getAttribute($xml, 'Encoding', null),
250
            self::getAttribute($xml, 'Recipient', null),
251
            array_pop($carriedKeyNames),
252
            array_pop($encryptionMethod),
253
            array_pop($keyInfo),
254
            array_pop($referenceLists)
255
        );
256
    }
257
258
259
    /**
260
     * @inheritDoc
261
     */
262
    public function toXML(DOMElement $parent = null): DOMElement
263
    {
264
        /** @psalm-var \DOMDocument $e->ownerDocument */
265
        $e = parent::toXML($parent);
266
267
        if ($this->referenceList !== null) {
268
            $this->referenceList->toXML($e);
269
        }
270
271
        if ($this->carriedKeyName !== null) {
272
            $this->carriedKeyName->toXML($e);
273
        }
274
275
        if ($this->recipient !== null) {
276
            $e->setAttribute('Recipient', $this->recipient);
277
        }
278
279
        return $e;
280
    }
281
}
282