You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fx-dev@ws.apache.org by we...@apache.org on 2005/09/10 21:41:30 UTC

svn commit: r280033 - in /webservices/wss4j/trunk/src/org/apache/ws/security: ./ components/crypto/ handler/ message/ message/token/

Author: werner
Date: Sat Sep 10 12:41:18 2005
New Revision: 280033

URL: http://svn.apache.org/viewcvs?rev=280033&view=rev
Log:
Implment the WSS 1.1 Thumprint key identifier.

Modified:
    webservices/wss4j/trunk/src/org/apache/ws/security/WSConstants.java
    webservices/wss4j/trunk/src/org/apache/ws/security/components/crypto/Crypto.java
    webservices/wss4j/trunk/src/org/apache/ws/security/components/crypto/Merlin.java
    webservices/wss4j/trunk/src/org/apache/ws/security/components/crypto/errors.properties
    webservices/wss4j/trunk/src/org/apache/ws/security/handler/WSHandler.java
    webservices/wss4j/trunk/src/org/apache/ws/security/handler/WSHandlerConstants.java
    webservices/wss4j/trunk/src/org/apache/ws/security/message/WSEncryptBody.java
    webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSignEnvelope.java
    webservices/wss4j/trunk/src/org/apache/ws/security/message/token/SecurityTokenReference.java

Modified: webservices/wss4j/trunk/src/org/apache/ws/security/WSConstants.java
URL: http://svn.apache.org/viewcvs/webservices/wss4j/trunk/src/org/apache/ws/security/WSConstants.java?rev=280033&r1=280032&r2=280033&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/WSConstants.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/WSConstants.java Sat Sep 10 12:41:18 2005
@@ -36,18 +36,28 @@
 
     /*
      * The base UIRs for the various profiles.
-     * No new base URIs in WSS specification 1.1
      */
     public static final String SOAPMESSAGE_NS = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0";
-    public static final String USERNAMETOKEN_NS = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0";
+    public static final String SOAPMESSAGE_NS11 = "http://docs.oasis-open.org/wss/2004/xx/oasis-2004xx-wss-soap-message-security-1.0";
+    public static final String USERNAMETOKEN_NS = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.1";
     public static final String X509TOKEN_NS = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0";
-    
+    public static final String SAMLTOKEN_NS = "http://docs.oasis-open.org/wss/2004/XX/oasis-2004XX-wss-saml-token-profile-1.0";
     /*
      * The Element name (local name) of the security header
      */
     public static final String WSSE_LN = "Security";
 
     /*
+     * The Thumbprint relative URI string (without #)
+     * Combine it with SOAPMESSAGE_NS11, #, to get the full URL
+     */
+    public static final String THUMBPRINT ="ThumbprintSHA1";
+    
+    /*
+     * The SAMLAssertionID relative URI string (without #)
+     */
+    public static final String SAML_ASSERTION_ID = "SAMLAssertionID";
+    /*
      * The namespace prefixes used. We uses the same prefix convention
      * as shown in the specifications
      */
@@ -306,6 +316,17 @@
      * to WS-Trust specification.
      */
     public static final int UT_SIGNING = 7;
+    
+    /**
+     * <code>THUMPRINT_IDENTIFIER</code> is used to set the specific key identifier
+     * ThumbprintSHA1.
+     * 
+     * This identifier uses the SHA-1 digest of a security token to
+     * identify the security token. Please refer to chapter 7.2 of the OASIS WSS 1.1
+     * specification.
+     * 
+     */
+    public static final int THUMBPRINT_IDENTIFIER = 8;
 
     /*
      * The following values are bits that can be combined to for a set.

Modified: webservices/wss4j/trunk/src/org/apache/ws/security/components/crypto/Crypto.java
URL: http://svn.apache.org/viewcvs/webservices/wss4j/trunk/src/org/apache/ws/security/components/crypto/Crypto.java?rev=280033&r1=280032&r2=280033&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/components/crypto/Crypto.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/components/crypto/Crypto.java Sat Sep 10 12:41:18 2005
@@ -172,7 +172,23 @@
      * @return The byte array conating the binary SKI data
      */
     public byte[] getSKIBytesFromCert(X509Certificate cert) throws WSSecurityException;
