[jboss-cvs] Picketlink SVN: r252 - in federation/trunk/picketlink-fed-core/src: test/java/org/picketlink/test/identity/federation/core/wstrust and 1 other directory.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Wed May 19 13:48:31 EDT 2010


Author: sguilhen at redhat.com
Date: 2010-05-19 13:48:31 -0400 (Wed, 19 May 2010)
New Revision: 252

Modified:
   federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/StandardRequestHandler.java
   federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/WSTrustJAXBFactory.java
   federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/WSTrustUtil.java
   federation/trunk/picketlink-fed-core/src/test/java/org/picketlink/test/identity/federation/core/wstrust/PicketLinkSTSUnitTestCase.java
Log:
PLFED-71: StandardRequestHandler now correctly handles certificates used as proof-of-possession tokens. Tests have been added to show the usage of certificates and public keys as proof tokens

Modified: federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/StandardRequestHandler.java
===================================================================
--- federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/StandardRequestHandler.java	2010-05-18 21:45:45 UTC (rev 251)
+++ federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/StandardRequestHandler.java	2010-05-19 17:48:31 UTC (rev 252)
@@ -51,6 +51,7 @@
 import org.picketlink.identity.federation.ws.trust.StatusType;
 import org.picketlink.identity.federation.ws.trust.UseKeyType;
 import org.picketlink.identity.xmlsec.w3.xmldsig.KeyInfoType;
+import org.picketlink.identity.xmlsec.w3.xmldsig.X509DataType;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
@@ -158,7 +159,7 @@
             Principal onBehalfOfPrincipal = WSTrustUtil.getOnBehalfOfPrincipal(request.getOnBehalfOf());
             requestContext.setOnBehalfOfPrincipal(onBehalfOfPrincipal);
          }
-         
+
          // get the key type and size from the request, setting default values if not specified.
          URI keyType = request.getKeyType();
          if (keyType == null)
@@ -239,7 +240,16 @@
                Object value = useKeyType.getAny();
                if (value instanceof JAXBElement<?> || value instanceof Element)
                {
-                  //TODO: parse the token properly. If it is a X509 cert, we should create a X509DataType with it.
+                  String elementName = (value instanceof Element)
+                        ? ((Element) value).getLocalName()
+                        : ((JAXBElement<?>) value).getName().getLocalPart();
+                  // if the specified key is a X509 certificate we must insert it into a X509Data element.
+                  if (elementName.equals("X509Certificate"))
+                  {
+                     X509DataType data = new X509DataType();
+                     data.getX509IssuerSerialOrX509SKIOrX509SubjectName().add(value);
+                     value = new org.picketlink.identity.xmlsec.w3.xmldsig.ObjectFactory().createX509Data(data);
+                  }
                   KeyInfoType keyInfo = new KeyInfoType();
                   keyInfo.getContent().add(value);
                   requestContext.setProofTokenInfo(keyInfo);
@@ -303,7 +313,7 @@
 
       Node securityToken = request.getRenewTargetElement().getFirstChild();
       if (securityToken == null)
-    	  throw new WSTrustException("Unable to renew token: security token is null");
+         throw new WSTrustException("Unable to renew token: security token is null");
 
       SecurityTokenProvider provider = this.configuration.getProviderForTokenElementNS(securityToken.getLocalName(),
             securityToken.getNamespaceURI());
@@ -393,8 +403,8 @@
 
       Node securityToken = request.getValidateTargetElement().getFirstChild();
       if (securityToken == null)
-    	  throw new WSTrustException("Unable to validate token: security token is null");
-      
+         throw new WSTrustException("Unable to validate token: security token is null");
+
       SecurityTokenProvider provider = this.configuration.getProviderForTokenElementNS(securityToken.getLocalName(),
             securityToken.getNamespaceURI());
       if (provider == null)
@@ -487,8 +497,8 @@
       // obtain the token provider that will handle the request.
       Node securityToken = request.getCancelTargetElement().getFirstChild();
       if (securityToken == null)
-    	  throw new WSTrustException("Unable to cancel token: security token is null");
-    	  
+         throw new WSTrustException("Unable to cancel token: security token is null");
+
       SecurityTokenProvider provider = this.configuration.getProviderForTokenElementNS(securityToken.getLocalName(),
             securityToken.getNamespaceURI());
       if (provider == null)
@@ -504,7 +514,7 @@
          context.setOnBehalfOfPrincipal(onBehalfOfPrincipal);
       }
       provider.cancelToken(context);
