commons-ssl

ebug(Object o, Throwable t)
  {
    l.debug(o, t);
  }
  
  void info(Object o)
  {
    l.info(o);
  }
  
  void info(Object o, Throwable t)
  {
    l.info(o, t);
  }
  
  void warn(Object o)
  {
    l.warn(o);
  }
  
  void warn(Object o, Throwable t)
  {
    l.warn(o, t);
  }
  
  void error(Object o)
  {
    l.error(o);
  }
  
  void error(Object o, Throwable t)
  {
    l.error(o, t);
  }
  
  void fatal(Object o)
  {
    l.fatal(o);
  }
  
  void fatal(Object o, Throwable t)
  {
    l.fatal(o, t);
  }
  
  boolean isDebugEnabled()
  {
    return l.isDebugEnabled();
  }
  
  boolean isInfoEnabled()
  {
    return l.isInfoEnabled();
  }
  
  Object getLog4jLogger()
  {
    return l;
  }
}

/* Location:
 * Qualified Name:     org.apache.commons.ssl.LogHelper
 * Java Class Version: 1.2 (46.0)
 * JD-Core Version:    0.7.1
 */
package org.apache.commons.ssl;

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

public class LogWrapper
{
  static final String[] LEVELS = { "+", " ", "!", "*", "#" };
  static final String TIMESTAMP_PATTERN = "zzz:yyyy-MM-dd/HH:mm:ss.SSS";
  static final int TIMESTAMP_LENGTH = "zzz:yyyy-MM-dd/HH:mm:ss.SSS".length();
  static final String LINE_SEPARATOR = System.getProperty("line.separator");
  static final DateFormat DF = new SimpleDateFormat("zzz:yyyy-MM-dd/HH:mm:ss.SSS");
  private static final LogWrapper NOOP = new LogWrapper();
  private static final boolean DEBUG = true;
  public static final boolean log4j;
  private static volatile OutputStream backup = System.out;
  private static volatile PrintStream wrappingPrintStream = null;
  private final LogHelper h;
  
  static
  {
    boolean avail = false;
    try
    {
      LogHelper lh = new LogHelper(LogWrapper.class);
      lh.hashCode();
      avail = true;
    }
    catch (Throwable t)
    {
      avail = false;
    }
    finally
    {
      log4j = avail;
    }
  }
  
  public static boolean isLog4jAvailable()
  {
    return log4j;
  }
  
  public static LogWrapper getLogger(Class c)
  {
    return log4j ? new LogWrapper(c) : NOOP;
  }
  
  public static LogWrapper getLogger(String s)
  {
    return log4j ? new LogWrapper(s) : NOOP;
  }
  
  private LogWrapper()
  {
    h = null;
  }
  
  private LogWrapper(Class c)
  {
    h = new LogHelper(c);
  }
  
  private LogWrapper(String s)
  {
    h = new LogHelper(s);
  }
  
  public void debug(Object o)
  {
    if (t(0, o, null)) {
      h.debug(o);
    }
  }
  
  public void debug(Object o, Throwable t)
  {
    if (t(0, o, t)) {
      h.debug(o, t);
    }
  }
  
  public void info(Object o)
  {
    if (t(1, o, null)) {
      h.info(o);
    }
  }
  
  public void info(Object o, Throwable t)
  {
    if (t(1, o, t)) {
      h.info(o, t);
    }
  }
  
  public void warn(Object o)
  {
    if (t(2, o, null)) {
      h.warn(o);
    }
  }
  
  public void warn(Object o, Throwable t)
  {
    if (t(2, o, t)) {
      h.warn(o, t);
    }
  }
  
  public void error(Object o)
  {
    if (t(3, o, null)) {
      h.error(o);
    }
  }
  
  public void error(Object o, Throwable t)
  {
    if (t(3, o, t)) {
      h.error(o, t);
    }
  }
  
  public void fatal(Object o)
  {
    if (t(4, o, null)) {
      h.fatal(o);
    }
  }
  
  public void fatal(Object o, Throwable t)
  {
    if (t(4, o, t)) {
      h.fatal(o, t);
    }
  }
  
  public boolean isDebugEnabled()
  {
    return log4j ? h.isDebugEnabled() : true;
  }
  
  public boolean isInfoEnabled()
  {
    return (!log4j) || (h.isInfoEnabled());
  }
  
  public Object getLog4jLogger()
  {
    return log4j ? h.getLog4jLogger() : null;
  }
  
  private boolean t(int level, Object o, Throwable t)
  {
    if (log4j) {
      return true;
    }
    if (backup != null)
    {
      String s = "";
      if (o != null) {
        try
        {
          s = (String)o;
        }
        catch (ClassCastException cce)
        {
          s = o.toString();
        }
      }
      int len = s.length() + TIMESTAMP_LENGTH + 9;
      String timestamp = DF.format(new Date());
      StringBuffer buf = new StringBuffer(len);
      buf.append(timestamp);
      if (LEVELS[level].length() == 1)
      {
        buf.append(LEVELS[level]);
      }
      else
      {
        buf.append(' ');
        buf.append(LEVELS[level]);
        buf.append(' ');
      }
      buf.append(s);
      buf.append(LINE_SEPARATOR);
      s = buf.toString();
      byte[] logBytes = s.getBytes();
      try
      {
        if (t == null) {
          backup.write(logBytes);
        } else {
          synchronized (backup)
          {
            backup.write(logBytes);
            if (t != null)
            {
              if (wrappingPrintStream == null) {
                wrappingPrintStream = new PrintStream(backup, false);
              }
              t.printStackTrace(wrappingPrintStream);
              wrappingPrintStream.flush();
            }
          }
        }
        backup.flush();
      }
      catch (IOException ioe)
      {
        throw new RuntimeException(ioe.toString());
      }
    }
    return false;
  }
  
