/*
* Copyright [2006] [University Corporation for Advanced Internet Development, Inc.]
*
* Licensed 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.opensaml.saml2.encryption;
import java.util.ArrayList;
import java.util.List;
import org.opensaml.common.BaseTestCase;
import org.opensaml.saml2.core.Assertion;
import org.opensaml.saml2.core.Attribute;
import org.opensaml.saml2.core.EncryptedAssertion;
import org.opensaml.saml2.core.EncryptedAttribute;
import org.opensaml.saml2.core.EncryptedID;
import org.opensaml.saml2.core.NameID;
import org.opensaml.saml2.core.NewEncryptedID;
import org.opensaml.saml2.core.NewID;
import org.opensaml.xml.XMLObject;
import org.opensaml.xml.encryption.EncryptionConstants;
import org.opensaml.xml.encryption.EncryptionException;
import org.opensaml.xml.encryption.EncryptionParameters;
import org.opensaml.xml.encryption.KeyEncryptionParameters;
import org.opensaml.xml.security.SecurityTestHelper;
import org.opensaml.xml.security.keyinfo.StaticKeyInfoGenerator;
import org.opensaml.xml.signature.KeyInfo;
import org.opensaml.xml.signature.KeyName;
import org.opensaml.xml.util.DatatypeHelper;
/**
* Simple tests for encryption.
*/
public class SimpleEncryptionTest extends BaseTestCase {
private Encrypter encrypter;
private EncryptionParameters encParams;
private KeyEncryptionParameters kekParamsRSA;
private List<KeyEncryptionParameters> kekParamsList;
private KeyInfo keyInfo;
private String algoURI;
private String expectedKeyName;
private String kekURIRSA;
private String kekExpectedKeyNameRSA;
/**
* Constructor.
*
*/
public SimpleEncryptionTest() {
super();
expectedKeyName = "SuperSecretKey";
algoURI = EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES128;
kekExpectedKeyNameRSA = "RSAKeyEncryptionKey";
kekURIRSA = EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSA15;
}
/** {@inheritDoc} */
protected void setUp() throws Exception {
super.setUp();
encParams = new EncryptionParameters();
encParams.setAlgorithm(algoURI);
encParams.setEncryptionCredential(SecurityTestHelper.generateKeyAndCredential(algoURI));
kekParamsRSA = new KeyEncryptionParameters();
kekParamsRSA.setAlgorithm(kekURIRSA);
kekParamsRSA.setEncryptionCredential(SecurityTestHelper.generateKeyPairAndCredential(kekURIRSA, 1024, false));
kekParamsList = new ArrayList<KeyEncryptionParameters>();
keyInfo = (KeyInfo) buildXMLObject(KeyInfo.DEFAULT_ELEMENT_NAME);
}
/**
* Test basic encryption with symmetric key, no key wrap,
* set key name in passed KeyInfo object.
*/
public void testAssertion() {
Assertion target = (Assertion) unmarshallElement("/data/org/opensaml/saml2/encryption/Assertion.xml");
KeyName keyName = (KeyName) buildXMLObject(org.opensaml.xml.signature.KeyName.DEFAULT_ELEMENT_NAME);
keyName.setValue(expectedKeyName);
keyInfo.getKeyNames().add(keyName);
encParams.setKeyInfoGenerator(new StaticKeyInfoGenerator(keyInfo));
encrypter = new Encrypter(encParams, kekParamsList);
EncryptedAssertion encTarget = null;
XMLObject encObject = null;
try {
encObject = encrypter.encrypt(target);
} catch (EncryptionException e) {
fail("Object encryption failed: " + e);
}
assertNotNull("Encrypted object was null", encObject);
assertTrue("Encrypted object was not an instance of the expected type",
encObject instanceof EncryptedAssertion);
encTarget = (EncryptedAssertion) encObject;
assertEquals("Type attribute", EncryptionConstants.TYPE_ELEMENT, encTarget.getEncryptedData().getType());
assertEquals("Algorithm attribute", algoURI,
encTarget.getEncryptedData().getEncryptionMethod().getAlgorithm());
assertNotNull("KeyInfo", encTarget.getEncryptedData().getKeyInfo());
assertEquals("KeyName", expectedKeyName,
encTarget.getEncryptedData().getKeyInfo().getKeyNames().get(0).getValue());
assertEquals("Number of EncryptedKeys", 0,
encTarget.getEncryptedData().getKeyInfo().getEncryptedKeys().size());
assertFalse("EncryptedData ID attribute was empty",
DatatypeHelper.isEmpty(encTarget.getEncryptedData().getID()));
}
/**
* Test basic encryption with symmetric key, no key wrap,
* set key name in passed KeyInfo object.
*/
public void testAssertionAsID() {
Assertion target = (Assertion) unmarshallElement("/data/org/opensaml/saml2/encryption/Assertion.xml");
KeyName keyName = (KeyName) buildXMLObject(org.opensaml.xml.signature.KeyName.DEFAULT_ELEMENT_NAME);
keyName.setValue(expectedKeyName);
keyInfo.getKeyNames().add(keyName);
encParams.setKeyInfoGenerator(new StaticKeyInfoGenerator(keyInfo));
encrypter = new Encrypter(encParams, kekParamsList);
EncryptedID encTarget = null;
XMLObject encObject = null;
try {
encObject = encrypter.encryptAsID(target);
} catch (EncryptionException e) {
fail("Object encryption failed: " + e);
}
assertNotNull("Encrypted object was null", encObject);
assertTrue("Encrypted object was not an instance of the expected type",
encObject instanceof EncryptedID);
encTarget = (EncryptedID) encObject;
assertEquals("Type attribute", EncryptionConstants.TYPE_ELEMENT, encTarget.getEncryptedData().getType());
assertEquals("Algorithm attribute", algoURI,
encTarget.getEncryptedData().getEncryptionMethod().getAlgorithm());
assertNotNull("KeyInfo", encTarget.getEncryptedData().getKeyInfo());
assertEquals("KeyName", expectedKeyName,
encTarget.getEncryptedData().getKeyInfo().getKeyNames().get(0).getValue());
assertEquals("Number of EncryptedKeys", 0,
encTarget.getEncryptedData().getKeyInfo().getEncryptedKeys().size());
assertFalse("EncryptedData ID attribute was empty",
DatatypeHelper.isEmpty(encTarget.getEncryptedData().getID()));
}
/**
* Test basic encryption with symmetric key, no key wrap,
* set key name in passed KeyInfo object.
*/
public void testNameID() {
Assertion assertion = (Assertion) unmarshallElement("/data/org/opensaml/saml2/encryption/Assertion.xml");
NameID target = assertion.getSubject().getNameID();
KeyName keyName = (KeyName) buildXMLObject(org.opensaml.xml.signature.KeyName.DEFAULT_ELEMENT_NAME);
keyName.setValue(expectedKeyName);
keyInfo.getKeyNames().add(keyName);
encParams.setKeyInfoGenerator(new StaticKeyInfoGenerator(keyInfo));
encrypter = new Encrypter(encParams, kekParamsList);
EncryptedID encTarget = null;
XMLObject encObject = null;
try {
encObject = encrypter.encrypt(target);
} catch (EncryptionException e) {
fail("Object encryption failed: " + e);
}
assertNotNull("Encrypted object was null", encObject);
assertTrue("Encrypted object was not an instance of the expected type",
encObject instanceof EncryptedID);
encTarget = (EncryptedID) encObject;
assertEquals("Type attribute", EncryptionConstants.TYPE_ELEMENT, encTarget.getEncryptedData().getType());
assertEquals("Algorithm attribute", algoURI,
encTarget.getEncryptedData().getEncryptionMethod().getAlgorithm());
assertNotNull("KeyInfo", encTarget.getEncryptedData().getKeyInfo());
assertEquals("KeyName", expectedKeyName,
encTarget.getEncryptedData().getKeyInfo().getKeyNames().get(0).getValue());
assertEquals("Number of EncryptedKeys", 0,
encTarget.getEncryptedData().getKeyInfo().getEncryptedKeys().size());
assertFalse("EncryptedData ID attribute was empty",
DatatypeHelper.isEmpty(encTarget.getEncryptedData().getID()));
}
/**
* Test basic encryption with symmetric key, no key wrap,
* set key name in passed KeyInfo object.
*/
public void testAttribute() {
Assertion assertion = (Assertion) unmarshallElement("/data/org/opensaml/saml2/encryption/Assertion.xml");
Attribute target = assertion.getAttributeStatements().get(0).getAttributes().get(0);
KeyName keyName = (KeyName) buildXMLObject(org.opensaml.xml.signature.KeyName.DEFAULT_ELEMENT_NAME);
keyName.setValue(expectedKeyName);
keyInfo.getKeyNames().add(keyName);
encParams.setKeyInfoGenerator(new StaticKeyInfoGenerator(keyInfo));
encrypter = new Encrypter(encParams, kekParamsList);
EncryptedAttribute encTarget = null;
XMLObject encObject = null;
try {
encObject = encrypter.encrypt(target);
} catch (EncryptionException e) {
fail("Object encryption failed: " + e);
}
assertNotNull("Encrypted object was null", encObject);
assertTrue("Encrypted object was not an instance of the expected type",
encObject instanceof EncryptedAttribute);
encTarget = (EncryptedAttribute) encObject;
assertEquals("Type attribute", EncryptionConstants.TYPE_ELEMENT, encTarget.getEncryptedData().getType());
assertEquals("Algorithm attribute", algoURI,
encTarget.getEncryptedData().getEncryptionMethod().getAlgorithm());
assertNotNull("KeyInfo", encTarget.getEncryptedData().getKeyInfo());
assertEquals("KeyName", expectedKeyName,
encTarget.getEncryptedData().getKeyInfo().getKeyNames().get(0).getValue());
assertEquals("Number of EncryptedKeys", 0,
encTarget.getEncryptedData().getKeyInfo().getEncryptedKeys().size());
assertFalse("EncryptedData ID attribute was empty",
DatatypeHelper.isEmpty(encTarget.getEncryptedData().getID()));
}
/**
* Test basic encryption with symmetric key, no key wrap,
* set key name in passed KeyInfo object.
*/
public void testNewID() {
NewID target = (NewID) buildXMLObject(NewID.DEFAULT_ELEMENT_NAME);
target.setNewID("SomeNewID");
KeyName keyName = (KeyName) buildXMLObject(org.opensaml.xml.signature.KeyName.DEFAULT_ELEMENT_NAME);
keyName.setValue(expectedKeyName);
keyInfo.getKeyNames().add(keyName);
encParams.setKeyInfoGenerator(new StaticKeyInfoGenerator(keyInfo));
encrypter = new Encrypter(encParams, kekParamsList);
NewEncryptedID encTarget = null;
XMLObject encObject = null;
try {
encObject = encrypter.encrypt(target);
} catch (EncryptionException e) {
fail("Object encryption failed: " + e);
}
assertNotNull("Encrypted object was null", encObject);
assertTrue("Encrypted object was not an instance of the expected type",
encObject instanceof NewEncryptedID);
encTarget = (NewEncryptedID) encObject;
assertEquals("Type attribute", EncryptionConstants.TYPE_ELEMENT, encTarget.getEncryptedData().getType());
assertEquals("Algorithm attribute", algoURI,
encTarget.getEncryptedData().getEncryptionMethod().getAlgorithm());
assertNotNull("KeyInfo", encTarget.getEncryptedData().getKeyInfo());
assertEquals("KeyName", expectedKeyName,
encTarget.getEncryptedData().getKeyInfo().getKeyNames().get(0).getValue());
assertEquals("Number of EncryptedKeys", 0,
encTarget.getEncryptedData().getKeyInfo().getEncryptedKeys().size());
assertFalse("EncryptedData ID attribute was empty",
DatatypeHelper.isEmpty(encTarget.getEncryptedData().getID()));
}
/** Test that reuse of the encrypter with the same encryption and key encryption parameters is allowed. */
public void testReuse() {
Assertion assertion = (Assertion) unmarshallElement("/data/org/opensaml/saml2/encryption/Assertion.xml");
Attribute target = assertion.getAttributeStatements().get(0).getAttributes().get(0);
Attribute target2 = assertion.getAttributeStatements().get(0).getAttributes().get(1);
KeyName keyName = (KeyName) buildXMLObject(org.opensaml.xml.signature.KeyName.DEFAULT_ELEMENT_NAME);
keyName.setValue(expectedKeyName);
keyInfo.getKeyNames().add(keyName);
encParams.setKeyInfoGenerator(new StaticKeyInfoGenerator(keyInfo));
encrypter = new Encrypter(encParams, kekParamsList);
XMLObject encObject = null;
try {
encObject = encrypter.encrypt(target);
} catch (EncryptionException e) {
fail("Object encryption failed: " + e);
}
assertNotNull("Encrypted object was null", encObject);
assertTrue("Encrypted object was not an instance of the expected type",
encObject instanceof EncryptedAttribute);
XMLObject encObject2 = null;
try {
encObject2 = encrypter.encrypt(target2);
} catch (EncryptionException e) {
fail("Object encryption failed: " + e);
}
assertNotNull("Encrypted object was null", encObject2);
assertTrue("Encrypted object was not an instance of the expected type",
encObject2 instanceof EncryptedAttribute);
}
/** Test that a data encryption key is auto-generated if it is not supplied. */
public void testAutoKeyGen() {
Assertion target = (Assertion) unmarshallElement("/data/org/opensaml/saml2/encryption/Assertion.xml");
encParams.setEncryptionCredential(null);
kekParamsList.add(kekParamsRSA);
encrypter = new Encrypter(encParams, kekParamsList);
XMLObject encObject = null;
try {
encObject = encrypter.encrypt(target);
} catch (EncryptionException e) {
fail("Object encryption failed: " + e);
}
assertNotNull("Encrypted object was null", encObject);
assertTrue("Encrypted object was not an instance of the expected type",
encObject instanceof EncryptedAssertion);
}
/** Test that an error is thrown if the no data encryption credential is supplied and no KEK is specified. */
public void testAutoKeyGenNoKEK() {
Assertion target = (Assertion) unmarshallElement("/data/org/opensaml/saml2/encryption/Assertion.xml");
encParams.setEncryptionCredential(null);
kekParamsList.clear();
encrypter = new Encrypter(encParams, kekParamsList);
XMLObject encObject = null;
try {
encObject = encrypter.encrypt(target);
fail("Object encryption should have failed: no KEK supplied with auto key generation for data encryption");
} catch (EncryptionException e) {
//do nothing, should fail
}
}
}