[PIRK-74] Close Hash Key information leak - closes apache/incubator-pirk#111
diff --git a/src/main/java/org/apache/pirk/encryption/Paillier.java b/src/main/java/org/apache/pirk/encryption/Paillier.java
index 6502e0d..5bc4694 100644
--- a/src/main/java/org/apache/pirk/encryption/Paillier.java
+++ b/src/main/java/org/apache/pirk/encryption/Paillier.java
@@ -18,10 +18,7 @@
  */
 package org.apache.pirk.encryption;
 
-import java.io.Serializable;
-import java.math.BigInteger;
-import java.security.GeneralSecurityException;
-import java.security.SecureRandom;
+import org.apache.pirk.utils.RandomProvider;
 
 import com.google.gson.annotations.Expose;
 import org.apache.pirk.utils.PIRException;
@@ -29,6 +26,9 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.io.Serializable;
+import java.math.BigInteger;
+
 /**
  * Implementation of the Paillier cryptosystem.
  * <p>
@@ -72,31 +72,6 @@
 
   private static final Logger logger = LoggerFactory.getLogger(Paillier.class);
 
-  private static final SecureRandom secureRandom;
-
-  static
-  {
-    try
-    {
-      String alg = SystemConfiguration.getProperty("pallier.secureRandom.algorithm");
-      if (alg == null)
-      {
-        secureRandom = new SecureRandom();
-      }
-      else
-      {
-        String provider = SystemConfiguration.getProperty("pallier.secureRandom.provider");
-        secureRandom = (provider == null) ? SecureRandom.getInstance(alg) : SecureRandom.getInstance(alg, provider);
-      }
-      logger.info("Using secure random from " + secureRandom.getProvider().getName() + ":" + secureRandom.getAlgorithm());
-    } catch (GeneralSecurityException e)
-    {
-      logger.error("Unable to instantiate a SecureRandom object with the requested algorithm.", e);
-      throw new RuntimeException("Unable to instantiate a SecureRandom object with the requested algorithm.", e);
-    }
-  }
-
-  @Expose
   private BigInteger p; // large prime
   @Expose
   private BigInteger q; // large prime
@@ -281,7 +256,7 @@
   private void getKeys(int bitLength, int certainty)
   {
     // Generate the primes
-    BigInteger[] pq = PrimeGenerator.getPrimePair(bitLength, certainty, secureRandom);
+    BigInteger[] pq = PrimeGenerator.getPrimePair(bitLength, certainty, RandomProvider.SECURE_RANDOM);
     p = pq[0];
     q = pq[1];
 
@@ -310,10 +285,10 @@
   public BigInteger encrypt(BigInteger m) throws PIRException
   {
     // Generate a random value r in (Z/NZ)*
-    BigInteger r = (new BigInteger(bitLength, secureRandom)).mod(N);
+    BigInteger r = (new BigInteger(bitLength, RandomProvider.SECURE_RANDOM)).mod(N);
     while (r.equals(BigInteger.ZERO) || r.equals(BigInteger.ONE) || r.mod(p).equals(BigInteger.ZERO) || r.mod(q).equals(BigInteger.ZERO))
     {
-      r = (new BigInteger(bitLength, secureRandom)).mod(N);
+      r = (new BigInteger(bitLength, RandomProvider.SECURE_RANDOM)).mod(N);
     }
 
     return encrypt(m, r);
diff --git a/src/main/java/org/apache/pirk/querier/wideskies/EncryptionPropertiesBuilder.java b/src/main/java/org/apache/pirk/querier/wideskies/EncryptionPropertiesBuilder.java
index 1f7d2cd..d3e913c 100644
--- a/src/main/java/org/apache/pirk/querier/wideskies/EncryptionPropertiesBuilder.java
+++ b/src/main/java/org/apache/pirk/querier/wideskies/EncryptionPropertiesBuilder.java
@@ -27,7 +27,6 @@
 import static org.apache.pirk.querier.wideskies.QuerierProps.DATAPARTITIONSIZE;
 import static org.apache.pirk.querier.wideskies.QuerierProps.EMBEDSELECTOR;
 import static org.apache.pirk.querier.wideskies.QuerierProps.HASHBITSIZE;
-import static org.apache.pirk.querier.wideskies.QuerierProps.HASHKEY;
 import static org.apache.pirk.querier.wideskies.QuerierProps.NUMTHREADS;
 import static org.apache.pirk.querier.wideskies.QuerierProps.PAILLIERBITSIZE;
 import static org.apache.pirk.querier.wideskies.QuerierProps.QUERYTYPE;
@@ -84,12 +83,6 @@
     return this;
   }
 
-  public EncryptionPropertiesBuilder hashKey(String hashKey)
-  {
-    properties.setProperty(HASHKEY, hashKey);
-    return this;
-  }
-
   public EncryptionPropertiesBuilder dataPartitionBitSize(int dataPartitionBitSize)
   {
     properties.setProperty(DATAPARTITIONSIZE, String.valueOf(dataPartitionBitSize));
diff --git a/src/main/java/org/apache/pirk/querier/wideskies/QuerierCLI.java b/src/main/java/org/apache/pirk/querier/wideskies/QuerierCLI.java
index 7cf25b9..ca8693f 100644
--- a/src/main/java/org/apache/pirk/querier/wideskies/QuerierCLI.java
+++ b/src/main/java/org/apache/pirk/querier/wideskies/QuerierCLI.java
@@ -237,13 +237,6 @@
     optionHASHBITSIZE.setType(String.class);
     options.addOption(optionHASHBITSIZE);
 
-    // HASHKEY
-    Option optionHASHKEY = new Option("hk", QuerierProps.HASHKEY, true, "required for encryption -- String key for the keyed hash functionality");
-    optionHASHKEY.setRequired(false);
-    optionHASHKEY.setArgName(QuerierProps.HASHKEY);
-    optionHASHKEY.setType(String.class);
-    options.addOption(optionHASHKEY);
-
     // DATAPARTITIONSIZE
     Option optionDATAPARTITIONSIZE = new Option("dps", QuerierProps.DATAPARTITIONSIZE, true,
         "required for encryption -- Partition bit size in data partitioning");
diff --git a/src/main/java/org/apache/pirk/querier/wideskies/QuerierDriver.java b/src/main/java/org/apache/pirk/querier/wideskies/QuerierDriver.java
index 2baeec5..122a7c4 100644
--- a/src/main/java/org/apache/pirk/querier/wideskies/QuerierDriver.java
+++ b/src/main/java/org/apache/pirk/querier/wideskies/QuerierDriver.java
@@ -84,7 +84,6 @@
 
     // Encryption variables
     int hashBitSize;
-    String hashKey;
     int dataPartitionBitSize;
     int paillierBitSize;
     int certainty;
@@ -103,13 +102,12 @@
     if (action.equals("encrypt"))
     {
       hashBitSize = Integer.parseInt(SystemConfiguration.getProperty(QuerierProps.HASHBITSIZE));
-      hashKey = SystemConfiguration.getProperty(QuerierProps.HASHKEY);
       dataPartitionBitSize = Integer.parseInt(SystemConfiguration.getProperty(QuerierProps.DATAPARTITIONSIZE));
       paillierBitSize = Integer.parseInt(SystemConfiguration.getProperty(QuerierProps.PAILLIERBITSIZE));
       certainty = Integer.parseInt(SystemConfiguration.getProperty(QuerierProps.CERTAINTY));
 
       logger.info("Performing encryption: \n inputFile = " + inputFile + "\n outputFile = " + outputFile + "\n numThreads = " + numThreads + "\n hashBitSize = "
-          + hashBitSize + "\n hashKey = " + hashKey + "\n dataPartitionBitSize = " + dataPartitionBitSize + "\n paillierBitSize = " + paillierBitSize
+          + hashBitSize + "\n dataPartitionBitSize = " + dataPartitionBitSize + "\n paillierBitSize = " + paillierBitSize
           + "\n certainty = " + certainty);
 
       // Read in the selectors and extract the queryIdentifier - first line in the file
diff --git a/src/main/java/org/apache/pirk/querier/wideskies/QuerierFactory.java b/src/main/java/org/apache/pirk/querier/wideskies/QuerierFactory.java
index 709da6d..0f8ecc1 100644
--- a/src/main/java/org/apache/pirk/querier/wideskies/QuerierFactory.java
+++ b/src/main/java/org/apache/pirk/querier/wideskies/QuerierFactory.java
@@ -65,7 +65,6 @@
     String queryType = properties.getProperty(QuerierProps.QUERYTYPE);
     int hashBitSize = Integer.parseInt(properties.getProperty(QuerierProps.HASHBITSIZE));
     int bitSet = Integer.parseInt(properties.getProperty(QuerierProps.BITSET));
-    String hashKey = properties.getProperty(QuerierProps.HASHKEY);
     int dataPartitionBitSize = Integer.parseInt(properties.getProperty(QuerierProps.DATAPARTITIONSIZE));
     int paillierBitSize = Integer.parseInt(properties.getProperty(QuerierProps.PAILLIERBITSIZE));
     int certainty = Integer.parseInt(properties.getProperty(QuerierProps.CERTAINTY));
@@ -90,7 +89,7 @@
     }
 
     // Set the necessary QueryInfo and Paillier objects
-    QueryInfo queryInfo = new QueryInfo(queryIdentifier, numSelectors, hashBitSize, hashKey, dataPartitionBitSize, queryType, useMemLookupTable, embedSelector,
+    QueryInfo queryInfo = new QueryInfo(queryIdentifier, numSelectors, hashBitSize, dataPartitionBitSize, queryType, useMemLookupTable, embedSelector,
         useHDFSLookupTable);
 
     if ("true".equals(properties.getProperty(QuerierProps.EMBEDQUERYSCHEMA, "false")))
diff --git a/src/main/java/org/apache/pirk/querier/wideskies/QuerierProps.java b/src/main/java/org/apache/pirk/querier/wideskies/QuerierProps.java
index b6da06c..397899d 100644
--- a/src/main/java/org/apache/pirk/querier/wideskies/QuerierProps.java
+++ b/src/main/java/org/apache/pirk/querier/wideskies/QuerierProps.java
@@ -42,7 +42,6 @@
 
   // Encryption properties
   static final String HASHBITSIZE = "querier.hashBitSize";
-  static final String HASHKEY = "querier.hashKey";
   static final String DATAPARTITIONSIZE = "querier.dataPartitionBitSize";
   static final String PAILLIERBITSIZE = "querier.paillierBitSize";
   static final String BITSET = "querier.bitSet";
@@ -59,7 +58,7 @@
   // Decryption properties
   static final String QUERIERFILE = "querier.querierFile";
 
-  static final List<String> PROPSLIST = Arrays.asList(ACTION, INPUTFILE, OUTPUTFILE, QUERYTYPE, NUMTHREADS, EMBEDQUERYSCHEMA, HASHBITSIZE, HASHKEY,
+  static final List<String> PROPSLIST = Arrays.asList(ACTION, INPUTFILE, OUTPUTFILE, QUERYTYPE, NUMTHREADS, EMBEDQUERYSCHEMA, HASHBITSIZE,
       DATAPARTITIONSIZE, PAILLIERBITSIZE, BITSET, CERTAINTY, QUERYSCHEMAS, DATASCHEMAS, EMBEDSELECTOR, USEMEMLOOKUPTABLE, USEHDFSLOOKUPTABLE, SR_ALGORITHM,
       SR_PROVIDER);
 
@@ -177,12 +176,6 @@
       valid = false;
     }
 
-    if (!properties.containsKey(HASHKEY))
-    {
-      logger.info("For action='encrypt': Must have the option " + HASHKEY);
-      valid = false;
-    }
-
     if (!properties.containsKey(DATAPARTITIONSIZE))
     {
       logger.info("For action='encrypt': Must have the option " + DATAPARTITIONSIZE);
diff --git a/src/main/java/org/apache/pirk/querier/wideskies/encrypt/EncryptQuery.java b/src/main/java/org/apache/pirk/querier/wideskies/encrypt/EncryptQuery.java
index afa41c5..83ec02c 100644
--- a/src/main/java/org/apache/pirk/querier/wideskies/encrypt/EncryptQuery.java
+++ b/src/main/java/org/apache/pirk/querier/wideskies/encrypt/EncryptQuery.java
@@ -18,6 +18,23 @@
  */
 package org.apache.pirk.querier.wideskies.encrypt;
 