  public static void setBackupLogFile(String f)
    throws IOException
  {
    if (!log4j)
    {
      OutputStream out = new FileOutputStream(f, true);
      out = new BufferedOutputStream(out);
      setBackupStream(out);
    }
  }
  
  public static void setBackupStream(OutputStream os)
  {
    if (backup != null) {
      synchronized (backup)
      {
        wrappingPrintStream = null;
        backup = os;
      }
    }
    wrappingPrintStream = null;
    backup = os;
  }
  
  public static OutputStream getBackupStream()
  {
    return backup;
  }
}

/* Location:
 * Qualified Name:     org.apache.commons.ssl.LogWrapper
 * Java Class Version: 1.2 (46.0)
 * JD-Core Version:    0.7.1
 */
package org.apache.commons.ssl;

public class OpenSSL$CipherInfo
{
  public final String javaCipher;
  public final String blockMode;
  public final int keySize;
  public final boolean des2;
  
  public OpenSSL$CipherInfo(String javaCipher, String blockMode, int keySize, boolean des2)
  {
    this.javaCipher = javaCipher;
    this.blockMode = blockMode;
    this.keySize = keySize;
    this.des2 = des2;
  }
  
  public String toString()
  {
    return javaCipher + "/" + blockMode + " " + keySize + "bit  des2=" + des2;
  }
}

/* Location:
 * Qualified Name:     org.apache.commons.ssl.OpenSSL.CipherInfo
 * Java Class Version: 1.2 (46.0)
 * JD-Core Version:    0.7.1
 */
package org.apache.commons.ssl;

import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.util.StringTokenizer;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;

public class OpenSSL
{
  public static InputStream decrypt(String cipher, byte[] pwd, InputStream encrypted)
    throws IOException, GeneralSecurityException
  {
    CipherInfo cipherInfo = lookup(cipher);
    MessageDigest md5 = MessageDigest.getInstance("MD5");
    boolean salted = false;
    
    byte[] saltLine = Util.streamToBytes(encrypted, 16);
    if (saltLine.length <= 0) {
      throw new IOException("encrypted InputStream is empty");
    }
    String firstEightBytes = "";
    if (saltLine.length >= 8) {
      firstEightBytes = new String(saltLine, 0, 8);
    }
    if ("SALTED__".equalsIgnoreCase(firstEightBytes))
    {
      salted = true;
    }
    else if (Base64.isArrayByteBase64(saltLine))
    {
      InputStream head = new ByteArrayInputStream(saltLine);
      
      encrypted = new ComboInputStream(head, encrypted);
      encrypted = new Base64InputStream(encrypted, true);
      saltLine = Util.streamToBytes(encrypted, 16);
      if (saltLine.length >= 8) {
        firstEightBytes = new String(saltLine, 0, 8);
      }
      if ("SALTED__".equalsIgnoreCase(firstEightBytes)) {
        salted = true;
      }
    }
    byte[] salt = null;
    if (salted)
    {
      salt = new byte[8];
      System.arraycopy(saltLine, 8, salt, 0, 8);
    }
    else
    {
      InputStream head = new ByteArrayInputStream(saltLine);
      encrypted = new ComboInputStream(head, encrypted);
    }
    int keySize = keySize;
    int ivSize = 64;
    if (javaCipher.startsWith("AES")) {
      ivSize = 128;
    }
    DerivedKey dk = deriveKey(pwd, salt, keySize, ivSize, md5);
    Cipher c = PKCS8Key.generateCipher(javaCipher, blockMode, dk, des2, null, true);
    
    return new CipherInputStream(encrypted, c);
  }
  
  public static InputStream encrypt(String cipher, byte[] pwd, InputStream data)
    throws IOException, GeneralSecurityException
  {
    return encrypt(cipher, pwd, data, true);
  }
  
  public static InputStream encrypt(String cipher, byte[] pwd, InputStream data, boolean toBase64)
    throws IOException, GeneralSecurityException
  {
    return encrypt(cipher, pwd, data, toBase64, true);
  }
  
  public static InputStream encrypt(String cipher, byte[] pwd, InputStream data, boolean toBase64, boolean useSalt)
    throws IOException, GeneralSecurityException
  {
    CipherInfo cipherInfo = lookup(cipher);
    MessageDigest md5 = MessageDigest.getInstance("MD5");
    byte[] salt = null;
    if (useSalt)
    {
      SecureRandom rand = SecureRandom.getInstance("SHA1PRNG");
      salt = new byte[8];
      rand.nextBytes(salt);
    }
    int keySize = keySize;
    int ivSize = 64;
    if (javaCipher.startsWith("AES")) {
      ivSize = 128;
    }
    DerivedKey dk = deriveKey(pwd, salt, keySize, ivSize, md5);
    Cipher c = PKCS8Key.generateCipher(javaCipher, blockMode, dk, des2, null, false);
    
    InputStream cipherStream = new CipherInputStream(data, c);
    if (useSalt)
    {
      byte[] saltLine = new byte[16];
      byte[] salted = "Salted__".getBytes();
      System.arraycopy(salted, 0, saltLine, 0, salted.length);
      System.arraycopy(salt, 0, saltLine, salted.length, salt.length);
      InputStream head = new ByteArrayInputStream(saltLine);
      cipherStream = new ComboInputStream(head, cipherStream);
    }
    if (toBase64) {
      cipherStream = new Base64InputStream(cipherStream, false);
    }
    return cipherStream;
  }
  
