Skip to content

Commit

Permalink
Improved PR about encryption at rest
Browse files Browse the repository at this point in the history
  • Loading branch information
lvca committed Aug 11, 2015
1 parent ddf047a commit 139f403
Show file tree
Hide file tree
Showing 14 changed files with 370 additions and 320 deletions.
@@ -1,26 +1,29 @@
/* /*
* *
* * Copyright 2014 Orient Technologies LTD (info(at)orientechnologies.com) * * Copyright 2014 Orient Technologies LTD (info(at)orientechnologies.com)
* * * *
* * Licensed under the Apache License, Version 2.0 (the "License"); * * Licensed under the Apache License, Version 2.0 (the "License");
* * you may not use this file except in compliance with the License. * * you may not use this file except in compliance with the License.
* * You may obtain a copy of the License at * * You may obtain a copy of the License at
* * * *
* * http://www.apache.org/licenses/LICENSE-2.0 * * http://www.apache.org/licenses/LICENSE-2.0
* * * *
* * Unless required by applicable law or agreed to in writing, software * * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, * * distributed under the License is distributed on an "AS IS" BASIS,
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and * * See the License for the specific language governing permissions and
* * limitations under the License. * * limitations under the License.
* * * *
* * For more information: http://www.orientechnologies.com * * For more information: http://www.orientechnologies.com
* *
*/ */


package com.orientechnologies.orient.core.compression; package com.orientechnologies.orient.core.compression;


/** /**
* Interface for compression. This interface is used to compress/uncompress at storage level. This can be used also to implement
* encryption at rest.
*
* @author Andrey Lomakin * @author Andrey Lomakin
* @since 05.06.13 * @since 05.06.13
*/ */
Expand Down
@@ -1,29 +1,25 @@
/* /*
* *
* * Copyright 2014 Orient Technologies LTD (info(at)orientechnologies.com) * * Copyright 2014 Orient Technologies LTD (info(at)orientechnologies.com)
* * * *
* * Licensed under the Apache License, Version 2.0 (the "License"); * * Licensed under the Apache License, Version 2.0 (the "License");
* * you may not use this file except in compliance with the License. * * you may not use this file except in compliance with the License.
* * You may obtain a copy of the License at * * You may obtain a copy of the License at
* * * *
* * http://www.apache.org/licenses/LICENSE-2.0 * * http://www.apache.org/licenses/LICENSE-2.0
* * * *
* * Unless required by applicable law or agreed to in writing, software * * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, * * distributed under the License is distributed on an "AS IS" BASIS,
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and * * See the License for the specific language governing permissions and
* * limitations under the License. * * limitations under the License.
* * * *
* * For more information: http://www.orientechnologies.com * * For more information: http://www.orientechnologies.com
* *
*/ */


package com.orientechnologies.orient.core.compression; package com.orientechnologies.orient.core.compression;


import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import com.orientechnologies.orient.core.compression.impl.OAESCompression; import com.orientechnologies.orient.core.compression.impl.OAESCompression;
import com.orientechnologies.orient.core.compression.impl.ODESCompression; import com.orientechnologies.orient.core.compression.impl.ODESCompression;
import com.orientechnologies.orient.core.compression.impl.OGZIPCompression; import com.orientechnologies.orient.core.compression.impl.OGZIPCompression;
Expand All @@ -32,6 +28,10 @@
import com.orientechnologies.orient.core.compression.impl.ONothingCompression; import com.orientechnologies.orient.core.compression.impl.ONothingCompression;
import com.orientechnologies.orient.core.compression.impl.OSnappyCompression; import com.orientechnologies.orient.core.compression.impl.OSnappyCompression;


