[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