  public static DerivedKey deriveKey(byte[] password, byte[] salt, int keySize, MessageDigest md)
  {
    return deriveKey(password, salt, keySize, 0, md);
  }
  
  public static DerivedKey deriveKey(byte[] password, byte[] salt, int keySize, int ivSize, MessageDigest md)
  {
    md.reset();
    byte[] keyAndIv = new byte[keySize / 8 + ivSize / 8];
    if ((salt == null) || (salt.length == 0)) {
      salt = null;
    }
    int currentPos = 0;
    while (currentPos < keyAndIv.length)
    {
      md.update(password);
      if (salt != null) {
        md.update(salt, 0, 8);
      }
      byte[] result = md.digest();
      int stillNeed = keyAndIv.length - currentPos;
      if (result.length > stillNeed)
      {
        byte[] b = new byte[stillNeed];
        System.arraycopy(result, 0, b, 0, b.length);
        result = b;
      }
      System.arraycopy(result, 0, keyAndIv, currentPos, result.length);
      currentPos += result.length;
      if (currentPos < keyAndIv.length)
      {
        md.reset();
        md.update(result);
      }
    }
    if (ivSize == 0) {
      return new DerivedKey(keyAndIv, salt);
    }
    byte[] key = new byte[keySize / 8];
    byte[] iv = new byte[ivSize / 8];
    System.arraycopy(keyAndIv, 0, key, 0, key.length);
    System.arraycopy(keyAndIv, key.length, iv, 0, iv.length);
    return new DerivedKey(key, iv);
  }
  
  public static class CipherInfo
  {
    public final String javaCipher;
    public final String blockMode;
    public final int keySize;
    public final boolean des2;
    
    public CipherInfo(String javaCipher, String blockMode, int keySize, boolean des2)
    {
      this.javaCipher = javaCipher;
      this.blockMode = blockMode;
      this.keySize = keySize;
      this.des2 = des2;
    }
    
    public String toString()
    {
      return javaCipher + "/" + blockMode + " " + keySize + "bit  des2=" + des2;
    }
  }
  
  public static CipherInfo lookup(String openSSLCipher)
  {
    openSSLCipher = openSSLCipher.trim();
    if (openSSLCipher.charAt(0) == '-') {
      openSSLCipher = openSSLCipher.substring(1);
    }
    String javaCipher = openSSLCipher;
    String blockMode = "CBC";
    int keySize = -1;
    boolean des2 = false;
    
    StringTokenizer st = new StringTokenizer(openSSLCipher, "-");
    if (st.hasMoreTokens())
    {
      javaCipher = st.nextToken().toUpperCase();
      if (st.hasMoreTokens())
      {
        String tok = st.nextToken();
        if (st.hasMoreTokens())
        {
          try
          {
            keySize = Integer.parseInt(tok);
          }
          catch (NumberFormatException nfe)
          {
            String upper = tok.toUpperCase();
            if ("EDE3".equals(upper)) {
              javaCipher = "DESede";
            }
            if ("EDE".equals(upper))
            {
              javaCipher = "DESede";
              des2 = true;
            }
          }
          blockMode = st.nextToken().toUpperCase();
        }
        else
        {
          blockMode = tok.toUpperCase();
          if ("EDE".equals(blockMode))
          {
            javaCipher = "DESede";
            blockMode = "ECB";
            des2 = true;
          }
          else if ("EDE3".equals(blockMode))
          {
            javaCipher = "DESede";
            blockMode = "ECB";
          }
        }
      }
    }
    if ("BF".equals(javaCipher)) {
      javaCipher = "Blowfish";
    }
    if ("DES3".equals(javaCipher))
    {
      javaCipher = "DESede";
    }
    else if ("DES2".equals(javaCipher))
    {
      javaCipher = "DESede";
      des2 = true;
    }
    else if ("AES128".equals(javaCipher))
    {
      javaCipher = "AES";
      keySize = 128;
    }
    else if ("AES192".equals(javaCipher))
    {
      javaCipher = "AES";
      keySize = 192;
    }
    else if ("AES256".equals(javaCipher))
    {
      javaCipher = "AES";
      keySize = 256;
    }
    if (keySize == -1) {
      if (javaCipher.startsWith("DESede")) {
        keySize = 192;
      } else if (javaCipher.startsWith("DES")) {
        keySize = 64;
      } else {
        keySize = 128;
      }
    }
    return new CipherInfo(javaCipher, blockMode, keySize, des2);
  }
  
