EncryptedKey::getCarriedKeyName()   A
last analyzed

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 0
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\SchemaValidatableElementInterface;
10
use SimpleSAML\XML\SchemaValidatableElementTrait;
11
use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException;
12
use SimpleSAML\XMLSchema\Exception\TooManyElementsException;
13
use SimpleSAML\XMLSchema\Type\AnyURIValue;
14
use SimpleSAML\XMLSchema\Type\Base64BinaryValue;
15
use SimpleSAML\XMLSchema\Type\IDValue;
16
use SimpleSAML\XMLSchema\Type\StringValue;
17
use SimpleSAML\XMLSecurity\Alg\Encryption\EncryptionAlgorithmInterface;
18
use SimpleSAML\XMLSecurity\Exception\InvalidArgumentException;
19
use SimpleSAML\XMLSecurity\Key\KeyInterface;
20
use SimpleSAML\XMLSecurity\XML\ds\KeyInfo;
21
22
use function strval;
23
24
/**
25
 * Class representing an encrypted key.
26
 *
27
 * @package simplesamlphp/xml-security
28
 */
29
final class EncryptedKey extends AbstractEncryptedType implements SchemaValidatableElementInterface
30
{
31
    use SchemaValidatableElementTrait;
0 ignored issues
show
introduced by
The trait SimpleSAML\XML\SchemaValidatableElementTrait requires some properties which are not provided by SimpleSAML\XMLSecurity\XML\xenc\EncryptedKey: $message, $line
Loading history...
32
33
34
    /**
35
     * EncryptedKey constructor.
36
     *
37
     * @param \SimpleSAML\XMLSecurity\XML\xenc\CipherData $cipherData The CipherData object of this EncryptedData.
38
     * @param \SimpleSAML\XMLSchema\Type\IDValue|null $id
39
     *   The Id attribute of this object. Optional.
40
     * @param \SimpleSAML\XMLSchema\Type\AnyURIValue|null $type
41
     *   The Type attribute of this object. Optional.
42
     * @param \SimpleSAML\XMLSchema\Type\StringValue|null $mimeType
43
     *   The MimeType attribute of this object. Optional.
44
     * @param \SimpleSAML\XMLSchema\Type\AnyURIValue|null $encoding
45
     *   The Encoding attribute of this object. Optional.
46
     * @param \SimpleSAML\XMLSchema\Type\StringValue|null $recipient
47
     *   The Recipient attribute of this object. Optional.
48
     * @param \SimpleSAML\XMLSecurity\XML\xenc\CarriedKeyName|null $carriedKeyName
49
     *   The value of the CarriedKeyName element of this EncryptedData.
50
     * @param \SimpleSAML\XMLSecurity\XML\xenc\EncryptionMethod|null $encryptionMethod
51
     *   The EncryptionMethod object of this EncryptedData. Optional.
52
     * @param \SimpleSAML\XMLSecurity\XML\ds\KeyInfo|null $keyInfo The KeyInfo object of this EncryptedData. Optional.
53
     * @param \SimpleSAML\XMLSecurity\XML\xenc\ReferenceList|null $referenceList
54
     *   The ReferenceList object of this EncryptedData. Optional.
55
     */
56
    final public function __construct(
57
        CipherData $cipherData,
58
        ?IDValue $id = null,
59
        ?AnyURIValue $type = null,
60
        ?StringValue $mimeType = null,
61
        ?AnyURIValue $encoding = null,
62
        protected ?StringValue $recipient = null,
63
        protected ?CarriedKeyName $carriedKeyName = null,
64
        ?EncryptionMethod $encryptionMethod = null,
65
        ?KeyInfo $keyInfo = null,
66
        protected ?ReferenceList $referenceList = null,
67
    ) {
68
        parent::__construct($cipherData, $id, $type, $mimeType, $encoding, $encryptionMethod, $keyInfo);
69
    }
70
71
72
    /**
73
     * Get the value of the CarriedKeyName property.
74
     *
75
     * @return \SimpleSAML\XMLSecurity\XML\xenc\CarriedKeyName|null
76
     */
77
    public function getCarriedKeyName(): ?CarriedKeyName
78
    {
79
        return $this->carriedKeyName;
80
    }
81
82
83
    /**
84
     * Get the value of the Recipient attribute.
85
     *
86
     * @return \SimpleSAML\XMLSchema\Type\StringValue|null
87
     */
88
    public function getRecipient(): ?StringValue
89
    {
90
        return $this->recipient;
91
    }
92
93
94
    /**
95
     * Get the ReferenceList object.
96
     *
97
     * @return \SimpleSAML\XMLSecurity\XML\xenc\ReferenceList|null
98
     */
99
    public function getReferenceList(): ?ReferenceList
100
    {
101
        return $this->referenceList;
102
    }
103
104
105
    /**
106
     * @param \SimpleSAML\XMLSecurity\Alg\Encryption\EncryptionAlgorithmInterface $decryptor The decryptor to use
107
     * to decrypt the key.
108
     *
109
     * @return string The decrypted key.
110
     */
111
    public function decrypt(EncryptionAlgorithmInterface $decryptor): string
112
    {
113
        $cipherValue =  $this->getCipherData()->getCipherValue();
114
        Assert::notNull(
115
            $cipherValue,
116
            'Decrypting keys by reference is not supported.',
117
            InvalidArgumentException::class,
118
        );
119
120
        Assert::eq(
121
            $decryptor->getAlgorithmId(),
122
            $this->getEncryptionMethod()?->getAlgorithm(),
123
            'Decryptor algorithm does not match algorithm used.',
124
            InvalidArgumentException::class,
125
        );
126
127
        return $decryptor->decrypt(base64_decode($cipherValue->getContent()->getValue(), true));
128
    }
129
130
131
    /**
132
     * Create an EncryptedKey by encrypting a given key.
133
     *
134
     * @param \SimpleSAML\XMLSecurity\Key\KeyInterface $keyToEncrypt The key to encrypt.
135
     * @param \SimpleSAML\XMLSecurity\Alg\Encryption\EncryptionAlgorithmInterface $encryptor The encryptor to use.
136
     * @param \SimpleSAML\XMLSecurity\XML\xenc\EncryptionMethod $encryptionMethod
137
     *   The EncryptionMethod object of this EncryptedData. Optional.
138
     * @param \SimpleSAML\XMLSchema\Type\IDValue|null $id The Id attribute of this object. Optional.
139
     * @param \SimpleSAML\XMLSchema\Type\AnyURIValue|null $type The Type attribute of this object. Optional.
140
     * @param \SimpleSAML\XMLSchema\Type\StringValue|null $mimeType
141
     *   The MimeType attribute of this object. Optional.
142
     * @param \SimpleSAML\XMLSchema\Type\AnyURIValue|null $encoding
143
     *   The Encoding attribute of this object. Optional.
144
     * @param \SimpleSAML\XMLSchema\Type\StringValue|null $recipient
145
     *   The Recipient attribute of this object. Optional.
146
     * @param \SimpleSAML\XMLSecurity\XML\xenc\CarriedKeyName|null $carriedKeyName
147
     *   The value of the CarriedKeyName element of this EncryptedData.
148
     * @param \SimpleSAML\XMLSecurity\XML\ds\KeyInfo|null $keyInfo The KeyInfo object of this EncryptedData. Optional.
149
     * @param \SimpleSAML\XMLSecurity\XML\xenc\ReferenceList|null $referenceList
150
     *   The ReferenceList object of this EncryptedData. Optional.
151
     *
152
     * @return \SimpleSAML\XMLSecurity\XML\xenc\EncryptedKey The new EncryptedKey object.
153
     */
154
    public static function fromKey(
155
        KeyInterface $keyToEncrypt,
156
        EncryptionAlgorithmInterface $encryptor,
157
        EncryptionMethod $encryptionMethod,
158
        ?IDValue $id = null,
159
        ?AnyURIValue $type = null,
160
        ?StringValue $mimeType = null,
161
        ?AnyURIValue $encoding = null,
162
        ?StringValue $recipient = null,
163
        ?CarriedKeyName $carriedKeyName = null,
164
        ?KeyInfo $keyInfo = null,
165
        ?ReferenceList $referenceList = null,
166
    ): EncryptedKey {
167
        Assert::eq(
168
            $encryptor->getAlgorithmId(),
169
            $encryptionMethod->getAlgorithm()->getValue(),
170
            'Encryptor algorithm and encryption method do not match.',
171
            InvalidArgumentException::class,
172
        );
173
174
        return new self(
175
            new CipherData(
176
                new CipherValue(
177
                    Base64BinaryValue::fromString(base64_encode(
178
                        $encryptor->encrypt($keyToEncrypt->getMaterial()),
179
                    )),
180
                ),
181
            ),
182
            $id,
183
            $type,
184
            $mimeType,
185
            $encoding,
186
            $recipient,
187
            $carriedKeyName,
188
            $encryptionMethod,
189
            $keyInfo,
190
            $referenceList,
191
        );
192
    }
193
194
195
    /**
196
     * @inheritDoc
197
     *
198
     * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException
199
     *   If the qualified name of the supplied element is wrong
200
     */
201
    public static function fromXML(DOMElement $xml): static
202
    {
203
        Assert::same($xml->localName, 'EncryptedKey', InvalidDOMElementException::class);
204
        Assert::same($xml->namespaceURI, EncryptedKey::NS, InvalidDOMElementException::class);
205
206
        $cipherData = CipherData::getChildrenOfClass($xml);
207
        Assert::count(
208
            $cipherData,
209
            1,
210
            'No or more than one CipherData element found in <xenc:EncryptedKey>.',
211
            TooManyElementsException::class,
212
        );
213
214
        $encryptionMethod = EncryptionMethod::getChildrenOfClass($xml);
215
        Assert::maxCount(
216
            $encryptionMethod,
217
            1,
218
            'No more than one EncryptionMethod element allowed in <xenc:EncryptedKey>.',
219
            TooManyElementsException::class,
220
        );
221
222
        $keyInfo = KeyInfo::getChildrenOfClass($xml);
223
        Assert::maxCount(
224
            $keyInfo,
225
            1,
226
            'No more than one KeyInfo element allowed in <xenc:EncryptedKey>.',
227
            TooManyElementsException::class,
228
        );
229
230
        $referenceLists = ReferenceList::getChildrenOfClass($xml);
231
        Assert::maxCount(
232
            $keyInfo,
233
            1,
234
            'Only one ReferenceList element allowed in <xenc:EncryptedKey>.',
235
            TooManyElementsException::class,
236
        );
237
238
        $carriedKeyNames = CarriedKeyName::getChildrenOfClass($xml);
239
        Assert::maxCount(
240
            $carriedKeyNames,
241
            1,
242
            'Only one CarriedKeyName element allowed in <xenc:EncryptedKey>.',
243
            TooManyElementsException::class,
244
        );
245
246
        return new static(
247
            $cipherData[0],
248
            self::getOptionalAttribute($xml, 'Id', IDValue::class, null),
249
            self::getOptionalAttribute($xml, 'Type', AnyURIValue::class, null),
250
            self::getOptionalAttribute($xml, 'MimeType', StringValue::class, null),
251
            self::getOptionalAttribute($xml, 'Encoding', AnyURIValue::class, null),
252
            self::getOptionalAttribute($xml, 'Recipient', StringValue::class, null),
253
            array_pop($carriedKeyNames),
254
            array_pop($encryptionMethod),
255
            array_pop($keyInfo),
256
            array_pop($referenceLists),
257
        );
258
    }
259
260
261
    /**
262
     * @inheritDoc
263
     */
264
    public function toXML(?DOMElement $parent = null): DOMElement
265
    {
266
        $e = parent::toXML($parent);
267
268
        if ($this->getRecipient() !== null) {
269
            $e->setAttribute('Recipient', strval($this->getRecipient()));
270
        }
271
272
        $this->getReferenceList()?->toXML($e);
273
        $this->getCarriedKeyName()?->toXML($e);
274
275
        return $e;
276
    }
277
}
278