+ 
+    /**
+     * Lookup a X509 Certificate in the keystore according to a given
+     * Thumbprint.
+     * 
+     * The search gets all alias names of the keystore, then reads the certificate chain
+     * or certificate for each alias. Then the thumbprint for each user certificate
+     * is compared with the thumbprint parameter.
+     *
+     * @param thumb The SHA1 thumbprint info bytes
+     * @return alias name of the certificate that matches the thumbprint
+     *         or null if no such certificate was found.
+     * @throws WSSecurityException if problems during keystore handling or wrong certificate
+     */
 
+    public String getAliasForX509CertThumb(byte[] thumb) throws WSSecurityException;
+ 
     /**
      * Gets the Keystore that was loaded by the underlying implementation
      *

Modified: webservices/wss4j/trunk/src/org/apache/ws/security/components/crypto/Merlin.java
URL: http://svn.apache.org/viewcvs/webservices/wss4j/trunk/src/org/apache/ws/security/components/crypto/Merlin.java?rev=280033&r1=280032&r2=280033&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/components/crypto/Merlin.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/components/crypto/Merlin.java Sat Sep 10 12:41:18 2005
@@ -24,6 +24,7 @@
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.util.Base64;
 
 import java.io.ByteArrayInputStream;
 import java.io.FileInputStream;
@@ -55,6 +56,7 @@
 import java.util.List;
 import java.util.Properties;
 import java.util.Vector;
+import java.util.Arrays;
 
 /**
  * JDK1.4 based implementation of Crypto (uses keystore).
@@ -390,14 +392,7 @@
                 if (data.length != skiBytes.length) {
                     continue;
                 }
-                for (int ii = 0; ii < data.length; ii++) {
-                    if (data[ii] != skiBytes[ii]) {
-                        found = false;
-                        break;
-                    }
-                    found = true;
-                }
-                if (found) {
+                if (Arrays.equals(data, skiBytes)) {
                     return alias;
                 }
             }
@@ -487,6 +482,68 @@
             x509certs[i] = (X509Certificate) certs[i];
         }
         return x509certs;
+    }
+
+    /**
+     * Lookup a X509 Certificate in the keystore according to a given
+     * Thumbprint.
+     * 
+     * The search gets all alias names of the keystore, then reads the certificate chain
+     * or certificate for each alias. Then the thumbprint for each user certificate
+     * is compared with the thumbprint parameter.
+     *
+     * @param thumb The SHA1 thumbprint info bytes
+     * @return alias name of the certificate that matches the thumbprint
+     *         or null if no such certificate was found.
+     * @throws WSSecurityException if problems during keystore handling or wrong certificate
+     */
+
+    public String getAliasForX509CertThumb(byte[] thumb) throws WSSecurityException {
+        Certificate cert = null;
+        MessageDigest sha = null;
+
+        try {
+            sha = MessageDigest.getInstance("SHA-1");
+        } catch (NoSuchAlgorithmException e1) {
+            throw new WSSecurityException(
+                    0,
+                    "noSHA1availabe");
+        }
+        try {
+            for (Enumeration e = keystore.aliases(); e.hasMoreElements();) {
+                String alias = (String) e.nextElement();
+                Certificate[] certs = keystore.getCertificateChain(alias);
+                if (certs == null || certs.length == 0) {
+                    // no cert chain, so lets check if getCertificate gives us a  result.
+                    cert = keystore.getCertificate(alias);
+                    if (cert == null) {
+                        return null;
+                    }
+                } else {
+                    cert = certs[0];
+                }
+                if (!(cert instanceof X509Certificate)) {
+                    continue;
+                }
+                sha.reset();
+                try {
+                    sha.update(cert.getEncoded());
+                } catch (CertificateEncodingException e1) {
+                    throw new WSSecurityException(
+                            WSSecurityException.SECURITY_TOKEN_UNAVAILABLE,
+                            "encodeError");
+                }
+                byte[] data = sha.digest();
+
+                if (Arrays.equals(data, thumb)) {
+                    return alias;
+                }
+            }
+        } catch (KeyStoreException e) {
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "keystore");
+        }
+        return null;
     }
 
     /**

Modified: webservices/wss4j/trunk/src/org/apache/ws/security/components/crypto/errors.properties
URL: http://svn.apache.org/viewcvs/webservices/wss4j/trunk/src/org/apache/ws/security/components/crypto/errors.properties?rev=280033&r1=280032&r2=280033&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/components/crypto/errors.properties (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/components/crypto/errors.properties Sat Sep 10 12:41:18 2005
@@ -17,3 +17,4 @@
 noSKIHandling = Problem with SKI information: {0}
 badBase64Data = Unable to decode Base64 encoded data
 badEncoding = Problem with Encoding: {0}
+noSHA1availabe = Crypto provider does not suppor1 SHA-1 digest

Modified: webservices/wss4j/trunk/src/org/apache/ws/security/handler/WSHandler.java
URL: http://svn.apache.org/viewcvs/webservices/wss4j/trunk/src/org/apache/ws/security/handler/WSHandler.java?rev=280033&r1=280032&r2=280033&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/handler/WSHandler.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/handler/WSHandler.java Sat Sep 10 12:41:18 2005
@@ -716,7 +716,8 @@
             if (!(reqData.getSigKeyId() == WSConstants.ISSUER_SERIAL
                     || reqData.getSigKeyId() == WSConstants.BST_DIRECT_REFERENCE
                     || reqData.getSigKeyId() == WSConstants.X509_KEY_IDENTIFIER
-                    || reqData.getSigKeyId() == WSConstants.SKI_KEY_IDENTIFIER)) {
+                    || reqData.getSigKeyId() == WSConstants.SKI_KEY_IDENTIFIER
+                    || reqData.getSigKeyId() == WSConstants.THUMBPRINT_IDENTIFIER)) {
                 throw new WSSecurityException("WSHandler: Signature: illegal key identification");
             }
         }
@@ -770,7 +771,8 @@
                     || reqData.getEncKeyId() == WSConstants.X509_KEY_IDENTIFIER
                     || reqData.getEncKeyId() == WSConstants.SKI_KEY_IDENTIFIER
                     || reqData.getEncKeyId() == WSConstants.BST_DIRECT_REFERENCE
-                    || reqData.getEncKeyId() == WSConstants.EMBEDDED_KEYNAME)) {
+                    || reqData.getEncKeyId() == WSConstants.EMBEDDED_KEYNAME
+                    || reqData.getSigKeyId() == WSConstants.THUMBPRINT_IDENTIFIER)) {
                 throw new WSSecurityException("WSHandler: Encryption: illegal key identification");
             }
         }

Modified: webservices/wss4j/trunk/src/org/apache/ws/security/handler/WSHandlerConstants.java
URL: http://svn.apache.org/viewcvs/webservices/wss4j/trunk/src/org/apache/ws/security/handler/WSHandlerConstants.java?rev=280033&r1=280032&r2=280033&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/handler/WSHandlerConstants.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/handler/WSHandlerConstants.java Sat Sep 10 12:41:18 2005
@@ -314,6 +314,7 @@
     /**
      * Specifying this name as {@link ENCRYPTION_USER}
      * triggers a special action to get the public key to use for encryption.
+     * <p/>
      * The handler uses the public key of the sender's certificate. Using this
      * way to define an encryption key simplifies certificate management to
      * a large extend.
@@ -668,6 +669,8 @@
      * </li>
      * <li><code>EmbeddedKeyName</code> for {@link WSConstants#EMBEDDED_KEYNAME}
      * </li>
+     * <li><code>Thumbprint</code> for {@link WSConstants#THUMBPRINT}
+     * </li>
      * </ul
      * See {@link #SIG_KEY_ID} {@link #ENC_KEY_ID}.
      */
