You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-dev@axis.apache.org by di...@apache.org on 2003/10/14 14:04:45 UTC

cvs commit: ws-axis/contrib/wss4j/src/org/apache/ws/security/components/crypto BouncyCastle.java CredentialException.java Crypto.java CryptoFactory.java Merlin.java errors.properties

dims        2003/10/14 05:04:45

  Added:       contrib/wss4j/src/org/apache/ws/security/components/crypto
                        BouncyCastle.java CredentialException.java
                        Crypto.java CryptoFactory.java Merlin.java
                        errors.properties
  Log:
  ******* WORK IN PROGRESS *******
  
  Initial check-in of my sandbox for ws-security related code.
  
  Revision  Changes    Path
  1.1                  ws-axis/contrib/wss4j/src/org/apache/ws/security/components/crypto/BouncyCastle.java
  
  Index: BouncyCastle.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2001-2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Axis" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.ws.security.components.crypto;
  
  import org.apache.axis.encoding.Base64;
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  import org.bouncycastle.asn1.*;
  import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
  import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
  import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
  import org.bouncycastle.jce.provider.BouncyCastleProvider;
  
  import java.io.*;
  import java.security.*;
  import java.security.cert.CertificateEncodingException;
  import java.security.cert.CertificateFactory;
  import java.security.cert.X509Certificate;
  import java.security.spec.PKCS8EncodedKeySpec;
  import java.util.Properties;
  import java.util.Vector;
  
  /**
   * Bouncy Castle crypto provider (for use with JDK1.3).
   * <p>
   * @author  Davanum Srinivas (dims@yahoo.com).
   */
  public class BouncyCastle implements Crypto {
      private static Log log = LogFactory.getLog(BouncyCastle.class);
      private static CertificateFactory certFact = null;
      private PrivateKey key = null;
      private X509Certificate[] certs = null;
      private Properties properties = null;
  
      static {
          Security.addProvider(new BouncyCastleProvider());
          installSecureRandomProvider();
      }
  
      /**
       * Constructor.
       * <p>
       * @param   properties                                    
       * @throws  CredentialException                          
       */
      public BouncyCastle(Properties properties) throws CredentialException {
          this.properties = properties;
          try {
              InputStream in = new FileInputStream(getProxyFile(this.properties));
              load(in);
          } catch (Exception e) {
              throw new CredentialException(3, "proxyNotFound", new Object[]{getProxyFile(this.properties)});
          }
      }
  
      /**
       * get the singleton certificate factory.
       * <p>
       * @return                                           
       * @throws  GeneralSecurityException                
       */
      private static synchronized CertificateFactory getCertificateFactory() throws GeneralSecurityException {
          if (certFact == null) {
              certFact = CertificateFactory.getInstance("X.509");
          }
          return certFact;
      }
  
      /**
       * loads certificate from an input stream.
       * <p>
       * @param   in                                       
       * @return                                           
       * @throws  GeneralSecurityException                
       */
      public X509Certificate loadCertificate(InputStream in) throws GeneralSecurityException {
          return (X509Certificate) getCertificateFactory().generateCertificate(in);
      }
  
      /** installs the secure random provider. */
      private static void installSecureRandomProvider() {
          String providerName = "cryptix.jce.provider.CryptixRandom";
          try {
              log.debug("Loading SecureRandom provider: " + providerName);
              Class providerClass = Class.forName(providerName);
              Security.insertProviderAt((Provider) providerClass.newInstance(), 1);
          } catch (Exception e) {
              log.debug("Unable to install PRNG. Using default PRNG.", e);
          }
      }
  
      /**
       * convert bytes into corresponding DER object.
       * <p>
       * @param   data                  
       * @return                        
       * @throws  IOException          
       */
      private static DERObject toDERObject(byte[] data) throws IOException {
          ByteArrayInputStream inStream = new ByteArrayInputStream(data);
          DERInputStream derInputStream = new DERInputStream(inStream);
          return derInputStream.readObject();
      }
  
      /**
       * get an array of certificates from a byte array.
       * <p>
       * @param   data                                     
       * @param   reverse                                  
       * @return                                           
       * @throws  IOException                             
       * @throws  GeneralSecurityException                
       */
      public X509Certificate[] getX509Certificates(byte[] data, boolean reverse) throws IOException, GeneralSecurityException {
          X509Certificate[] certs;
          DERObject obj = BouncyCastle.toDERObject(data);
          ASN1Sequence seq = ASN1Sequence.getInstance(obj);
          int size = seq.size();
          ByteArrayInputStream in;
          certs = new X509Certificate[size];
          for (int i = 0; i < size; i++) {
              obj = seq.getObjectAt(i).getDERObject();
              data = BouncyCastle.toByteArray(obj);
              in = new ByteArrayInputStream(data);
              certs[(reverse) ? (size - 1 - i) : i] = loadCertificate(in);
          }
          return certs;
      }
  
      /**
       * get a byte array given an array of certificates.
       * <p>
       * @param   reverse                                           
       * @param   certs                                             
       * @return                                                    
       * @throws  IOException                                      
       * @throws  CertificateEncodingException                     
       */
      public byte[] getCertificateData(boolean reverse, X509Certificate[] certs) throws IOException, CertificateEncodingException {
          DEREncodableVector vec = new DEREncodableVector();
          if (reverse) {
              for (int i = certs.length - 1; i >= 0; i--) {
                  vec.add(BouncyCastle.toDERObject(certs[i].getEncoded()));
              }
          } else {
              for (int i = 0; i < certs.length; i++) {
                  vec.add(BouncyCastle.toDERObject(certs[i].getEncoded()));
              }
          }
          DERSequence seq = new DERSequence(vec);
          byte[] data = BouncyCastle.toByteArray(seq);
          return data;
      }
  
      /**
       * load the private key and certificates from the input stream.
       * <p>
       * @param   input                 
       * @throws  Exception            
       */
      private void load(InputStream input) throws Exception {
          if (input == null) {
              throw new IllegalArgumentException("input stream cannot be null");
          }
          PrivateKey key = null;
          X509Certificate cert = null;
          Vector chain = new Vector(3);
          BufferedReader reader = null;
          try {
              reader = new BufferedReader(new InputStreamReader(input));
              String s;
              while ((s = reader.readLine()) != null) {
                  if (s.indexOf("BEGIN CERTIFICATE") != -1) {
                      byte[] data = getDecodedPEMObject(reader);
                      cert = loadCertificate(new ByteArrayInputStream(data));
                      chain.addElement(cert);
                  } else if (s.indexOf("BEGIN RSA PRIVATE KEY") != -1) {
                      byte[] data = getDecodedPEMObject(reader);
                      key = getKey("RSA", data);
                  }
              }
          } catch (IOException e) {
              throw new CredentialException(3, "ioError00", e);
          } catch (GeneralSecurityException e) {
              throw new CredentialException(3, "secError00", e);
          } catch (Exception e) {
              throw new CredentialException(-1, "error00", e);
          } finally {
              if (reader != null) {
                  try {
                      reader.close();
                  } catch (IOException e) {
                  }
              }
          }
          int size = chain.size();
          if (size == 0) {
              throw new CredentialException(3, "noCerts00", (Exception) null);
          }
          if (key == null) {
              throw new CredentialException(3, "noKey00", (Exception) null);
          } else {
              certs = new X509Certificate[size];
              chain.copyInto(certs);
              this.key = key;
              return;
          }
      }
  
      /**
       * convert a DER object into its byte representation.
       * <p>
       * @param   obj                   
       * @return                        
       * @throws  IOException          
       */
      private static byte[] toByteArray(DERObject obj) throws IOException {
          ByteArrayOutputStream bout = new ByteArrayOutputStream();
          DEROutputStream der = new DEROutputStream(bout);
          der.writeObject(obj);
          return bout.toByteArray();
      }
  
      /**
       * get the decoded information.
       * <p>
       * @param   reader                
       * @return                        
       * @throws  IOException          
       */
      private static final byte[] getDecodedPEMObject(BufferedReader reader) throws IOException {
          StringBuffer buf = new StringBuffer();
          String s;
          while ((s = reader.readLine()) != null) {
              if (s.indexOf("--END") != -1) {
                  return Base64.decode(buf.toString());
              }
              buf.append(s);
          }
          throw new EOFException("PEM footer missing");
      }
  
      /**
       * get the private key from the byte array.
       * <p>
       * @param   alg                                      
       * @param   data                                     
       * @return                                           
       * @throws  GeneralSecurityException                
       */
      private PrivateKey getKey(String alg, byte[] data) throws GeneralSecurityException {
          if (alg.equals("RSA")) {
              try {
                  ByteArrayInputStream bis = new ByteArrayInputStream(data);
                  byte[] keyData = getKeyData(bis);
                  PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyData);
                  KeyFactory kfac = KeyFactory.getInstance("RSA");
                  return kfac.generatePrivate(spec);
              } catch (IOException e) {
                  return null;
              }
          } else {
              return null;
          }
      }
  
      /**
       * construct the private key byte representation from the info in the input stream.
       * <p>
       * @param   bis                   
       * @return                        
       * @throws  IOException          
       */
      private byte[] getKeyData(InputStream bis) throws IOException {
          DERInputStream derin = new DERInputStream(bis);
          DERObject keyInfo = derin.readObject();
          DERObjectIdentifier rsa_oid = PKCSObjectIdentifiers.rsaEncryption;
          AlgorithmIdentifier rsa = new AlgorithmIdentifier(rsa_oid);
          PrivateKeyInfo pkeyinfo = new PrivateKeyInfo(rsa, keyInfo);
          DERObject derkey = pkeyinfo.getDERObject();
          byte[] keyData = toByteArray(derkey);
          return keyData;
      }
  
      /**
       * get the list of certificates.
       * <p>
       * @return   
       */
      public X509Certificate[] getCertificates() {
          return certs;
      }
  
      /**
       * get the private key.
       * <p>
       * @return   
       */
      public PrivateKey getPrivateKey() {
          return key;
      }
  
      /**
       * get the name of the file where the key/certificate information is stored.
       * <p>
       * @param   properties   
       * @return               
       */
      private static String getProxyFile(Properties properties) {
          String location = properties.getProperty("org.apache.ws.security.crypto.bouncycastle.file");
          if (location != null) {
              return location;
          } else {
              return getProxyDefaultLocation();
          }
      }
  
      /**
       * get the default location.
       * <p>
       * @return   
       */
      private static String getProxyDefaultLocation() {
          String dir = System.getProperty("user.home");
          File f = new File(dir, "x509.txt");
          return f.getAbsolutePath();
      }
  }
  
  
  1.1                  ws-axis/contrib/wss4j/src/org/apache/ws/security/components/crypto/CredentialException.java
  
  Index: CredentialException.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2001-2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Axis" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.ws.security.components.crypto;
  
  import java.text.MessageFormat;
  import java.util.MissingResourceException;
  import java.util.ResourceBundle;
  
  /**
   * CredentialException.
   * <p>
   * @author  Davanum Srinivas (dims@yahoo.com).
   */
  public class CredentialException extends Exception {
      public static final int FAILURE = -1;
      public static final int EXPIRED = 1;
      public static final int DEFECTIVE = 2;
      public static final int IO_ERROR = 3;
      public static final int SEC_ERROR = 3;
      private static ResourceBundle resources;
      private int errorCode;
  
      static {
          try {
              resources = ResourceBundle.getBundle("org.apache.ws.security.components.crypto.errors");
          } catch (MissingResourceException e) {
              throw new RuntimeException(e.getMessage());
          }
      }
  
      /**
       * Constructor.
       * <p>
       * @param  errorCode   
       * @param  msgId       
       * @param  root        
       */
      public CredentialException(int errorCode, String msgId, Throwable root) {
          this(errorCode, msgId, null, root);
      }
  
      /**
       * Constructor.
       * <p>
       * @param  errorCode   
       * @param  msgId       
       * @param  args        
       */
      public CredentialException(int errorCode, String msgId, Object[] args) {
          this(errorCode, msgId, args, null);
      }
  
      /**
       * Constructor.
       * <p>
       * @param  errorCode   
       * @param  msgId       
       * @param  args        
       * @param  root        
       */
      public CredentialException(int errorCode, String msgId, Object[] args, Throwable root) {
          super(getMessage(msgId, args) + " Inner Exception: [" + root.getMessage() + "]");
          this.errorCode = -1;
          this.errorCode = errorCode;
      }
  
      /**
       * get the error code.
       * <p>
       * @return  TODO: Put description of return value here.
       */
      public int getErrorCode() {
          return errorCode;
      }
  
      /**
       * get the actual message.
       * <p>
       * @param   msgId   
       * @param   args    
       * @return         TODO: Put description of return value here.
       */
      private static String getMessage(String msgId, Object[] args) {
          try {
              return MessageFormat.format(resources.getString(msgId), args);
          } catch (MissingResourceException e) {
              throw new RuntimeException("bad" + msgId);
          }
      }
  }
  
  
  1.1                  ws-axis/contrib/wss4j/src/org/apache/ws/security/components/crypto/Crypto.java
  
  Index: Crypto.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2001-2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Axis" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.ws.security.components.crypto;
  
  import java.io.IOException;
  import java.io.InputStream;
  import java.security.GeneralSecurityException;
  import java.security.PrivateKey;
  import java.security.cert.CertificateEncodingException;
  import java.security.cert.X509Certificate;
  
  /**
   * Crypto.
   * <p>
   * @author  Davanum Srinivas (dims@yahoo.com).
   */
  public interface Crypto {
      /**
       * returns a X509Certificate from the given input stream.
       * <p>
       * @param   in                         
       * @return                             
       * @throws  GeneralSecurityException  
       */
      X509Certificate loadCertificate(InputStream in) throws GeneralSecurityException;
  
      /**
       * returns a X509Certificate array from the given byte array.
       * <p>
       * @param   data                       
       * @param   reverse                    
       * @return                             
       * @throws  IOException               
       * @throws  GeneralSecurityException  
       */
      X509Certificate[] getX509Certificates(byte[] data, boolean reverse) throws IOException, GeneralSecurityException;
  
      /**
       * get a byte array representation of the certificate information.
       * <p>
       * @param   reverse                        
       * @param   certs                          
       * @return                                 
       * @throws  IOException                   
       * @throws  CertificateEncodingException  
       */
      byte[] getCertificateData(boolean reverse, X509Certificate[] certs) throws IOException, CertificateEncodingException;
  
      /**
       * Returns the private key.
       * <p>
       * @return  the private key.
       */
      public PrivateKey getPrivateKey();
  
      /**
       * returns the list of certificates.
       * <p>
       * @return  the array of X509 certificates.
       */
      public X509Certificate[] getCertificates();
  }
  
  
  1.1                  ws-axis/contrib/wss4j/src/org/apache/ws/security/components/crypto/CryptoFactory.java
  
  Index: CryptoFactory.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2001-2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Axis" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.ws.security.components.crypto;
  
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  import org.apache.ws.security.util.Loader;
  
  import java.lang.reflect.Constructor;
  import java.net.URL;
  import java.util.Properties;
  
  /**
   * CryptoFactory.
   * <p>
   * @author  Davanum Srinivas (dims@yahoo.com).
   */
  public abstract class CryptoFactory {
      private static Log log = LogFactory.getLog(CryptoFactory.class);
      private static final String defaultCryptoClassName = "org.apache.ws.security.components.crypto.BouncyCastle";
      private static Crypto crypto = null;
  
      /**
       * getInstance
       * <p>
       * Returns the singleton instance of Crypto.
       * <p>
       * @return  TODO: Put description of return value here.
       */
      public static synchronized Crypto getInstance() {
          if (crypto == null) {
              crypto = getInstance(null);
          }
          return crypto;
      }
  
      /**
       * getInstance
       * <p>
       * Returns an instance of Crypto.
       * <p>
       * @param   cryptoClassName   
       * @return                   TODO: Put description of return value here.
       */
      private static Crypto getInstance(String cryptoClassName) {
          Crypto crypto = null;
          Properties properties = getProperties();
          if ((cryptoClassName == null) || (cryptoClassName.length() == 0)) {
              cryptoClassName = System.getProperty("org.apache.ws.security.crypto.provider");
              if ((cryptoClassName == null) || (cryptoClassName.length() == 0)) {
                  // use the default Crypto implementation
                  cryptoClassName = properties.getProperty("org.apache.ws.security.crypto.provider", defaultCryptoClassName);
              }
          }
          Class cryptogenClass = null;
          try {
              // instruct the class loader to load the crypto implementation
              cryptogenClass = java.lang.Class.forName(cryptoClassName);
          } catch (ClassNotFoundException e) {
              throw new RuntimeException(cryptoClassName + " Not Found");
          }
          log.info("Using Crypto Engine [" + cryptoClassName + "]");
          try {
              Class[] classes = new Class[]{Properties.class};
              Constructor c = cryptogenClass.getConstructor(classes);
              crypto = (Crypto) c.newInstance(new Object[]{properties});
              return crypto;
          } catch (java.lang.Exception e) {
              log.debug(cryptoClassName + " cannot create instance with properties constructor");
          }
          try {
              // try to instantiate the Crypto subclass
              crypto = (Crypto) cryptogenClass.newInstance();
              return crypto;
          } catch (java.lang.Exception e) {
              throw new RuntimeException(cryptoClassName + " cannot create instance");
          }
      }
  
      /**
       * get the properties for crypto.
       * <p>
       * @return  TODO: Put description of return value here.
       */
      private static Properties getProperties() {
          Properties properties = new Properties();
          try {
              URL url = Loader.getResource("crypto.properties");
              properties.load(url.openStream());
          } catch (Exception e) {
              log.debug("Cannot find crypto.properties");
          }
          return properties;
      }
  }
  
  
  1.1                  ws-axis/contrib/wss4j/src/org/apache/ws/security/components/crypto/Merlin.java
  
  Index: Merlin.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2001-2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Axis" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.ws.security.components.crypto;
  
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  
  import java.io.*;
  import java.security.GeneralSecurityException;
  import java.security.KeyStore;
  import java.security.PrivateKey;
  import java.security.cert.*;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Properties;
  import java.util.Vector;
  
  /**
   * JDK1.4 based implementation of Crypto (uses keystore).
   * <p>
   * @author  Davanum Srinivas (dims@yahoo.com).
   */
  public class Merlin implements Crypto {
      private static Log log = LogFactory.getLog(Merlin.class);
      private static CertificateFactory certFact;
      protected PrivateKey key = null;
      protected Certificate[] certs = null;
      private Properties properties = null;
  
      /**
       * Constructor.
       * <p>
       * @param   properties   
       * @throws  Exception   
       */
      public Merlin(Properties properties) throws Exception {
          this.properties = properties;
          try {
              FileInputStream is = new FileInputStream(getProxyKeyStore(this.properties));
              load(is);
          } catch (Exception e) {
              throw new CredentialException(3, "proxyNotFound", new Object[]{getProxyKeyStore(this.properties)});
          }
      }
  
      /**
       * Singleton certificate factory.
       * <p>
       * @return                             
       * @throws  GeneralSecurityException  
       */
      private static synchronized CertificateFactory getCertificateFactory() throws GeneralSecurityException {
          if (certFact == null) {
              certFact = CertificateFactory.getInstance("X.509");
          }
          return certFact;
      }
  
      /**
       * load a X509Certificate from the input stream.
       * <p>
       * @param   in                         
       * @return                             
       * @throws  GeneralSecurityException  
       */
      public X509Certificate loadCertificate(InputStream in) throws GeneralSecurityException {
          return (X509Certificate) getCertificateFactory().generateCertificate(in);
      }
  
      /**
       * get an array of X509Certificate's from the byte array.
       * <p>
       * @param   data                       
       * @param   reverse                    
       * @return                             
       * @throws  IOException               
       * @throws  GeneralSecurityException  
       */
      public X509Certificate[] getX509Certificates(byte[] data, boolean reverse) throws IOException, GeneralSecurityException {
          InputStream in = new ByteArrayInputStream(data);
          CertPath path = getCertificateFactory().generateCertPath(in);
          List l = path.getCertificates();
          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();
          }
          return certs;
      }
  
      /**
       * get a byte array given an array of certificates.
       * <p>
       * @param   reverse                        
       * @param   certs                          
       * @return                                 
       * @throws  IOException                   
       * @throws  CertificateEncodingException  
       */
      public byte[] getCertificateData(boolean reverse, X509Certificate[] certs) throws IOException, CertificateEncodingException {
          Vector list = new Vector();
          for (int i = 0; i < certs.length; i++) {
              if (reverse) {
                  list.insertElementAt(certs[i], 0);
              } else {
                  list.add(certs[i]);
              }
          }
          try {
              CertPath path = getCertificateFactory().generateCertPath(list);
              return path.getEncoded();
          } catch (GeneralSecurityException gse) {
              gse.printStackTrace();
          }
          return null;
      }
  
      /**
       * get the private key.
       * <p>
       * @return   
       */
      public PrivateKey getPrivateKey() {
          return key;
      }
  
      /**
       * get the list of certificates.
       * <p>
       * @return   
       */
      public X509Certificate[] getCertificates() {
          X509Certificate[] certs = new X509Certificate[this.certs.length];
          for (int i = 0; i < this.certs.length; i++) {
              certs[i] = (X509Certificate) this.certs[i];
          }
          return certs;
      }
  
      /**
       * load the private key and certificates from the input stream (of the keystore).
       * <p>
       * @param   input       
       * @throws  Exception  
       */
      public void load(InputStream input) throws Exception {
          if (input == null) {
              throw new IllegalArgumentException("input stream cannot be null");
          }
          try {
              KeyStore keystore = KeyStore.getInstance(properties.getProperty("org.apache.ws.security.crypto.merlin.keystore.type", KeyStore.getDefaultType()));
              String alias = properties.getProperty("org.apache.ws.security.crypto.merlin.keystore.alias", "security");
              String password = properties.getProperty("org.apache.ws.security.crypto.merlin.keystore.password", "security");
              keystore.load(input, password.toCharArray());
              boolean b = keystore.isKeyEntry(alias);
              log.info("Private Key:" + b);
              if (!b) {
                  log.error("Cannot find key");
                  throw new Exception("Cannot find key");
              }
              String password2 = properties.getProperty("org.apache.ws.security.crypto.merlin.alias.password", "security");
              key = (PrivateKey) keystore.getKey(alias, password2.toCharArray());
              if (!(key instanceof PrivateKey)) {
                  throw new Exception("Key is not a private key");
              }
              certs = keystore.getCertificateChain(alias);
          } catch (IOException e) {
              throw new CredentialException(3, "ioError00", e);
          } catch (GeneralSecurityException e) {
              throw new CredentialException(3, "secError00", e);
          } catch (Exception e) {
              throw new CredentialException(-1, "error00", e);
          }
          if ((certs == null) || (certs.length == 0)) {
              throw new CredentialException(3, "noCerts00", (Exception) null);
          }
          if (key == null) {
              throw new CredentialException(3, "noKey00", (Exception) null);
          }
      }
  
      /**
       * location of the key store.
       * <p>
       * @param   properties   
       * @return               
       */
      private static String getProxyKeyStore(Properties properties) {
          String location = properties.getProperty("org.apache.ws.security.crypto.merlin.file");
          if (location != null) {
              return location;
          } else {
              return getProxyDefaultKeyStore();
          }
      }
  
      /**
       * get the default location.
       * <p>
       * @return   
       */
      private static String getProxyDefaultKeyStore() {
          String dir = System.getProperty("user.home");
          File f = new File(dir, "x509.keystore");
          return f.getAbsolutePath();
      }
  }
  
  
  1.1                  ws-axis/contrib/wss4j/src/org/apache/ws/security/components/crypto/errors.properties
  
  Index: errors.properties
  ===================================================================
  ## defines error code - str message mapping
  0 = General security error
  1 = An unsupported token was provided
  2 = An unsupported signature or encryption algorithm was used
  3 = An error was discovered processing the <wsse:Security> header.
  4 = An invalid security token was provided
  5 = The security token could not be authenticated or authorized
  6 = The signature or decryption was invalid
  7 = Referenced security token could not be retrieved.
  
  proxyNotFound = Proxy file ({0}) not found.
  ioError00 = Failed to load credentials.
  secError00 = Failed to load credentials.
  error00 = Failed to load credentials.
  noCerts00 = No certificates loaded
  noKey00 = No private key loaded