You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by no...@apache.org on 2015/03/04 20:12:54 UTC
svn commit: r1664116 - in /lucene/dev/trunk/solr/core/src:
java/org/apache/solr/cloud/CloudUtil.java
java/org/apache/solr/util/CryptoKeys.java
test/org/apache/solr/cloud/TestCryptoKeys.java
Author: noble
Date: Wed Mar 4 19:12:53 2015
New Revision: 1664116
URL: http://svn.apache.org/r1664116
Log:
SOLR-7126: Utility classes for Crypto
Added:
lucene/dev/trunk/solr/core/src/java/org/apache/solr/util/CryptoKeys.java (with props)
lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/TestCryptoKeys.java (with props)
Modified:
lucene/dev/trunk/solr/core/src/java/org/apache/solr/cloud/CloudUtil.java
Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/cloud/CloudUtil.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/cloud/CloudUtil.java?rev=1664116&r1=1664115&r2=1664116&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/cloud/CloudUtil.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/cloud/CloudUtil.java Wed Mar 4 19:12:53 2015
@@ -19,6 +19,10 @@ package org.apache.solr.cloud;
import java.io.File;
import java.io.IOException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import org.apache.commons.io.FileUtils;
@@ -26,10 +30,12 @@ import org.apache.solr.common.SolrExcept
import org.apache.solr.common.SolrException.ErrorCode;
import org.apache.solr.common.cloud.Replica;
import org.apache.solr.common.cloud.Slice;
+import org.apache.solr.common.cloud.SolrZkClient;
import org.apache.solr.common.cloud.ZkStateReader;
import org.apache.solr.core.CoreContainer;
import org.apache.solr.core.CoreDescriptor;
import org.apache.solr.core.SolrResourceLoader;
+import org.apache.zookeeper.KeeperException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -99,4 +105,27 @@ public class CloudUtil {
((ZkSolrResourceLoader) loader).getConfigSetZkPath() + "/" :
loader.getConfigDir();
}
+
+ /**Read the list of public keys from ZK
+ */
+
+ public static Map<String, byte[]> getTrustedKeys(SolrZkClient zk){
+ Map<String,byte[]> result = new HashMap<>();
+ try {
+ List<String> children = zk.getChildren("/keys", null, true);
+ for (String key : children) {
+ result.put(key, zk.getData("/keys/"+key,null,null,true));
+ }
+ } catch (KeeperException.NoNodeException e) {
+ log.warn("Error fetching key names");
+ return Collections.EMPTY_MAP;
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new SolrException(ErrorCode.SERVER_ERROR,"Unable to read crypto keys",e );
+ } catch (KeeperException e) {
+ throw new SolrException(ErrorCode.SERVER_ERROR,"Unable to read crypto keys",e );
+ }
+ return result;
+
+ }
}
Added: lucene/dev/trunk/solr/core/src/java/org/apache/solr/util/CryptoKeys.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/util/CryptoKeys.java?rev=1664116&view=auto
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/util/CryptoKeys.java (added)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/util/CryptoKeys.java Wed Mar 4 19:12:53 2015
@@ -0,0 +1,107 @@
+package org.apache.solr.util;
+
+/*
+ * 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.
+ */
+
+import java.nio.ByteBuffer;
+import java.security.InvalidKeyException;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.PublicKey;
+import java.security.Signature;
+import java.security.SignatureException;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.solr.common.util.Base64;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**A utility class to verify signatures
+ *
+ */
+public final class CryptoKeys {
+ private static final Logger log = LoggerFactory.getLogger(CryptoKeys.class);
+
+ private final Map<String, PublicKey> keys;
+
+
+ public CryptoKeys(Map<String, byte[]> trustedKeys) throws Exception {
+ HashMap<String, PublicKey> m = new HashMap<>();
+ for (Map.Entry<String, byte[]> e : trustedKeys.entrySet()) {
+ m.put(e.getKey(), getX509PublicKey(e.getValue()));
+
+ }
+ this.keys = m;
+ }
+
+ /**
+ * Try with all signatures and return the name of the signature that matched
+ */
+ public String verify(String sig, byte[] data) {
+
+ for (Map.Entry<String, PublicKey> entry : keys.entrySet()) {
+ boolean verified;
+ try {
+ verified = CryptoKeys.verify(entry.getValue(), Base64.base64ToByteArray(sig), ByteBuffer.wrap(data));
+ log.info("verified {} ", verified);
+ if (verified) return entry.getKey();
+ } catch (Exception e) {
+ log.info("NOT verified ");
+ }
+
+ }
+
+ return null;
+ }
+
+
+ /**
+ * Create PublicKey from a .DER file
+ */
+ public static PublicKey getX509PublicKey(byte[] buf)
+ throws Exception {
+ X509EncodedKeySpec spec = new X509EncodedKeySpec(buf);
+ KeyFactory kf = KeyFactory.getInstance("RSA");
+ return kf.generatePublic(spec);
+ }
+
+ /**
+ * Verify the signature of a file
+ *
+ * @param publicKey the public key used to sign this
+ * @param sig the signature
+ * @param data The data tha is signed
+ */
+ public static boolean verify(PublicKey publicKey, byte[] sig, ByteBuffer data) throws InvalidKeyException, SignatureException {
+ Signature signature = null;
+ try {
+ signature = Signature.getInstance("SHA1withRSA");
+ signature.initVerify(publicKey);
+ signature.update(data);
+ boolean verify = signature.verify(sig);
+ return verify;
+
+ } catch (NoSuchAlgorithmException e) {
+ //will not happen
+ }
+ return false;
+ }
+
+
+}
Added: lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/TestCryptoKeys.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/TestCryptoKeys.java?rev=1664116&view=auto
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/TestCryptoKeys.java (added)
+++ lucene/dev/trunk/solr/core/src/test/org/apache/solr/cloud/TestCryptoKeys.java Wed Mar 4 19:12:53 2015
@@ -0,0 +1,117 @@
+package org.apache.solr.cloud;
+
+/*
+ * 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.
+ */
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Map;
+
+import org.apache.solr.common.cloud.SolrZkClient;
+import org.apache.solr.util.CryptoKeys;
+import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.KeeperException;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class TestCryptoKeys extends AbstractFullDistribZkTestBase {
+ private static final Logger logger = LoggerFactory.getLogger(TestCryptoKeys.class);
+
+
+ @Override
+ public void distribSetUp() throws Exception {
+ super.distribSetUp();
+ System.setProperty("numShards", Integer.toString(sliceCount));
+ }
+
+ public TestCryptoKeys() {
+ super();
+ sliceCount = 1;
+ }
+
+ @Test
+ public void test() throws Exception {
+ String pk1sig = "G8LEW7uJ1is81Aqqfl3Sld3qDtOxPuVFeTLJHFJWecgDvUkmJNFXmf7nkHOVlXnDWahp1vqZf0W02VHXg37lBw==";
+ String pk2sig = "pCyBQycB/0YvLVZfKLDIIqG1tFwM/awqzkp2QNpO7R3ThTqmmrj11wEJFDRLkY79efuFuQPHt40EE7jrOKoj9jLNELsfEqvU3jw9sZKiDONY+rV9Bj9QPeW8Pgt+F9Y1";
+ String wrongKeySig = "xTk2hTipfpb+J5s4x3YZGOXkmHWtnJz05Vvd8RTm/Q1fbQVszR7vMk6dQ1URxX08fcg4HvxOo8g9bG2TSMOGjg==";
+ String result = null;
+ CryptoKeys cryptoKeys = null;
+ SolrZkClient zk = getCommonCloudSolrClient().getZkStateReader().getZkClient();
+ cryptoKeys = new CryptoKeys(CloudUtil.getTrustedKeys(zk));
+ byte[] samplefile = readFile("samplefile.bin");
+ //there are no keys
+
+ result = cryptoKeys.verify( pk1sig,samplefile);
+ assertNull(result);
+
+ zk.makePath("/keys", true);
+
+ createNode(zk, "pubk1.der");
+ createNode(zk, "pubk2.der");
+
+ Map<String, byte[]> trustedKeys = CloudUtil.getTrustedKeys(zk);
+
+
+ cryptoKeys = new CryptoKeys(trustedKeys);
+
+
+ result = cryptoKeys.verify(pk2sig, samplefile);
+ assertEquals("pubk2.der", result);
+
+
+ result = cryptoKeys.verify(pk1sig, samplefile);
+ assertEquals("pubk1.der", result);
+
+ try {
+ result = cryptoKeys.verify(wrongKeySig,samplefile);
+ assertNull(result);
+ } catch (Exception e) {
+ //pass
+ }
+
+
+ try {
+ result = cryptoKeys.verify( "SGVsbG8gV29ybGQhCg==", samplefile);
+ assertNull(result);
+ } catch (Exception e) {
+ //pass
+
+ }
+
+
+ }
+
+
+
+ private void createNode(SolrZkClient zk, String fname) throws IOException, KeeperException, InterruptedException {
+ byte[] buf = readFile(fname);
+ zk.create("/keys/" + fname, buf, CreateMode.PERSISTENT, true);
+
+ }
+
+ private byte[] readFile(String fname) throws IOException {
+ byte[] buf = null;
+ try (FileInputStream fis = new FileInputStream(getFile("cryptokeys/" + fname))) {
+ buf = new byte[fis.available()];
+ fis.read(buf);
+ }
+ return buf;
+ }
+
+
+}