ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
Signer.php
Go to the documentation of this file.
1 <?php
2 
12 namespace SimpleSAML\XML;
13 
14 use DOMComment;
15 use DOMElement;
16 use DOMText;
20 
21 class 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 
217  public function setIDAttribute($idAttrName)
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),
296  $options
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 }
__construct($options=array())
Constructor for the metadata signer.
Definition: Signer.php:61
loadPublicKeyArray($publickey)
Set the public key / certificate we should include in the signature.
Definition: Signer.php:163
loadPrivateKey($file, $pass=null, $full_path=false)
Set the private key.
Definition: Signer.php:126
setIDAttribute($idAttrName)
Set the attribute name for the ID value.
Definition: Signer.php:217
loadCertificate($file, $full_path=false)
Set the certificate we should include in the signature.
Definition: Signer.php:189
addCertificate($file, $full_path=false)
Add an extra certificate to the certificate chain in the signature.
Definition: Signer.php:236
loadPrivateKeyArray($privatekey)
Set the private key from an array.
Definition: Signer.php:100
static getCertPath($path)
Resolves a path that may be relative to the cert-directory.
Definition: Config.php:22