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 2004/02/29 13:30:35 UTC

cvs commit: ws-fx/wss4j/src/org/apache/ws/security/message WSSignEnvelope.java

werner      2004/02/29 04:30:35

  Modified:    wss4j/src/org/apache/ws/security/components/crypto
                        errors.properties Crypto.java Merlin.java
                        BouncyCastle.java
               wss4j/src/org/apache/ws/security WSConstants.java
                        WSSecurityEngine.java
               wss4j/src/org/apache/ws/security/message/token
                        BinarySecurity.java PKIPathSecurity.java
                        X509Security.java SecurityTokenReference.java
               wss4j/src/org/apache/ws/security/transform STRTransform.java
               wss4j/src/org/apache/ws/security/message WSSignEnvelope.java
  Log:
  Finish the SKI functions.
  Upgrade the identifiers, encoding types, etc to conform to current 
  OASIS WSS specifications.
  
  Revision  Changes    Path
  1.2       +1 -0      ws-fx/wss4j/src/org/apache/ws/security/components/crypto/errors.properties
  
  Index: errors.properties
  ===================================================================
  RCS file: /home/cvs/ws-fx/wss4j/src/org/apache/ws/security/components/crypto/errors.properties,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- errors.properties	13 Feb 2004 20:43:08 -0000	1.1
  +++ errors.properties	29 Feb 2004 12:30:35 -0000	1.2
  @@ -14,3 +14,4 @@
   error00 = Failed to load credentials.
   noCerts00 = No certificates loaded
   noKey00 = No private key loaded
  +noSKIHandling = Problem with SKI information: {0}
  
  
  
  1.2       +22 -0     ws-fx/wss4j/src/org/apache/ws/security/components/crypto/Crypto.java
  
  Index: Crypto.java
  ===================================================================
  RCS file: /home/cvs/ws-fx/wss4j/src/org/apache/ws/security/components/crypto/Crypto.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- Crypto.java	13 Feb 2004 20:43:08 -0000	1.1
  +++ Crypto.java	29 Feb 2004 12:30:35 -0000	1.2
  @@ -126,4 +126,26 @@
        */
       public String getAliasForX509Cert(String issuer, BigInteger serialNumber) throws Exception;
   
  +	/**
  +	 * Lookup a X509 Certificate in the keystore according to a given 
  +	 * SubjectKeyIdentifier.
  +	 * <p/>
  +	 * The search gets all alias names of the keystore and gets the certificate chain
  +	 * or certificate for each alias. Then the SKI for each user certificate 
  +	 * is compared with the SKI parameter.
  +	 * 
  +	 * @param skiBytes       The SKI info bytes
  +	 * @return alias name of the certificate that matches serialNumber and issuer name
  +	 *         or null if no such certificate was found.
  +	 */
  +	public String getAliasForX509Cert(byte[] skiBytes) throws Exception;
  +	/**
  +	 * Reads the SubjectKeyIdentifier information from the certificate. 
  +	 * <p/> 
  +	 * 
  +	 * @param cert       The certificate to read SKI
  +	 * @return 			 The byte array conating the binary SKI data
  +	 */
  +	public byte[] getSKIBytesFromCert(X509Certificate cert)	throws CredentialException, IOException;
  +
   }
  
  
  
  1.3       +144 -16   ws-fx/wss4j/src/org/apache/ws/security/components/crypto/Merlin.java
  
  Index: Merlin.java
  ===================================================================
  RCS file: /home/cvs/ws-fx/wss4j/src/org/apache/ws/security/components/crypto/Merlin.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- Merlin.java	26 Feb 2004 12:59:43 -0000	1.2
  +++ Merlin.java	29 Feb 2004 12:30:35 -0000	1.3
  @@ -41,6 +41,9 @@
   import java.util.Properties;
   import java.util.Vector;
   
  +import sun.security.util.DerValue;
  +
  +
   /**
    * JDK1.4 based implementation of Crypto (uses keystore).
    * <p/>
  @@ -239,25 +242,85 @@
           String issuerSplit[] = splitAndTrim(issuer);
           X509Certificate x509cert = null;
           String certIssuer[] = null;
  -        for (Enumeration e = keystore.aliases(); e.hasMoreElements();) {
  -            String alias = (String) e.nextElement();
  -            Certificate[] certs = keystore.getCertificateChain(alias);
  -            for (int i = 0; i < certs.length; i++) {
  -                if (!(certs[i] instanceof X509Certificate)) {
  -                    continue;
  -                }
  -                x509cert = (X509Certificate) certs[i];
  -                if (x509cert.getSerialNumber().compareTo(serialNumber) == 0) {
  -                    certIssuer = splitAndTrim(x509cert.getIssuerDN().getName());
  -                    if (equalsStringArray(issuerSplit, certIssuer)) {
  -                        return alias;
  -                    }
  -                }
  -            }
  -        }
  +		Certificate cert = null;
  +
  +		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;
  +			}
  +			x509cert = (X509Certificate) cert;
  +			if (x509cert.getSerialNumber().compareTo(serialNumber) == 0) {
  +				certIssuer = splitAndTrim(x509cert.getIssuerDN().getName());
  +				if (equalsStringArray(issuerSplit, certIssuer)) {
  +					return alias;
  +				}
  +			}
  +		}
           return null;
       }
   
  +	/**
  +	 * Lookup a X509 Certificate in the keystore according to a given 
  +	 * SubjectKeyIdentifier.
  +	 * <p/>
  +	 * The search gets all alias names of the keystore and gets the certificate chain
  +	 * or certificate for each alias. Then the SKI for each user certificate 
  +	 * is compared with the SKI parameter.
  +	 * 
  +	 * @param skiBytes       The SKI info bytes
  +	 * @return alias name of the certificate that matches serialNumber and issuer name
  +	 *         or null if no such certificate was found.
  +	 */
  +
  +	public String getAliasForX509Cert(byte[] skiBytes) throws Exception {
  +		String certIssuer[] = null;
  +		Certificate cert = null;
  +		boolean found = false;
  +
  +		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;
  +			}
  +			byte[] data = getSKIBytesFromCert((X509Certificate) cert);
  +			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) {
  +				return alias;
  +			}
  +		}
  +		return null;
  +	}
  +
       /**
        * Return a X509 Certificate alias in the keystore according to a given Certificate
        * <p/>
  @@ -336,6 +399,71 @@
               throw new CredentialException(-1, "error00", e);
           }
       }
  +
  +	/**
  +	 * Reads the SubjectKeyIdentifier information from the certificate. 
  +	 * <p/> 
  +	 * 
  +	 * @param cert       The certificate to read SKI
  +	 * @return 			 The byte array conating the binary SKI data
  +	 */
  +	static String SKI_OID = "2.5.29.14";
  +	public byte[] getSKIBytesFromCert(X509Certificate cert)
  +		throws CredentialException, IOException {
  +
  +		byte data[] = null;
  +		byte abyte0[] = null;
  +		if (cert.getVersion() < 3) {
  +			Object exArgs[] = { new Integer(cert.getVersion())};
  +			throw new CredentialException(
  +				1,
  +				"noSKIHandling",
  +				new Object[] { "Wrong certificate version (<3)" });
  +		}
  +
  +		/*
  +		 * Gets the DER-encoded OCTET string for the extension value (extnValue)
  +		 * identified by the passed-in oid String. The oid string is
  +		 * represented by a set of positive whole numbers separated by periods.
  +		 */
  +		data = cert.getExtensionValue(SKI_OID);
  +
  +		if (data == null) {
  +			throw new CredentialException(
  +				1,
  +				"noSKIHandling",
  +				new Object[] { "No extension data" });
  +		}
  +		DerValue dervalue = new DerValue(data);
  +
  +		if (dervalue == null) {
  +			throw new CredentialException(
  +				1,
  +				"noSKIHandling",
  +				new Object[] { "No DER value" });
  +		}
  +		if (dervalue.tag != DerValue.tag_OctetString) {
  +			throw new CredentialException(
  +				1,
  +				"noSKIHandling",
  +				new Object[] { "No octet string" });
  +		}
  +		byte[] extensionValue = dervalue.getOctetString();
  +
  +		/**
  +		 * Strip away first two bytes from the DerValue (tag and length)
  +		 */
  +		abyte0 = new byte[extensionValue.length - 2];
  +
  +		System.arraycopy(extensionValue, 2, abyte0, 0, abyte0.length);
  +
  +		/*
  +		byte abyte0[] = new byte[derEncodedValue.length - 4];
  +		System.arraycopy(derEncodedValue, 4, abyte0, 0, abyte0.length);
  +		*/
  +		return abyte0;
  +	}
  +
   
       /**
        * location of the key store.
  
  
  
  1.2       +8 -0      ws-fx/wss4j/src/org/apache/ws/security/components/crypto/BouncyCastle.java
  
  Index: BouncyCastle.java
  ===================================================================
  RCS file: /home/cvs/ws-fx/wss4j/src/org/apache/ws/security/components/crypto/BouncyCastle.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- BouncyCastle.java	13 Feb 2004 20:43:08 -0000	1.1
  +++ BouncyCastle.java	29 Feb 2004 12:30:35 -0000	1.2
  @@ -417,6 +417,14 @@
       public PrivateKey getPrivateKey(String alias, String password) throws Exception {
           throw new RuntimeException("Not Yet Implemented");
       }
  +    
  +	public byte[] getSKIBytesFromCert(X509Certificate cert)	throws CredentialException, IOException {
  +		throw new RuntimeException("Not Yet Implemented");
  +	}
  +
  +	public String getAliasForX509Cert(byte[] skiBytes) throws Exception {
  +		throw new RuntimeException("Not Yet Implemented");
  +	}
   
       /**
        * get the name of the file where the key/certificate information is stored.
  
  
  
  1.3       +2 -2      ws-fx/wss4j/src/org/apache/ws/security/WSConstants.java
  
  Index: WSConstants.java
  ===================================================================
  RCS file: /home/cvs/ws-fx/wss4j/src/org/apache/ws/security/WSConstants.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- WSConstants.java	26 Feb 2004 12:59:42 -0000	1.2
  +++ WSConstants.java	29 Feb 2004 12:30:35 -0000	1.3
  @@ -23,10 +23,10 @@
    * Constants in WS-Security spec.
    */
   public interface WSConstants {
  -    public static final String WSSE_NS = "http://schemas.xmlsoap.org/ws/2002/07/secext";
  +    public static final String WSSE_NS = "http://www.docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
       public static final String WSSE_PREFIX = "wsse";
       public static final String WSSE_LN = "Security";
  -    public static final String WSU_NS = "http://schemas.xmlsoap.org/ws/2002/07/utility";
  +    public static final String WSU_NS = "http://www.docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd";
       public static final String WSU_PREFIX = "wsu";
       public static final String SIG_NS = "http://www.w3.org/2000/09/xmldsig#";
       public static final String SIG_PREFIX = "ds";
  
  
  
  1.3       +1 -1      ws-fx/wss4j/src/org/apache/ws/security/WSSecurityEngine.java
  
  Index: WSSecurityEngine.java
  ===================================================================
  RCS file: /home/cvs/ws-fx/wss4j/src/org/apache/ws/security/WSSecurityEngine.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- WSSecurityEngine.java	26 Feb 2004 12:59:42 -0000	1.2
  +++ WSSecurityEngine.java	29 Feb 2004 12:30:35 -0000	1.3
  @@ -554,7 +554,7 @@
        */
       private BinarySecurity createSecurityToken(Element element) throws WSSecurityException {
           BinarySecurity token = new BinarySecurity(element);
  -        QName type = token.getValueType();
  +        String type = token.getValueType();
           Class clazz = (Class) tokenImpl.get(type);
           if (clazz == null) {
               throw new WSSecurityException(WSSecurityException.UNSUPPORTED_SECURITY_TOKEN,
  
  
  
  1.2       +9 -11     ws-fx/wss4j/src/org/apache/ws/security/message/token/BinarySecurity.java
  
  Index: BinarySecurity.java
  ===================================================================
  RCS file: /home/cvs/ws-fx/wss4j/src/org/apache/ws/security/message/token/BinarySecurity.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- BinarySecurity.java	13 Feb 2004 20:43:08 -0000	1.1
  +++ BinarySecurity.java	29 Feb 2004 12:30:35 -0000	1.2
  @@ -38,7 +38,7 @@
   public class BinarySecurity {
       public static final QName TOKEN = new QName(WSConstants.WSSE_NS, "BinarySecurityToken");
       public static final QName TOKEN_KI = new QName(WSConstants.WSSE_NS, "KeyIdentifier");
  -    public static final QName BASE64_ENCODING = new QName(WSConstants.WSSE_NS, "Base64Binary");
  +    public static final String BASE64_ENCODING = WSConstants.WSSE_NS + "#Base64Binary";
       protected Element element = null;
   
       /**
  @@ -78,9 +78,8 @@
        * 
        * @return 
        */
  -    public QName getValueType() {
  -        String value = this.element.getAttribute("ValueType");
  -        return WSSecurityUtil.getQNameFromString(value, this.element);
  +    public String getValueType() {
  +        return this.element.getAttribute("ValueType");
       }
   
       /**
  @@ -89,8 +88,8 @@
        * 
        * @param type 
        */
  -    protected void setValueType(QName type) {
  -        this.element.setAttributeNS(null, "ValueType", WSSecurityUtil.getStringForQName(type, this.element));
  +    protected void setValueType(String type) {
  +        this.element.setAttributeNS(null, "ValueType", type);
       }
   
       /**
  @@ -99,9 +98,8 @@
        * 
        * @return 
        */
  -    public QName getEncodingType() {
  -        String value = this.element.getAttribute("EncodingType");
  -        return WSSecurityUtil.getQNameFromString(value, this.element);
  +    public String getEncodingType() {
  +        return this.element.getAttribute("EncodingType");
       }
   
       /**
  @@ -110,8 +108,8 @@
        * 
        * @param encoding 
        */
  -    protected void setEncodingType(QName encoding) {
  -        this.element.setAttributeNS(null, "EncodingType", WSSecurityUtil.getStringForQName(encoding, this.element));
  +    protected void setEncodingType(String encoding) {
  +        this.element.setAttributeNS(null, "EncodingType", encoding);
       }
   
       /**
  
  
  
  1.2       +1 -2      ws-fx/wss4j/src/org/apache/ws/security/message/token/PKIPathSecurity.java
  
  Index: PKIPathSecurity.java
  ===================================================================
  RCS file: /home/cvs/ws-fx/wss4j/src/org/apache/ws/security/message/token/PKIPathSecurity.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- PKIPathSecurity.java	13 Feb 2004 20:43:08 -0000	1.1
  +++ PKIPathSecurity.java	29 Feb 2004 12:30:35 -0000	1.2
  @@ -23,7 +23,6 @@
   import org.w3c.dom.Document;
   import org.w3c.dom.Element;
   
  -import javax.xml.namespace.QName;
   import java.io.IOException;
   import java.security.GeneralSecurityException;
   import java.security.cert.CertificateEncodingException;
  @@ -36,7 +35,7 @@
    * @author Davanum Srinivas (dims@yahoo.com).
    */
   public class PKIPathSecurity extends BinarySecurity {
  -    public static final QName TYPE = new QName(WSConstants.WSSE_NS, "PKIPath");
  +    public static final String TYPE = WSConstants.WSSE_NS + "#X509PKIPathv1";
   
       /**
        * Constructor.
  
  
  
  1.3       +1 -2      ws-fx/wss4j/src/org/apache/ws/security/message/token/X509Security.java
  
  Index: X509Security.java
  ===================================================================
  RCS file: /home/cvs/ws-fx/wss4j/src/org/apache/ws/security/message/token/X509Security.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- X509Security.java	26 Feb 2004 12:59:43 -0000	1.2
  +++ X509Security.java	29 Feb 2004 12:30:35 -0000	1.3
  @@ -23,7 +23,6 @@
   import org.w3c.dom.Document;
   import org.w3c.dom.Element;
   
  -import javax.xml.namespace.QName;
   import java.io.ByteArrayInputStream;
   import java.security.GeneralSecurityException;
   import java.security.cert.CertificateEncodingException;
  @@ -36,7 +35,7 @@
    * @author Davanum Srinivas (dims@yahoo.com).
    */
   public class X509Security extends BinarySecurity {
  -    public static final QName TYPE = new QName(WSConstants.WSSE_NS, "X509v3");
  +    public static final String TYPE = WSConstants.WSSE_NS + "#X509v3";
   	
   	/*
   	 * Stores the associated X.509 Certificate. This saves numerous
  
  
  
  1.4       +79 -102   ws-fx/wss4j/src/org/apache/ws/security/message/token/SecurityTokenReference.java
  
  Index: SecurityTokenReference.java
  ===================================================================
  RCS file: /home/cvs/ws-fx/wss4j/src/org/apache/ws/security/message/token/SecurityTokenReference.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- SecurityTokenReference.java	26 Feb 2004 12:59:43 -0000	1.3
  +++ SecurityTokenReference.java	29 Feb 2004 12:30:35 -0000	1.4
  @@ -35,9 +35,7 @@
   
   import javax.xml.namespace.QName;
   import java.security.cert.X509Certificate;
  -import java.io.IOException;
   
  -import sun.security.util.DerValue;
   
   /**
    * Security Token Reference.
  @@ -52,8 +50,10 @@
   
   	public static final QName TOKEN =
   		new QName(WSConstants.WSSE_NS, "SecurityTokenReference");
  +	public static final String SKI_URI = WSConstants.WSSE_NS + "#X509SubjectKeyIdentifier";
   	protected Element element = null;
   	private XMLX509IssuerSerial issuerSerial = null;
  +	private byte[] skiBytes = null;
   
   	private static boolean doDebug = false;
   
  @@ -184,8 +184,8 @@
   		Text certText = doc.createTextNode(Base64.encode(data));
   		Element keyId =
   			doc.createElementNS(WSConstants.WSSE_NS, "wsse:KeyIdentifier");
  -		keyId.setAttributeNS(null, "ValueType", "wsse:X509v3");
  -		keyId.setAttributeNS(null, "EncodingType", "wsse:Base64Binary");
  +		keyId.setAttributeNS(null, "ValueType", X509Security.TYPE);
  +		keyId.setAttributeNS(null, "EncodingType",  BinarySecurity.BASE64_ENCODING);
   		keyId.appendChild(certText);
   		Element elem = getFirstElement();
   		if (elem != null) {
  @@ -201,18 +201,16 @@
   	 * in the <code>wsse:SecurityTokenReference</code> element.
   	 * 
   	 * @param cert is the X509 certficate to get the SKI
  +	 * @param crypto is the Crypto implementation. Used to read SKI info bytes from certificate
   	 */
  -	public void setKeyIdentifierSKI(X509Certificate cert) throws Exception {
  +	public void setKeyIdentifierSKI(X509Certificate cert, Crypto crypto) throws Exception {
   		Document doc = this.element.getOwnerDocument();
  -		byte data[] = getSKIBytesFromCert(cert);
  +		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",
  -			"wsse:X509SubjectKeyIdentifier");
  -		keyId.setAttributeNS(null, "EncodingType", "wsse:Base64Binary");
  +		keyId.setAttributeNS(null, "ValueType", SKI_URI);
  +		keyId.setAttributeNS(null, "EncodingType", BinarySecurity.BASE64_ENCODING);
   		keyId.appendChild(skiText);
   		Element elem = getFirstElement();
   		if (elem != null) {
  @@ -233,31 +231,51 @@
   		X509Security token = null;
   		Element elem = getFirstElement();
   		String value = elem.getAttribute("ValueType");
  -		if (value.equals("wsse:X509v3")) {
  +		if (value.equals(X509Security.TYPE)) {
   			token = new X509Security(elem);
  -		} else if (value.equals("wsse:X509SubjectKeyIdentifier")) {
  +			if (token != null) {
  +				X509Certificate cert = token.getX509Certificate(crypto);
  +				X509Certificate[] certs = new X509Certificate[1];
  +				certs[0] = cert;
  +				return certs;
  +			}
  +		} else if (value.equals(SKI_URI)) {
   			token = getEmbeddedTokenFromSKI(element.getOwnerDocument(), crypto);
  -			if (token == null) { // TODO: get cert from key store using SKI
  +			if (token != null) {
  +				X509Certificate cert = token.getX509Certificate(crypto);
  +				X509Certificate[] certs = new X509Certificate[1];
  +				certs[0] = cert;
  +				return certs;
  +			}
  +			else {
  +				String alias = getX509SKIAlias(crypto);
  +				if (alias != null) {
  +					return crypto.getCertificates(alias);
  +				}
   			}
   		}
  -		if (token != null) {
  -			X509Certificate cert = token.getX509Certificate(crypto);
  -			X509Certificate[] certs = new X509Certificate[1];
  -			certs[0] = cert;
  -			return certs;
  -		}
   		return null;
   	}
  -
  -	public X509Security getEmbeddedTokenFromSKI(Document doc, Crypto crypto)
  -		throws Exception {
  -
  +	
  +	public String getX509SKIAlias(Crypto crypto) throws Exception {
  +		if (skiBytes == null) {
  +			skiBytes = getSKIBytes();
  +			if (skiBytes == null) {
  +				return null;
  +			}
  +		}
  +		String alias =
  +			crypto.getAliasForX509Cert(skiBytes);
   		if (doDebug) {
  -			log.debug("getCertFromSKI: enter");
  +			log.info("X509 SKI alias: " + alias);
   		}
  -		X509Security found = null;
  +		return alias;
  +	}
   
  -		byte[] skiBytes = null;
  +	public byte[] getSKIBytes() {
  +		if (skiBytes != null) {
  +			return skiBytes;
  +		} 
   		Node node = getFirstElement().getFirstChild();
   		if (node == null) {
   			return null;
  @@ -269,6 +287,23 @@
   				return null;
   			}
   		}
  +		return skiBytes;
  +	}
  +
  +	public X509Security getEmbeddedTokenFromSKI(Document doc, Crypto crypto)
  +		throws Exception {
  +
  +		if (doDebug) {
  +			log.debug("getCertFromSKI: enter");
  +		}
  +		X509Security found = null;
  +
  +		if (skiBytes == null) {
  +			skiBytes = getSKIBytes();
  +			if (skiBytes == null) {
  +				return null;
  +			}
  +		}
   		if (doDebug) {
   			log.debug("Cert SKI: got SKI bytes");
   		}
  @@ -284,7 +319,7 @@
   			}
   			Element bstElement = (Element) nl.item(i);
   			String value = bstElement.getAttribute("ValueType");
  -			if (!value.equals("wsse:X509v3")) {
  +			if (!value.equals(X509Security.TYPE)) {
   				continue;
   			}
   			X509Security token = new X509Security(bstElement);
  @@ -295,7 +330,7 @@
   			if (doDebug) {
   				log.debug("Cert SKI: got cert from BST");
   			}
  -			byte data[] = getSKIBytesFromCert(cert);
  +			byte data[] = crypto.getSKIBytesFromCert(cert);
   			if (data.length != skiBytes.length) {
   				continue;
   			}
  @@ -308,75 +343,14 @@
   					break;
   				}
   			}
  -			if (doDebug) {
  -				log.debug("Cert SKI: found embedded BST: " + token);
  +			if (doDebug && token != null) {
  +				log.debug("Cert SKI: found embedded BST");
   			}
   			found = token;
   		}
   		return found;
   	}
   
  -
  -	static String SKI_OID = "2.5.29.14";
  -	public byte[] getSKIBytesFromCert(X509Certificate cert)
  -		throws WSSecurityException, IOException {
  -
  -		byte data[] = null;
  -		byte abyte0[] = null;
  -		if (cert.getVersion() < 3) {
  -			Object exArgs[] = { new Integer(cert.getVersion())};
  -			throw new WSSecurityException(
  -				WSSecurityException.FAILURE,
  -				"noSKIHandling",
  -				new Object[] { "Wrong certificate version (<3)" });
  -		}
  -
  -		/*
  -		 * Gets the DER-encoded OCTET string for the extension value (extnValue)
  -		 * identified by the passed-in oid String. The oid string is
  -		 * represented by a set of positive whole numbers separated by periods.
  -		 */
  -		data = cert.getExtensionValue(SKI_OID);
  -
  -		if (data == null) {
  -			throw new WSSecurityException(
  -				WSSecurityException.FAILURE,
  -				"noSKIHandling",
  -				new Object[] { "No extension data" });
  -		}
  -		DerValue dervalue = new DerValue(data);
  -
  -		if (dervalue == null) {
  -			throw new WSSecurityException(
  -				WSSecurityException.FAILURE,
  -				"noSKIHandling",
  -				new Object[] { "No DER value" });
  -		}
  -		if (dervalue.tag != DerValue.tag_OctetString) {
  -			throw new WSSecurityException(
  -				WSSecurityException.FAILURE,
  -				"noSKIHandling",
  -				new Object[] { "No octet string" });
  -		}
  -		byte[] extensionValue = dervalue.getOctetString();
  -
  -		/**
  -		 * Strip away first two bytes from the DerValue (tag and length)
  -		 */
  -		abyte0 = new byte[extensionValue.length - 2];
  -
  -		System.arraycopy(extensionValue, 2, abyte0, 0, abyte0.length);
  -
  -		/*
  -		byte abyte0[] = new byte[derEncodedValue.length - 4];
  -		System.arraycopy(derEncodedValue, 4, abyte0, 0, abyte0.length);
  -		*/
  -		if (doDebug) {
  -			log.debug("Base64 of SKI is " + Base64.encode(abyte0));
  -		}
  -		return abyte0;
  -	}
  -
   	/*
   	 * Here the methods that handle the IssuerSerial key identifiaton
   	 */
  @@ -398,18 +372,14 @@
   
   	/**
   	 * Gets the certificate identified with X509 issuerSerial data.
  -	 * This method first tries to get the certificate from the keystore.
  -	 * If this fails it checks if the certificate is embedded in the
  -	 * message.
  +	 * This method first tries to get the embedded certificate.
  +	 * If this fails it checks if the certificate is  in the
  +	 * keystore.
   	 * 
   	 * @return a certificate array or null if nothing found
   	 */
   	public X509Certificate[] getX509IssuerSerial(Crypto crypto)
   		throws Exception {
  -		String alias = getX509IssuerSerialAlias(crypto);
  -		if (alias != null) {
  -			return crypto.getCertificates(alias);
  -		}
   		X509Security token =
   			getEmbeddedTokenFromIS(element.getOwnerDocument(), crypto);
   		if (token != null) {
  @@ -418,6 +388,10 @@
   			certs[0] = cert;
   			return certs;
   		}
  +		String alias = getX509IssuerSerialAlias(crypto);
  +		if (alias != null) {
  +			return crypto.getCertificates(alias);
  +		}
   		return null;
   	}
   
  @@ -439,7 +413,7 @@
   				issuerSerial.getIssuerName(),
   				issuerSerial.getSerialNumber());
   		if (doDebug) {
  -			log.info("Verify X509IssuerSerial alias: " + alias);
  +			log.info("X509IssuerSerial alias: " + alias);
   		}
   		return alias;
   	}
  @@ -471,7 +445,7 @@
   			}
   			Element bstElement = (Element) nl.item(i);
   			String value = bstElement.getAttribute("ValueType");
  -			if (!value.equals("wsse:X509v3")) {
  +			if (!value.equals(X509Security.TYPE)) {
   				continue;
   			}
   
  @@ -481,7 +455,7 @@
   				continue;
   			}
   			if (doDebug) {
  -				log.debug("Cert IS: got cert from BST");
  +				log.debug("Cert IS: got cert from BST: " + cert);
   			}
   			/*
   			 * Note: the direct compar of IssuerName/Name may fail because
  @@ -501,6 +475,9 @@
   				}
   				return token;
   			}
  +		}
  +		if (doDebug) {
  +			log.debug("Cert IS: no embedded BST found");
   		}
   		return null;
   	}
  
  
  
  1.3       +57 -21    ws-fx/wss4j/src/org/apache/ws/security/transform/STRTransform.java
  
  Index: STRTransform.java
  ===================================================================
  RCS file: /home/cvs/ws-fx/wss4j/src/org/apache/ws/security/transform/STRTransform.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- STRTransform.java	26 Feb 2004 12:59:42 -0000	1.2
  +++ STRTransform.java	29 Feb 2004 12:30:35 -0000	1.3
  @@ -20,7 +20,6 @@
   import org.apache.ws.security.WSDocInfo;
   import org.apache.ws.security.WSDocInfoStore;
   import org.apache.ws.security.WSConstants;
  -import org.apache.ws.security.WSSecurityException;
   import org.apache.ws.security.message.token.SecurityTokenReference;
   import org.apache.ws.security.message.token.X509Security;
   import org.apache.ws.security.util.WSSecurityUtil;
  @@ -37,6 +36,7 @@
   import org.apache.xml.security.c14n.InvalidCanonicalizerException;
   import org.apache.xml.security.transforms.TransformSpi;
   import org.apache.xml.security.utils.XMLUtils;
  +import org.apache.xml.security.utils.Base64;
   import org.apache.xpath.XPathAPI;
   
   import javax.xml.parsers.DocumentBuilder;
  @@ -44,11 +44,14 @@
   import javax.xml.parsers.ParserConfigurationException;
   import javax.xml.transform.TransformerException;
   
  +import java.security.cert.X509Certificate;
  +
   import org.xml.sax.SAXException;
   import org.w3c.dom.Node;
   import org.w3c.dom.Element;
   import org.w3c.dom.NodeList;
   import org.w3c.dom.Document;
  +import org.w3c.dom.Text;
   
   import org.apache.commons.logging.Log;
   import org.apache.commons.logging.LogFactory;
  @@ -64,7 +67,8 @@
   
   	/** Field implementedTransformURI */
   	public static final String implementedTransformURI =
  -		"http://schemas.xmlsoap.org/2003/06/STR-Transform";
  +		"http://www.docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd#STRTransform";
  +
   
   	private static Log log = LogFactory.getLog(STRTransform.class.getName());
   	private static boolean doDebug = false;
  @@ -213,7 +217,7 @@
   				str = dereferenceSTR(thisDoc, (Element) tmpEl);
   				/*
   				 * Keep in mind: the returned element belong to "thisDoc", thus
  -				 * import it to "doc" before replace it.
  +				 * import it to "doc" before replacing it.
   				 */
   
   				/*
  @@ -262,7 +266,7 @@
   		}
   	}
   
  -	private Element dereferenceSTR(Document doc, Element tmpE)
  +	private Element dereferenceSTR(Document doc, Element secRefE)
   		throws Exception {
   
   		/*
  @@ -279,12 +283,12 @@
   		 * 
   		 *
   		 * Forth step: after security token was located, prepare it. Either
  -		 * return BinarySeciurityToken or wrap the located token
  +		 * return BinarySecurityToken or wrap the located token
   		 * in a newly created BST element as specified in WS Specification.
   		 * 
  -		 * Note: every element (also newly created elemets) belong to the
  -		 * document defined by the parameter. This is the main SOAP document
  -		 * and _not_ the document part that is to be signed/verified. Thus
  +		 * Note: every element (also newly created elements) belong to the
  +		 * document defined by the doc parameter. This is the main SOAP document
  +		 * (thisDoc) and _not_ the document part that is to be signed/verified. Thus
   		 * the caller must import the returned element into the document 
   		 * part that is signed/verified.
   		 * 
  @@ -292,7 +296,7 @@
   		SecurityTokenReference secRef = null;
   		Element tokElement = null;
   		
  -		secRef = new SecurityTokenReference(tmpE);
  +		secRef = new SecurityTokenReference(secRefE);
   		
   		/*
   		 * First case: direct reference, according to chap 7.2 of OASIS
  @@ -300,44 +304,76 @@
   		 */
   		if (secRef.containsReference()) {
   			if (doDebug) {
  -				log.debug("Found str reference");
  +				log.debug("STR: Reference");
   			}
   			tokElement = secRef.getTokenElement(secRef, doc);
  -			/*
  -			 * second case: IssuerSerial, first try to get embedded 
  -			 * certificate, if that fails, lookup in keystore, wrap
  -			 * in BST according to specification
  -			 */
  -		} else if (secRef.containsX509IssuerSerial()) {
  +			if (tokElement == null) {
  +				throw new CanonicalizationException("empty");
  +			}
  +		} 
  +		/*
  +		 * second case: IssuerSerial, first try to get embedded 
  +		 * certificate, if that fails, lookup in keystore, wrap
  +		 * in BST according to specification
  +		 */
  +		else if (secRef.containsX509IssuerSerial()) {
   			if (doDebug) {
  -				log.debug("STR issuerSerial embedded");
  +				log.debug("STR: IssuerSerial");
   			}
   			X509Security x509token = secRef.getEmbeddedTokenFromIS(doc, wsDocInfo.getCrypto());
   			if (x509token != null) {
   				tokElement = x509token.getElement();
   			}
   			else {
  -				return null; //TODO: handle certificate from keystore, binary
  +				X509Certificate[] certs = secRef.getX509IssuerSerial(wsDocInfo.getCrypto());
  +				if (certs == null || certs.length == 0 || certs[0] == null) {
  +					throw new CanonicalizationException("empty");
  +				}
  +				tokElement = createBST(doc, certs[0], secRefE);
   			}	
   		}
   		/*
  -		 * third case: IKeyIdentifier, must be SKI, first try to get embedded 
  +		 * third case: KeyIdentifier, must be SKI, first try to get embedded 
   		 * certificate, if that fails, lookup in keystore, wrap
   		 * in BST according to specification. No other KeyIdentifier
   		 * type handled here - just SKI
   		 */
   		else if (secRef.containsKeyIdentifier()) {
   			if (doDebug) {
  -				log.debug("KeyIdentifier issuerSerial embedded");
  +				log.debug("STR: KeyIdentifier");
   			}
   			X509Security x509token = secRef.getEmbeddedTokenFromSKI(doc, wsDocInfo.getCrypto());
   			if (x509token != null) {
   				tokElement = x509token.getElement();
   			}
   			else {
  -				return null; //TODO: handle certificate from keystore, binary
  +				X509Certificate[] certs = secRef.getKeyIdentifier(wsDocInfo.getCrypto());
  +				if (certs == null || certs.length == 0 || certs[0] == null) {
  +					throw new CanonicalizationException("empty");
  +				}
  +				tokElement = createBST(doc, certs[0], secRefE);
   			}
   		}
   		return (Element) tokElement;
  +	}
  +	
  +	private Element createBST(
  +		Document doc,
  +		X509Certificate cert,
  +		Element secRefE)
  +		throws Exception {
  +		byte data[] = cert.getEncoded();
  +		String prefix = WSSecurityUtil.getPrefix(WSConstants.WSSE_NS, secRefE);
  +		Element elem =
  +			doc.createElementNS(
  +				WSConstants.WSSE_NS,
  +				prefix + ":BinarySecurityToken");
  +		WSSecurityUtil.setNamespace(elem, WSConstants.WSSE_NS, prefix);
  +
  +		elem.setAttributeNS(null, "ValueType", X509Security.TYPE);
  +		Text certText = doc.createTextNode(Base64.encode(data));
  +		// Text certText = doc.createTextNode(data);
  +		elem.appendChild(certText);
  +		return elem;
   	}
   }
  
  
  
  1.3       +2 -3      ws-fx/wss4j/src/org/apache/ws/security/message/WSSignEnvelope.java
  
  Index: WSSignEnvelope.java
  ===================================================================
  RCS file: /home/cvs/ws-fx/wss4j/src/org/apache/ws/security/message/WSSignEnvelope.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- WSSignEnvelope.java	26 Feb 2004 12:59:42 -0000	1.2
  +++ WSSignEnvelope.java	29 Feb 2004 12:30:35 -0000	1.3
  @@ -304,7 +304,7 @@
   				// fall thru
   			}
   			case WSConstants.SKI_KEY_IDENTIFIER :
  -				secRef.setKeyIdentifierSKI(certs[0]);
  +				secRef.setKeyIdentifierSKI(certs[0], crypto);
   				break;
   			default :
   				throw new WSSecurityException(
  @@ -360,9 +360,8 @@
   			WSConstants.SIG_NS,
   			WSConstants.SIG_PREFIX);
   			
  -		canonElem.setAttributeNS(null, "Algorithm", "http://www.w3.org/TR/2001/REC-xml-c14n-20010315");
  +		canonElem.setAttributeNS(null, "Algorithm", Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);
   		transformParam.appendChild(canonElem);
   		return transformParam;
       }
  -
   }