  public static void main(String[] args)
    throws IOException, GeneralSecurityException
  {
    if (args.length < 3)
    {
      System.out.println(Version.versionString());
      System.out.println("Pure-java utility to decrypt files previously encrypted by 'openssl enc'");
      System.out.println();
      System.out.println("Usage:  java -cp commons-ssl.jar org.apache.commons.ssl.OpenSSL [args]");
      System.out.println("        [args]   == [password] [cipher] [file-to-decrypt]");
      System.out.println("        [cipher] == des, des3, des-ede3-cbc, aes256, rc2, rc4, bf, bf-cbc, etc...");
      System.out.println("                    Try 'man enc' on a unix box to see what's possible.");
      System.out.println();
      System.out.println("This utility can handle base64 or raw, salted or unsalted.");
      System.out.println();
      System.exit(1);
    }
    char[] password = args[0].toCharArray();
    byte[] pwdAsBytes = new byte[password.length];
    for (int i = 0; i < password.length; i++) {
      pwdAsBytes[i] = ((byte)password[i]);
    }
    InputStream in = new FileInputStream(args[2]);
    in = decrypt(args[1], pwdAsBytes, in);
    
    Util.pipeStream(in, System.out, false);
    byte[] output = Util.streamToBytes(in);
    System.out.write(output);
    System.out.flush();
  }
}

/* Location:
 * Qualified Name:     org.apache.commons.ssl.OpenSSL
 * Java Class Version: 1.2 (46.0)
 * JD-Core Version:    0.7.1
 */
package org.apache.commons.ssl;

import java.util.Collections;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.TreeMap;

public class PEMItem
{
  public static final String DEK_INFO = "dek-info";
  private final byte[] derBytes;
  public final String pemType;
  public final Map properties;
  public final String dekInfo;
  public final byte[] iv;
  public final String cipher;
  public final boolean des2;
  public final String mode;
  public final int keySizeInBits;
  
  public PEMItem(byte[] derBytes, String type)
  {
    this(derBytes, type, null);
  }
  
  public PEMItem(byte[] derBytes, String type, Map properties)
  {
    this.derBytes = derBytes;
    pemType = type;
    if (properties == null) {
      properties = new TreeMap();
    }
    this.properties = Collections.unmodifiableMap(properties);
    String di = (String)properties.get("dek-info");
    String diCipher = "";
    String diIV = "";
    if (di != null)
    {
      StringTokenizer st = new StringTokenizer(di, ",");
      if (st.hasMoreTokens()) {
        diCipher = st.nextToken().trim().toLowerCase();
      }
      if (st.hasMoreTokens()) {
        diIV = st.nextToken().trim().toLowerCase();
      }
    }
    dekInfo = diCipher;
    iv = PEMUtil.hexToBytes(diIV);
    if (!"".equals(diCipher))
    {
      OpenSSL.CipherInfo cipherInfo = OpenSSL.lookup(diCipher);
      cipher = javaCipher;
      mode = blockMode;
      keySizeInBits = keySize;
      des2 = des2;
    }
    else
    {
      mode = "";
      cipher = "UNKNOWN";
      keySizeInBits = -1;
      des2 = false;
    }
  }
  
  public byte[] getDerBytes()
  {
    byte[] b = new byte[derBytes.length];
    System.arraycopy(derBytes, 0, b, 0, derBytes.length);
    return b;
  }
}

/* Location:
 * Qualified Name:     org.apache.commons.ssl.PEMItem
 * Java Class Version: 1.2 (46.0)
 * JD-Core Version:    0.7.1
 */
package org.apache.commons.ssl;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.interfaces.RSAPrivateCrtKey;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

public class PEMUtil
{
  static final String LINE_SEPARATOR = System.getProperty("line.separator");
  
  public static byte[] encode(Collection items)
    throws IOException
  {
    byte[] LINE_SEPARATOR_BYTES = LINE_SEPARATOR.getBytes("UTF-8");
    ByteArrayOutputStream out = new ByteArrayOutputStream(4096);
    Iterator it = items.iterator();
    while (it.hasNext())
    {
      PEMItem item = (PEMItem)it.next();
      out.write("-----BEGIN ".getBytes("UTF-8"));
      out.write(pemType.getBytes("UTF-8"));
      out.write("-----".getBytes("UTF-8"));
      out.write(LINE_SEPARATOR_BYTES);
      
      byte[] derBytes = item.getDerBytes();
      ByteArrayInputStream bin = new ByteArrayInputStream(derBytes);
      byte[] line = Util.streamToBytes(bin, 48);
      while (line.length == 48)
      {
        byte[] base64Line = Base64.encodeBase64(line);
        out.write(base64Line);
        out.write(LINE_SEPARATOR_BYTES);
        line = Util.streamToBytes(bin, 48);
      }
      if (line.length > 0)
      {
        byte[] base64Line = Base64.encodeBase64(line);
        out.write(base64Line);
        out.write(LINE_SEPARATOR_BYTES);
      }
      out.write("-----END ".getBytes("UTF-8"));
      out.write(pemType.getBytes("UTF-8"));
      out.write("-----".getBytes("UTF-8"));
      out.write(LINE_SEPARATOR_BYTES);
    }
    return out.toByteArray();
  }
  
