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

EncryptedElementTrait::fromUnencryptedElement()   B

Complexity

Conditions 7
Paths 7

Size

Total Lines 37
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 23
c 1
b 0
f 0
nc 7
nop 2
dl 0
loc 37
rs 8.6186
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SAML2;
6
7
use DOMElement;
8
use RobRichards\XMLSecLibs\XMLSecEnc;
9
use RobRichards\XMLSecLibs\XMLSecurityKey;
10
use SAML2\XML\AbstractXMLElement;
11
use SAML2\XML\xenc\EncryptedData;
12
use SAML2\XML\xenc\EncryptedKey;
13
use Webmozart\Assert\Assert;
14
15
/**
16
 * Trait aggregating functionality for encrypted elements.
17
 *
18
 * @package simplesamlphp/saml2
19
 */
20
trait EncryptedElementTrait
21
{
22
23
    /**
24
     * The current encrypted ID.
25
     *
26
     * @var \SAML2\XML\xenc\EncryptedData
27
     * @psalm-suppress PropertyNotSetInConstructor
28
     */
29
    protected $encryptedData;
30
31
    /**
32
     * A list of encrypted keys.
33
     *
34
     * @var \SAML2\XML\xenc\EncryptedKey[]
35
     */
36
    protected $encryptedKeys = [];
37
38
39
    /**
40
     * Constructor for encrypted elements.
41
     *
42
     * @param \SAML2\XML\xenc\EncryptedData $encryptedData The EncryptedData object.
43
     * @param \SAML2\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 \SAML2\XML\xenc\EncryptedData
56
     */
57
    public function getEncryptedData(): EncryptedData
58
    {
59
        return $this->encryptedData;
60
    }
61
62
63
    /**
64
     * @param \SAML2\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 \SAML2\XML\xenc\EncryptedKey[]
76
     */
77
    public function getEncryptedKeys(): array
78
    {
79
        return $this->encryptedKeys;
80
    }
81
82
83
    /**
84
     * @param \SAML2\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.'
0 ignored issues
show
Bug introduced by
It seems like getQualifiedName() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

91
            'All encrypted keys in <' . $this->/** @scrutinizer ignore-call */ getQualifiedName() . '> must be an instance of EncryptedKey.'
Loading history...
92
        );
93
        $this->encryptedKeys = $encryptedKeys;
94
    }
95
96
97
    /**
98
     * Create an encrypted element from a given unencrypted element and a key.
99
     *
100
     * @param \SAML2\XML\AbstractXMLElement $element
101
     * @param \RobRichards\XMLSecLibs\XMLSecurityKey $key
102
     *
103
     * @return \SAML2\EncryptedElementInterface
104
     * @throws \Exception
105
     */
106
    public static function fromUnencryptedElement(
107
        AbstractXMLElement $element,
108
        XMLSecurityKey $key
109
    ): EncryptedElementInterface {
110
        $xml = $element->toXML();
111
112
        Utils::getContainer()->debugMessage($xml, 'encrypt');
113
114
        $enc = new XMLSecEnc();
115
        $enc->setNode($xml);
116
        $enc->type = XMLSecEnc::Element;
117
118
        switch ($key->type) {
119
            case XMLSecurityKey::TRIPLEDES_CBC:
120
            case XMLSecurityKey::AES128_CBC:
121
            case XMLSecurityKey::AES192_CBC:
122
            case XMLSecurityKey::AES256_CBC:
123
                $symmetricKey = $key;
124
                break;
125
126
            case XMLSecurityKey::RSA_1_5:
127
            case XMLSecurityKey::RSA_OAEP_MGF1P:
128
                $symmetricKey = new XMLSecurityKey(XMLSecurityKey::AES128_CBC);
129
                $symmetricKey->generateSessionKey();
130
131
                $enc->encryptKey($key, $symmetricKey);
132
133
                break;
134
135
            default:
136
                throw new \Exception('Unknown key type for encryption: ' . $key->type);
137
        }
138
139
        $dom = $enc->encryptNode($symmetricKey);
140
        /** @var \SAML2\XML\xenc\EncryptedData $encData */
141
        $encData = EncryptedData::fromXML($dom);
142
        return new static($encData, []);
0 ignored issues
show
Bug Best Practice introduced by
The expression return new static($encData, array()) returns the type SAML2\EncryptedElementTrait which is incompatible with the type-hinted return SAML2\EncryptedElementInterface.
Loading history...
143
    }
144
145
146
    /**
147
     * @inheritDoc
148
     * @return AbstractXMLElement
149
     */
150
    public static function fromXML(DOMElement $xml): object
151
    {
152
        Assert::same($xml->localName, self::getClassName(static::class));
153
        Assert::same($xml->namespaceURI, static::NS);
0 ignored issues
show
Bug introduced by
The constant SAML2\EncryptedElementTrait::NS was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
154
155
        $ed = EncryptedData::getChildrenOfClass($xml);
156
        Assert::count($ed, 1, 'No more or less than one EncryptedData element allowed in ' .
157
            AbstractXMLElement::getClassName(static::class) . '.');
158
159
        $ek = EncryptedKey::getChildrenOfClass($xml);
160
161
        return new static($ed[0], $ek);
0 ignored issues
show
Bug Best Practice introduced by
The expression return new static($ed[0], $ek) returns the type SAML2\EncryptedElementTrait which is incompatible with the documented return type SAML2\XML\AbstractXMLElement.
Loading history...
162
    }
163
164
165
    /**
166
     * @inheritDoc
167
     */
168
    public function toXML(DOMElement $parent = null): DOMElement
169
    {
170
        $e = $this->instantiateParentElement($parent);
0 ignored issues
show
Bug introduced by
It seems like instantiateParentElement() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

170
        /** @scrutinizer ignore-call */ 
171
        $e = $this->instantiateParentElement($parent);
Loading history...
171
172
        $this->encryptedData->toXML($e);
173
174
        foreach ($this->encryptedKeys as $key) {
175
            $key->toXML($e);
176
        }
177
178
        return $e;
179
    }
180
}
181