-      
+
       // if no exception has been raised, the token has been successfully canceled.
       RequestSecurityTokenResponse response = new RequestSecurityTokenResponse();
       if (request.getContext() != null)

Modified: federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/WSTrustJAXBFactory.java
===================================================================
--- federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/WSTrustJAXBFactory.java	2010-05-18 21:45:45 UTC (rev 251)
+++ federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/WSTrustJAXBFactory.java	2010-05-19 17:48:31 UTC (rev 252)
@@ -110,6 +110,7 @@
       packages.append(":org.picketlink.identity.federation.ws.trust");
       packages.append(":org.picketlink.identity.federation.ws.wss.secext");
       packages.append(":org.picketlink.identity.federation.ws.wss.utility");
+      packages.append(":org.picketlink.identity.xmlsec.w3.xmldsig");
       return packages.toString();
    }
 

Modified: federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/WSTrustUtil.java
===================================================================
--- federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/WSTrustUtil.java	2010-05-18 21:45:45 UTC (rev 251)
+++ federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/WSTrustUtil.java	2010-05-19 17:48:31 UTC (rev 252)
@@ -30,6 +30,8 @@
 import java.security.PublicKey;
 import java.security.SecureRandom;
 import java.security.cert.Certificate;
+import java.security.interfaces.DSAPublicKey;
+import java.security.interfaces.RSAPublicKey;
 import java.util.GregorianCalendar;
 import java.util.Map;
 
@@ -61,7 +63,10 @@
 import org.picketlink.identity.federation.ws.wss.secext.KeyIdentifierType;
 import org.picketlink.identity.federation.ws.wss.secext.SecurityTokenReferenceType;
 import org.picketlink.identity.federation.ws.wss.secext.UsernameTokenType;
+import org.picketlink.identity.xmlsec.w3.xmldsig.DSAKeyValueType;
 import org.picketlink.identity.xmlsec.w3.xmldsig.KeyInfoType;
+import org.picketlink.identity.xmlsec.w3.xmldsig.KeyValueType;
+import org.picketlink.identity.xmlsec.w3.xmldsig.RSAKeyValueType;
 import org.picketlink.identity.xmlsec.w3.xmldsig.X509DataType;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
@@ -460,4 +465,52 @@
       return keyInfo;
    }
 
