/*
* Copyright 2013 ForgeRock AS
*
* The contents of this file are subject to the terms of the Common Development and
* Distribution License (the License). You may not use this file except in compliance with the
* License.
*
* You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
* specific language governing permission and limitations under the License.
*
* When distributing Covered Software, include this CDDL Header Notice in each file and include
* the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
* Header, with the fields enclosed by brackets [] replaced by your own identifying
* information: "Portions copyright [year] [name of copyright owner]".
*/
package com.sun.identity.saml.xmlsig;
import com.sun.identity.saml2.common.SAML2Constants;
import com.sun.identity.saml2.common.SAML2Utils;
import com.sun.identity.security.EncodeAction;
import com.sun.identity.shared.encode.URLEncDec;
import com.sun.identity.shared.xml.XMLUtils;
import org.forgerock.openam.utils.AMKeyProvider;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import java.security.AccessController;
public class XMLSignatureManagerTest {
private static final String KEY_STORE_FILE = URLEncDec.decode(ClassLoader.getSystemResource("keystore.jks")
.getFile());
private static final String KEY_STORE_TYPE = "JKS";
private static final String KEY_STORE_PASS = "testcase";
private static final String DEFAULT_PRIVATE_KEY_PASS = "testcase";
private static final String PRIVATE_KEY_PASS = "keypass";
private static final String DEFAULT_PRIVATE_KEY_ALIAS = "defaultkey";
private static final String PRIVATE_KEY_ALIAS = "privatekey";
private static final String XML_DOCUMENT_TO_SIGN = "documenttosign.xml";
private static final String SIGNED_XML_DOCUMENT_RESPONSEID = "signeddocument-responseid.xml";
private static final String SIGNED_XML_DOCUMENT = "signeddocument.xml";
private static final String ID_ATTRIBUTE_VALUE = "signme";
private static final String RESPONSE_ID = "ResponseID";
private XMLSignatureManager xmlSignatureManager;
@BeforeClass
public void setUp() {
KeyProvider keyProvider =
new AMKeyProvider(true, KEY_STORE_FILE, KEY_STORE_PASS, KEY_STORE_TYPE, DEFAULT_PRIVATE_KEY_PASS);
SignatureProvider signatureProvider = new AMSignatureProvider();
xmlSignatureManager = XMLSignatureManager.getInstance(keyProvider, signatureProvider);
}
@Test
public void signXMLWithPrivateKeyUsingPassword() {
Document documentToSign =
XMLUtils.toDOMDocument(ClassLoader.getSystemResourceAsStream(XML_DOCUMENT_TO_SIGN), SAML2Utils.debug);
Element signature = null;
String encodedPrivatePass = AccessController.doPrivileged(new EncodeAction(PRIVATE_KEY_PASS));
try {
signature = xmlSignatureManager.signXMLUsingKeyPass(documentToSign, PRIVATE_KEY_ALIAS,
encodedPrivatePass, null, SAML2Constants.ID, ID_ATTRIBUTE_VALUE, true, null);
} catch (XMLSignatureException e) {
Assert.fail(e.getMessage());
}
Assert.assertNotNull(signature);
NodeList nodes = documentToSign.getElementsByTagName("ds:Signature");
Assert.assertTrue(nodes.getLength() > 0);
Assert.assertTrue(signature.isEqualNode(nodes.item(0)));
}
@Test
public void signXMLWithPrivateKeyAndNullPassword() {
Document documentToSign =
XMLUtils.toDOMDocument(ClassLoader.getSystemResourceAsStream(XML_DOCUMENT_TO_SIGN), SAML2Utils.debug);
Element signature = null;
try {
signature = xmlSignatureManager.signXMLUsingKeyPass(documentToSign, PRIVATE_KEY_ALIAS,
null, null, SAML2Constants.ID, ID_ATTRIBUTE_VALUE, true, null);
Assert.fail("Null private key exception expected.");
} catch (XMLSignatureException e) {
}
Assert.assertNull(signature);
}
@Test
public void signXMLWithPrivateKeyUsingDefaultPassword() {
Document documentToSign =
XMLUtils.toDOMDocument(ClassLoader.getSystemResourceAsStream(XML_DOCUMENT_TO_SIGN), SAML2Utils.debug);
Element signature = null;
try {
signature = xmlSignatureManager.signXML(documentToSign, PRIVATE_KEY_ALIAS,
null, SAML2Constants.ID, ID_ATTRIBUTE_VALUE, true, null);
Assert.fail("Null private key exception expected.");
} catch (XMLSignatureException e) {
}
Assert.assertNull(signature);
}
@Test
public void signXMLWithDefaultPrivateKeyAndNullPassword() {
Document documentToSign =
XMLUtils.toDOMDocument(ClassLoader.getSystemResourceAsStream(XML_DOCUMENT_TO_SIGN), SAML2Utils.debug);
Element signature = null;
try {
// Passing null for password should trigger using default keystore password to load private key
signature = xmlSignatureManager.signXMLUsingKeyPass(documentToSign, DEFAULT_PRIVATE_KEY_ALIAS,
null, null, SAML2Constants.ID, ID_ATTRIBUTE_VALUE, true, null);
} catch (XMLSignatureException e) {
Assert.fail(e.getMessage());
}
Assert.assertNotNull(signature);
NodeList nodes = documentToSign.getElementsByTagName("ds:Signature");
Assert.assertTrue(nodes.getLength() > 0);
Assert.assertTrue(signature.isEqualNode(nodes.item(0)));
}
@Test
public void signXMLWithDefaultPrivateKey() {
Document documentToSign =
XMLUtils.toDOMDocument(ClassLoader.getSystemResourceAsStream(XML_DOCUMENT_TO_SIGN), SAML2Utils.debug);
Element signature = null;
try {
// Should trigger using default keystore password to load private key
signature = xmlSignatureManager.signXML(documentToSign, DEFAULT_PRIVATE_KEY_ALIAS,
null, SAML2Constants.ID, ID_ATTRIBUTE_VALUE, true, null);
} catch (XMLSignatureException e) {
Assert.fail(e.getMessage());
}
Assert.assertNotNull(signature);
NodeList nodes = documentToSign.getElementsByTagName("ds:Signature");
Assert.assertTrue(nodes.getLength() > 0);
Assert.assertTrue(signature.isEqualNode(nodes.item(0)));
}
@Test
public void verifyDocumentResponseID() {
// Test that a signed document can be verified with an ID
// from the set of "AssertionID", "RequestID", "ResponseID"
Document signedDocument =
XMLUtils.toDOMDocument(ClassLoader.getSystemResourceAsStream(SIGNED_XML_DOCUMENT_RESPONSEID),
SAML2Utils.debug);
boolean verified = false;
try {
verified = xmlSignatureManager.verifyXMLSignature(signedDocument.getDocumentElement(),
RESPONSE_ID, DEFAULT_PRIVATE_KEY_ALIAS);
} catch (XMLSignatureException e) {
Assert.fail(e.getMessage());
}
Assert.assertTrue(verified);
}
@Test
public void verifyDocument() {
// Test that a signed document can be verified
Document signedDocument =
XMLUtils.toDOMDocument(ClassLoader.getSystemResourceAsStream(SIGNED_XML_DOCUMENT), SAML2Utils.debug);
boolean verified = false;
try {
verified = xmlSignatureManager.verifyXMLSignature(signedDocument.getDocumentElement(),
SAML2Constants.ID, DEFAULT_PRIVATE_KEY_ALIAS);
} catch (XMLSignatureException e) {
Assert.fail(e.getMessage());
}
Assert.assertTrue(verified);
}
}