import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/** /**
* @author Andrey Lomakin * @author Andrey Lomakin
* @since 05.06.13 * @since 05.06.13
Expand All @@ -42,24 +42,33 @@ public class OCompressionFactory {
private final Map<String, OCompression> compressions = new HashMap<String, OCompression>(); private final Map<String, OCompression> compressions = new HashMap<String, OCompression>();


public OCompressionFactory() { public OCompressionFactory() {
register(OHighZIPCompression.INSTANCE); init();
register(OLowZIPCompression.INSTANCE); }
register(OGZIPCompression.INSTANCE);
register(OSnappyCompression.INSTANCE); public void init() {
register(ONothingCompression.INSTANCE); compressions.clear();
register(ODESCompression.INSTANCE); register(new OHighZIPCompression());
register(OAESCompression.INSTANCE); register(new OLowZIPCompression());
register(new OGZIPCompression());
register(new OSnappyCompression());
register(new ONothingCompression());
register(new ODESCompression());
register(new OAESCompression());
}

public void reinit() {
init();
} }


public OCompression getCompression(String name) { public OCompression getCompression(final String name) {
OCompression compression = compressions.get(name); final OCompression compression = compressions.get(name);
if (compression == null) if (compression == null)
throw new IllegalArgumentException("Compression with name " + name + " is absent."); throw new IllegalArgumentException("Compression with name '" + name + "' is absent.");


return compression; return compression;
} }


public void register(OCompression compression) { public void register(final OCompression compression) {
if (compressions.containsKey(compression.name())) if (compressions.containsKey(compression.name()))
throw new IllegalArgumentException("Compression with name " + compression.name() + " was already registered."); throw new IllegalArgumentException("Compression with name " + compression.name() + " was already registered.");


Expand Down
@@ -1,81 +1,76 @@
package com.orientechnologies.orient.core.compression.impl; package com.orientechnologies.orient.core.compression.impl;


import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;

import com.orientechnologies.orient.core.config.OGlobalConfiguration; import com.orientechnologies.orient.core.config.OGlobalConfiguration;
import com.orientechnologies.orient.core.exception.OSecurityException; import com.orientechnologies.orient.core.exception.OSecurityException;
import com.orientechnologies.orient.core.exception.OStorageException;
import com.orientechnologies.orient.core.serialization.OBase64Utils; import com.orientechnologies.orient.core.serialization.OBase64Utils;


import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

/*** /***
* @see https://github.com/orientechnologies/orientdb/issues/89 * Compression implementation that encrypt the content using AES
* * (https://docs.oracle.com/javase/7/docs/technotes/guides/security/SunProviders.html). Issue
* @see https://docs.oracle.com/javase/7/docs/technotes/guides/security/SunProviders.html * https://github.com/orientechnologies/orientdb/issues/89.
* *
* @author giastfader * @author giastfader
* *
*/ */
public class OAESCompression extends OAbstractEncryptedCompression { public class OAESCompression extends OAbstractEncryptedCompression {
private byte[] key; // @see https://docs.oracle.com/javase/7/docs/technotes/guides/security/SunProviders.html#SunJCEProvider

private final String TRANSFORMATION = "AES/ECB/PKCS5Padding"; // we use ECB because we cannot store the
//@see https://docs.oracle.com/javase/7/docs/technotes/guides/security/SunProviders.html#SunJCEProvider private final String ALGORITHM_NAME = "AES";
private final String transformation="AES/ECB/PKCS5Padding"; //we use ECB because we cannot store the Initialization Vector
private final String algorithmName="AES"; private final SecretKeySpec theKey;

private final Cipher cipher;


private boolean initialized; private boolean initialized = false;



public static final String NAME = "aes-encrypted";
public static final OAESCompression INSTANCE = new OAESCompression();
public static final String NAME = "aes-encrypted"; @Override

public String name() {
@Override return NAME;
public String name() { }
return NAME;
} public OAESCompression() {

initialized = false;
protected OAESCompression(){
super(); final String configuredKey = OGlobalConfiguration.STORAGE_ENCRYPTION_AES_KEY.getValueAsString();
}

if (configuredKey == null)
protected void init() { throw new OStorageException("AES compression has been selected, but no key was found. Please configure '"
initialized=false; + OGlobalConfiguration.STORAGE_ENCRYPTION_AES_KEY.getKey() + "' setting or remove AES compression by setting '"
key = OBase64Utils.decode(OGlobalConfiguration.STORAGE_ENCRYPTION_AES_KEY.getValueAsString()); + OGlobalConfiguration.STORAGE_COMPRESSION_METHOD.getKey() + "=nothing'");
SecretKeySpec ks = new SecretKeySpec(key, algorithmName); //AES
try { try {
Cipher cipher = Cipher.getInstance(transformation); final byte[] key = OBase64Utils.decode(configuredKey);
cipher.init(Cipher.ENCRYPT_MODE, ks);
} catch (NoSuchAlgorithmException e) { theKey = new SecretKeySpec(key, ALGORITHM_NAME); // AES
throw new OSecurityException("The AES alghorithm is not available on this platform",e); cipher = Cipher.getInstance(TRANSFORMATION);
} catch (NoSuchPaddingException e) {
throw new OSecurityException(e.getMessage(),e); } catch (Exception e) {
} catch (InvalidKeyException e) { throw new OSecurityException(
throw new OSecurityException("Invalid AES key.",e); "Cannot initialize AES encryption with current key. Assure the key is a BASE64 - 128 oe 256 bits long", e);
}
this.initialized=true; }
}

this.initialized = true;
public byte[] encryptOrDecrypt(int mode, byte[] input, int offset, int length) throws Throwable { }
if (!initialized) throw new OSecurityException("aes-encrypted compression is not available");

public byte[] encryptOrDecrypt(final int mode, final byte[] input, final int offset, final int length) throws Throwable {
SecretKeySpec ks = new SecretKeySpec(key, algorithmName); if (!initialized)
Cipher cipher = Cipher.getInstance(transformation); throw new OSecurityException("AES encryption algorithm is not available");
cipher.init(mode, ks);

cipher.init(mode, theKey);
byte[] content;
if (offset==0 && length==input.length){ final byte[] content;
content=input; if (offset == 0 && length == input.length) {
}else{ content = input;
content = new byte[length]; } else {
System.arraycopy(input,offset,content,0,length); content = new byte[length];
} System.arraycopy(input, offset, content, 0, length);
byte[] output=cipher.doFinal(content); }
return output; return cipher.doFinal(content);
} }


} }
@@ -1,58 +1,50 @@
package com.orientechnologies.orient.core.compression.impl; package com.orientechnologies.orient.core.compression.impl;


