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 };
3438use Symfony \Bridge \PsrHttpMessage \Factory \{HttpFoundationFactory , PsrHttpFactory };
3539use Symfony \Component \HttpFoundation \Request ;
3640
@@ -159,7 +163,7 @@ public function main(/** @scrutinizer ignore-unused */ Request $request): Runnab
159163 }
160164
161165 // $returnAttributes contains the attributes we should return. Send them
162- $ clock = Utils ::getContainer ()->getClock ();
166+ $ clock = SAML2_Utils ::getContainer ()->getClock ();
163167
164168 $ assertion = new Assertion (
165169 issuer: new Issuer ($ idpEntityId ),
@@ -192,8 +196,7 @@ public function main(/** @scrutinizer ignore-unused */ Request $request): Runnab
192196 ],
193197 );
194198
195- // TODO: Fix signing; should use xml-security lib
196- Message::addSign ($ idpMetadata , $ spMetadata , $ assertion );
199+ self ::addSign ($ idpMetadata , $ spMetadata , $ assertion );
197200
198201 $ response = new Response (
199202 status: new Status (
@@ -208,8 +211,7 @@ public function main(/** @scrutinizer ignore-unused */ Request $request): Runnab
208211 assertions: [$ assertion ],
209212 );
210213
211- // TODO: Fix signing; should use xml-security lib
212- Message::addSign ($ idpMetadata , $ spMetadata , $ response );
214+ self ::addSign ($ idpMetadata , $ spMetadata , $ response );
213215
214216 $ httpPost = new HTTPPost ();
215217 $ httpPost ->setRelayState ($ binding ->getRelayState ());
@@ -238,4 +240,57 @@ private function filterAttributeValues(array $reqValues, array $values): array
238240
239241 return $ result ;
240242 }
243+
244+
245+ /**
246+ * Add signature key and sender certificate to an element (Message or Assertion).
247+ *
248+ * @param \SimpleSAML\Configuration $srcMetadata The metadata of the sender.
249+ * @param \SimpleSAML\Configuration $dstMetadata The metadata of the recipient.
250+ * @param \SimpleSAML\XMLSecurity\XML\SignableElementInterface $element The element we should add the data to.
251+ */
252+ private static function addSign (
253+ Configuration $ srcMetadata ,
254+ Configuration $ dstMetadata ,
255+ SignableElementInterface &$ element ,
256+ ): void {
257+ $ dstPrivateKey = $ dstMetadata ->getOptionalString ('signature.privatekey ' , null );
258+ $ cryptoUtils = new Utils \Crypto ();
259+
260+ if ($ dstPrivateKey !== null ) {
261+ /** @var array $keyArray */
262+ $ keyArray = $ cryptoUtils ->loadPrivateKey ($ dstMetadata , true , 'signature. ' );
263+ $ certArray = $ cryptoUtils ->loadPublicKey ($ dstMetadata , false , 'signature. ' );
264+ } else {
265+ /** @var array $keyArray */
266+ $ keyArray = $ cryptoUtils ->loadPrivateKey ($ srcMetadata , true );
267+ $ certArray = $ cryptoUtils ->loadPublicKey ($ srcMetadata , false );
268+ }
269+
270+ $ algo = $ dstMetadata ->getOptionalString ('signature.algorithm ' , null );
271+ if ($ algo === null ) {
272+ $ algo = $ srcMetadata ->getOptionalString ('signature.algorithm ' , C::SIG_RSA_SHA256 );
273+ }
274+
275+ $ privateKey = new PrivateKey (PEM ::fromString ($ keyArray ['PEM ' ]));
276+
277+ $ keyInfo = null ;
278+ if ($ certArray !== null ) {
279+ $ certificate = new X509Certificate (PEM ::fromString ($ keyArray ['PEM ' ]));
280+ $ keyInfo = new KeyInfo ([
281+ new X509Data (
282+ [
283+ new X509Certificate ($ certArray ['PEM ' ]),
284+ ],
285+ ),
286+ ]);
287+ }
288+
289+ $ signer = (new SignatureAlgorithmFactory ())->getAlgorithm (
290+ $ algo ,
291+ $ privateKey ,
292+ );
293+
294+ $ element ->sign ($ signer , C::C14N_EXCLUSIVE_WITHOUT_COMMENTS , $ keyInfo );
295+ }
241296}
0 commit comments