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";