99use SimpleSAML \{Configuration , Error , Logger };
1010use SimpleSAML \HTTP \RunnableResponse ;
1111use SimpleSAML \Metadata \MetaDataStorageHandler ;
12- use SimpleSAML \Module \saml \Message ;;
1312use SimpleSAML \SAML2 \Binding ;
1413use SimpleSAML \SAML2 \Binding \HTTPPost ;
1514use SimpleSAML \SAML2 \Constants as C ;
16- use SimpleSAML \SAML2 \Utils ;
15+ use SimpleSAML \SAML2 \Utils as SAML2_Utils ;
1716use SimpleSAML \SAML2 \XML \saml \{
1817 Assertion ,
1918 Attribute ,
3029 SubjectConfirmationData ,
3130};
3231use SimpleSAML \SAML2 \XML \samlp \{AttributeQuery , Response };
32+ use SimpleSAML \Utils ;
3333use SimpleSAML \XML \Utils \Random ;
34+ use SimpleSAML \XMLSecurity \Alg \Signature \SignatureAlgorithmFactory ;
35+ use SimpleSAML \XMLSecurity \CryptoEncoding \PEM ;
36+ use SimpleSAML \XMLSecurity \Key \PrivateKey ;
37+ use SimpleSAML \XMLSecurity \XML \ds \{KeyInfo , X509Certificate , X509Data };
38+ use SimpleSAML \XMLSecurity \XML \SignableElementInterface ;
3439use Symfony \Bridge \PsrHttpMessage \Factory \{HttpFoundationFactory , PsrHttpFactory };
3540use Symfony \Component \HttpFoundation \Request ;
3641
@@ -159,7 +164,7 @@ public function main(/** @scrutinizer ignore-unused */ Request $request): Runnab
159164 }
160165
161166 // $returnAttributes contains the attributes we should return. Send them
162- $ clock = Utils ::getContainer ()->getClock ();
167+ $ clock = SAML2_Utils ::getContainer ()->getClock ();
163168
164169 $ assertion = new Assertion (
165170 issuer: new Issuer ($ idpEntityId ),
@@ -192,8 +197,7 @@ public function main(/** @scrutinizer ignore-unused */ Request $request): Runnab
192197 ],
193198 );
194199
195- // TODO: Fix signing; should use xml-security lib
196- Message::addSign ($ idpMetadata , $ spMetadata , $ assertion );
200+ self ::addSign ($ idpMetadata , $ spMetadata , $ assertion );
197201
198202 $ response = new Response (
199203 status: new Status (
@@ -208,8 +212,7 @@ public function main(/** @scrutinizer ignore-unused */ Request $request): Runnab
208212 assertions: [$ assertion ],
209213 );
210214
211- // TODO: Fix signing; should use xml-security lib
212- Message::addSign ($ idpMetadata , $ spMetadata , $ response );
215+ self ::addSign ($ idpMetadata , $ spMetadata , $ response );
213216
214217 $ httpPost = new HTTPPost ();
215218 $ httpPost ->setRelayState ($ binding ->getRelayState ());
@@ -238,4 +241,57 @@ private function filterAttributeValues(array $reqValues, array $values): array
238241
239242 return $ result ;
240243 }
244+
245+
246+ /**
247+ * Add signature key and sender certificate to an element (Message or Assertion).
248+ *
249+ * @param \SimpleSAML\Configuration $srcMetadata The metadata of the sender.
250+ * @param \SimpleSAML\Configuration $dstMetadata The metadata of the recipient.
251+ * @param \SimpleSAML\XMLSecurity\XML\SignableElementInterface $element The element we should add the data to.
252+ */
253+ private static function addSign (
254+ Configuration $ srcMetadata ,
255+ Configuration $ dstMetadata ,
256+ SignableElementInterface &$ element ,
257+ ): void {
258+ $ dstPrivateKey = $ dstMetadata ->getOptionalString ('signature.privatekey ' , null );
259+ $ cryptoUtils = new Utils \Crypto ();
260+
261+ if ($ dstPrivateKey !== null ) {
262+ /** @var array $keyArray */
263+ $ keyArray = $ cryptoUtils ->loadPrivateKey ($ dstMetadata , true , 'signature. ' );
264+ $ certArray = $ cryptoUtils ->loadPublicKey ($ dstMetadata , false , 'signature. ' );
265+ } else {
266+ /** @var array $keyArray */
267+ $ keyArray = $ cryptoUtils ->loadPrivateKey ($ srcMetadata , true );
268+ $ certArray = $ cryptoUtils ->loadPublicKey ($ srcMetadata , false );
269+ }
270+
271+ $ algo = $ dstMetadata ->getOptionalString ('signature.algorithm ' , null );
272+ if ($ algo === null ) {
273+ $ algo = $ srcMetadata ->getOptionalString ('signature.algorithm ' , C::SIG_RSA_SHA256 );
274+ }
275+
276+ $ privateKey = new PrivateKey (PEM ::fromString ($ keyArray ['PEM ' ]));
277+
278+ $ keyInfo = null ;
279+ if ($ certArray !== null ) {
280+ $ certificate = new X509Certificate (PEM ::fromString ($ keyArray ['PEM ' ]));
281+ $ keyInfo = new KeyInfo ([
282+ new X509Data (
283+ [
284+ new X509Certificate ($ certArray ['PEM ' ]),
285+ ],
286+ ),
287+ ]);
288+ }
289+
290+ $ signer = (new SignatureAlgorithmFactory ())->getAlgorithm (
291+ $ algo ,
292+ $ privateKey ,
293+ );
294+
295+ $ element ->sign ($ signer , C::C14N_EXCLUSIVE_WITHOUT_COMMENTS , $ keyInfo );
296+ }
241297}
0 commit comments