Author: coheigea
Date: Thu Mar  5 16:00:47 2009
New Revision: 750484

URL: http://svn.apache.org/viewvc?rev=750484&view=rev
Log:
[WSS-168] - A fix for different issuer DN formats breaking 
decryption/verification
 - This fix introduces a compile-time dependency on BouncyCastle.
 - The idea is to convert the issuer DN to a java X500Principal object first. 
 - This is to ensure interop with a DN constructed from .NET, where e.g. it 
uses "S" instead of "ST".
 - Then convert it to a BouncyCastle X509Name, which will order the attributes 
of the DN in a 
   particular way (see WSS-168). 
 - If the conversion to an X500Principal object fails (e.g. if the DN contains 
"E" instead of 
  "EMAILADDRESS"), then fall back on a direct conversion to a BC X509Name.


Modified:
    webservices/wss4j/trunk/pom.xml
    webservices/wss4j/trunk/src/org/apache/ws/security/WSSConfig.java
    
webservices/wss4j/trunk/src/org/apache/ws/security/components/crypto/BouncyCastle.java
    
webservices/wss4j/trunk/src/org/apache/ws/security/components/crypto/CryptoBase.java
    
webservices/wss4j/trunk/src/org/apache/ws/security/components/crypto/CryptoFactory.java
    
webservices/wss4j/trunk/src/org/apache/ws/security/components/crypto/Merlin.java
    webservices/wss4j/trunk/test/wssec/TestWSSecurityWSS86.java

Modified: webservices/wss4j/trunk/pom.xml
URL: 
http://svn.apache.org/viewvc/webservices/wss4j/trunk/pom.xml?rev=750484&r1=750483&r2=750484&view=diff
==============================================================================
--- webservices/wss4j/trunk/pom.xml (original)
+++ webservices/wss4j/trunk/pom.xml Thu Mar  5 16:00:47 2009
@@ -200,6 +200,7 @@
                               !org.apache.ws.axis.security.*,
                               javax.xml.crypto.*,
                               org.apache.xml.security.*,
+                              org.bouncycastle.*,
                               org.jcp.xml.dsig.internal.*,
                               org.opensaml.*;resolution:=optional,
                               *;resolution:=optional
@@ -349,7 +350,7 @@
                     <groupId>bouncycastle</groupId>
                     <artifactId>bcprov-jdk14</artifactId>
                     <version>${bcprov.jdk14.version}</version>
-                    <scope>runtime</scope>
+                    <scope>compile</scope>
                 </dependency>
             </dependencies>
         </profile>
@@ -363,7 +364,7 @@
                     <groupId>bouncycastle</groupId>
                     <artifactId>bcprov-jdk15</artifactId>
                     <version>${bcprov.jdk15.version}</version>
-                    <scope>runtime</scope>
+                    <scope>compile</scope>
                 </dependency>
             </dependencies>
         </profile>

Modified: webservices/wss4j/trunk/src/org/apache/ws/security/WSSConfig.java
URL: 
http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/WSSConfig.java?rev=750484&r1=750483&r2=750484&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/WSSConfig.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/WSSConfig.java Thu Mar  
5 16:00:47 2009
@@ -498,7 +498,7 @@
                         (java.security.Provider) c.newInstance(), 2
                     );
                 if (log.isDebugEnabled()) {
-                    log.debug("The provider " + id + " was added at: " + ret);
+                    log.debug("The provider " + id + " was added at position: 
" + ret);
                 }                
             }
             return true;

Modified: 
webservices/wss4j/trunk/src/org/apache/ws/security/components/crypto/BouncyCastle.java
URL: 
http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/components/crypto/BouncyCastle.java?rev=750484&r1=750483&r2=750484&view=diff
==============================================================================
--- 
webservices/wss4j/trunk/src/org/apache/ws/security/components/crypto/BouncyCastle.java
 (original)
