/* * 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.security.KeyPair; 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.encryption.Encrypter.KeyPlacement; import org.opensaml.xml.XMLObject; import org.opensaml.xml.encryption.DataReference; import org.opensaml.xml.encryption.EncryptedData; import org.opensaml.xml.encryption.EncryptedKey; 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.credential.Credential; import org.opensaml.xml.security.keyinfo.StaticKeyInfoGenerator; import org.opensaml.xml.signature.KeyInfo; import org.opensaml.xml.signature.KeyName; import org.opensaml.xml.signature.RetrievalMethod; import org.opensaml.xml.util.DatatypeHelper; /** * Tests for encryption using single and multicast key encryption keys, * and peer vs. inline key placement. */ public class ComplexEncryptionTest extends BaseTestCase { private Encrypter encrypter; private EncryptionParameters encParams; private List<KeyEncryptionParameters> kekParamsList; private KeyEncryptionParameters kekParamsRSA, kekParamsAES; private KeyInfo keyInfo, kekKeyInfoRSA, kekKeyInfoAES; private String algoURI, kekURIRSA, kekURIAES; private String expectedKeyName, expectedKeyNameRSA, expectedKeyNameAES; private String expectedRecipientRSA, expectedRecipientAES; /** * Constructor. * */ public ComplexEncryptionTest() { super(); expectedKeyName = "SuperSecretKey"; expectedKeyNameRSA = "RSAKeyWrapper"; expectedKeyNameAES = "AESKeyWrapper"; expectedRecipientRSA = "RSARecipient"; expectedRecipientAES = "AESRecipient"; algoURI = EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES128; kekURIRSA = EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSA15; kekURIAES = EncryptionConstants.ALGO_ID_KEYWRAP_AES128; } /** {@inheritDoc} */ protected void setUp() throws Exception { super.setUp(); Credential encCred = SecurityTestHelper.generateKeyAndCredential(algoURI); Credential kekCredAES = SecurityTestHelper.generateKeyAndCredential(kekURIAES); Credential kekCredRSA = SecurityTestHelper.generateKeyPairAndCredential(kekURIRSA, 2048, false); encParams = new EncryptionParameters(); encParams.setAlgorithm(algoURI); encParams.setEncryptionCredential(encCred); kekParamsAES = new KeyEncryptionParameters(); kekParamsAES.setAlgorithm(kekURIAES); kekParamsAES.setEncryptionCredential(kekCredAES); kekParamsRSA = new KeyEncryptionParameters(); kekParamsRSA.setAlgorithm(kekURIRSA); kekParamsRSA.setEncryptionCredential(kekCredRSA); kekParamsList = new ArrayList<KeyEncryptionParameters>(); keyInfo = (KeyInfo) buildXMLObject(KeyInfo.DEFAULT_ELEMENT_NAME); kekKeyInfoRSA = (KeyInfo) buildXMLObject(KeyInfo.DEFAULT_ELEMENT_NAME); kekKeyInfoAES = (KeyInfo) buildXMLObject(KeyInfo.DEFAULT_ELEMENT_NAME); } /** * Test encryption with a single key encryption key with key placement inline. */ public void testSingleKEKInline() { Assertion target = (Assertion) unmarshallElement("/data/org/opensaml/saml2/encryption/Assertion.xml"); KeyName keyName = (KeyName) buildXMLObject(KeyName.DEFAULT_ELEMENT_NAME); keyName.setValue(expectedKeyNameRSA); kekKeyInfoRSA.getKeyNames().add(keyName); kekParamsRSA.setKeyInfoGenerator(new StaticKeyInfoGenerator(kekKeyInfoRSA)); kekParamsList.add(kekParamsRSA); encrypter = new Encrypter(encParams, kekParamsList); encrypter.setKeyPlacement(Encrypter.KeyPlacement.INLINE); 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("Number of inline EncryptedKeys", 1, encTarget.getEncryptedData().getKeyInfo().getEncryptedKeys().size()); assertEquals("Number of peer EncryptedKeys", 0, encTarget.getEncryptedKeys().size()); EncryptedKey encKey = encTarget.getEncryptedData().getKeyInfo().getEncryptedKeys().get(0); assertNotNull("EncryptedKey was null", encKey); assertEquals("Algorithm attribute", kekURIRSA, encKey.getEncryptionMethod().getAlgorithm()); assertNotNull("KeyInfo", encKey.getKeyInfo()); assertEquals("KeyName", expectedKeyNameRSA, encKey.getKeyInfo().getKeyNames().get(0).getValue()); assertFalse("EncryptedKey ID attribute was empty", DatatypeHelper.isEmpty(encKey.getID())); EncryptedData encData = encTarget.getEncryptedData(); assertNotNull("EncryptedData KeyInfo wasn't null", encData.getKeyInfo()); assertEquals("EncryptedData improperly contained a RetrievalMethod", 0, encData.getKeyInfo().getRetrievalMethods().size()); assertNull("EncryptedKey ReferenceList wasn't null", encKey.getReferenceList()); assertNull("EncryptedKey CarriedKeyName wasn't null", encKey.getCarriedKeyName()); } /** * Test encryption with a single key encryption key with key placement as peer. */ public void testSingleKEKPeer() { Assertion target = (Assertion) unmarshallElement("/data/org/opensaml/saml2/encryption/Assertion.xml"); KeyName keyName = (KeyName) buildXMLObject(KeyName.DEFAULT_ELEMENT_NAME); keyName.setValue(expectedKeyNameRSA); kekKeyInfoRSA.getKeyNames().add(keyName); kekParamsRSA.setKeyInfoGenerator(new StaticKeyInfoGenerator(kekKeyInfoRSA)); kekParamsList.add(kekParamsRSA); encrypter = new Encrypter(encParams, kekParamsList); encrypter.setKeyPlacement(Encrypter.KeyPlacement.PEER); 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("Number of inline EncryptedKeys", 0, encTarget.getEncryptedData().getKeyInfo().getEncryptedKeys().size()); assertEquals("Number of peer EncryptedKeys", 1, encTarget.getEncryptedKeys().size()); EncryptedKey encKey = encTarget.getEncryptedKeys().get(0); assertNotNull("EncryptedKey was null", encKey); assertEquals("Algorithm attribute", kekURIRSA, encKey.getEncryptionMethod().getAlgorithm()); assertNotNull("KeyInfo", encKey.getKeyInfo()); assertEquals("KeyName", expectedKeyNameRSA, encKey.getKeyInfo().getKeyNames().get(0).getValue()); assertFalse("EncryptedKey ID attribute was empty", DatatypeHelper.isEmpty(encKey.getID())); EncryptedData encData = encTarget.getEncryptedData(); assertNotNull("EncryptedData KeyInfo wasn't null", encData.getKeyInfo()); assertEquals("EncryptedData contained invalid number RetrievalMethods", 1, encData.getKeyInfo().getRetrievalMethods().size()); RetrievalMethod rm = encData.getKeyInfo().getRetrievalMethods().get(0); assertEquals("EncryptedData RetrievalMethod had incorrect type attribute", EncryptionConstants.TYPE_ENCRYPTED_KEY, rm.getType()); assertEquals("EncryptedData RetrievalMethod had incorrect URI value", "#" + encKey.getID(), rm.getURI()); assertNotNull("EncryptedKey ReferenceList was null", encKey.getReferenceList()); assertEquals("EncryptedKey contained invalid number DataReferences", 1, encKey.getReferenceList().getDataReferences().size()); DataReference dr = encKey.getReferenceList().getDataReferences().get(0); assertEquals("EncryptedKey DataReference had incorrect URI value", "#" + encData.getID(), dr.getURI()); assertNull("EncryptedKey CarriedKeyName wasn't null", encKey.getCarriedKeyName()); } /** Test encryption with multicast key encryption keys with key placement as peer. */ public void testMulticastKEKPeer() { Assertion target = (Assertion) unmarshallElement("/data/org/opensaml/saml2/encryption/Assertion.xml"); String multicastKeyNameValue = "MulticastDataEncryptionKeyName"; KeyName keyName = (KeyName) buildXMLObject(KeyName.DEFAULT_ELEMENT_NAME); keyName.setValue(multicastKeyNameValue); keyInfo.getKeyNames().add(keyName); encParams.setKeyInfoGenerator(new StaticKeyInfoGenerator(keyInfo)); kekParamsRSA.setRecipient(expectedRecipientRSA); kekParamsList.add(kekParamsRSA); kekParamsAES.setRecipient(expectedRecipientAES); kekParamsList.add(kekParamsAES); encrypter = new Encrypter(encParams, kekParamsList); encrypter.setKeyPlacement(Encrypter.KeyPlacement.PEER); 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("Number of inline EncryptedKeys", 0, encTarget.getEncryptedData().getKeyInfo().getEncryptedKeys().size()); assertEquals("Number of peer EncryptedKeys", 2, encTarget.getEncryptedKeys().size()); EncryptedKey encKeyRSA = encTarget.getEncryptedKeys().get(0); EncryptedKey encKeyAES = encTarget.getEncryptedKeys().get(1); assertNotNull("EncryptedKey was null", encKeyRSA); assertNotNull("EncryptedKey was null", encKeyAES); assertEquals("Algorithm attribute", kekURIRSA, encKeyRSA.getEncryptionMethod().getAlgorithm()); assertEquals("Algorithm attribute", kekURIAES, encKeyAES.getEncryptionMethod().getAlgorithm()); assertFalse("EncryptedKey ID attribute was empty", DatatypeHelper.isEmpty(encKeyRSA.getID())); assertFalse("EncryptedKey ID attribute was empty", DatatypeHelper.isEmpty(encKeyAES.getID())); EncryptedData encData = encTarget.getEncryptedData(); assertNotNull("EncryptedData KeyInfo wasn't null", encData.getKeyInfo()); assertEquals("EncryptedData contained invalid number RetrievalMethods", 0, encData.getKeyInfo().getRetrievalMethods().size()); assertEquals("EncryptedData contained invalid number KeyNames", 1, encData.getKeyInfo().getKeyNames().size()); KeyName encDataKeyName = encData.getKeyInfo().getKeyNames().get(0); assertEquals("EncryptedData KeyName value", multicastKeyNameValue, encDataKeyName.getValue()); DataReference dr = null; assertEquals("EncryptedKey recipient attribute had invalid value", expectedRecipientRSA, encKeyRSA.getRecipient()); assertNotNull("EncryptedKey ReferenceList was null", encKeyRSA.getReferenceList()); assertEquals("EncryptedKey contained invalid number DataReferences", 1, encKeyRSA.getReferenceList().getDataReferences().size()); dr = encKeyRSA.getReferenceList().getDataReferences().get(0); assertEquals("EncryptedKey DataReference had incorrect URI value", "#" + encData.getID(), dr.getURI()); assertNotNull("EncryptedKey CarriedKeyName wasn't null", encKeyRSA.getCarriedKeyName()); assertEquals("EncrypteKey CarriedKeyName had incorrect value", multicastKeyNameValue, encKeyRSA.getCarriedKeyName().getValue()); assertEquals("EncryptedKey recipient attribute had invalid value", expectedRecipientAES, encKeyAES.getRecipient()); assertNotNull("EncryptedKey ReferenceList was null", encKeyAES.getReferenceList()); assertEquals("EncryptedKey contained invalid number DataReferences", 1, encKeyAES.getReferenceList().getDataReferences().size()); dr = encKeyAES.getReferenceList().getDataReferences().get(0); assertEquals("EncryptedKey DataReference had incorrect URI value", "#" + encData.getID(), dr.getURI()); assertNotNull("EncryptedKey CarriedKeyName wasn't null", encKeyAES.getCarriedKeyName()); assertEquals("EncrypteKey CarriedKeyName had incorrect value", multicastKeyNameValue, encKeyAES.getCarriedKeyName().getValue()); } /** Test that reuse is allowed with same key encryption parameters. */ 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(KeyName.DEFAULT_ELEMENT_NAME); keyName.setValue(expectedKeyNameRSA); kekKeyInfoRSA.getKeyNames().add(keyName); kekParamsRSA.setKeyInfoGenerator(new StaticKeyInfoGenerator(kekKeyInfoRSA)); kekParamsList.add(kekParamsRSA); encrypter = new Encrypter(encParams, kekParamsList); encrypter.setKeyPlacement(KeyPlacement.PEER); 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); } }