import javax.crypto.Cipher;

import com.orientechnologies.orient.core.exception.OSecurityException; import com.orientechnologies.orient.core.exception.OSecurityException;


import javax.crypto.Cipher;

/*** /***
* @see https://github.com/orientechnologies/orientdb/issues/89 * Abstract compression implementation for encryption
* * (https://docs.oracle.com/javase/7/docs/technotes/guides/security/SunProviders.html). See
* @see https://docs.oracle.com/javase/7/docs/technotes/guides/security/SunProviders.html * https://github.com/orientechnologies/orientdb/issues/89
* *
* @author giastfader * @author giastfader
* *
*/ */
public abstract class OAbstractEncryptedCompression extends OAbstractCompression { public abstract class OAbstractEncryptedCompression extends OAbstractCompression {


@Override @Override
public abstract String name(); public abstract String name();


protected OAbstractEncryptedCompression(){ @Override
this.init(); public byte[] compress(final byte[] content, final int offset, final int length) {
} try {

return encryptOrDecrypt(Cipher.ENCRYPT_MODE, content, offset, length);
protected abstract void init(); } catch (Throwable e) {

throw new OSecurityException("Cannot encrypt content", e);

}
@Override };
public byte[] compress(byte[] content, int offset, int length){
try { @Override
byte[] encriptedContent = encryptOrDecrypt(Cipher.ENCRYPT_MODE,content, offset, length); public byte[] uncompress(final byte[] content, final int offset, final int length) {
return encriptedContent; try {
} catch (Throwable e) { return encryptOrDecrypt(Cipher.DECRYPT_MODE, content, offset, length);
throw new OSecurityException(e.getMessage(),e); } catch (Throwable e) {
} throw new OSecurityException("Cannot decrypt content", e);
}; }

};
@Override
public byte[] uncompress(byte[] content, int offset, int length){ /***
try { *
byte[] decriptedContent = encryptOrDecrypt(Cipher.DECRYPT_MODE,content, offset, length); * @param mode
return decriptedContent; * it can be Cipher.ENCRYPT_MODE or Cipher.DECRYPT_MODE
} catch (Throwable e) { * @param input
throw new OSecurityException(e.getMessage(),e); * @param offset
} * @param length
}; * @return

* @throws Throwable
/*** */
* public abstract byte[] encryptOrDecrypt(int mode, byte[] input, int offset, int length) throws Throwable;
* @param mode it can be Cipher.ENCRYPT_MODE or Cipher.DECRYPT_MODE
* @param input
* @param offset
* @param length
* @return
* @throws Throwable
*/
public abstract byte[] encryptOrDecrypt(int mode, byte[] input, int offset, int length) throws Throwable;


} }

0 comments on commit 139f403

Please sign in to comment.