+++ 
webservices/wss4j/trunk/src/org/apache/ws/security/components/crypto/BouncyCastle.java
 Thu Mar  5 16:00:47 2009
@@ -59,7 +59,8 @@
         super(properties);
     }
 
-    public BouncyCastle(Properties properties, ClassLoader loader) throws 
CredentialException, IOException {
+    public BouncyCastle(Properties properties, ClassLoader loader) 
+        throws CredentialException, IOException {
         super(properties,loader);
     }
 
@@ -76,7 +77,7 @@
      *
      */
     public X509Certificate[] getX509Certificates(byte[] data, boolean reverse)
-            throws WSSecurityException {
+        throws WSSecurityException {
         InputStream in = new ByteArrayInputStream(data);
         CertPath path = null;
         try {
@@ -109,11 +110,11 @@
      *
      */
     public byte[] getCertificateData(boolean reverse, X509Certificate[] certs)
-            throws WSSecurityException {
-        Vector list = new Vector();
+        throws WSSecurityException {
+        List list = new Vector();
         for (int i = 0; i < certs.length; i++) {
             if (reverse) {
-                list.insertElementAt(certs[i], 0);
+                list.add(0, certs[i]);
             } else {
                 list.add(certs[i]);
             }

Modified: 
webservices/wss4j/trunk/src/org/apache/ws/security/components/crypto/CryptoBase.java
URL: 
http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/components/crypto/CryptoBase.java?rev=750484&r1=750483&r2=750484&view=diff
==============================================================================
--- 
webservices/wss4j/trunk/src/org/apache/ws/security/components/crypto/CryptoBase.java
 (original)
+++ 
webservices/wss4j/trunk/src/org/apache/ws/security/components/crypto/CryptoBase.java
 Thu Mar  5 16:00:47 2009
@@ -20,6 +20,8 @@
 import org.apache.commons.logging.LogFactory;
 import org.apache.ws.security.WSSecurityException;
 
+import org.bouncycastle.asn1.x509.X509Name;
+
 import java.io.ByteArrayInputStream;
 import java.io.InputStream;
 import java.math.BigInteger;
@@ -81,6 +83,7 @@
         }
         return s;
     }
+    
     /**
      * Singleton certificate factory for this Crypto instance.
      * <p/>
@@ -224,8 +227,7 @@
      * @return alias name of the certificate that matches the issuer name
      *         or null if no such certificate was found.
      */
-    public String getAliasForX509Cert(String issuer)
-            throws WSSecurityException {
+    public String getAliasForX509Cert(String issuer) throws 
WSSecurityException {
         return getAliasForX509Cert(issuer, null, false);
     }
 
@@ -243,7 +245,7 @@
      *         or null if no such certificate was found.
      */
     public String getAliasForX509Cert(String issuer, BigInteger serialNumber)
-            throws WSSecurityException {
+        throws WSSecurityException {
         return getAliasForX509Cert(issuer, serialNumber, true);
     }
 
@@ -255,20 +257,36 @@
     * (this should work as well).
     * --- remains to be tested in several ways --
     */
-    private String getAliasForX509Cert(String issuer, BigInteger serialNumber,
-                                       boolean useSerialNumber)
-            throws WSSecurityException {
-        X500Principal issuerRDN = new X500Principal(issuer);
-        X509Certificate x509cert;
-        X500Principal certRDN;
+    private String getAliasForX509Cert(
+        String issuer, 
+        BigInteger serialNumber,
+        boolean useSerialNumber
+    ) throws WSSecurityException {
+        X500Principal issuerRDN = null;
+        X509Name issuerName = null;
         Certificate cert = null;
+        
+        //
+        // Convert the issuer DN to a java X500Principal object first. This is 
to ensure
+        // interop with a DN constructed from .NET, where e.g. it uses "S" 
instead of "ST".
+        // Then convert it to a BouncyCastle X509Name, which will order the 
attributes of
+        // the DN in a particular way (see WSS-168). If the conversion to an 
X500Principal
+        // object fails (e.g. if the DN contains "E" instead of 
"EMAILADDRESS"), then fall
+        // back on a direct conversion to a BC X509Name
+        //
+        try {
+            issuerRDN = new X500Principal(issuer);
+            issuerName =  new X509Name(issuerRDN.getName());
+        } catch (java.lang.IllegalArgumentException ex) {
+            issuerName = new X509Name(issuer);
+        }
 
         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.
+                    // no cert chain, so lets check if getCertificate gives us 
a result.
                     cert = keystore.getCertificate(alias);
                     if (cert == null) {
                         return null;
@@ -279,11 +297,10 @@
                 if (!(cert instanceof X509Certificate)) {
                     continue;
                 }
-                x509cert = (X509Certificate) cert;
-                if (!useSerialNumber ||
-                        useSerialNumber && 
x509cert.getSerialNumber().compareTo(serialNumber) == 0) {
-                    certRDN = new 
X500Principal(x509cert.getIssuerDN().getName());
-                    if (certRDN.equals(issuerRDN)) {
+                X509Certificate x509cert = (X509Certificate) cert;
+                if (!useSerialNumber || 
x509cert.getSerialNumber().compareTo(serialNumber) == 0) {
+                    X509Name certName = new 
X509Name(x509cert.getIssuerDN().getName());
+                    if (certName.equals(issuerName)) {
                         return alias;
                     }
                 }
@@ -308,7 +325,6 @@
      * @throws org.apache.ws.security.WSSecurityException
      *          if problems during keystore handling or wrong certificate (no 
SKI data)
      */
-
     public String getAliasForX509Cert(byte[] skiBytes) throws 
WSSecurityException {
         Certificate cert = null;
 
@@ -350,15 +366,12 @@
      * @return alias name of the certificate that matches the given certificate
      *         or null if no such certificate was found.
      */
-
-    /*
-     * See comment above
-     */
     public String getAliasForX509Cert(Certificate cert) throws 
WSSecurityException {
         try {
             String alias = keystore.getCertificateAlias(cert);
-            if (alias != null)
+            if (alias != null) {
                 return alias;
+            }
             // Use brute force search
             Enumeration e = keystore.aliases();
             while (e.hasMoreElements()) {
@@ -436,7 +449,6 @@
      * @throws org.apache.ws.security.WSSecurityException
      *          if problems during keystore handling or wrong certificate
      */
-
     public String getAliasForX509CertThumb(byte[] thumb) throws 
WSSecurityException {
         Certificate cert = null;
         MessageDigest sha = null;
@@ -509,13 +521,12 @@
      * @param cert The certificate to read SKI
      * @return The byte array containing the binary SKI data
      */
-    public byte[] getSKIBytesFromCert(X509Certificate cert)
-            throws WSSecurityException {
-        /*
-         * 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.
-         */
+    public byte[] getSKIBytesFromCert(X509Certificate cert) throws 
WSSecurityException {
+        //
+        // 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.
+        //
         byte[] derEncodedValue = cert.getExtensionValue(SKI_OID);
 
         if (cert.getVersion() < 3 || derEncodedValue == null) {
@@ -545,10 +556,10 @@
             return sha.digest();
         }
 
-        /*
-         * Strip away first four bytes from the DerValue (tag and length of
-         * ExtensionValue OCTET STRING and KeyIdentifier OCTET STRING)
-         */
+        //
+        // Strip away first four bytes from the DerValue (tag and length of
+        // ExtensionValue OCTET STRING and KeyIdentifier OCTET STRING)
+        //
         byte abyte0[] = new byte[derEncodedValue.length - 4];
 
         System.arraycopy(derEncodedValue, 4, abyte0, 0, abyte0.length);
@@ -602,7 +613,7 @@
      * @throws WSSecurityException
      */
     public byte[] getCertificateData(boolean reverse, X509Certificate[] certs)
-            throws WSSecurityException {
+        throws WSSecurityException {
         Vector list = new Vector();
         for (int i = 0; i < certs.length; i++) {
             if (reverse) {
@@ -639,7 +650,7 @@
      * @throws WSSecurityException
      */
     public X509Certificate[] getX509Certificates(byte[] data, boolean reverse)
-            throws WSSecurityException {
+        throws WSSecurityException {
         InputStream in = new ByteArrayInputStream(data);
         CertPath path = null;
         try {
@@ -672,7 +683,6 @@
     validateCertPath(
         java.security.cert.X509Certificate[] certs
     ) throws org.apache.ws.security.WSSecurityException {
-
         try {
             // Generate cert path
             java.util.List cert_list = java.util.Arrays.asList(certs);
@@ -748,7 +758,6 @@
     private Vector getAlias(X500Principal subjectRDN, KeyStore store) throws 
WSSecurityException {
         // Store the aliases found
         Vector aliases = new Vector();
-
         Certificate cert = null;
         
         try {

Modified: 
webservices/wss4j/trunk/src/org/apache/ws/security/components/crypto/CryptoFactory.java
URL: 
http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/components/crypto/CryptoFactory.java?rev=750484&r1=750483&r2=750484&view=diff
==============================================================================
--- 
webservices/wss4j/trunk/src/org/apache/ws/security/components/crypto/CryptoFactory.java
 (original)
+++ 
webservices/wss4j/trunk/src/org/apache/ws/security/components/crypto/CryptoFactory.java
 Thu Mar  5 16:00:47 2009
@@ -255,8 +255,9 @@
             if (log.isDebugEnabled()) {
                 log.debug("Cannot find crypto property file: " + propFilename, 
e);
             }
-            throw new RuntimeException("CryptoFactory: Cannot load properties: 
" +
-                    propFilename, e);
+            throw new RuntimeException(
+                "CryptoFactory: Cannot load properties: " + propFilename, e
+            );
         }
         return properties;
     }

Modified: 
webservices/wss4j/trunk/src/org/apache/ws/security/components/crypto/Merlin.java
URL: 
http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/components/crypto/Merlin.java?rev=750484&r1=750483&r2=750484&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
 Thu Mar  5 16:00:47 2009
@@ -62,13 +62,12 @@
      * @throws CredentialException
      * @throws IOException
      */
-    public Merlin(Properties properties) throws CredentialException,
-            IOException {
+    public Merlin(Properties properties) throws CredentialException, 
IOException {
         super(properties);
     }
 
     public Merlin(Properties properties, ClassLoader loader)
-            throws CredentialException, IOException {
+        throws CredentialException, IOException {
         super(properties, loader);
     }
 
@@ -85,7 +84,7 @@
      * @throws WSSecurityException
      */
     public X509Certificate[] getX509Certificates(byte[] data, boolean reverse)
-            throws WSSecurityException {
+        throws WSSecurityException {
         InputStream in = new ByteArrayInputStream(data);
         CertPath path = null;
         try {
@@ -99,8 +98,7 @@
         X509Certificate[] certs = new X509Certificate[l.size()];
         Iterator iterator = l.iterator();
         for (int i = 0; i < l.size(); i++) {
-            certs[(reverse) ? (l.size() - 1 - i) : i] = (X509Certificate) 
iterator
-                    .next();
+            certs[(reverse) ? (l.size() - 1 - i) : i] = (X509Certificate) 
iterator.next();
         }
         return certs;
     }
@@ -118,11 +116,11 @@
      * @throws WSSecurityException
      */
     public byte[] getCertificateData(boolean reverse, X509Certificate[] certs)
-            throws WSSecurityException {
-        Vector list = new Vector();
+        throws WSSecurityException {
+        List list = new Vector();
         for (int i = 0; i < certs.length; i++) {
             if (reverse) {
-                list.insertElementAt(certs[i], 0);
+                list.add(0, certs[i]);
             } else {
                 list.add(certs[i]);
             }
@@ -141,23 +139,20 @@
         }
     }
 
-    public boolean validateCertPath(X509Certificate[] certs)
-            throws WSSecurityException {
+    public boolean validateCertPath(X509Certificate[] certs) throws 
WSSecurityException {
         try {
             // Generate cert path
             java.util.List certList = java.util.Arrays.asList(certs);
-            CertPath path = this.getCertificateFactory().generateCertPath(
-                    certList);
-
-            HashSet set = new HashSet();
+            CertPath path = 
this.getCertificateFactory().generateCertPath(certList);
 
+            java.util.Set set = new HashSet();
             Enumeration cacertsAliases = this.cacerts.aliases();
             while (cacertsAliases.hasMoreElements()) {
                 String alias = (String) cacertsAliases.nextElement();
-                X509Certificate cert = (X509Certificate) this.cacerts
-                        .getCertificate(alias);
-                TrustAnchor anchor = new TrustAnchor(cert, cert
-                        .getExtensionValue(NAME_CONSTRAINTS_OID));
+                X509Certificate cert = 
+                    (X509Certificate) this.cacerts.getCertificate(alias);
+                TrustAnchor anchor = 
+                    new TrustAnchor(cert, 
cert.getExtensionValue(NAME_CONSTRAINTS_OID));
                 set.add(anchor);
             }
 
@@ -165,10 +160,10 @@
             Enumeration aliases = this.keystore.aliases();
             while (aliases.hasMoreElements()) {
                 String alias = (String) aliases.nextElement();
-                X509Certificate cert = (X509Certificate) this.keystore
-                        .getCertificate(alias);
-                TrustAnchor anchor = new TrustAnchor(cert, cert
-                        .getExtensionValue(NAME_CONSTRAINTS_OID));
+                X509Certificate cert = 
+                    (X509Certificate) this.keystore.getCertificate(alias);
+                TrustAnchor anchor = 
+                    new TrustAnchor(cert, 
cert.getExtensionValue(NAME_CONSTRAINTS_OID));
                 set.add(anchor);
             }
 
@@ -178,14 +173,13 @@
             param.setRevocationEnabled(false);
 
             // Verify the trust path using the above settings
-            String provider = properties
-                    
.getProperty("org.apache.ws.security.crypto.merlin.cert.provider");
+            String provider = 
+                
properties.getProperty("org.apache.ws.security.crypto.merlin.cert.provider");
             CertPathValidator certPathValidator;
             if (provider == null || provider.length() == 0) {
                 certPathValidator = CertPathValidator.getInstance("PKIX");
             } else {
-                certPathValidator = CertPathValidator.getInstance("PKIX",
-                        provider);
+                certPathValidator = CertPathValidator.getInstance("PKIX", 
provider);
             }
             certPathValidator.validate(path, param);
         } catch (NoSuchProviderException ex) {

Modified: webservices/wss4j/trunk/test/wssec/TestWSSecurityWSS86.java
URL: 
http://svn.apache.org/viewvc/webservices/wss4j/trunk/test/wssec/TestWSSecurityWSS86.java?rev=750484&r1=750483&r2=750484&view=diff
==============================================================================
--- webservices/wss4j/trunk/test/wssec/TestWSSecurityWSS86.java (original)
+++ webservices/wss4j/trunk/test/wssec/TestWSSecurityWSS86.java Thu Mar  5 
16:00:47 2009
@@ -32,8 +32,10 @@
 import org.apache.ws.security.WSConstants;
 import org.apache.ws.security.components.crypto.Crypto;
 import org.apache.ws.security.components.crypto.CryptoFactory;
+import org.apache.ws.security.message.WSSecEncrypt;
 import org.apache.ws.security.message.WSSecSignature;
 import org.apache.ws.security.message.WSSecHeader;
+import org.apache.xml.security.utils.RFC2253Parser;
 import org.w3c.dom.Document;
 
 import javax.security.auth.callback.Callback;
@@ -42,6 +44,8 @@
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
 
 /**
  * This is a test for WSS-86 - "CryptoBase.splitAndTrim does not take into 
account the format of a 
@@ -172,6 +176,53 @@
     }
     
     /**
+     * Test loading a certificate using BouncyCastle, and using it to encrypt 
a message, but
+     * decrypt the message using the Java Keystore provider
+     */
+    public void testInterop() throws Exception {
+        // 
+        // This cert corresponds to the cert in wss86.keystore
+        //
+        byte[] certBytes = 
+            org.apache.ws.security.util.Base64.decode(
+                
"MIICfDCCAeUCBElPtuwwDQYJKoZIhvcNAQEEBQAwgYQxCzAJBgNVBAYTAkRFMQ8wDQYDVQQIEwZC"
+                + 
"YXllcm4xDzANBgNVBAcTBk11bmljaDEPMA0GA1UEChMGQXBhY2hlMQ4wDAYDVQQLEwVXU1M0SjEP"
+                + 
"MA0GA1UEAxMGV2VybmVyMSEwHwYJKoZIhvcNAQkBFhJXZXJuZXJAZXhhbXBsZS5jb20wHhcNMDgx"
+                + 
"MjIyMTU0OTAwWhcNMDkwMzIyMTU0OTAwWjCBhDELMAkGA1UEBhMCREUxDzANBgNVBAgTBkJheWVy"
+                + 
"bjEPMA0GA1UEBxMGTXVuaWNoMQ8wDQYDVQQKEwZBcGFjaGUxDjAMBgNVBAsTBVdTUzRKMQ8wDQYD"
+                + 
"VQQDEwZXZXJuZXIxITAfBgkqhkiG9w0BCQEWEldlcm5lckBleGFtcGxlLmNvbTCBnzANBgkqhkiG"
+                + 
"9w0BAQEFAAOBjQAwgYkCgYEA0CudLx3cFcAVBZsk4PuMYD2w3fg0pAXP4J2GkWdIw/ydyfBaMcMy"
+                + 
"Q6LfIEWITj5IY9M7JSddj9Mil8po5ClvSKiu07pC7ePD7VbcXqA+D4CEjwkkkb3mBJ1ohUraCdI5"
+                + 
"/B2PsEY9QpAkoknMEKaKFn5JOE7BKfPG85rCCYC/B8cCAwEAATANBgkqhkiG9w0BAQQFAAOBgQBx"
+                + 
"4dlaLgJF74/mwhhWp49pxwk+MY/udrPw6GRiTdTFuAbkODuDL+zvssY6l6nZij2TL22ouTe4H/cf"
+                + 
"n/rjslklB73ZIcxgbfHar914UZd970AgbSt2NUGepybdr57zmKdi7wdLVojgdRQMHN6/NoUOicj3"
+                + "TRZG7slsfImuGsxMJw=="
+            );
+        CertificateFactory factory = 
+            CertificateFactory.getInstance("X.509", "BC");
+        X509Certificate cert = 
+            (X509Certificate)factory.generateCertificate(
+                new java.io.ByteArrayInputStream(certBytes)
+            );
+
+        SOAPEnvelope unsignedEnvelope = message.getSOAPEnvelope();
+        WSSecEncrypt encrypt = new WSSecEncrypt();
+        encrypt.setUseThisCert(cert);
+        Document doc = unsignedEnvelope.getAsDocument();
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        Document encryptedDoc = encrypt.build(doc, crypto, secHeader);
+        
+        if (LOG.isDebugEnabled()) {
+            String outputString = 
+                
org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(encryptedDoc);
+            LOG.debug(outputString);
+        }
+        verify(encryptedDoc);
+        
+    }
+    
+    /**
      * Verifies the soap envelope
      * <p/>
      * 



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to