  public static List decode(byte[] pemBytes)
  {
    LinkedList pemItems = new LinkedList();
    ByteArrayInputStream in = new ByteArrayInputStream(pemBytes);
    String line = Util.readLine(in);
    while (line != null)
    {
      int len = 0;
      
      ArrayList listOfByteArrays = new ArrayList(64);
      Map properties = new HashMap();
      String type = "[unknown]";
      while ((line != null) && (!beginBase64(line))) {
        line = Util.readLine(in);
      }
      if (line != null)
      {
        String upperLine = line.toUpperCase();
        int x = upperLine.indexOf("-BEGIN") + "-BEGIN".length();
        int y = upperLine.indexOf("-", x);
        type = upperLine.substring(x, y).trim();
        line = Util.readLine(in);
      }
      while ((line != null) && (!endBase64(line)))
      {
        line = Util.trim(line);
        if (!"".equals(line))
        {
          int x = line.indexOf(':');
          if (x > 0)
          {
            String k = line.substring(0, x).trim();
            String v = "";
            if (line.length() > x + 1) {
              v = line.substring(x + 1).trim();
            }
            properties.put(k.toLowerCase(), v.toLowerCase());
          }
          else
          {
            byte[] base64 = line.getBytes();
            byte[] rawBinary = Base64.decodeBase64(base64);
            listOfByteArrays.add(rawBinary);
            len += rawBinary.length;
          }
        }
        line = Util.readLine(in);
      }
      if (line != null) {
        line = Util.readLine(in);
      }
      if (!listOfByteArrays.isEmpty())
      {
        byte[] decoded = new byte[len];
        int pos = 0;
        Iterator it = listOfByteArrays.iterator();
        while (it.hasNext())
        {
          byte[] oneLine = (byte[])it.next();
          System.arraycopy(oneLine, 0, decoded, pos, oneLine.length);
          pos += oneLine.length;
        }
        PEMItem item = new PEMItem(decoded, type, properties);
        pemItems.add(item);
      }
    }
    return pemItems;
  }
  
  private static boolean beginBase64(String line)
  {
    line = line != null ? line.trim().toUpperCase() : "";
    int x = line.indexOf("-BEGIN");
    return (x > 0) && (startsAndEndsWithDashes(line));
  }
  
  private static boolean endBase64(String line)
  {
    line = line != null ? line.trim().toUpperCase() : "";
    int x = line.indexOf("-END");
    return (x > 0) && (startsAndEndsWithDashes(line));
  }
  
  private static boolean startsAndEndsWithDashes(String line)
  {
    line = Util.trim(line);
    char c = line.charAt(0);
    char d = line.charAt(line.length() - 1);
    return (c == '-') && (d == '-');
  }
  
  public static String formatRSAPrivateKey(RSAPrivateCrtKey key)
  {
    StringBuffer buf = new StringBuffer(2048);
    buf.append("Private-Key:");
    buf.append(LINE_SEPARATOR);
    buf.append("modulus:");
    buf.append(LINE_SEPARATOR);
    buf.append(formatBigInteger(key.getModulus(), 258));
    buf.append(LINE_SEPARATOR);
    buf.append("publicExponent: ");
    buf.append(key.getPublicExponent());
    buf.append(LINE_SEPARATOR);
    buf.append("privateExponent:");
    buf.append(LINE_SEPARATOR);
    buf.append(formatBigInteger(key.getPrivateExponent(), 256));
    buf.append(LINE_SEPARATOR);
    buf.append("prime1:");
    buf.append(LINE_SEPARATOR);
    buf.append(formatBigInteger(key.getPrimeP(), 130));
    buf.append(LINE_SEPARATOR);
    buf.append("prime2:");
    buf.append(LINE_SEPARATOR);
    buf.append(formatBigInteger(key.getPrimeQ(), 130));
    buf.append(LINE_SEPARATOR);
    buf.append("exponent1:");
    buf.append(LINE_SEPARATOR);
    buf.append(formatBigInteger(key.getPrimeExponentP(), 130));
    buf.append(LINE_SEPARATOR);
    buf.append("exponent2:");
    buf.append(LINE_SEPARATOR);
    buf.append(formatBigInteger(key.getPrimeExponentQ(), 130));
    buf.append(LINE_SEPARATOR);
    buf.append("coefficient:");
    buf.append(LINE_SEPARATOR);
    buf.append(formatBigInteger(key.getCrtCoefficient(), 130));
    return buf.toString();
  }
  
  public static String formatBigInteger(BigInteger bi, int length)
  {
    String s = bi.toString(16);
    StringBuffer buf = new StringBuffer(s.length());
    int zeroesToAppend = length - s.length();
    int count = 0;
    buf.append("    ");
    for (int i = 0; i < zeroesToAppend; i++)
    {
      count++;
      buf.append('0');
      if (i % 2 == 1) {
        buf.append(':');
      }
    }
    for (int i = 0; i < s.length() - 2; i++)
    {
      count++;
      buf.append(s.charAt(i));
      if (i % 2 == 1) {
        buf.append(':');
      }
      if (count % 30 == 0)
      {
        buf.append(LINE_SEPARATOR);
        buf.append("    ");
      }
    }
    buf.append(s.substring(s.length() - 2));
    return buf.toString();
  }
  
  public static byte[] hexToBytes(String s)
  {
    byte[] b = new byte[s.length() / 2];
    for (int i = 0; i < b.length; i++)
    {
      String hex = s.substring(2 * i, 2 * (i + 1));
      b[i] = ((byte)Integer.parseInt(hex, 16));
    }
    return b;
  }
  
  public static String bytesToHex(byte[] b)
  {
    return bytesToHex(b, 0, b.length);
  }
  
