You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@manifoldcf.apache.org by kw...@apache.org on 2014/11/08 14:04:29 UTC

svn commit: r1637560 - in /manifoldcf/trunk: ./ framework/core/src/main/java/org/apache/manifoldcf/core/ framework/core/src/main/java/org/apache/manifoldcf/core/system/ framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/system/

Author: kwright
Date: Sat Nov  8 13:04:29 2014
New Revision: 1637560

URL: http://svn.apache.org/r1637560
Log:
Fix for CONNECTORS-1076.  WARNING: This is a non-backwards-compatible change, since it changes the encryption for obfuscated passwords.

Modified:
    manifoldcf/trunk/CHANGES.txt
    manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/Obfuscate.java
    manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/system/ManifoldCF.java
    manifoldcf/trunk/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/system/ManifoldCF.java

Modified: manifoldcf/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/CHANGES.txt?rev=1637560&r1=1637559&r2=1637560&view=diff
==============================================================================
--- manifoldcf/trunk/CHANGES.txt (original)
+++ manifoldcf/trunk/CHANGES.txt Sat Nov  8 13:04:29 2014
@@ -3,6 +3,10 @@ $Id$
 
 ======================= 2.0-dev =====================
 
+CONNECTORS-1076: Revamp ManifoldCF obfuscation to use a
+standard encryption algorithm.
+(Karl Wright)
+
 CONNECTORS-1099: Update Metadata Adjuster documentation.
 (Karl Wright)
 

