ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
Signer.php
Go to the documentation of this file.
1<?php
2
12namespace SimpleSAML\XML;
13
14use DOMComment;
15use DOMElement;
16use DOMText;
20
21class Signer
22{
26 private $idAttrName = '';
27
31 private $privateKey = false;
32
36 private $certificate = '';
37
38
42 private $extraCertificates = array();
43
44
61 public function __construct($options = array())
62 {
63 assert(is_array($options));
64
65 if (array_key_exists('privatekey', $options)) {
66 $pass = null;
67 if (array_key_exists('privatekey_pass', $options)) {
68 $pass = $options['privatekey_pass'];
69 }
70
71 $this->loadPrivateKey($options['privatekey'], $pass);
72 }
73
74 if (array_key_exists('certificate', $options)) {
75 $this->loadCertificate($options['certificate']);
76 }
77
78 if (array_key_exists('privatekey_array', $options)) {
79 $this->loadPrivateKeyArray($options['privatekey_array']);
80 }
81
82 if (array_key_exists('publickey_array', $options)) {
83 $this->loadPublicKeyArray($options['publickey_array']);
84 }
85
86 if (array_key_exists('id', $options)) {
87 $this->setIdAttribute($options['id']);
88 }
89 }
90
91
100 public function loadPrivateKeyArray($privatekey)
101 {
102 assert(is_array($privatekey));
103 assert(array_key_exists('PEM', $privatekey));
104
105 $this->privateKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA256, array('type' => 'private'));
106 if (array_key_exists('password', $privatekey)) {
107 $this->privateKey->passphrase = $privatekey['password'];
108 }
109 $this->privateKey->loadKey($privatekey['PEM'], false);
110 }
111
112
126 public function loadPrivateKey($file, $pass = null, $full_path = false)
127 {
128 assert(is_string($file));
129 assert(is_string($pass) || $pass === null);
130 assert(is_bool($full_path));
131
132 if (!$full_path) {
133 $keyFile = Config::getCertPath($file);
134 } else {
135 $keyFile = $file;
136 }
137
138 if (!file_exists($keyFile)) {
139 throw new \Exception('Could not find private key file "' . $keyFile . '".');
140 }
141 $keyData = file_get_contents($keyFile);
142 if ($keyData === false) {
143 throw new \Exception('Unable to read private key file "' . $keyFile . '".');
144 }
145
146 $privatekey = array('PEM' => $keyData);
147 if ($pass !== null) {
148 $privatekey['password'] = $pass;
149 }
150 $this->loadPrivateKeyArray($privatekey);
151 }
152
153
163 public function loadPublicKeyArray($publickey)
164 {
165 assert(is_array($publickey));
166
167 if (!array_key_exists('PEM', $publickey)) {
168 // We have a public key with only a fingerprint
169 throw new \Exception('Tried to add a certificate fingerprint in a signature.');
170 }
171
172 // For now, we only assume that the public key is an X509 certificate
173 $this->certificate = $publickey['PEM'];
174 }
175
176
189 public function loadCertificate($file, $full_path = false)
190 {
191 assert(is_string($file));
192 assert(is_bool($full_path));
193
194 if (!$full_path) {
195 $certFile = Config::getCertPath($file);
196 } else {
197 $certFile = $file;
198 }
199
200 if (!file_exists($certFile)) {
201 throw new \Exception('Could not find certificate file "' . $certFile . '".');
202 }
203
204 $cert = file_get_contents($certFile);
205 if ($cert === false) {
206 throw new \Exception('Unable to read certificate file "' . $certFile . '".');
207 }
208 $this->certificate = $cert;
209 }
210
211
218 {
219 assert(is_string($idAttrName));
220
221 $this->idAttrName = $idAttrName;
222 }
223
224
236 public function addCertificate($file, $full_path = false)
237 {
238 assert(is_string($file));
239 assert(is_bool($full_path));
240
241 if (!$full_path) {
242 $certFile = Config::getCertPath($file);
243 } else {
244 $certFile = $file;
245 }
246
247 if (!file_exists($certFile)) {
248 throw new \Exception('Could not find extra certificate file "' . $certFile . '".');
249 }
250
251 $certificate = file_get_contents($certFile);
252 if ($certificate === false) {
253 throw new \Exception('Unable to read extra certificate file "' . $certFile . '".');
254 }
255
256 $this->extraCertificates[] = $certificate;
257 }
258
259
272 public function sign($node, $insertInto, $insertBefore = null)
273 {
274 assert($node instanceof DOMElement);
275 assert($insertInto instanceof DOMElement);
276 assert($insertBefore === null || $insertBefore instanceof DOMElement ||
277 $insertBefore instanceof DOMComment || $insertBefore instanceof DOMText);
278
279 if ($this->privateKey === false) {
280 throw new \Exception('Private key not set.');
281 }
282
283
284 $objXMLSecDSig = new XMLSecurityDSig();
285 $objXMLSecDSig->setCanonicalMethod(XMLSecurityDSig::EXC_C14N);
286
287 $options = array();
288 if (!empty($this->idAttrName)) {
289 $options['id_name'] = $this->idAttrName;
290 }
291
292 $objXMLSecDSig->addReferenceList(
293 array($node),
295 array('http://www.w3.org/2000/09/xmldsig#enveloped-signature', XMLSecurityDSig::EXC_C14N),
297 );
298
300 $objXMLSecDSig->sign($this->privateKey);
301
302
303 // Add the certificate to the signature
304 $objXMLSecDSig->add509Cert($this->certificate, true);
305
306 // Add extra certificates
307 foreach ($this->extraCertificates as $certificate) {
308 $objXMLSecDSig->add509Cert($certificate, true);
309 }
310
311 $objXMLSecDSig->insertSignature($insertInto, $insertBefore);
312 }
313}
An exception for terminatinating execution or to throw for unit testing.
static getCertPath($path)
Resolves a path that may be relative to the cert-directory.
Definition: Config.php:22
loadPrivateKey($file, $pass=null, $full_path=false)
Set the private key.
Definition: Signer.php:126
__construct($options=array())
Constructor for the metadata signer.
Definition: Signer.php:61
addCertificate($file, $full_path=false)
Add an extra certificate to the certificate chain in the signature.
Definition: Signer.php:236
loadCertificate($file, $full_path=false)
Set the certificate we should include in the signature.
Definition: Signer.php:189
setIDAttribute($idAttrName)
Set the attribute name for the ID value.
Definition: Signer.php:217
loadPublicKeyArray($publickey)
Set the public key / certificate we should include in the signature.
Definition: Signer.php:163
loadPrivateKeyArray($privatekey)
Set the private key from an array.
Definition: Signer.php:100