  public static String bytesToHex(byte[] b, int offset, int length)
  {
    StringBuffer buf = new StringBuffer();
    int len = Math.min(offset + length, b.length);
    for (int i = offset; i < len; i++)
    {
      int c = b[i];
      if (c < 0) {
        c += 256;
      }
      if ((c >= 0) && (c <= 15)) {
        buf.append('0');
      }
      buf.append(Integer.toHexString(c));
    }
    return buf.toString();
  }
}

/* Location:
 * Qualified Name:     org.apache.commons.ssl.PEMUtil
 * Java Class Version: 1.2 (46.0)
 * JD-Core Version:    0.7.1
 */
package org.apache.commons.ssl;

public class PKCS8Key$DecryptResult
{
  public final String transformation;
  public final int keySize;
  public final byte[] bytes;
  
  protected PKCS8Key$DecryptResult(String transformation, int keySize, byte[] decryptedBytes)
  {
    this.transformation = transformation;
    this.keySize = keySize;
    bytes = decryptedBytes;
  }
}

/* Location:
 * Qualified Name:     org.apache.commons.ssl.PKCS8Key.DecryptResult
 * Java Class Version: 1.2 (46.0)
 * JD-Core Version:    0.7.1
 */
package org.apache.commons.ssl;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.security.GeneralSecurityException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.Mac;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.RC2ParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.ssl.asn1.ASN1OutputStream;
import org.apache.commons.ssl.asn1.DEREncodable;
import org.apache.commons.ssl.asn1.DERInteger;
import org.apache.commons.ssl.asn1.DERNull;
import org.apache.commons.ssl.asn1.DERObjectIdentifier;
import org.apache.commons.ssl.asn1.DEROctetString;
import org.apache.commons.ssl.asn1.DERSequence;

public class PKCS8Key
{
  public static final String RSA_OID = "1.2.840.113549.1.1.1";
  public static final String DSA_OID = "1.2.840.10040.4.1";
  public static final String PKCS8_UNENCRYPTED = "PRIVATE KEY";
  public static final String PKCS8_ENCRYPTED = "ENCRYPTED PRIVATE KEY";
  public static final String OPENSSL_RSA = "RSA PRIVATE KEY";
  public static final String OPENSSL_DSA = "DSA PRIVATE KEY";
  private final PrivateKey privateKey;
  private final byte[] decryptedBytes;
  private final String transformation;
  private final int keySize;
  private final boolean isDSA;
  private final boolean isRSA;
  
  public PKCS8Key(InputStream in, char[] password)
    throws GeneralSecurityException, IOException
  {
    this(Util.streamToBytes(in), password);
  }
  
  public PKCS8Key(ByteArrayInputStream in, char[] password)
    throws GeneralSecurityException
  {
    this(Util.streamToBytes(in), password);
  }
  
