ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
Signer.php
Go to the documentation of this file.
1<?php
2
3
11{
12
25 private static function findKeyCert($config, $entityMetadata, $type)
26 {
27 // first we look for metadata.privatekey and metadata.certificate in the metadata
28 if (array_key_exists('metadata.sign.privatekey', $entityMetadata)
29 || array_key_exists('metadata.sign.certificate', $entityMetadata)
30 ) {
31 if (!array_key_exists('metadata.sign.privatekey', $entityMetadata)
32 || !array_key_exists('metadata.sign.certificate', $entityMetadata)
33 ) {
34 throw new Exception(
35 'Missing either the "metadata.sign.privatekey" or the'.
36 ' "metadata.sign.certificate" configuration option in the metadata for'.
37 ' the '.$type.' "'.$entityMetadata['entityid'].'". If one of'.
38 ' these options is specified, then the other must also be specified.'
39 );
40 }
41
42 $ret = array(
43 'privatekey' => $entityMetadata['metadata.sign.privatekey'],
44 'certificate' => $entityMetadata['metadata.sign.certificate']
45 );
46
47 if (array_key_exists('metadata.sign.privatekey_pass', $entityMetadata)) {
48 $ret['privatekey_pass'] = $entityMetadata['metadata.sign.privatekey_pass'];
49 }
50
51 return $ret;
52 }
53
54 // then we look for default values in the global configuration
55 $privatekey = $config->getString('metadata.sign.privatekey', null);
56 $certificate = $config->getString('metadata.sign.certificate', null);
57 if ($privatekey !== null || $certificate !== null) {
58 if ($privatekey === null || $certificate === null) {
59 throw new Exception(
60 'Missing either the "metadata.sign.privatekey" or the'.
61 ' "metadata.sign.certificate" configuration option in the global'.
62 ' configuration. If one of these options is specified, then the other'.
63 ' must also be specified.'
64 );
65 }
66 $ret = array('privatekey' => $privatekey, 'certificate' => $certificate);
67
68 $privatekey_pass = $config->getString('metadata.sign.privatekey_pass', null);
69 if ($privatekey_pass !== null) {
70 $ret['privatekey_pass'] = $privatekey_pass;
71 }
72
73 return $ret;
74 }
75
76 // as a last resort we attempt to use the privatekey and certificate option from the metadata
77 if (array_key_exists('privatekey', $entityMetadata)
78 || array_key_exists('certificate', $entityMetadata)
79 ) {
80 if (!array_key_exists('privatekey', $entityMetadata)
81 || !array_key_exists('certificate', $entityMetadata)
82 ) {
83 throw new Exception(
84 'Both the "privatekey" and the "certificate" option must'.
85 ' be set in the metadata for the '.$type.' "'.
86 $entityMetadata['entityid'].'" before it is possible to sign metadata'.
87 ' from this entity.'
88 );
89 }
90
91 $ret = array(
92 'privatekey' => $entityMetadata['privatekey'],
93 'certificate' => $entityMetadata['certificate']
94 );
95
96 if (array_key_exists('privatekey_pass', $entityMetadata)) {
97 $ret['privatekey_pass'] = $entityMetadata['privatekey_pass'];
98 }
99
100 return $ret;
101 }
102
103 throw new Exception(
104 'Could not find what key & certificate should be used to sign the metadata'.
105 ' for the '.$type.' "'.$entityMetadata['entityid'].'".'
106 );
107 }
108
109
121 private static function isMetadataSigningEnabled($config, $entityMetadata, $type)
122 {
123 // first check the metadata for the entity
124 if (array_key_exists('metadata.sign.enable', $entityMetadata)) {
125 if (!is_bool($entityMetadata['metadata.sign.enable'])) {
126 throw new Exception(
127 'Invalid value for the "metadata.sign.enable" configuration option for'.
128 ' the '.$type.' "'.$entityMetadata['entityid'].'". This option'.
129 ' should be a boolean.'
130 );
131 }
132
133 return $entityMetadata['metadata.sign.enable'];
134 }
135
136 $enabled = $config->getBoolean('metadata.sign.enable', false);
137
138 return $enabled;
139 }
140
141
157 private static function getMetadataSigningAlgorithm($config, $entityMetadata, $type)
158 {
159 // configure the algorithm to use
160 if (array_key_exists('metadata.sign.algorithm', $entityMetadata)) {
161 if (!is_string($entityMetadata['metadata.sign.algorithm'])) {
162 throw new \SimpleSAML\Error\CriticalConfigurationError(
163 "Invalid value for the 'metadata.sign.algorithm' configuration option for the ".$type.
164 "'".$entityMetadata['entityid']."'. This option has restricted values"
165 );
166 }
167 $alg = $entityMetadata['metadata.sign.algorithm'];
168 } else {
169 $alg = $config->getString('metadata.sign.algorithm', XMLSecurityKey::RSA_SHA256);
170 }
171
172 $supported_algs = array(
173 XMLSecurityKey::RSA_SHA1,
174 XMLSecurityKey::RSA_SHA256,
175 XMLSecurityKey::RSA_SHA384,
176 XMLSecurityKey::RSA_SHA512,
177 );
178
179 if (!in_array($alg, $supported_algs, true)) {
180 throw new \SimpleSAML\Error\CriticalConfigurationError("Unknown signature algorithm '$alg'");
181 }
182
183 switch ($alg) {
184 case XMLSecurityKey::RSA_SHA256:
185 $digest = XMLSecurityDSig::SHA256;
186 break;
187 case XMLSecurityKey::RSA_SHA384:
188 $digest = XMLSecurityDSig::SHA384;
189 break;
190 case XMLSecurityKey::RSA_SHA512:
191 $digest = XMLSecurityDSig::SHA512;
192 break;
193 default:
194 $digest = XMLSecurityDSig::SHA1;
195 }
196
197 return array(
198 'algorithm' => $alg,
199 'digest' => $digest,
200 );
201 }
202
203
214 public static function sign($metadataString, $entityMetadata, $type)
215 {
217
218 // check if metadata signing is enabled
219 if (!self::isMetadataSigningEnabled($config, $entityMetadata, $type)) {
220 return $metadataString;
221 }
222
223 // find the key & certificate which should be used to sign the metadata
224 $keyCertFiles = self::findKeyCert($config, $entityMetadata, $type);
225
226 $keyFile = \SimpleSAML\Utils\Config::getCertPath($keyCertFiles['privatekey']);
227 if (!file_exists($keyFile)) {
228 throw new Exception('Could not find private key file ['.$keyFile.'], which is needed to sign the metadata');
229 }
230 $keyData = file_get_contents($keyFile);
231
232 $certFile = \SimpleSAML\Utils\Config::getCertPath($keyCertFiles['certificate']);
233 if (!file_exists($certFile)) {
234 throw new Exception(
235 'Could not find certificate file ['.$certFile.'], which is needed to sign the metadata'
236 );
237 }
238 $certData = file_get_contents($certFile);
239
240
241 // convert the metadata to a DOM tree
242 try {
244 } catch (Exception $e) {
245 throw new Exception('Error parsing self-generated metadata.');
246 }
247
248 $signature_cf = self::getMetadataSigningAlgorithm($config, $entityMetadata, $type);
249
250 // load the private key
251 $objKey = new XMLSecurityKey($signature_cf['algorithm'], array('type' => 'private'));
252 if (array_key_exists('privatekey_pass', $keyCertFiles)) {
253 $objKey->passphrase = $keyCertFiles['privatekey_pass'];
254 }
255 $objKey->loadKey($keyData, false);
256
257 // get the EntityDescriptor node we should sign
258 $rootNode = $xml->firstChild;
259
260 // sign the metadata with our private key
261 $objXMLSecDSig = new XMLSecurityDSig();
262
263 $objXMLSecDSig->setCanonicalMethod(XMLSecurityDSig::EXC_C14N);
264
265 $objXMLSecDSig->addReferenceList(
266 array($rootNode),
267 $signature_cf['digest'],
268 array('http://www.w3.org/2000/09/xmldsig#enveloped-signature', XMLSecurityDSig::EXC_C14N),
269 array('id_name' => 'ID')
270 );
271
272 $objXMLSecDSig->sign($objKey);
273
274 // add the certificate to the signature
275 $objXMLSecDSig->add509Cert($certData, true);
276
277 // add the signature to the metadata
278 $objXMLSecDSig->insertSignature($rootNode, $rootNode->firstChild);
279
280 // return the DOM tree as a string
281 return $xml->saveXML();
282 }
283}
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
static getInstance($instancename='simplesaml')
Get a configuration file by its instance name.
static findKeyCert($config, $entityMetadata, $type)
This functions finds what key & certificate files should be used to sign the metadata for the given e...
Definition: Signer.php:25
static getMetadataSigningAlgorithm($config, $entityMetadata, $type)
Determine the signature and digest algorithms to use when signing metadata.
Definition: Signer.php:157
static sign($metadataString, $entityMetadata, $type)
Signs the given metadata if metadata signing is enabled.
Definition: Signer.php:214
static isMetadataSigningEnabled($config, $entityMetadata, $type)
Determine whether metadata signing is enabled for the given metadata.
Definition: Signer.php:121
if(@file_exists(dirname(__FILE__).'/lang/eng.php')) $certificate
Definition: example_052.php:77
$config
Definition: bootstrap.php:15
$ret
Definition: parser.php:6
$type