+   /**
+    * <p>
+    * Creates a {@code KeyValueType} that wraps the specified public key. This method supports DSA and RSA keys.
+    * </p>
+    * 
+    * @param key the {@code PublicKey} that will be represented as a {@code KeyValueType}.
+    * @return the constructed {@code KeyValueType} or {@code null} if the specified key is neither a DSA nor a 
+    * RSA key.
+    */
+   public static KeyValueType createKeyValue(PublicKey key)
+   {
+      org.picketlink.identity.xmlsec.w3.xmldsig.ObjectFactory factory = new org.picketlink.identity.xmlsec.w3.xmldsig.ObjectFactory();
+      if (key instanceof RSAPublicKey)
+      {
+         RSAPublicKey pubKey = (RSAPublicKey) key;
+         byte[] encodedModulus = Base64.encodeBytes(pubKey.getModulus().toByteArray()).getBytes();
+         byte[] encodedExponent = Base64.encodeBytes(pubKey.getPublicExponent().toByteArray()).getBytes();
+
+         RSAKeyValueType rsaKeyValue = new RSAKeyValueType();
+         rsaKeyValue.setModulus(encodedModulus);
+         rsaKeyValue.setExponent(encodedExponent);
+
+         KeyValueType keyValue = new KeyValueType();
+         keyValue.getContent().add(factory.createRSAKeyValue(rsaKeyValue));
+         return keyValue;
+      }
+      else if (key instanceof DSAPublicKey)
+      {
+         DSAPublicKey pubKey = (DSAPublicKey) key;
+         byte[] encodedP = Base64.encodeBytes(pubKey.getParams().getP().toByteArray()).getBytes();
+         byte[] encodedQ = Base64.encodeBytes(pubKey.getParams().getQ().toByteArray()).getBytes();
+         byte[] encodedG = Base64.encodeBytes(pubKey.getParams().getG().toByteArray()).getBytes();
+         byte[] encodedY = Base64.encodeBytes(pubKey.getY().toByteArray()).getBytes();
+
+         DSAKeyValueType dsaKeyValue = new DSAKeyValueType();
+         dsaKeyValue.setP(encodedP);
+         dsaKeyValue.setQ(encodedQ);
+         dsaKeyValue.setG(encodedG);
+         dsaKeyValue.setY(encodedY);
+         
+         KeyValueType keyValue = new KeyValueType();
+         keyValue.getContent().add(factory.createDSAKeyValue(dsaKeyValue));
+         return keyValue;
+      }
+      else
+         return null;
+   }
+
 }

Modified: federation/trunk/picketlink-fed-core/src/test/java/org/picketlink/test/identity/federation/core/wstrust/PicketLinkSTSUnitTestCase.java
===================================================================
--- federation/trunk/picketlink-fed-core/src/test/java/org/picketlink/test/identity/federation/core/wstrust/PicketLinkSTSUnitTestCase.java	2010-05-18 21:45:45 UTC (rev 251)
+++ federation/trunk/picketlink-fed-core/src/test/java/org/picketlink/test/identity/federation/core/wstrust/PicketLinkSTSUnitTestCase.java	2010-05-19 17:48:31 UTC (rev 252)
@@ -21,8 +21,17 @@
  */
 package org.picketlink.test.identity.federation.core.wstrust;
 
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.math.BigInteger;
 import java.net.URI;
+import java.security.KeyFactory;
+import java.security.KeyStore;
 import java.security.Principal;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.RSAPublicKeySpec;
 import java.util.List;
 import java.util.Map;
 
@@ -40,6 +49,7 @@
 import org.picketlink.identity.federation.core.exceptions.ConfigurationException;
 import org.picketlink.identity.federation.core.saml.v2.common.IDGenerator;
 import org.picketlink.identity.federation.core.saml.v2.util.DocumentUtil;
+import org.picketlink.identity.federation.core.util.Base64;
 import org.picketlink.identity.federation.core.wstrust.PicketLinkSTS;
 import org.picketlink.identity.federation.core.wstrust.STSConfiguration;
 import org.picketlink.identity.federation.core.wstrust.SecurityTokenProvider;
@@ -76,10 +86,13 @@
 import org.picketlink.identity.federation.ws.trust.RequestedReferenceType;
 import org.picketlink.identity.federation.ws.trust.RequestedSecurityTokenType;
 import org.picketlink.identity.federation.ws.trust.StatusType;
+import org.picketlink.identity.federation.ws.trust.UseKeyType;
 import org.picketlink.identity.federation.ws.trust.ValidateTargetType;
 import org.picketlink.identity.federation.ws.wss.secext.KeyIdentifierType;
 import org.picketlink.identity.federation.ws.wss.secext.SecurityTokenReferenceType;
 import org.picketlink.identity.xmlsec.w3.xmldsig.KeyInfoType;
+import org.picketlink.identity.xmlsec.w3.xmldsig.KeyValueType;
+import org.picketlink.identity.xmlsec.w3.xmldsig.RSAKeyValueType;
 import org.picketlink.identity.xmlsec.w3.xmldsig.X509DataType;
 import org.picketlink.identity.xmlsec.w3.xmlenc.EncryptedKeyType;
 import org.w3c.dom.Document;