  public PKCS8Key(byte[] encoded, char[] password)
    throws GeneralSecurityException
  {
    DecryptResult decryptResult = new DecryptResult("UNENCRYPTED", 0, encoded);
    
    List pemItems = PEMUtil.decode(encoded);
    PEMItem keyItem = null;
    byte[] derBytes = null;
    if (pemItems.isEmpty())
    {
      derBytes = encoded;
    }
    else
    {
      Iterator it = pemItems.iterator();
      boolean opensslRSA = false;
      boolean opensslDSA = false;
      while (it.hasNext())
      {
        PEMItem item = (PEMItem)it.next();
        String type = pemType.trim().toUpperCase();
        boolean plainPKCS8 = type.startsWith("PRIVATE KEY");
        boolean encryptedPKCS8 = type.startsWith("ENCRYPTED PRIVATE KEY");
        boolean rsa = type.startsWith("RSA PRIVATE KEY");
        boolean dsa = type.startsWith("DSA PRIVATE KEY");
        if ((plainPKCS8) || (encryptedPKCS8) || (rsa) || (dsa))
        {
          opensslRSA = (opensslRSA) || (rsa);
          opensslDSA = (opensslDSA) || (dsa);
          if (derBytes != null) {
            throw new ProbablyNotPKCS8Exception("More than one pkcs8 or OpenSSL key found in the supplied PEM Base64 stream");
          }
          derBytes = item.getDerBytes();
          keyItem = item;
          decryptResult = new DecryptResult("UNENCRYPTED", 0, derBytes);
        }
      }
      if (derBytes == null) {
        throw new ProbablyNotPKCS8Exception("No pkcs8 or OpenSSL key found in the supplied PEM Base64 stream");
      }
      if ((opensslDSA) || (opensslRSA))
      {
        String c = cipher.trim();
        boolean encrypted = (!"UNKNOWN".equals(c)) && (!"".equals(c));
        if (encrypted) {
          decryptResult = opensslDecrypt(keyItem, password);
        }
        String oid = "1.2.840.113549.1.1.1";
        if (opensslDSA) {
          oid = "1.2.840.10040.4.1";
        }
        derBytes = formatAsPKCS8(bytes, oid, null);
        
        String tf = transformation;
        int ks = keySize;
        decryptResult = new DecryptResult(tf, ks, derBytes);
      }
    }
    try
    {
      pkcs8 = ASN1Util.analyze(derBytes);
    }
    catch (Exception e)
    {
      ASN1Structure pkcs8;
      throw new ProbablyNotPKCS8Exception("asn1 parse failure: " + e);
    }
    ASN1Structure pkcs8;
    String oid = "1.2.840.113549.1.1.1";
    
    int derIntegerCount = -1;
    if (derIntegers != null) {
      derIntegerCount = derIntegers.size();
    }
    switch (derIntegerCount)
    {
    case 6: 
      oid = "1.2.840.10040.4.1";
    case 9: 
      derBytes = formatAsPKCS8(derBytes, oid, pkcs8);
      oid1 = oid;
      
      String tf = transformation;
      int ks = keySize;
      decryptResult = new DecryptResult(tf, ks, derBytes);
      break;
    }
    oid = oid1;
    if (!oid.startsWith("1.2.840.113549.1"))
    {
      boolean isOkay = false;
      if (oid.startsWith("1.2.840.10040.4."))
      {
        String s = oid.substring("1.2.840.10040.4.".length());
        
        isOkay = (s.equals("1")) || (s.startsWith("1.")) || (s.equals("3")) || (s.startsWith("3."));
      }
      if (!isOkay) {
        throw new ProbablyNotPKCS8Exception("Valid ASN.1, but not PKCS8 or OpenSSL format.  OID=" + oid);
      }
    }
    boolean isRSA = "1.2.840.113549.1.1.1".equals(oid);
    boolean isDSA = "1.2.840.10040.4.1".equals(oid);
    boolean encrypted = (!isRSA) && (!isDSA);
    byte[] decryptedPKCS8 = encrypted ? null : derBytes;
    if (encrypted)
    {
      decryptResult = decryptPKCS8(pkcs8, password);
      decryptedPKCS8 = bytes;
    }
    if (encrypted)
    {
      try
      {
        pkcs8 = ASN1Util.analyze(decryptedPKCS8);
      }
      catch (Exception e)
      {
        throw new ProbablyBadPasswordException("Decrypted stream not ASN.1.  Probably bad decryption password.");
      }
      oid = oid1;
      isDSA = "1.2.840.10040.4.1".equals(oid);
    }
    KeySpec spec = new PKCS8EncodedKeySpec(decryptedPKCS8);
    String type = "RSA";
    try
    {
      KeyFactory KF;
      KeyFactory KF;
      if (isDSA)
      {
        type = "DSA";
        KF = KeyFactory.getInstance("DSA");
      }
      else
      {
        KF = KeyFactory.getInstance("RSA");
      }
      pk = KF.generatePrivate(spec);
    }
    catch (Exception e)
    {
      PrivateKey pk;
      throw new ProbablyBadPasswordException("Cannot create " + type + " private key from decrypted stream.  Probably bad decryption password. " + e);
    }
    PrivateKey pk;
    if (pk != null)
    {
      privateKey = pk;
      this.isDSA = isDSA;
      this.isRSA = (!isDSA);
      decryptedBytes = decryptedPKCS8;
      transformation = transformation;
      keySize = keySize;
    }
    else
    {
      throw new GeneralSecurityException("KeyFactory.generatePrivate() returned null and didn't throw exception!");
    }
  }
  
  public boolean isRSA()
  {
    return isRSA;
  }
  
  public boolean isDSA()
  {
    return isDSA;
  }
  
  public String getTransformation()
  {
    return transformation;
  }
  
  public int getKeySize()
  {
    return keySize;
  }
  
  public byte[] getDecryptedBytes()
  {
    return decryptedBytes;
  }
  
  public PrivateKey getPrivateKey()
  {
    return privateKey;
  }
  
  public static class DecryptResult
  {
    public final String transformation;
    public final int keySize;
    public final byte[] bytes;
    
    protected DecryptResult(String transformation, int keySize, byte[] decryptedBytes)
    {
      this.transformation = transformation;
      this.keySize = keySize;
      bytes = decryptedBytes;
    }
  }
  
  private static DecryptResult opensslDecrypt(PEMItem item, char[] password)
    throws GeneralSecurityException
  {
    String cipher = item.cipher;
    String mode = item.mode;
    int keySize = keySizeInBits;
    byte[] salt = iv;
    byte[] pwd = new byte[password.length];
    for (int i = 0; i < password.length; i++) {
      pwd[i] = ((byte)password[i]);
    }
    MessageDigest md = MessageDigest.getInstance("MD5");
    DerivedKey dk = OpenSSL.deriveKey(pwd, salt, keySize, md);
    return decrypt(cipher, mode, dk, des2, null, item.getDerBytes());
  }
  
  public static Cipher generateCipher(String cipher, String mode, DerivedKey dk, boolean des2, byte[] iv, boolean decryptMode)
    throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException
  {
    if ((des2) && (key.length >= 24)) {
      System.arraycopy(key, 0, key, 16, 8);
    }
    int keySize = key.length * 8;
    cipher = cipher.trim();
    mode = mode.trim().toUpperCase();
    
    Cipher.getInstance(cipher);
    String padding = "PKCS5Padding";
    if (("CFB".equals(mode)) || ("OFB".equals(mode))) {
      padding = "NoPadding";
    }
    String transformation = cipher + "/" + mode + "/" + padding;
    if ("RC4".equals(cipher)) {
      transformation = cipher;
    }
    SecretKey secret = new SecretKeySpec(key, cipher);
    IvParameterSpec ivParams;
    IvParameterSpec ivParams;
    if (iv != null) {
      ivParams = new IvParameterSpec(iv);
    } else {
      ivParams = iv != null ? new IvParameterSpec(iv) : null;
    }
    Cipher c = Cipher.getInstance(transformation);
    int cipherMode = 1;
    if (decryptMode) {
      cipherMode = 2;
    }
    if ("RC2".equalsIgnoreCase(cipher))
    {
      RC2ParameterSpec rcParams;
      RC2ParameterSpec rcParams;
      if (("ECB".equals(mode)) || (ivParams == null)) {
        rcParams = new RC2ParameterSpec(keySize);
      } else {
        rcParams = new RC2ParameterSpec(keySize, ivParams.getIV());
      }
      c.init(cipherMode, secret, rcParams);
    }
    else if (("ECB".equals(mode)) || ("RC4".equals(cipher)))
    {
      c.init(cipherMode, secret);
    }
    else
    {
      c.init(cipherMode, secret, ivParams);
    }
    return c;
  }
  