Modified: manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/Obfuscate.java
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/Obfuscate.java?rev=1637560&r1=1637559&r2=1637560&view=diff
==============================================================================
--- manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/Obfuscate.java (original)
+++ manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/Obfuscate.java Sat Nov  8 13:04:29 2014
@@ -42,7 +42,9 @@ public class Obfuscate
     String string = args[0];
     try
     {
-      UTF8Stdout.println(ManifoldCF.obfuscate(string));
+      String ob = ManifoldCF.obfuscate(string);
+      UTF8Stdout.println(ob);
+      //System.err.println("("+ManifoldCF.deobfuscate(ob)+")");
     }
     catch (ManifoldCFException e)
     {

Modified: manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/system/ManifoldCF.java
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/system/ManifoldCF.java?rev=1637560&r1=1637559&r2=1637560&view=diff
==============================================================================
--- manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/system/ManifoldCF.java (original)
+++ manifoldcf/trunk/framework/core/src/main/java/org/apache/manifoldcf/core/system/ManifoldCF.java Sat Nov  8 13:04:29 2014
@@ -20,9 +20,27 @@ package org.apache.manifoldcf.core.syste
 
 import org.apache.manifoldcf.core.interfaces.*;
 import java.io.*;
-import java.nio.charset.StandardCharsets;
 import java.util.*;
+import java.nio.charset.StandardCharsets;
 import java.security.MessageDigest;
+import java.security.GeneralSecurityException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.InvalidParameterException;
+import java.security.Key;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.KeySpec;
+import javax.crypto.Cipher;
+import javax.crypto.CipherInputStream;
+import javax.crypto.CipherOutputStream;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.PBEKeySpec;
+import javax.crypto.spec.SecretKeySpec;
 
 public class ManifoldCF
 {
@@ -146,6 +164,9 @@ public class ManifoldCF
   /** File to look for to block access to UI during database maintenance */
   public static final String maintenanceFileSignalProperty = "org.apache.manifoldcf.database.maintenanceflag";
 
+  /** Encryption salt property */
+  public static final String saltProperty = "org.apache.manifoldcf.salt";
+
   /** Reset environment, minting a thread context for convenience and backwards
   * compatibility.
   */
@@ -560,7 +581,9 @@ public class ManifoldCF
   public static String hash(String input)
     throws ManifoldCFException
   {
-    return encrypt(input);
+    MessageDigest hash = startHash();
+    addToHash(hash,input);
+    return getHashValue(hash);
   }
 
   /** Start creating a hash
@@ -637,22 +660,171 @@ public class ManifoldCF
     return false;
   }
   
-  /** Perform standard one-way encryption of a string.
-  *@param input is the string to encrypt.
-  *@return the encrypted string.
+  protected static final int IV_LENGTH = 16;
+
+  protected static String getSaltValue(IThreadContext threadContext)
+    throws ManifoldCFException
+  {
+    final String saltValue = LockManagerFactory.getProperty(threadContext, saltProperty);
+
+    if (saltValue == null || saltValue.length() == 0)
+      throw new ManifoldCFException("Missing required SALT value");
+
+    return saltValue;
+  }
+  
+  protected static Cipher getCipher(IThreadContext threadContext, final int mode, final String passCode, final byte[] iv)
+    throws ManifoldCFException
+  {
+    return getCipher(getSaltValue(threadContext), mode, passCode, iv);
+  }
+  
+  protected static Cipher getCipher(String saltValue, final int mode, final String passCode, final byte[] iv)
+    throws ManifoldCFException
+  {
+    try
+    {
+      SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
+      KeySpec keySpec = new PBEKeySpec(passCode.toCharArray(), saltValue.getBytes(), 1024, 128);
+      SecretKey secretKey = factory.generateSecret(keySpec);
+
+      Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
+      SecretKeySpec key = new SecretKeySpec(secretKey.getEncoded(), "AES");
+      IvParameterSpec parameterSpec = new IvParameterSpec(iv);
+      cipher.init(mode, key, parameterSpec);
+      return cipher;
+    }
+    catch (GeneralSecurityException gse)
+    {
+      throw new ManifoldCFException("Could not build a cipher: " + gse.getMessage(),gse);
+    }
+  }
+  
+  protected static byte[] getSecureRandom()
+  {
+    SecureRandom random = new SecureRandom();
+    byte[] iv = new byte[IV_LENGTH];
+    random.nextBytes(iv);
+    return iv;
+  }
+  
+  private static String OBFUSCATION_PASSCODE = "NowIsTheTime";
+  private static String OBFUSCATION_SALT = "Salty";
+  
+  /** Encode a string in a reversible obfuscation.
+  *@param input is the input string.
+  *@return the output string.
   */
-  public static String encrypt(String input)
+  public static String obfuscate(String input)
     throws ManifoldCFException
   {
-    MessageDigest hash = startHash();
-    addToHash(hash,input);
-    return getHashValue(hash);
+    return encrypt(OBFUSCATION_SALT, OBFUSCATION_PASSCODE, input);
   }
+  
+  /** Decode a string encoded using the obfuscation
+  * technique.
+  *@param input is the input string.
+  *@return the decoded string.
+  */
+  public static String deobfuscate(String input)
+    throws ManifoldCFException
+  {
+    return decrypt(OBFUSCATION_SALT, OBFUSCATION_PASSCODE, input);
+  }
+  
+  /** Encrypt a string in a reversible encryption.
+  *@param saltValue is the salt value.
+  *@param passCode is the pass code.
+  *@param input is the input string.
+  *@return the output string.
+  */
+  public static String encrypt(String saltValue, String passCode, String input)
+    throws ManifoldCFException
+  {
+    if (input == null)
+      return null;
+    if (input.length() == 0)
+      return input;
 
+    try
+    {
+      ByteArrayOutputStream os = new ByteArrayOutputStream();
+      
+      // Write IV as a prefix:
+      byte[] iv = getSecureRandom();
+      os.write(iv);
+      os.flush();
+            
+      Cipher cipher = getCipher(saltValue, Cipher.ENCRYPT_MODE, passCode, iv);
+      CipherOutputStream cos = new CipherOutputStream(os, cipher);
+      Writer w = new OutputStreamWriter(cos,java.nio.charset.StandardCharsets.UTF_8);
+      w.write(input);
+      w.flush();
+      // These two shouldn't be necessary, but they are.
+      cos.flush();
+      cos.close();
+      byte[] bytes = os.toByteArray();
+      return new org.apache.manifoldcf.core.common.Base64().encodeByteArray(bytes);
+    }
+    catch (IOException e)
+    {
+      throw new ManifoldCFException(e.getMessage(),e);
+    }
+  }
+        
+  /** Decrypt a string.
+  *@param saltValue is the salt value.
+  *@param passCode is the pass code.
+  *@param input is the input string.
+  *@return the decoded string.
+  */
+  public static String decrypt(String saltValue, String passCode, String input)
+    throws ManifoldCFException
+  {
+    if (input == null)
+      return null;
+    if (input.length() == 0)
+      return input;
+
+    try
+    {
+      ByteArrayInputStream is = new ByteArrayInputStream(new org.apache.manifoldcf.core.common.Base64().decodeString(input));
+      
+      byte[] iv = new byte[IV_LENGTH];
+      int pointer = 0;
+      while (pointer < iv.length)
+      {
+        int amt = is.read(iv,pointer,iv.length-pointer);
+        if (amt == -1)
+          throw new ManifoldCFException("String can't be decrypted: too short");
+        pointer += amt;
+      }
+
+      Cipher cipher = getCipher(saltValue, Cipher.DECRYPT_MODE, passCode, iv);
+      CipherInputStream cis = new CipherInputStream(is, cipher);
+      InputStreamReader reader = new InputStreamReader(cis,java.nio.charset.StandardCharsets.UTF_8);
+      StringBuilder sb = new StringBuilder();
+      char[] buffer = new char[65536];
+      while (true)
+      {
+        int amt = reader.read(buffer,0,buffer.length);
+        if (amt == -1)
+          break;
+        sb.append(buffer,0,amt);
+      }
+      return sb.toString();
+    }
+    catch (IOException e)
+    {
+      throw new ManifoldCFException(e.getMessage(),e);
+    }
+  }
+  
   /** Encode a string in a reversible obfuscation.
   *@param input is the input string.
   *@return the output string.
   */
+  /*
   public static String obfuscate(String input)
     throws ManifoldCFException
   {
@@ -686,11 +858,12 @@ public class ManifoldCF
       }
       return rval.toString();
   }
-
+*/
   /** Write a hex nibble.
   *@param value is the value to write.
   *@return the character.
   */
+
   protected static char writeNibble(int value)
   {
     if (value >= 10)
@@ -699,11 +872,13 @@ public class ManifoldCF
       return (char)(value+'0');
   }
 
+
   /** Decode a string encoded using the obfuscation
   * technique.
   *@param input is the input string.
   *@return the decoded string.
   */
+  /*
   public static String deobfuscate(String input)
     throws ManifoldCFException
   {
@@ -742,7 +917,8 @@ public class ManifoldCF
       // Convert from utf-8 to a string
       return new String(bytes,StandardCharsets.UTF_8);
   }
-
+  */
+  
   /** Read a hex nibble.
   *@param value is the character.
   *@return the value.

Modified: manifoldcf/trunk/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/system/ManifoldCF.java
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/system/ManifoldCF.java?rev=1637560&r1=1637559&r2=1637560&view=diff
==============================================================================
--- manifoldcf/trunk/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/system/ManifoldCF.java (original)
+++ manifoldcf/trunk/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/system/ManifoldCF.java Sat Nov  8 13:04:29 2014
@@ -62,7 +62,6 @@ public class ManifoldCF extends org.apac
   protected static final String connectorsConfigurationFileProperty = "org.apache.manifoldcf.connectorsconfigurationfile";
   protected static final String databaseSuperuserNameProperty = "org.apache.manifoldcf.dbsuperusername";
   protected static final String databaseSuperuserPasswordProperty = "org.apache.manifoldcf.dbsuperuserpassword";
-  protected static final String saltProperty = "org.apache.manifoldcf.salt";
 
   
   /** Initialize environment.
@@ -676,22 +675,11 @@ public class ManifoldCF extends org.apac
         {
           
           // Write IV as a prefix:
-          SecureRandom random = new SecureRandom();
-          byte[] iv = new byte[IV_LENGTH];
-          random.nextBytes(iv);
+          byte[] iv = getSecureRandom();
           os.write(iv);
           os.flush();
           
-          Cipher cipher = null; 
-          try
-          {
-            cipher = getCipher(threadContext, Cipher.ENCRYPT_MODE, passCode, iv);
-          }
-          catch (GeneralSecurityException gse)
-          {
-            throw new ManifoldCFException("Could not encrypt configuratiom file: " + gse.getMessage());
-          }
-          
+          Cipher cipher = getCipher(threadContext, Cipher.ENCRYPT_MODE, passCode, iv);
           cos = new CipherOutputStream(os, cipher);
           zos = new java.util.zip.ZipOutputStream(cos);
         }
@@ -821,15 +809,7 @@ public class ManifoldCF extends org.apac
           byte[] iv = new byte[IV_LENGTH];
           is.read(iv);
 
-          Cipher cipher = null; 
-          try
-          {
-            cipher = getCipher(threadContext, Cipher.DECRYPT_MODE, passCode, iv);
-          }
-          catch (GeneralSecurityException gse)
-          {
-            throw new ManifoldCFException("Could not decrypt configuratiom file: " + gse.getMessage());
-          }
+          Cipher cipher = getCipher(threadContext, Cipher.DECRYPT_MODE, passCode, iv);
           cis = new CipherInputStream(is, cipher);
           zis = new java.util.zip.ZipInputStream(cis);
         }
@@ -1197,28 +1177,6 @@ public class ManifoldCF extends org.apac
     return activityList;
   }
   
-  private static final int IV_LENGTH = 16;
-  
-  private static Cipher getCipher(IThreadContext threadContext, final int mode, final String passCode, final byte[] iv) throws GeneralSecurityException,
-    ManifoldCFException
-  {
-    final String saltValue = LockManagerFactory.getProperty(threadContext, saltProperty);
-
-    if (saltValue == null || saltValue.length() == 0)
-      throw new ManifoldCFException("Missing required SALT value");
-    
-    SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
-    KeySpec keySpec = new PBEKeySpec(passCode.toCharArray(), saltValue.getBytes(), 1024, 128);
-    SecretKey secretKey = factory.generateSecret(keySpec);
-
-    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
-    SecretKeySpec key = new SecretKeySpec(secretKey.getEncoded(), "AES");
-    IvParameterSpec parameterSpec = new IvParameterSpec(iv);
-    cipher.init(mode, key, parameterSpec);
-    return cipher;
-  }
-  
-  
   // ========================== API support ===========================
   
   protected static final String API_JOBNODE = "job";