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/05/07 15:33:23 UTC
svn commit: r1678195 - in /lucene/dev/trunk/solr: ./
contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/
contrib/dataimporthandler/src/test/org/apache/solr/handler/dataimport/
core/src/java/org/apache/solr/util/
Author: noble
Date: Thu May 7 13:33:23 2015
New Revision: 1678195
URL: http://svn.apache.org/r1678195
Log:
SOLR-4392: Make it possible to specify AES encrypted password in dataconfig.xml
Modified:
lucene/dev/trunk/solr/CHANGES.txt
lucene/dev/trunk/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/JdbcDataSource.java
lucene/dev/trunk/solr/contrib/dataimporthandler/src/test/org/apache/solr/handler/dataimport/TestJdbcDataSource.java
lucene/dev/trunk/solr/core/src/java/org/apache/solr/util/CryptoKeys.java
Modified: lucene/dev/trunk/solr/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/CHANGES.txt?rev=1678195&r1=1678194&r2=1678195&view=diff
==============================================================================
--- lucene/dev/trunk/solr/CHANGES.txt (original)
+++ lucene/dev/trunk/solr/CHANGES.txt Thu May 7 13:33:23 2015
@@ -169,6 +169,8 @@ New Features
* SOLR-6220: Rule Based Replica Assignment during collection creation (Noble Paul)
+* SOLR-4392: Make it possible to specify AES encrypted password in dataconfig.xml (Noble Paul)
+
Bug Fixes
----------------------
Modified: lucene/dev/trunk/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/JdbcDataSource.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/JdbcDataSource.java?rev=1678195&r1=1678194&r2=1678195&view=diff
==============================================================================
--- lucene/dev/trunk/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/JdbcDataSource.java (original)
+++ lucene/dev/trunk/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/JdbcDataSource.java Thu May 7 13:33:23 2015
@@ -19,12 +19,16 @@ package org.apache.solr.handler.dataimpo
import static org.apache.solr.handler.dataimport.DataImportHandlerException.wrapAndThrow;
import static org.apache.solr.handler.dataimport.DataImportHandlerException.SEVERE;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.util.CryptoKeys;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.naming.InitialContext;
import javax.naming.NamingException;
+import java.io.FileReader;
+import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.*;
@@ -61,6 +65,7 @@ public class JdbcDataSource extends
@Override
public void init(Context context, Properties initProps) {
+ initProps = decryptPwd(initProps);
Object o = initProps.get(CONVERT_TYPE);
if (o != null)
convertType = Boolean.parseBoolean(o.toString());
@@ -101,6 +106,34 @@ public class JdbcDataSource extends
}
}
+ private Properties decryptPwd(Properties initProps) {
+ String encryptionKey = initProps.getProperty("encryptKeyFile");
+ if (initProps.getProperty("password") != null && encryptionKey != null) {
+ // this means the password is encrypted and use the file to decode it
+ try {
+ try (FileReader fr = new FileReader(encryptionKey)) {
+ char[] chars = new char[100];//max 100 char password
+ int len = fr.read(chars);
+ if (len < 6)
+ throw new DataImportHandlerException(SEVERE, "There should be a password of length 6 atleast " + encryptionKey);
+ Properties props = new Properties();
+ props.putAll(initProps);
+ String password = null;
+ try {
+ password = CryptoKeys.decodeAES(initProps.getProperty("password"), new String(chars, 0, len)).trim();
+ } catch (SolrException se) {
+ throw new DataImportHandlerException(SEVERE, "Error decoding password", se.getCause());
+ }
+ props.put("password", password);
+ initProps = props;
+ }
+ } catch (IOException e) {
+ throw new DataImportHandlerException(SEVERE, "Could not load encryptKeyFile " + encryptionKey);
+ }
+ }
+ return initProps;
+ }
+
protected Callable<Connection> createConnectionFactory(final Context context,
final Properties initProps) {
// final VariableResolver resolver = context.getVariableResolver();
@@ -395,7 +428,7 @@ public class JdbcDataSource extends
}
}
- private Connection getConnection() throws Exception {
+ Connection getConnection() throws Exception {
long currTime = System.nanoTime();
if (currTime - connLastUsed > CONN_TIME_OUT) {
synchronized (this) {
Modified: lucene/dev/trunk/solr/contrib/dataimporthandler/src/test/org/apache/solr/handler/dataimport/TestJdbcDataSource.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/contrib/dataimporthandler/src/test/org/apache/solr/handler/dataimport/TestJdbcDataSource.java?rev=1678195&r1=1678194&r2=1678195&view=diff
==============================================================================
--- lucene/dev/trunk/solr/contrib/dataimporthandler/src/test/org/apache/solr/handler/dataimport/TestJdbcDataSource.java (original)
+++ lucene/dev/trunk/solr/contrib/dataimporthandler/src/test/org/apache/solr/handler/dataimport/TestJdbcDataSource.java Thu May 7 13:33:23 2015
@@ -16,6 +16,9 @@
*/
package org.apache.solr.handler.dataimport;
+import java.io.File;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
@@ -123,6 +126,36 @@ public class TestJdbcDataSource extends
mockControl.verify();
+ assertSame("connection", conn, connection);
+ }
+
+ @Test
+ public void testRetrieveFromJndiWithCredentialsWithEncryptedPwd() throws Exception {
+ MockInitialContextFactory.bind("java:comp/env/jdbc/JndiDB", dataSource);
+ File tmpdir = File.createTempFile("test", "tmp", createTempDir().toFile());
+ Files.delete(tmpdir.toPath());
+ tmpdir.mkdir();
+ byte[] content = "secret".getBytes(StandardCharsets.UTF_8);
+ createFile(tmpdir, "enckeyfile.txt", content, false);
+
+ props.put(JdbcDataSource.JNDI_NAME, "java:comp/env/jdbc/JndiDB");
+ props.put("user", "Fred");
+ props.put("encryptKeyFile", new File(tmpdir, "enckeyfile.txt").getAbsolutePath());
+ props.put("password", "U2FsdGVkX18QMjY0yfCqlfBMvAB4d3XkwY96L7gfO2o=");
+ props.put("holdability", "HOLD_CURSORS_OVER_COMMIT");
+ EasyMock.expect(dataSource.getConnection("Fred", "MyPassword")).andReturn(
+ connection);
+ jdbcDataSource.init(context, props);
+
+ connection.setAutoCommit(false);
+ connection.setHoldability(1);
+
+ mockControl.replay();
+
+ Connection conn = jdbcDataSource.getConnection();
+
+ mockControl.verify();
+
assertSame("connection", conn, connection);
}
Modified: 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=1678195&r1=1678194&r2=1678195&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/util/CryptoKeys.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/util/CryptoKeys.java Thu May 7 13:33:23 2015
@@ -17,17 +17,27 @@ package org.apache.solr.util;
* limitations under the License.
*/
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
+import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.X509EncodedKeySpec;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
+import org.apache.solr.common.SolrException;
import org.apache.solr.common.util.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -107,5 +117,139 @@ public final class CryptoKeys {
return false;
}
+ private static byte[][] evpBytesTokey(int key_len, int iv_len, MessageDigest md,
+ byte[] salt, byte[] data, int count) {
+ byte[][] both = new byte[2][];
+ byte[] key = new byte[key_len];
+ int key_ix = 0;
+ byte[] iv = new byte[iv_len];
+ int iv_ix = 0;
+ both[0] = key;
+ both[1] = iv;
+ byte[] md_buf = null;
+ int nkey = key_len;
+ int niv = iv_len;
+ int i = 0;
+ if (data == null) {
+ return both;
+ }
+ int addmd = 0;
+ for (; ; ) {
+ md.reset();
+ if (addmd++ > 0) {
+ md.update(md_buf);
+ }
+ md.update(data);
+ if (null != salt) {
+ md.update(salt, 0, 8);
+ }
+ md_buf = md.digest();
+ for (i = 1; i < count; i++) {
+ md.reset();
+ md.update(md_buf);
+ md_buf = md.digest();
+ }
+ i = 0;
+ if (nkey > 0) {
+ for (; ; ) {
+ if (nkey == 0)
+ break;
+ if (i == md_buf.length)
+ break;
+ key[key_ix++] = md_buf[i];
+ nkey--;
+ i++;
+ }
+ }
+ if (niv > 0 && i != md_buf.length) {
+ for (; ; ) {
+ if (niv == 0)
+ break;
+ if (i == md_buf.length)
+ break;
+ iv[iv_ix++] = md_buf[i];
+ niv--;
+ i++;
+ }
+ }
+ if (nkey == 0 && niv == 0) {
+ break;
+ }
+ }
+ for (i = 0; i < md_buf.length; i++) {
+ md_buf[i] = 0;
+ }
+ return both;
+ }
+
+ public static String decodeAES(String base64CipherTxt, String pwd) {
+ int[] strengths = new int[]{256, 192, 128};
+ Exception e = null;
+ for (int strength : strengths) {
+ try {
+ return decodeAES(base64CipherTxt, pwd, strength);
+ } catch (Exception exp) {
+ e = exp;
+ }
+ }
+ throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Error decoding ", e);
+ }
+
+
+ public static String decodeAES(String base64CipherTxt, String pwd, final int keySizeBits) {
+ final Charset ASCII = Charset.forName("ASCII");
+ final int INDEX_KEY = 0;
+ final int INDEX_IV = 1;
+ final int ITERATIONS = 1;
+ final int SALT_OFFSET = 8;
+ final int SALT_SIZE = 8;
+ final int CIPHERTEXT_OFFSET = SALT_OFFSET + SALT_SIZE;
+
+ try {
+ byte[] headerSaltAndCipherText = Base64.base64ToByteArray(base64CipherTxt);
+
+ // --- extract salt & encrypted ---
+ // header is "Salted__", ASCII encoded, if salt is being used (the default)
+ byte[] salt = Arrays.copyOfRange(
+ headerSaltAndCipherText, SALT_OFFSET, SALT_OFFSET + SALT_SIZE);
+ byte[] encrypted = Arrays.copyOfRange(
+ headerSaltAndCipherText, CIPHERTEXT_OFFSET, headerSaltAndCipherText.length);
+
+ // --- specify cipher and digest for evpBytesTokey method ---
+
+ Cipher aesCBC = Cipher.getInstance("AES/CBC/PKCS5Padding");
+ MessageDigest md5 = MessageDigest.getInstance("MD5");
+
+ // --- create key and IV ---
+
+ // the IV is useless, OpenSSL might as well have use zero's
+ final byte[][] keyAndIV = evpBytesTokey(
+ keySizeBits / Byte.SIZE,
+ aesCBC.getBlockSize(),
+ md5,
+ salt,
+ pwd.getBytes(ASCII),
+ ITERATIONS);
+
+ SecretKeySpec key = new SecretKeySpec(keyAndIV[INDEX_KEY], "AES");
+ IvParameterSpec iv = new IvParameterSpec(keyAndIV[INDEX_IV]);
+
+ // --- initialize cipher instance and decrypt ---
+
+ aesCBC.init(Cipher.DECRYPT_MODE, key, iv);
+ byte[] decrypted = aesCBC.doFinal(encrypted);
+ return new String(decrypted, ASCII);
+ } catch (BadPaddingException e) {
+ // AKA "something went wrong"
+ throw new IllegalStateException(
+ "Bad password, algorithm, mode or padding;" +
+ " no salt, wrong number of iterations or corrupted ciphertext.", e);
+ } catch (IllegalBlockSizeException e) {
+ throw new IllegalStateException(
+ "Bad algorithm, mode or corrupted (resized) ciphertext.", e);
+ } catch (GeneralSecurityException e) {
+ throw new IllegalStateException(e);
+ }
+ }
}
Re: svn commit: r1678195 - in /lucene/dev/trunk/solr: ./
contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/
contrib/dataimporthandler/src/test/org/apache/solr/handler/dataimport/
core/src/java/org/apache/solr/util/
Posted by Chris Hostetter <ho...@fucit.org>.
This violates "ant precommit" because of forbidden API (default charset)
problems.
: Date: Thu, 07 May 2015 13:33:23 -0000
: From: noble@apache.org
: Reply-To: dev@lucene.apache.org
: To: commits@lucene.apache.org
: Subject: svn commit: r1678195 - in /lucene/dev/trunk/solr: ./
: contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/
: contrib/dataimporthandler/src/test/org/apache/solr/handler/dataimport/
: core/src/java/org/apache/solr/util/
:
: Author: noble
: Date: Thu May 7 13:33:23 2015
: New Revision: 1678195
:
: URL: http://svn.apache.org/r1678195
: Log:
: SOLR-4392: Make it possible to specify AES encrypted password in dataconfig.xml
:
: Modified:
: lucene/dev/trunk/solr/CHANGES.txt
: lucene/dev/trunk/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/JdbcDataSource.java
: lucene/dev/trunk/solr/contrib/dataimporthandler/src/test/org/apache/solr/handler/dataimport/TestJdbcDataSource.java
: lucene/dev/trunk/solr/core/src/java/org/apache/solr/util/CryptoKeys.java
:
: Modified: lucene/dev/trunk/solr/CHANGES.txt
: URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/CHANGES.txt?rev=1678195&r1=1678194&r2=1678195&view=diff
: ==============================================================================
: --- lucene/dev/trunk/solr/CHANGES.txt (original)
: +++ lucene/dev/trunk/solr/CHANGES.txt Thu May 7 13:33:23 2015
: @@ -169,6 +169,8 @@ New Features
:
: * SOLR-6220: Rule Based Replica Assignment during collection creation (Noble Paul)
:
: +* SOLR-4392: Make it possible to specify AES encrypted password in dataconfig.xml (Noble Paul)
: +
:
: Bug Fixes
: ----------------------
:
: Modified: lucene/dev/trunk/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/JdbcDataSource.java
: URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/JdbcDataSource.java?rev=1678195&r1=1678194&r2=1678195&view=diff
: ==============================================================================
: --- lucene/dev/trunk/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/JdbcDataSource.java (original)
: +++ lucene/dev/trunk/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/JdbcDataSource.java Thu May 7 13:33:23 2015
: @@ -19,12 +19,16 @@ package org.apache.solr.handler.dataimpo
: import static org.apache.solr.handler.dataimport.DataImportHandlerException.wrapAndThrow;
: import static org.apache.solr.handler.dataimport.DataImportHandlerException.SEVERE;
:
: +import org.apache.solr.common.SolrException;
: +import org.apache.solr.util.CryptoKeys;
: import org.slf4j.Logger;
: import org.slf4j.LoggerFactory;
:
: import javax.naming.InitialContext;
: import javax.naming.NamingException;
:
: +import java.io.FileReader;
: +import java.io.IOException;
: import java.math.BigDecimal;
: import java.math.BigInteger;
: import java.sql.*;
: @@ -61,6 +65,7 @@ public class JdbcDataSource extends
:
: @Override
: public void init(Context context, Properties initProps) {
: + initProps = decryptPwd(initProps);
: Object o = initProps.get(CONVERT_TYPE);
: if (o != null)
: convertType = Boolean.parseBoolean(o.toString());
: @@ -101,6 +106,34 @@ public class JdbcDataSource extends
: }
: }
:
: + private Properties decryptPwd(Properties initProps) {
: + String encryptionKey = initProps.getProperty("encryptKeyFile");
: + if (initProps.getProperty("password") != null && encryptionKey != null) {
: + // this means the password is encrypted and use the file to decode it
: + try {
: + try (FileReader fr = new FileReader(encryptionKey)) {
: + char[] chars = new char[100];//max 100 char password
: + int len = fr.read(chars);
: + if (len < 6)
: + throw new DataImportHandlerException(SEVERE, "There should be a password of length 6 atleast " + encryptionKey);
: + Properties props = new Properties();
: + props.putAll(initProps);
: + String password = null;
: + try {
: + password = CryptoKeys.decodeAES(initProps.getProperty("password"), new String(chars, 0, len)).trim();
: + } catch (SolrException se) {
: + throw new DataImportHandlerException(SEVERE, "Error decoding password", se.getCause());
: + }
: + props.put("password", password);
: + initProps = props;
: + }
: + } catch (IOException e) {
: + throw new DataImportHandlerException(SEVERE, "Could not load encryptKeyFile " + encryptionKey);
: + }
: + }
: + return initProps;
: + }
: +
: protected Callable<Connection> createConnectionFactory(final Context context,
: final Properties initProps) {
: // final VariableResolver resolver = context.getVariableResolver();
: @@ -395,7 +428,7 @@ public class JdbcDataSource extends
: }
: }
:
: - private Connection getConnection() throws Exception {
: + Connection getConnection() throws Exception {
: long currTime = System.nanoTime();
: if (currTime - connLastUsed > CONN_TIME_OUT) {
: synchronized (this) {
:
: Modified: lucene/dev/trunk/solr/contrib/dataimporthandler/src/test/org/apache/solr/handler/dataimport/TestJdbcDataSource.java
: URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/contrib/dataimporthandler/src/test/org/apache/solr/handler/dataimport/TestJdbcDataSource.java?rev=1678195&r1=1678194&r2=1678195&view=diff
: ==============================================================================
: --- lucene/dev/trunk/solr/contrib/dataimporthandler/src/test/org/apache/solr/handler/dataimport/TestJdbcDataSource.java (original)
: +++ lucene/dev/trunk/solr/contrib/dataimporthandler/src/test/org/apache/solr/handler/dataimport/TestJdbcDataSource.java Thu May 7 13:33:23 2015
: @@ -16,6 +16,9 @@
: */
: package org.apache.solr.handler.dataimport;
:
: +import java.io.File;
: +import java.nio.charset.StandardCharsets;
: +import java.nio.file.Files;
: import java.sql.Connection;
: import java.sql.Driver;
: import java.sql.DriverManager;
: @@ -123,6 +126,36 @@ public class TestJdbcDataSource extends
:
: mockControl.verify();
:
: + assertSame("connection", conn, connection);
: + }
: +
: + @Test
: + public void testRetrieveFromJndiWithCredentialsWithEncryptedPwd() throws Exception {
: + MockInitialContextFactory.bind("java:comp/env/jdbc/JndiDB", dataSource);
: + File tmpdir = File.createTempFile("test", "tmp", createTempDir().toFile());
: + Files.delete(tmpdir.toPath());
: + tmpdir.mkdir();
: + byte[] content = "secret".getBytes(StandardCharsets.UTF_8);
: + createFile(tmpdir, "enckeyfile.txt", content, false);
: +
: + props.put(JdbcDataSource.JNDI_NAME, "java:comp/env/jdbc/JndiDB");
: + props.put("user", "Fred");
: + props.put("encryptKeyFile", new File(tmpdir, "enckeyfile.txt").getAbsolutePath());
: + props.put("password", "U2FsdGVkX18QMjY0yfCqlfBMvAB4d3XkwY96L7gfO2o=");
: + props.put("holdability", "HOLD_CURSORS_OVER_COMMIT");
: + EasyMock.expect(dataSource.getConnection("Fred", "MyPassword")).andReturn(
: + connection);
: + jdbcDataSource.init(context, props);
: +
: + connection.setAutoCommit(false);
: + connection.setHoldability(1);
: +
: + mockControl.replay();
: +
: + Connection conn = jdbcDataSource.getConnection();
: +
: + mockControl.verify();
: +
: assertSame("connection", conn, connection);
: }
:
:
: Modified: 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=1678195&r1=1678194&r2=1678195&view=diff
: ==============================================================================
: --- lucene/dev/trunk/solr/core/src/java/org/apache/solr/util/CryptoKeys.java (original)
: +++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/util/CryptoKeys.java Thu May 7 13:33:23 2015
: @@ -17,17 +17,27 @@ package org.apache.solr.util;
: * limitations under the License.
: */
:
: +import javax.crypto.BadPaddingException;
: +import javax.crypto.Cipher;
: +import javax.crypto.IllegalBlockSizeException;
: +import javax.crypto.spec.IvParameterSpec;
: +import javax.crypto.spec.SecretKeySpec;
: import java.nio.ByteBuffer;
: +import java.nio.charset.Charset;
: +import java.security.GeneralSecurityException;
: import java.security.InvalidKeyException;
: import java.security.KeyFactory;
: +import java.security.MessageDigest;
: import java.security.NoSuchAlgorithmException;
: import java.security.PublicKey;
: import java.security.Signature;
: import java.security.SignatureException;
: import java.security.spec.X509EncodedKeySpec;
: +import java.util.Arrays;
: import java.util.HashMap;
: import java.util.Map;
:
: +import org.apache.solr.common.SolrException;
: import org.apache.solr.common.util.Base64;
: import org.slf4j.Logger;
: import org.slf4j.LoggerFactory;
: @@ -107,5 +117,139 @@ public final class CryptoKeys {
: return false;
: }
:
: + private static byte[][] evpBytesTokey(int key_len, int iv_len, MessageDigest md,
: + byte[] salt, byte[] data, int count) {
: + byte[][] both = new byte[2][];
: + byte[] key = new byte[key_len];
: + int key_ix = 0;
: + byte[] iv = new byte[iv_len];
: + int iv_ix = 0;
: + both[0] = key;
: + both[1] = iv;
: + byte[] md_buf = null;
: + int nkey = key_len;
: + int niv = iv_len;
: + int i = 0;
: + if (data == null) {
: + return both;
: + }
: + int addmd = 0;
: + for (; ; ) {
: + md.reset();
: + if (addmd++ > 0) {
: + md.update(md_buf);
: + }
: + md.update(data);
: + if (null != salt) {
: + md.update(salt, 0, 8);
: + }
: + md_buf = md.digest();
: + for (i = 1; i < count; i++) {
: + md.reset();
: + md.update(md_buf);
: + md_buf = md.digest();
: + }
: + i = 0;
: + if (nkey > 0) {
: + for (; ; ) {
: + if (nkey == 0)
: + break;
: + if (i == md_buf.length)
: + break;
: + key[key_ix++] = md_buf[i];
: + nkey--;
: + i++;
: + }
: + }
: + if (niv > 0 && i != md_buf.length) {
: + for (; ; ) {
: + if (niv == 0)
: + break;
: + if (i == md_buf.length)
: + break;
: + iv[iv_ix++] = md_buf[i];
: + niv--;
: + i++;
: + }
: + }
: + if (nkey == 0 && niv == 0) {
: + break;
: + }
: + }
: + for (i = 0; i < md_buf.length; i++) {
: + md_buf[i] = 0;
: + }
: + return both;
: + }
: +
: + public static String decodeAES(String base64CipherTxt, String pwd) {
: + int[] strengths = new int[]{256, 192, 128};
: + Exception e = null;
: + for (int strength : strengths) {
: + try {
: + return decodeAES(base64CipherTxt, pwd, strength);
: + } catch (Exception exp) {
: + e = exp;
: + }
: + }
: + throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Error decoding ", e);
: + }
: +
: +
: + public static String decodeAES(String base64CipherTxt, String pwd, final int keySizeBits) {
: + final Charset ASCII = Charset.forName("ASCII");
: + final int INDEX_KEY = 0;
: + final int INDEX_IV = 1;
: + final int ITERATIONS = 1;
: + final int SALT_OFFSET = 8;
: + final int SALT_SIZE = 8;
: + final int CIPHERTEXT_OFFSET = SALT_OFFSET + SALT_SIZE;
: +
: + try {
: + byte[] headerSaltAndCipherText = Base64.base64ToByteArray(base64CipherTxt);
: +
: + // --- extract salt & encrypted ---
: + // header is "Salted__", ASCII encoded, if salt is being used (the default)
: + byte[] salt = Arrays.copyOfRange(
: + headerSaltAndCipherText, SALT_OFFSET, SALT_OFFSET + SALT_SIZE);
: + byte[] encrypted = Arrays.copyOfRange(
: + headerSaltAndCipherText, CIPHERTEXT_OFFSET, headerSaltAndCipherText.length);
: +
: + // --- specify cipher and digest for evpBytesTokey method ---
: +
: + Cipher aesCBC = Cipher.getInstance("AES/CBC/PKCS5Padding");
: + MessageDigest md5 = MessageDigest.getInstance("MD5");
: +
: + // --- create key and IV ---
: +
: + // the IV is useless, OpenSSL might as well have use zero's
: + final byte[][] keyAndIV = evpBytesTokey(
: + keySizeBits / Byte.SIZE,
: + aesCBC.getBlockSize(),
: + md5,
: + salt,
: + pwd.getBytes(ASCII),
: + ITERATIONS);
: +
: + SecretKeySpec key = new SecretKeySpec(keyAndIV[INDEX_KEY], "AES");
: + IvParameterSpec iv = new IvParameterSpec(keyAndIV[INDEX_IV]);
: +
: + // --- initialize cipher instance and decrypt ---
: +
: + aesCBC.init(Cipher.DECRYPT_MODE, key, iv);
: + byte[] decrypted = aesCBC.doFinal(encrypted);
: + return new String(decrypted, ASCII);
: + } catch (BadPaddingException e) {
: + // AKA "something went wrong"
: + throw new IllegalStateException(
: + "Bad password, algorithm, mode or padding;" +
: + " no salt, wrong number of iterations or corrupted ciphertext.", e);
: + } catch (IllegalBlockSizeException e) {
: + throw new IllegalStateException(
: + "Bad algorithm, mode or corrupted (resized) ciphertext.", e);
: + } catch (GeneralSecurityException e) {
: + throw new IllegalStateException(e);
: + }
: + }
:
: }
:
:
:
-Hoss
http://www.lucidworks.com/
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@lucene.apache.org
For additional commands, e-mail: dev-help@lucene.apache.org