  public static DecryptResult decrypt(String cipher, String mode, DerivedKey dk, boolean des2, byte[] iv, byte[] encryptedBytes)
    throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException
  {
    Cipher c = generateCipher(cipher, mode, dk, des2, iv, true);
    String transformation = c.getAlgorithm();
    int keySize = key.length * 8;
    byte[] decryptedBytes = c.doFinal(encryptedBytes);
    return new DecryptResult(transformation, keySize, decryptedBytes);
  }
  
  private static DecryptResult decryptPKCS8(ASN1Structure pkcs8, char[] password)
    throws GeneralSecurityException
  {
    boolean isVersion1 = true;
    boolean isVersion2 = false;
    boolean usePKCS12PasswordPadding = false;
    boolean use2DES = false;
    String cipher = null;
    String hash = null;
    int keySize = -1;
    
    String mode = "CBC";
    
    int ivSize = 0;
    
    String oid = oid1;
    if (oid.startsWith("1.2.840.113549.1.12."))
    {
      usePKCS12PasswordPadding = true;
      
      oid = oid.substring("1.2.840.113549.1.12.".length());
      if ((oid.equals("1.1")) || (oid.startsWith("1.1.")))
      {
        hash = "SHA1";
        cipher = "RC4";
        keySize = 128;
      }
      else if ((oid.equals("1.2")) || (oid.startsWith("1.2.")))
      {
        hash = "SHA1";
        cipher = "RC4";
        keySize = 40;
      }
      else if ((oid.equals("1.3")) || (oid.startsWith("1.3.")))
      {
        hash = "SHA1";
        cipher = "DESede";
        keySize = 192;
      }
      else if ((oid.equals("1.4")) || (oid.startsWith("1.4.")))
      {
        hash = "SHA1";
        cipher = "DESede";
        keySize = 192;
        use2DES = true;
      }
      else if ((oid.equals("1.5")) || (oid.startsWith("1.5.")))
      {
        hash = "SHA1";
        cipher = "RC2";
        keySize = 128;
      }
      else if ((oid.equals("1.6")) || (oid.startsWith("1.6.")))
      {
        hash = "SHA1";
        cipher = "RC2";
        keySize = 40;
      }
    }
    else if (oid.startsWith("1.2.840.113549.1.5."))
    {
      oid = oid.substring("1.2.840.113549.1.5.".length());
      if ((oid.equals("1")) || (oid.startsWith("1.")))
      {
        hash = "MD2";
        cipher = "DES";
        keySize = 64;
      }
      else if ((oid.equals("3")) || (oid.startsWith("3.")))
      {
        hash = "MD5";
        cipher = "DES";
        keySize = 64;
      }
      else if ((oid.equals("4")) || (oid.startsWith("4.")))
      {
        hash = "MD2";
        cipher = "RC2";
        keySize = 64;
      }
      else if ((oid.equals("6")) || (oid.startsWith("6.")))
      {
        hash = "MD5";
        cipher = "RC2";
        keySize = 64;
      }
      else if ((oid.equals("10")) || (oid.startsWith("10.")))
      {
        hash = "SHA1";
        cipher = "DES";
        keySize = 64;
      }
      else if ((oid.equals("11")) || (oid.startsWith("11.")))
      {
        hash = "SHA1";
        cipher = "RC2";
        keySize = 64;
      }
      else if ((oid.equals("12")) || (oid.startsWith("12.")))
      {
        isVersion2 = true;
      }
      else if ((oid.equals("13")) || (oid.startsWith("13.")))
      {
        isVersion2 = true;
      }
      else if ((oid.equals("14")) || (oid.startsWith("14.")))
      {
        isVersion2 = true;
      }
    }
    if (isVersion2)
    {
      isVersion1 = false;
      hash = "HmacSHA1";
      oid = oid2;
      if (oid3 != null) {
        oid = oid3;
      }
      if (oid.startsWith("1.3.6.1.4.1.3029.1.2"))
      {
        cipher = "Blowfish";
        mode = "CBC";
        keySize = 128;
      }
      else if (oid.startsWith("1.3.14.3.2."))
      {
        oid = oid.substring("1.3.14.3.2.".length());
        if ((oid.equals("6")) || (oid.startsWith("6.")))
        {
          cipher = "DES";
          mode = "ECB";
          keySize = 64;
        }
 
1 2 3 4 5 6 7 8 9

Further reading...

For more information on Java 1.5 Tiger, you may find Java 1.5 Tiger, A developer's Notebook by D. Flanagan and B. McLaughlin from O'Reilly of interest.

New!JAR listings


Copyright 2006-2019. Infinite Loop Ltd