Changed metadata encryption to have a new dictionary type: d:encrypted

- Properties have to be encrypted and decrypted in code using MetadataEncryptor ('metadataEncryptor')
   - No conversion, encryption or decryption is done by Alfresco
   - Unencrypted values cannot be persisted and get thrown out
   - ALF-8646: RINF 38: Text data encryption
   - ALF-8956: RINF 38: Encryption key password specified by installer
   - ALF-9055: RINF 38: Support encryption against existing data


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@28480 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2011-06-20 11:50:37 +00:00
parent dc3139bef7
commit 1714397cac
31 changed files with 426 additions and 456 deletions

View File

@@ -176,14 +176,57 @@ public abstract class AbstractEncryptor implements Encryptor
}
@Override
public SealedObject sealObject(String keyAlias, AlgorithmParameters params, Serializable input)
public Serializable sealObject(String keyAlias, AlgorithmParameters params, Serializable input)
{
throw new UnsupportedOperationException();
if (input == null)
{
return null;
}
Cipher cipher = getCipher(keyAlias, params, Cipher.ENCRYPT_MODE);
if (cipher == null)
{
return input;
}
try
{
return new SealedObject(input, cipher);
}
catch (Exception e)
{
throw new AlfrescoRuntimeException("Failed to seal object", e);
}
}
@Override
public Serializable unsealObject(String keyAlias, SealedObject input)
public Serializable unsealObject(String keyAlias, Serializable input)
{
throw new UnsupportedOperationException();
}
if (input == null)
{
return input;
}
// Don't unseal it if it is not sealed
if (!(input instanceof SealedObject))
{
return input;
}
// Get the Key, rather than a Cipher
Key key = keyProvider.getKey(keyAlias);
if (key == null)
{
// The client will be expecting to unseal the object
throw new IllegalStateException("No key matching " + keyAlias + ". Cannot unseal object.");
}
// Unseal it using the key
SealedObject sealedInput = (SealedObject) input;
try
{
Serializable output = (Serializable) sealedInput.getObject(key);
// Done
return output;
}
catch (Exception e)
{
throw new AlfrescoRuntimeException("Failed to unseal object", e);
}
}
}

View File

@@ -1,21 +1,17 @@
package org.alfresco.repo.security.encryption;
import java.security.Key;
import org.alfresco.util.ParameterCheck;
/**
* Basic support for key providers
* <p/>
* TODO: This class will provide the alias name mapping so that use-cases can be mapped
* to different alias names in the keystore.
*
* @author Derek Hulley
* @since 4.0
*/
public abstract class AbstractKeyProvider implements KeyProvider
{
@Override
public Key getKey(AlfrescoKeyAlias keyAlias)
{
ParameterCheck.mandatory("keyAlias", keyAlias);
return getKey(keyAlias.name());
}
/*
* Not a useless class.
*/
}

View File

@@ -4,7 +4,6 @@ import java.io.Serializable;
import java.security.AlgorithmParameters;
import javax.crypto.Cipher;
import javax.crypto.SealedObject;
import org.alfresco.util.Pair;
@@ -64,23 +63,31 @@ public interface Encryptor
Object decryptObject(String keyAlias, AlgorithmParameters params, byte[] input);
/**
* Convenience method to seal on object up cryptographically
* Convenience method to seal on object up cryptographically.
* <p/>
* Note that the original object may be returned directly if there is no key associated with
* the alias.
*
* @param keyAlias the encryption key alias
* @param input the object to encrypt and seal
* @return the sealed object that can be decrypted with the original key
*/
SealedObject sealObject(String keyAlias, AlgorithmParameters params, Serializable input);
Serializable sealObject(String keyAlias, AlgorithmParameters params, Serializable input);
/**
* Convenience method to unseal on object up cryptographically.
* Convenience method to unseal on object sealed up cryptographically.
* <p/>
* Note that the algorithm parameters are stored in the sealed object and are
* not therefore required for decryption.
* Note that the algorithm parameters not provided on the assumption that a symmetric key
* algorithm is in use - only the key is required for unsealing.
* <p/>
* Note that the original object may be returned directly if there is no key associated with
* the alias or if the input object is not a <code>SealedObject</code>.
*
* @param keyAlias the encryption key alias
* @param input the object to decrypt and unseal
* @return the original unsealed object that was encrypted with the original key
* @throws IllegalStateException if the key alias is not valid <b>and</b> the input is a
* <tt>SealedObject</tt>
*/
Serializable unsealObject(String keyAlias, SealedObject input);
Serializable unsealObject(String keyAlias, Serializable input);
}

View File

@@ -1,5 +1,6 @@
package org.alfresco.repo.security.encryption;
import java.io.Serializable;
import java.security.AlgorithmParameters;
import junit.framework.TestCase;
@@ -58,4 +59,13 @@ public class EncryptorTest extends TestCase
encryptedPair.getFirst());
assertEquals("Encryption round trip failed. ", testObject, output);
}
public void testSealedObject()
{
Serializable testObject = " This is a string, but will be serialized ";
Serializable sealedObject = encryptor.sealObject("mykey2", null, testObject);
Object output = encryptor.unsealObject("mykey2", sealedObject);
assertEquals("Encryption round trip failed. ", testObject, output);
}
}

View File

@@ -9,17 +9,15 @@ import java.security.Key;
*/
public interface KeyProvider
{
// TODO: Allow the aliases to be configured i.e. include an alias mapper
/**
* Enumeration of key aliases supported internally by Alfresco
*
* @author derekh
* @since 4.0
* Constant representing the keystore alias for keys to encrypt/decrype node metadata
*/
public static enum AlfrescoKeyAlias
{
METADATA,
SOLR
}
public static final String ALIAS_METADATA = "metadata";
/**
* Constant representing the keystore alias for keys to encrypt/decrype SOLR transfer data
*/
public static final String ALIAS_SOLR = "solr";
/**
* Get an encryption key if available.
@@ -28,12 +26,4 @@ public interface KeyProvider
* @return the encryption key or <tt>null</tt> if there is no associated key
*/
public Key getKey(String keyAlias);
/**
* Get an encryption key if available, using a convenience constant.
*
* @param keyAlias the key alias
* @return the encryption key or <tt>null</tt> if there is no associated key
*/
public Key getKey(AlfrescoKeyAlias keyAlias);
}

View File

@@ -28,12 +28,11 @@ public class KeyStoreKeyProviderTest extends TestCase
private static final String ALIAS_TWO = "mykey2";
private static final String ALIAS_THREE = "mykey3";
public void setUp() throws Exception
{
}
/**
* Helper utility to create a two-alias keystore.
* <p/>
* TODO: Allow the required aliases and key types to be specified and generate
* a keystore on the fly
*/
/* package */ static KeystoreKeyProvider getTestKeyStoreProvider()
{
@@ -49,6 +48,10 @@ public class KeyStoreKeyProviderTest extends TestCase
return ks;
}
public void setUp() throws Exception
{
}
public void testNoKeyStorePasswords() throws Exception
{
KeystoreKeyProvider keyProvider = new KeystoreKeyProvider(