@@ -684,6 +687,8 @@
                 new Integer(WSConstants.SKI_KEY_IDENTIFIER));
         keyIdentifier.put("EmbeddedKeyName",
                 new Integer(WSConstants.EMBEDDED_KEYNAME));
+        keyIdentifier.put("Thumbprint",
+                new Integer(WSConstants.THUMBPRINT_IDENTIFIER));
     }
     /*
      * internally used property names to store values inside the message context

Modified: webservices/wss4j/trunk/src/org/apache/ws/security/message/WSEncryptBody.java
URL: http://svn.apache.org/viewcvs/webservices/wss4j/trunk/src/org/apache/ws/security/message/WSEncryptBody.java?rev=280033&r1=280032&r2=280033&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/message/WSEncryptBody.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/message/WSEncryptBody.java Sat Sep 10 12:41:18 2005
@@ -393,6 +393,10 @@
             case WSConstants.SKI_KEY_IDENTIFIER:
                 secToken.setKeyIdentifierSKI(remoteCert, crypto);
                 break;
+                
+            case WSConstants.THUMBPRINT_IDENTIFIER:
+                secToken.setKeyIdentifierThumb(remoteCert);
+                break;
 
             case WSConstants.ISSUER_SERIAL:
                 XMLX509IssuerSerial data = new XMLX509IssuerSerial(doc, remoteCert);

Modified: webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSignEnvelope.java
URL: http://svn.apache.org/viewcvs/webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSignEnvelope.java?rev=280033&r1=280032&r2=280033&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSignEnvelope.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSignEnvelope.java Sat Sep 10 12:41:18 2005
@@ -519,6 +519,10 @@
             secretKey = usernameToken.getSecretKey();
             break;
 
+        case WSConstants.THUMBPRINT_IDENTIFIER:
+            secRef.setKeyIdentifierThumb(certs[0]);
+            break;
+
         default:
             throw new WSSecurityException(WSSecurityException.FAILURE,
                     "unsupportedKeyId");

Modified: webservices/wss4j/trunk/src/org/apache/ws/security/message/token/SecurityTokenReference.java
URL: http://svn.apache.org/viewcvs/webservices/wss4j/trunk/src/org/apache/ws/security/message/token/SecurityTokenReference.java?rev=280033&r1=280032&r2=280033&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/message/token/SecurityTokenReference.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/message/token/SecurityTokenReference.java Sat Sep 10 12:41:18 2005
@@ -32,6 +32,8 @@
 import org.apache.xml.security.utils.Constants;
 import org.w3c.dom.*;
 
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
 import java.security.cert.CertificateEncodingException;
 import java.security.cert.X509Certificate;
 
@@ -48,6 +50,8 @@
     public static final String SECURITY_TOKEN_REFERENCE = "SecurityTokenReference";
     public static final String KEY_NAME = "KeyName";
     public static final String SKI_URI = WSConstants.X509TOKEN_NS + "#X509SubjectKeyIdentifier";
+    public static final String THUMB_URI = WSConstants.SOAPMESSAGE_NS11 + "#" + WSConstants.THUMBPRINT;
+    public static final String SAML_ID_URI = WSConstants.SAMLTOKEN_NS + "#" + WSConstants.SAML_ASSERTION_ID;
     protected Element element = null;
     private XMLX509IssuerSerial issuerSerial = null;
     private byte[] skiBytes = null;
@@ -231,45 +235,74 @@
             throws WSSecurityException {
         Document doc = this.element.getOwnerDocument();
         byte data[] = crypto.getSKIBytesFromCert(cert);
-        org.w3c.dom.Text skiText = doc.createTextNode(Base64.encode(data));
-        Element keyId =
-                doc.createElementNS(WSConstants.WSSE_NS, "wsse:KeyIdentifier");
-            keyId.setAttributeNS(null, "ValueType", SKI_URI);
-            keyId.setAttributeNS(null,
-                    "EncodingType",
-                    BinarySecurity.BASE64_ENCODING);
+        
+        org.w3c.dom.Text text = doc.createTextNode(Base64.encode(data));
+        createKeyIdentifier(doc, SKI_URI, text);        
+    }
 
-        keyId.appendChild(skiText);
-        Element elem = getFirstElement();
-        if (elem != null) {
-            this.element.replaceChild(keyId, elem);
-        } else {
-            this.element.appendChild(keyId);
+    /**
+     * Sets the KeyIdentifer Element as a Thumbprint.
+     * 
+     * Takes a X509 certificate, computes its thumbprint using SHA-1, converts
+     * into base 64 and inserts it into a <code>wsse:KeyIdentifier</code>
+     * element, which is placed in the <code>wsse:SecurityTokenReference</code>
+     * element.
+     * 
+     * @param cert
+     *            is the X509 certficate to get the thumbprint
+     * @param crypto
+     *            is the Crypto implementation. Used to read SKI info bytes from
+     *            certificate
+     */
+    public void setKeyIdentifierThumb(X509Certificate cert)
+            throws WSSecurityException {
+        Document doc = this.element.getOwnerDocument();
+        MessageDigest sha = null;
+        try {
+            sha = MessageDigest.getInstance("SHA-1");
+        } catch (NoSuchAlgorithmException e1) {
+            throw new WSSecurityException(0, "noSHA1availabe");
         }
-    }
+        sha.reset();
+        try {
+            sha.update(cert.getEncoded());
+        } catch (CertificateEncodingException e1) {
+            throw new WSSecurityException(
+                    WSSecurityException.SECURITY_TOKEN_UNAVAILABLE,
+                    "encodeError");
+        }
+        byte[] data = sha.digest();
 