+import org.apache.commons.codec.binary.Hex;
+import org.apache.pirk.encryption.Paillier;
+import org.apache.pirk.querier.wideskies.Querier;
+import org.apache.pirk.query.wideskies.Query;
+import org.apache.pirk.query.wideskies.QueryInfo;
+import org.apache.pirk.query.wideskies.QueryUtils;
+import org.apache.pirk.schema.data.DataSchema;
+import org.apache.pirk.schema.data.DataSchemaRegistry;
+import org.apache.pirk.schema.query.QuerySchema;
+import org.apache.pirk.schema.query.QuerySchemaRegistry;
+import org.apache.pirk.utils.KeyedHash;
+import org.apache.pirk.utils.PIRException;
+import org.apache.pirk.utils.RandomProvider;
+import org.apache.pirk.utils.SystemConfiguration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -32,24 +49,8 @@
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
-import org.apache.pirk.encryption.Paillier;
-import org.apache.pirk.querier.wideskies.Querier;
-import org.apache.pirk.query.wideskies.Query;
-import org.apache.pirk.query.wideskies.QueryInfo;
-import org.apache.pirk.query.wideskies.QueryUtils;
-import org.apache.pirk.schema.data.DataSchema;
-import org.apache.pirk.schema.data.DataSchemaRegistry;
-import org.apache.pirk.schema.query.QuerySchema;
-import org.apache.pirk.schema.query.QuerySchemaRegistry;
-import org.apache.pirk.utils.KeyedHash;
-import org.apache.pirk.utils.PIRException;
-import org.apache.pirk.utils.SystemConfiguration;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 /**
  * Class to perform PIR encryption
- *
  */
 public class EncryptQuery
 {
@@ -66,13 +67,10 @@
 
   /**
    * Constructs a query encryptor using the given query information, selectors, and Paillier cryptosystem.
-   * 
-   * @param queryInfo
-   *          Fundamental information about the query.
-   * @param selectors
-   *          the list of selectors for this query.
-   * @param paillier
-   *          the Paillier cryptosystem to use.
+   *
+   * @param queryInfo Fundamental information about the query.
+   * @param selectors the list of selectors for this query.
+   * @param paillier  the Paillier cryptosystem to use.
    */
   public EncryptQuery(QueryInfo queryInfo, List<String> selectors, Paillier paillier)
   {
@@ -87,12 +85,10 @@
    * The encryption builds a <code>Querier</code> object, calculating and setting the query vectors.
    * <p>
    * Uses the system configured number of threads to conduct the encryption, or a single thread if the configuration has not been set.
-   * 
-   * @throws InterruptedException
-   *           If the task was interrupted during encryption.
-   * @throws PIRException
-   *           If a problem occurs performing the encryption.
+   *
    * @return The querier containing the query, and all information required to perform decryption.
+   * @throws InterruptedException If the task was interrupted during encryption.
+   * @throws PIRException         If a problem occurs performing the encryption.
    */
   public Querier encrypt() throws InterruptedException, PIRException
   {
@@ -110,14 +106,11 @@
    * For encrypted query vector E = <E_0, ..., E_{(2^hashBitSize)-1}>:
    * <p>
    * E_i = 2^{j*dataPartitionBitSize} if i = H_k(selector_j) 0 otherwise
-   * 
-   * @param numThreads
-   *          the number of threads to use when performing the encryption.
-   * @throws InterruptedException
-   *           If the task was interrupted during encryption.
-   * @throws PIRException
-   *           If a problem occurs performing the encryption.
+   *
+   * @param numThreads the number of threads to use when performing the encryption.
    * @return The querier containing the query, and all information required to perform decryption.
+   * @throws InterruptedException If the task was interrupted during encryption.
+   * @throws PIRException         If a problem occurs performing the encryption.
    */
   public Querier encrypt(int numThreads) throws InterruptedException, PIRException
   {
@@ -156,10 +149,22 @@
     return new Querier(selectors, paillier, query, embedSelectorMap);
   }
 
+  /**
+   * Use this method to get a securely generated, random string of 2*numBytes length
+   *
+   * @param numBytes How many bytes of random data to return.
+   * @return Random hex string of 2*numBytes length
+   */
+  private String getRandByteString(int numBytes)
+  {
+    byte[] randomData = new byte[numBytes];
+    RandomProvider.SECURE_RANDOM.nextBytes(randomData);
+    return Hex.encodeHexString(randomData);
+  }
+
   private Map<Integer,Integer> computeSelectorQueryVecMap()
   {
-    String hashKey = queryInfo.getHashKey();
-    int keyCounter = 0;
+    String hashKey = getRandByteString(10);
     int numSelectors = selectors.size();
     Map<Integer,Integer> selectorQueryVecMapping = new HashMap<>(numSelectors);
 
@@ -178,11 +183,14 @@
       {
         // Hash collision
         selectorQueryVecMapping.clear();
-        hashKey = queryInfo.getHashKey() + ++keyCounter;
+        hashKey = getRandByteString(10);
         logger.debug("index = " + index + "selector = " + selector + " hash collision = " + hash + " new key = " + hashKey);
         index = -1;
       }
     }
+
+    // Save off the final hashKey that we ended up using
+    queryInfo.setHashKey(hashKey);
     return selectorQueryVecMapping;
   }
 
diff --git a/src/main/java/org/apache/pirk/query/wideskies/QueryInfo.java b/src/main/java/org/apache/pirk/query/wideskies/QueryInfo.java
index 999bf76..a08819b 100644
--- a/src/main/java/org/apache/pirk/query/wideskies/QueryInfo.java
+++ b/src/main/java/org/apache/pirk/query/wideskies/QueryInfo.java
@@ -87,14 +87,13 @@
   @Expose
   private QuerySchema qSchema = null;
 
-  public QueryInfo(int numSelectorsInput, int hashBitSizeInput, String hashKeyInput, int dataPartitionBitSizeInput, String queryTypeInput,
-      boolean useExpLookupTableInput, boolean embedSelectorInput, boolean useHDFSExpLookupTableInput)
+  public QueryInfo(int numSelectorsInput, int hashBitSizeInput, int dataPartitionBitSizeInput, String queryTypeInput, boolean useExpLookupTableInput, boolean embedSelectorInput, boolean useHDFSExpLookupTableInput)
   {
-    this(UUID.randomUUID(), numSelectorsInput, hashBitSizeInput, hashKeyInput, dataPartitionBitSizeInput, queryTypeInput, useExpLookupTableInput,
+    this(UUID.randomUUID(), numSelectorsInput, hashBitSizeInput, dataPartitionBitSizeInput, queryTypeInput, useExpLookupTableInput,
         embedSelectorInput, useHDFSExpLookupTableInput);
   }
 
-  public QueryInfo(UUID identifierInput, int numSelectorsInput, int hashBitSizeInput, String hashKeyInput, int dataPartitionBitSizeInput, String queryTypeInput,
+  public QueryInfo(UUID identifierInput, int numSelectorsInput, int hashBitSizeInput, int dataPartitionBitSizeInput, String queryTypeInput,
       boolean useExpLookupTableInput, boolean embedSelectorInput, boolean useHDFSExpLookupTableInput)
   {
     identifier = identifierInput;
@@ -103,7 +102,6 @@
     numSelectors = numSelectorsInput;
 
     hashBitSize = hashBitSizeInput;
-    hashKey = hashKeyInput;
 
     useExpLookupTable = useExpLookupTableInput;
     useHDFSExpLookupTable = useHDFSExpLookupTableInput;
@@ -120,6 +118,10 @@
     printQueryInfo();
   }
 
+  /**
+   * This constructor is used for deserialization only. The Hash Key should not be set manually in most cases because EncryptQuery
+   * will overwrite it with a new random one.
+   */
   public QueryInfo(UUID identifierInput, int numSelectorsInput, int hashBitSizeInput, String hashKeyInput, int dataPartitionBitSizeInput, String queryTypeInput,
       boolean useExpLookupTableInput, boolean embedSelectorInput, boolean useHDFSExpLookupTableInput, int numBitsPerDataElementInput,
       QuerySchema querySchemaInput)
@@ -202,6 +204,11 @@
     return hashKey;
   }
 
+  public void setHashKey(String hashKey)
+  {
+    this.hashKey = hashKey;
+  }
+
   public int getNumBitsPerDataElement()
   {
     return numBitsPerDataElement;
diff --git a/src/main/java/org/apache/pirk/test/distributed/testsuite/DistTestSuite.java b/src/main/java/org/apache/pirk/test/distributed/testsuite/DistTestSuite.java
index d02bb87..4cf5211 100644
--- a/src/main/java/org/apache/pirk/test/distributed/testsuite/DistTestSuite.java
+++ b/src/main/java/org/apache/pirk/test/distributed/testsuite/DistTestSuite.java
@@ -31,7 +31,6 @@
 import org.apache.pirk.querier.wideskies.Querier;
 import org.apache.pirk.querier.wideskies.decrypt.DecryptResponse;
 import org.apache.pirk.querier.wideskies.encrypt.EncryptQuery;
-import org.apache.pirk.query.wideskies.Query;
 import org.apache.pirk.query.wideskies.QueryInfo;
 import org.apache.pirk.responder.wideskies.ResponderProps;
 import org.apache.pirk.responder.wideskies.mapreduce.ComputeResponseTool;
@@ -51,7 +50,7 @@
 
 /**
  * Distributed test class for PIR
- * 
+ *
  */
 public class DistTestSuite
 {
@@ -427,7 +426,7 @@
     boolean useHDFSExpLookupTable = SystemConfiguration.getBooleanProperty("pirTest.useHDFSExpLookupTable", false);
 
     // Set the necessary objects
-    QueryInfo queryInfo = new QueryInfo(BaseTests.queryIdentifier, selectors.size(), BaseTests.hashBitSize, BaseTests.hashKey, BaseTests.dataPartitionBitSize,
+    QueryInfo queryInfo = new QueryInfo(BaseTests.queryIdentifier, selectors.size(), BaseTests.hashBitSize, BaseTests.dataPartitionBitSize,
         queryType, useExpLookupTable, embedSelector, useHDFSExpLookupTable);
 
     Paillier paillier = new Paillier(BaseTests.paillierBitSize, BaseTests.certainty);
diff --git a/src/main/java/org/apache/pirk/test/utils/BaseTests.java b/src/main/java/org/apache/pirk/test/utils/BaseTests.java
index bb2ed66..fc85df0 100644
--- a/src/main/java/org/apache/pirk/test/utils/BaseTests.java
+++ b/src/main/java/org/apache/pirk/test/utils/BaseTests.java
@@ -57,7 +57,6 @@
 
   // Encryption variables -- Paillier mechanisms are tested in the Paillier test code, so these are fixed...
   public static final int hashBitSize = 12;
-  public static final String hashKey = "someKey";
   public static final int paillierBitSize = 384;
   public static final int certainty = 128;
 
diff --git a/src/main/java/org/apache/pirk/test/utils/StandaloneQuery.java b/src/main/java/org/apache/pirk/test/utils/StandaloneQuery.java
index 6022f84..847b18b 100644
--- a/src/main/java/org/apache/pirk/test/utils/StandaloneQuery.java
+++ b/src/main/java/org/apache/pirk/test/utils/StandaloneQuery.java
@@ -77,7 +77,7 @@
         + fileResponse.getAbsolutePath() + " fileFinalResults = " + fileFinalResults.getAbsolutePath());
 
     Properties baseTestEncryptionProperties = EncryptionPropertiesBuilder.newBuilder().dataPartitionBitSize(BaseTests.dataPartitionBitSize)
-        .hashBitSize(BaseTests.hashBitSize).hashKey(BaseTests.hashKey).paillierBitSize(BaseTests.paillierBitSize).certainty(BaseTests.certainty)
+        .hashBitSize(BaseTests.hashBitSize).paillierBitSize(BaseTests.paillierBitSize).certainty(BaseTests.certainty)
         .queryType(queryType).build();
 
     Querier querier = QuerierFactory.createQuerier(BaseTests.queryIdentifier, selectors, baseTestEncryptionProperties);
diff --git a/src/main/java/org/apache/pirk/utils/RandomProvider.java b/src/main/java/org/apache/pirk/utils/RandomProvider.java
new file mode 100644
index 0000000..40cba06
--- /dev/null
+++ b/src/main/java/org/apache/pirk/utils/RandomProvider.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.pirk.utils;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.security.GeneralSecurityException;
+import java.security.SecureRandom;
+
+/**
+ * Class that provides access to an existing SecureRandom object.
+ * <p>
+ * SECURE_RANDOM is a globally available SecureRandom instantiated based on the "pallier.secureRandom.algorithm" and "pallier.secureRandom.provider"
+ * configuration variables.
+ * <p>
+ * This is safe because there is no way for a user to make the quality of the generated random worse nor to reveal critical state of the PRNG.
+ * <p>
+ * The two methods that would appear to cause problems <i>but don't</i> are:
+ * <ul>
+ * <li> {@code setSeed} - setSeed doesn't replace the seed in the SecureRandom object but instead "the given seed supplements, rather than replaces, the
+ * existing seed. Thus, repeated calls are guaranteed never to reduce randomness".
+ * <li> {@code getSeed} - getSeed doesn't return the seed of the SecureRandom object but returns new seed material generated with the same seed generation
+ * algorithm used to create the instance.
+ * <p>
+ * </ul>
+ */
+public class RandomProvider
+{
+  public static final SecureRandom SECURE_RANDOM;
+  private static final Logger logger = LoggerFactory.getLogger(RandomProvider.class);
+
+  static
+  {
+    try
+    {
+      String alg = SystemConfiguration.getProperty("pallier.secureRandom.algorithm");
+      if (alg == null)
+      {
+        SECURE_RANDOM = new SecureRandom();
+      }
+      else
+      {
+        String provider = SystemConfiguration.getProperty("pallier.secureRandom.provider");
+        SECURE_RANDOM = (provider == null) ? SecureRandom.getInstance(alg) : SecureRandom.getInstance(alg, provider);
+      }
+      logger.info("Using secure random from " + SECURE_RANDOM.getProvider().getName() + ":" + SECURE_RANDOM.getAlgorithm());
+    } catch (GeneralSecurityException e)
+    {
+      logger.error("Unable to instantiate a SecureRandom object with the requested algorithm.", e);
+      throw new RuntimeException("Unable to instantiate a SecureRandom object with the requested algorithm.", e);
+    }
+  }
+
+  /**
+   * Return a globally available SecureRandom instantiated based on the "pallier.secureRandom.algorithm" and "pallier.secureRandom.provider" configuration
+   * variables.
+   * <p>
+   * This is safe because there is no way for a caller to make the quality of the generated random worse nor to reveal critical state of the PRNG.
+   * <p>
+   * The two methods that would appear to cause problems <i>but don't</i> are:
+   * <ul>
+   * <li> {@code setSeed} - setSeed doesn't replace the seed in the SecureRandom object but instead "the given seed supplements, rather than replaces, the
+   * existing seed. Thus, repeated calls are guaranteed never to reduce randomness".
+   * <li> {@code getSeed} - getSeed doesn't return the seed of the SecureRandom object but returns new seed material generated with the same seed generation
+   * algorithm used to create the instance.
+   * <p>
+   * </ul>
+   *
+   * @return The pre-existing SecureRandom object instantiated based on the "pallier.secureRandom.algorithm" and "pallier.secureRandom.provider"
+   * configuration variables.
+   */
+  public static SecureRandom getSecureRandom()
+  {
+    return SECURE_RANDOM;
+  }
+}
diff --git a/src/main/resources/querier.properties b/src/main/resources/querier.properties
index 15e3acd..e26fb99 100644
--- a/src/main/resources/querier.properties
+++ b/src/main/resources/querier.properties
@@ -79,13 +79,10 @@
 #Whether or not to embed the QuerySchema in the Query (via QueryInfo)
 #Defaults to 'false'
 #querier.embedQuerySchema=
- 
+
 #hashBitSize - required for encryption-- Bit size of keyed hash
 #querier.hashBitSize=
 
-#hashKey -- required for encryption -- String key for the keyed hash functionality
-#querier.hashKey=
-
 #useHDFSLookupTable -- required for encryption -- 'true' or 'false'
 #Whether or not to generate and use a hdfs modular exponentation lookup table
 #Defaults to 'false'
@@ -99,7 +96,7 @@
 
 #paillierBitSize -- required for encryption -- Paillier modulus size N
 #querier.paillierBitSize=
- 
+
 #queryType -- required for encryption
 #Type of the query as defined in the 'schemaName' tag of the corresponding query schema file
 #querier.queryType=
@@ -111,10 +108,9 @@
 #secureRandomProvider -- specify the SecureRandom provider
 #Defaults to SUN
 #querier.secureRandomProvider=
-  
+
 ## Optional, but required for Decryption (ignored if not decrypting)
 
 #querierFile -- required for decryption
 #Fully qualified file containing the serialized Querier object
 #querier.querierFile=
-  
\ No newline at end of file
diff --git a/src/test/java/org/apache/pirk/storm/KafkaStormIntegrationTest.java b/src/test/java/org/apache/pirk/storm/KafkaStormIntegrationTest.java
index 425bb0b..224d94c 100644
--- a/src/test/java/org/apache/pirk/storm/KafkaStormIntegrationTest.java
+++ b/src/test/java/org/apache/pirk/storm/KafkaStormIntegrationTest.java
@@ -301,7 +301,7 @@
 
     nSquared = paillier.getNSquared();
 
-    queryInfo = new QueryInfo(BaseTests.queryIdentifier, selectors.size(), BaseTests.hashBitSize, BaseTests.hashKey, BaseTests.dataPartitionBitSize, queryType,
+    queryInfo = new QueryInfo(BaseTests.queryIdentifier, selectors.size(), BaseTests.hashBitSize, BaseTests.dataPartitionBitSize, queryType,
         false, true, false);
 
     // Perform the encryption