@@ -390,7 +403,7 @@
             SAMLUtil.SAML2_TOKEN_TYPE, null);
       OnBehalfOfType onBehalfOf = WSTrustUtil.createOnBehalfOfWithUsername("anotherduke", "id");
       request.setOnBehalfOf(onBehalfOf);
-      
+
       // use the factory to marshall the request.
       WSTrustJAXBFactory factory = WSTrustJAXBFactory.getInstance();
       Source requestMessage = factory.marshallRequestSecurityToken(request);
@@ -403,7 +416,7 @@
       // validate the security token response (assertion principal should be anotherduke as specified by OnBehalfOf).
       this.validateSAMLAssertionResponse(baseResponse, "testcontext", "anotherduke", SAMLUtil.SAML2_SENDER_VOUCHES_URI);
    }
-   
+
    /**
     * <p>
     * This test requests a SAMLV2.0 assertion and requires a symmetric key to be used as a proof-of-possession token.
@@ -433,7 +446,12 @@
             .parseRequestSecurityTokenResponse(responseMessage);
 
       // validate the security token response.
-      this.validateSAMLAssertionResponse(baseResponse, "testcontext", "jduke", SAMLUtil.SAML2_HOLDER_OF_KEY_URI);
+      AssertionType assertion = this.validateSAMLAssertionResponse(baseResponse, "testcontext", "jduke",
+            SAMLUtil.SAML2_HOLDER_OF_KEY_URI);
+      // validate the holder of key contents.
+      SubjectConfirmationType subjConfirmation = (SubjectConfirmationType) assertion.getSubject().getContent().get(1)
+            .getValue();
+      this.validateHolderOfKeyContents(subjConfirmation, WSTrustConstants.KEY_TYPE_SYMMETRIC, null, false);
 
       // check if the response contains the STS-generated key.
       RequestSecurityTokenResponseCollection collection = (RequestSecurityTokenResponseCollection) baseResponse;
@@ -487,7 +505,12 @@
             .parseRequestSecurityTokenResponse(responseMessage);
 
       // validate the security token response.
-      this.validateSAMLAssertionResponse(baseResponse, "testcontext", "jduke", SAMLUtil.SAML2_HOLDER_OF_KEY_URI);
+      AssertionType assertion = this.validateSAMLAssertionResponse(baseResponse, "testcontext", "jduke",
+            SAMLUtil.SAML2_HOLDER_OF_KEY_URI);
+      // validate the holder of key contents.
+      SubjectConfirmationType subjConfirmation = (SubjectConfirmationType) assertion.getSubject().getContent().get(1)
+            .getValue();
+      this.validateHolderOfKeyContents(subjConfirmation, WSTrustConstants.KEY_TYPE_SYMMETRIC, null, false);
 
       RequestSecurityTokenResponseCollection collection = (RequestSecurityTokenResponseCollection) baseResponse;
       RequestSecurityTokenResponse response = collection.getRequestSecurityTokenResponses().get(0);
@@ -514,6 +537,82 @@
 
    /**
     * <p>
+    * This test requests a SAMLV2.0 assertion and sends a X.509 certificate to be used as the proof-of-possession 
+    * token. The STS must include the specified certificate in the SAML subject confirmation. 
+    * </p>
+    * 
+    * @throws Exception if an error occurs while running the test.
+    */
+   public void testInvokeSAML20WithCertificate() throws Exception
+   {
+      // create a simple token request.
+      RequestSecurityToken request = this.createRequest("testcontext", WSTrustConstants.ISSUE_REQUEST, null,
+            "http://services.testcorp.org/provider2");
+      request.setKeyType(URI.create(WSTrustConstants.KEY_TYPE_PUBLIC));
+
+      // include a UseKey section that specifies the certificate in the request.
+      Certificate certificate = this.getCertificate("keystore/sts_keystore.jks", "testpass", "service1");
+      byte[] base64EncodedCert = Base64.encodeBytes(certificate.getEncoded()).getBytes();
+      JAXBElement<byte[]> certElement = new org.picketlink.identity.xmlsec.w3.xmldsig.ObjectFactory()
+            .createX509DataTypeX509Certificate(base64EncodedCert);
+      UseKeyType useKey = new UseKeyType();
+      useKey.setAny(certElement);
+      request.setUseKey(useKey);
+
+      // invoke the token service.
+      Source requestMessage = WSTrustJAXBFactory.getInstance().marshallRequestSecurityToken(request);
+      Source responseMessage = this.tokenService.invoke(requestMessage);
+      BaseRequestSecurityTokenResponse baseResponse = WSTrustJAXBFactory.getInstance()
+            .parseRequestSecurityTokenResponse(responseMessage);
+
+      // validate the security token response.
+      AssertionType assertion = this.validateSAMLAssertionResponse(baseResponse, "testcontext", "jduke",
+            SAMLUtil.SAML2_HOLDER_OF_KEY_URI);
+      // validate the holder of key contents.
+      SubjectConfirmationType subjConfirmation = (SubjectConfirmationType) assertion.getSubject().getContent().get(1)
+            .getValue();
+      this.validateHolderOfKeyContents(subjConfirmation, WSTrustConstants.KEY_TYPE_PUBLIC, certificate, false);
+   }
+
+   /**
+    * <p>
+    * This test requests a SAMLV2.0 assertion and sends a public key to be used as the proof-of-possession 
+    * token. The STS must include the specified public key in the SAML subject confirmation.
+    * </p>
+    *  
+    * @throws Exception if an error occurs while running the test.
+    */
+   public void testInvokeSAML20WithPublicKey() throws Exception
+   {
+      // create a simple token request.
+      RequestSecurityToken request = this.createRequest("testcontext", WSTrustConstants.ISSUE_REQUEST, null,
+            "http://services.testcorp.org/provider2");
+      request.setKeyType(URI.create(WSTrustConstants.KEY_TYPE_PUBLIC));
+
+      // include a UseKey section that sets the public key in the request.
+      Certificate certificate = this.getCertificate("keystore/sts_keystore.jks", "testpass", "service1");
+      KeyValueType keyValue = WSTrustUtil.createKeyValue(certificate.getPublicKey());
+      UseKeyType useKey = new UseKeyType();
+      useKey.setAny(new org.picketlink.identity.xmlsec.w3.xmldsig.ObjectFactory().createKeyValue(keyValue));
+      request.setUseKey(useKey);
+
+      // invoke the token service.
+      Source requestMessage = WSTrustJAXBFactory.getInstance().marshallRequestSecurityToken(request);
+      Source responseMessage = this.tokenService.invoke(requestMessage);
+      BaseRequestSecurityTokenResponse baseResponse = WSTrustJAXBFactory.getInstance()
+            .parseRequestSecurityTokenResponse(responseMessage);
+
+      // validate the security token response.
+      AssertionType assertion = this.validateSAMLAssertionResponse(baseResponse, "testcontext", "jduke",
+            SAMLUtil.SAML2_HOLDER_OF_KEY_URI);
+      // validate the holder of key contents.
+      SubjectConfirmationType subjConfirmation = (SubjectConfirmationType) assertion.getSubject().getContent().get(1)
+            .getValue();
+      this.validateHolderOfKeyContents(subjConfirmation, WSTrustConstants.KEY_TYPE_PUBLIC, certificate, true);
+   }
+
+   /**
+    * <p>
     * This test case first generates a SAMLV2.0 assertion and then sends a WS-Trust validate message to the STS to get
     * the assertion validated, checking the validation results.
     * </p>
@@ -863,8 +962,8 @@
       {
          assertNotNull("Unexpected null cause", we.getCause());
          assertTrue("Unexpected cause type", we.getCause() instanceof WSTrustException);
-         assertEquals("No SecurityTokenProvider configured for http://www.unknowntoken.org:UnknownToken", 
-               we.getCause().getMessage());
+         assertEquals("No SecurityTokenProvider configured for http://www.unknowntoken.org:UnknownToken", we.getCause()
+               .getMessage());
       }
    }
 
@@ -910,7 +1009,7 @@
          assertTrue("Unexpected cause type", we.getCause() instanceof WSTrustException);
          assertEquals("Unable to validate token: security token is null", we.getCause().getMessage());
       }
-      
+
       // a request to validate an unknown token (i.e. there's no provider can handle the token) should also fail.
       request.getValidateTarget().setAny(this.createUnknownToken());
       requestMessage = factory.marshallRequestSecurityToken(request);
@@ -923,8 +1022,8 @@
       {
          assertNotNull("Unexpected null cause", we.getCause());
          assertTrue("Unexpected cause type", we.getCause() instanceof WSTrustException);
-         assertEquals("No SecurityTokenProvider configured for http://www.unknowntoken.org:UnknownToken", 
-               we.getCause().getMessage());
+         assertEquals("No SecurityTokenProvider configured for http://www.unknowntoken.org:UnknownToken", we.getCause()
+               .getMessage());
       }
    }
 
@@ -970,7 +1069,7 @@
          assertTrue("Unexpected cause type", we.getCause() instanceof WSTrustException);
          assertEquals("Unable to cancel token: security token is null", we.getCause().getMessage());
       }
-      
+
       // a request to cancel an unknown token (i.e. there's no provider can handle the token) should also fail.
       request.getCancelTarget().setAny(this.createUnknownToken());
       requestMessage = factory.marshallRequestSecurityToken(request);
@@ -983,11 +1082,11 @@
       {
          assertNotNull("Unexpected null cause", we.getCause());
          assertTrue("Unexpected cause type", we.getCause() instanceof WSTrustException);
-         assertEquals("No SecurityTokenProvider configured for http://www.unknowntoken.org:UnknownToken", 
-               we.getCause().getMessage());
+         assertEquals("No SecurityTokenProvider configured for http://www.unknowntoken.org:UnknownToken", we.getCause()
+               .getMessage());
       }
    }
-   
+
    /**
     * <p>
     * Validates the contents of a WS-Trust response message that contains a custom token issued by the test {@code
@@ -1043,7 +1142,7 @@
     * @return the SAMLV2.0 assertion that has been extracted from the response. This object can be used by the test
     *         methods to perform extra validations depending on the scenario being tested.
     * @throws Exception
-    *            if one of the validation performed fail.
+    *            if an error occurs while performing the validation.
     */
    private AssertionType validateSAMLAssertionResponse(BaseRequestSecurityTokenResponse baseResponse, String context,
          String principal, String confirmationMethod) throws Exception