+        org.w3c.dom.Text text = doc.createTextNode(Base64.encode(data));
+        createKeyIdentifier(doc, THUMB_URI, text);
+    }
+    
 	public void setSAMLKeyIdentifier(String keyIdVal)
 			throws WSSecurityException {
 		Document doc = this.element.getOwnerDocument();
-		Element keyId =
-				doc.createElementNS(WSConstants.WSSE_NS, "wsse:KeyIdentifier");
-			keyId.setAttributeNS(WSConstants.WSSE_NS,
-					"ValueType",
-					"http://docs.oasis-open.org/wss/2004/XX/oasis-2004XX-wss-saml-token-profile-1.0#SAMLAssertionID");
-		keyId.appendChild(doc.createTextNode(keyIdVal));
-		Element elem = getFirstElement();
-		if (elem != null) {
-			this.element.replaceChild(keyId, elem);
-		} else {
-			this.element.appendChild(keyId);
-		}
+        createKeyIdentifier(doc, SAML_ID_URI, doc.createTextNode(keyIdVal));
 	}
 
+    private void createKeyIdentifier(Document doc, String uri, Node node) {
+        
+        Element keyId = doc.createElementNS(WSConstants.WSSE_NS,
+                "wsse:KeyIdentifier");
+        keyId.setAttributeNS(null, "ValueType", uri);
+        keyId.setAttributeNS(null, "EncodingType",
+                BinarySecurity.BASE64_ENCODING);
+
+        keyId.appendChild(node);
+        Element elem = getFirstElement();
+        if (elem != null) {
+            this.element.replaceChild(keyId, elem);
+        } else {
+            this.element.appendChild(keyId);
+        }
+    }
     /**
      * Gets the KeyIdentifer.
      *
-     * @return the {@link BinarySecurity} containing the X509
-     *         certificate or zero if a unknown key identifier
+     * @return the the X509 certficate or zero if a unknown key identifier
      *         type was detected.
      */
     public X509Certificate[] getKeyIdentifier(Crypto crypto)
@@ -277,6 +310,7 @@
         X509Security token = null;
         Element elem = getFirstElement();
         String value = elem.getAttribute("ValueType");
+        String alias = null;
 
         if (X509Security.getType().equals(value)) {
             token = new X509Security(elem);
@@ -287,10 +321,21 @@
                 return certs;
             }
         } else if (SKI_URI.equals(value)) {
-            String alias = getX509SKIAlias(crypto);
-            if (alias != null) {
-                return crypto.getCertificates(alias);
+            alias = getX509SKIAlias(crypto);
+        }
+        else if  (THUMB_URI.equals(value)) {
+            Node node = getFirstElement().getFirstChild();
+            if (node == null) {
+                return null;
             }
+            if (node.getNodeType() == Node.TEXT_NODE) {
+                byte[] thumb = Base64.decode(((Text) node).getData());
+                alias = crypto.getAliasForX509CertThumb(thumb);
+            }
+                 
+        }
+        if (alias != null) {
+            return crypto.getCertificates(alias);
         }
         return null;
     }



---------------------------------------------------------------------
To unsubscribe, e-mail: wss4j-dev-unsubscribe@ws.apache.org
For additional commands, e-mail: wss4j-dev-help@ws.apache.org