@@ -1104,27 +1203,76 @@
       SubjectConfirmationType subjType = (SubjectConfirmationType) content.get(1).getValue();
       assertEquals("Unexpected confirmation method", confirmationMethod, subjType.getMethod());
 
-      // if confirmation method is holder of key, make sure the assertion contains a KeyInfo with the proof token.
-      if (SAMLUtil.SAML2_HOLDER_OF_KEY_URI.equals(confirmationMethod))
+      // validate the assertion conditions.
+      assertNotNull("Unexpected null conditions", assertion.getConditions());
+      assertEquals(lifetime.getCreated(), assertion.getConditions().getNotBefore());
+      assertEquals(lifetime.getExpires(), assertion.getConditions().getNotOnOrAfter());
+
+      // verify if the assertion has been signed.
+      assertNotNull("Assertion should have been signed", assertion.getSignature());
+
+      return assertion;
+   }
+
+   /**
+    * <p>
+    * Validates the contents of the specified {@code SubjectConfirmationType} when the {@code HOLDER_OF_KEY} 
+    * confirmation method has been used.
+    * </p>
+    * 
+    * @param subjectConfirmation the {@code SubjectConfirmationType} to be validated.
+    * @param keyType the type of the proof-of-possession key (Symmetric or Public).
+    * @param certificate the certificate used in the Public Key scenarios.
+    * @param usePublicKey {@code true} if the certificate's Public Key was used as the proof-of-possession token;
+    *   {@code false} otherwise.
+    * @throws Exception if an error occurs while performing the validation.
+    */
+   private void validateHolderOfKeyContents(SubjectConfirmationType subjectConfirmation, String keyType,
+         Certificate certificate, boolean usePublicKey) throws Exception
+   {
+      SubjectConfirmationDataType subjConfirmationDataType = subjectConfirmation.getSubjectConfirmationData();
+      assertNotNull("Unexpected null subject confirmation data", subjConfirmationDataType);
+      List<Object> confirmationContent = subjConfirmationDataType.getContent();
+      assertEquals("Unexpected subject confirmation content size", 1, confirmationContent.size());
+      JAXBElement<?> keyInfoElement = (JAXBElement<?>) confirmationContent.get(0);
+      assertEquals("Unexpected subject confirmation context type", KeyInfoType.class, keyInfoElement.getDeclaredType());
+      KeyInfoType keyInfo = (KeyInfoType) keyInfoElement.getValue();
+      assertEquals("Unexpected key info content size", 1, keyInfo.getContent().size());
+
+      // if the key is a symmetric key, the KeyInfo should contain an encrypted element.
+      if (WSTrustConstants.KEY_TYPE_SYMMETRIC.equals(keyType))
       {
-         SubjectConfirmationDataType subjConfirmationDataType = subjType.getSubjectConfirmationData();
-         assertNotNull("Unexpected null subject confirmation data", subjConfirmationDataType);
-         List<Object> confirmationContent = subjConfirmationDataType.getContent();
-         assertEquals("Unexpected subject confirmation content size", 1, confirmationContent.size());
-         JAXBElement<?> keyInfoElement = (JAXBElement<?>) confirmationContent.get(0);
-         assertEquals("Unexpected subject confirmation context type", KeyInfoType.class, keyInfoElement
-               .getDeclaredType());
-         KeyInfoType keyInfo = (KeyInfoType) keyInfoElement.getValue();
-         assertEquals("Unexpected key info content size", 1, keyInfo.getContent().size());
+         JAXBElement<?> encKeyElement = (JAXBElement<?>) keyInfo.getContent().get(0);
+         assertEquals("Unexpected key info content type", EncryptedKeyType.class, encKeyElement.getDeclaredType());
+      }
+      // if the key is public, KeyInfo should either contain an encoded certificate or an encoded public key.
+      else if (WSTrustConstants.KEY_TYPE_PUBLIC.equals(keyType))
+      {
+         // if the public key has been used as proof, we should be able to retrieve it from KeyValueType.
+         if (usePublicKey == true)
+         {
+            JAXBElement<?> keyValueElement = (JAXBElement<?>) keyInfo.getContent().get(0);
+            assertEquals("Unexpected key info content type", KeyValueType.class, keyValueElement.getDeclaredType());
+            KeyValueType keyValue = (KeyValueType) keyValueElement.getValue();
+            List<Object> keyValueContent = keyValue.getContent();
+            assertEquals("Unexpected key value content size", 1, keyValueContent.size());
+            JAXBElement<?> rsaKeyValueElement = (JAXBElement<?>) keyValue.getContent().get(0);
+            assertEquals("Unexpected key value content type", RSAKeyValueType.class, rsaKeyValueElement
+                  .getDeclaredType());
+            RSAKeyValueType rsaKeyValue = (RSAKeyValueType) rsaKeyValueElement.getValue();
+            byte[] encodedModulus = rsaKeyValue.getModulus();
+            byte[] encodedExponent = rsaKeyValue.getExponent();
 
-         // if they key is a symmetric key, the KeyInfo should contain an encrypted element.
-         if (WSTrustConstants.KEY_TYPE_SYMMETRIC.equals(response.getKeyType().toString()))
-         {
-            JAXBElement<?> encKeyElement = (JAXBElement<?>) keyInfo.getContent().get(0);
-            assertEquals("Unexpected key info content type", EncryptedKeyType.class, encKeyElement.getDeclaredType());
+            // reconstruct the public key and check if it matches the public key of the provided certificate.
+            BigInteger decodedModulus = new BigInteger(1, Base64.decode(encodedModulus, 0, encodedModulus.length));
+            BigInteger decodedExponent = new BigInteger(1, Base64.decode(encodedExponent, 0, encodedExponent.length));
+            KeyFactory factory = KeyFactory.getInstance("RSA");
+            RSAPublicKeySpec spec = new RSAPublicKeySpec(decodedModulus, decodedExponent);
+            RSAPublicKey genKey = (RSAPublicKey) factory.generatePublic(spec);
+            assertEquals("Invalid public key", certificate.getPublicKey(), genKey);
          }
-         // if the key is a public key, the KeyInfo should contain an encoded certificate.
-         else if (WSTrustConstants.KEY_TYPE_PUBLIC.equals(response.getKeyType().toString()))
+         // if the whole certificate was used as proof, we should be able to retrieve it from X509DataType.
+         else
          {
             JAXBElement<?> x509DataElement = (JAXBElement<?>) keyInfo.getContent().get(0);
             assertEquals("Unexpected key info content type", X509DataType.class, x509DataElement.getDeclaredType());
@@ -1134,18 +1282,15 @@
             JAXBElement<?> x509CertElement = (JAXBElement<?>) x509Data.getX509IssuerSerialOrX509SKIOrX509SubjectName()
                   .get(0);
             assertEquals("Unexpected X509 data content type", byte[].class, x509CertElement.getDeclaredType());
+            byte[] encodedCertificate = (byte[]) x509CertElement.getValue();
+
+            // reconstruct the certificate and check if it matches the provided certificate.
+            byte[] decodedCertificate = Base64.decode(encodedCertificate, 0, encodedCertificate.length);
+            ByteArrayInputStream byteInputStream = new ByteArrayInputStream(decodedCertificate);
+            assertEquals("Invalid certificate in key info", certificate, CertificateFactory.getInstance("X.509")
+                  .generateCertificate(byteInputStream));
          }
       }
-
-      // validate the assertion conditions.
-      assertNotNull("Unexpected null conditions", assertion.getConditions());
-      assertEquals(lifetime.getCreated(), assertion.getConditions().getNotBefore());
-      assertEquals(lifetime.getExpires(), assertion.getConditions().getNotOnOrAfter());
-
-      // verify if the assertion has been signed.
-      assertNotNull("Assertion should have been signed", assertion.getSignature());
-
-      return assertion;
    }
 
    /**
@@ -1206,6 +1351,27 @@
 
    /**
     * <p>
+    * Obtains the {@code Certificate} stored under the specified alias in the specified keystore.
+    * </p>
+    * 
+    * @param keyStoreFile the name of the file that contains a JKS keystore.
+    * @param passwd the keystore password.
+    * @param certificateAlias the alias of a certificate in the keystore.
+    * @return a reference to the {@code Certificate} stored under the given alias.
+    * @throws Exception if an error occurs while handling the keystore.
+    */
+   private Certificate getCertificate(String keyStoreFile, String passwd, String certificateAlias) throws Exception
+   {
+      InputStream stream = Thread.currentThread().getContextClassLoader().getResourceAsStream(keyStoreFile);
+      KeyStore keyStore = KeyStore.getInstance("JKS");
+      keyStore.load(stream, passwd.toCharArray());
+
+      Certificate certificate = keyStore.getCertificate(certificateAlias);
+      return certificate;
+   }
+
+   /**
+    * <p>
     * Helper class that exposes the PicketLinkSTS methods as public for the tests to work.
     * </p>
     * 




More information about the jboss-cvs-commits mailing list