[Major] Changed XmlDomSigner to taked alias names for key finding

This commit is contained in:
Robert von Burg 2016-03-07 17:43:24 +01:00
parent 779bdbb3c1
commit cd5f98225d
3 changed files with 52 additions and 22 deletions

View File

@ -10,6 +10,8 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.security.KeyStore;
import java.security.KeyStore.PrivateKeyEntry;
import java.security.KeyStore.TrustedCertificateEntry;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
@ -48,26 +50,33 @@ import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import ch.eitchnet.utils.dbc.DBC;
public class XmlDomSigner {
private static final Logger logger = LoggerFactory.getLogger(XmlDomSigner.class);
private PrivateKeyEntry keyEntry;
private X509Certificate cert;
private KeyStore keyStore;
private String privateKeyAlias;
private String trustAlias;
public XmlDomSigner(File keyStorePath, String alias, char[] password) {
private char[] password;
public XmlDomSigner(File keyStorePath, String privateKeyAlias, String trustAlias, char[] password) {
DBC.PRE.assertNotEmpty("privateKeyAlias", privateKeyAlias);
DBC.PRE.assertNotEmpty("trustAlias", trustAlias);
try {
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream(keyStorePath), password);
this.keyEntry = (PrivateKeyEntry) ks.getEntry(ks.aliases().nextElement(),
new KeyStore.PasswordProtection(password));
this.cert = (X509Certificate) this.keyEntry.getCertificate();
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(new FileInputStream(keyStorePath), password);
this.keyStore = keyStore;
this.privateKeyAlias = privateKeyAlias;
this.trustAlias = trustAlias;
this.password = password;
} catch (Exception e) {
throw new RuntimeException(
"Failed to read certificate and private key from keystore " + keyStorePath + " and alias " + alias);
throw new RuntimeException("Failed to read keystore " + keyStorePath);
}
}
@ -93,7 +102,6 @@ public class XmlDomSigner {
transforms.add(fac.newTransform(CanonicalizationMethod.EXCLUSIVE, (TransformParameterSpec) null));
DigestMethod digestMethod = fac.newDigestMethod(DigestMethod.SHA1, null);
Reference ref = fac.newReference("#" + id, digestMethod, transforms, null, null);
//Reference ref = fac.newReference("", digestMethod, transforms, null, null);
// Create the SignedInfo.
SignedInfo signedInfo = fac.newSignedInfo(
@ -102,18 +110,23 @@ public class XmlDomSigner {
Collections.singletonList(ref));
// Load the KeyStore and get the signing key and certificate.
PrivateKeyEntry keyEntry = (PrivateKeyEntry) this.keyStore.getEntry(this.privateKeyAlias,
new KeyStore.PasswordProtection(this.password));
PrivateKey privateKey = keyEntry.getPrivateKey();
X509Certificate cert = (X509Certificate) keyEntry.getCertificate();
// Create the KeyInfo containing the X509Data.
KeyInfoFactory kif = fac.getKeyInfoFactory();
List<Object> x509Content = new ArrayList<>();
x509Content.add(this.cert.getSubjectX500Principal().getName());
x509Content.add(this.cert);
x509Content.add(cert.getSubjectX500Principal().getName());
x509Content.add(cert);
X509Data xd = kif.newX509Data(x509Content);
KeyInfo keyInfo = kif.newKeyInfo(Collections.singletonList(xd));
// Create a DOMSignContext and specify the RSA PrivateKey and
// location of the resulting XMLSignature's parent element.
DOMSignContext dsc = new DOMSignContext(this.keyEntry.getPrivateKey(), rootElement);
DOMSignContext dsc = new DOMSignContext(privateKey, rootElement);
//dsc.setDefaultNamespacePrefix("samlp");
dsc.putNamespacePrefix(XMLSignature.XMLNS, "ds");
@ -145,17 +158,13 @@ public class XmlDomSigner {
}
// Load the KeyStore and get the signing key and certificate.
PublicKey publicKey = this.keyEntry.getCertificate().getPublicKey();
TrustedCertificateEntry entry = (TrustedCertificateEntry) this.keyStore.getEntry(trustAlias, null);
PublicKey publicKey = entry.getTrustedCertificate().getPublicKey();
// Create a DOMValidateContext and specify a KeySelector
// and document context.
Node signatureNode = nl.item(0);
DOMValidateContext valContext = new DOMValidateContext(publicKey, signatureNode);
valContext.setDefaultNamespacePrefix("samlp");
valContext.putNamespacePrefix(XMLSignature.XMLNS, "ds");
valContext.putNamespacePrefix("urn:oasis:names:tc:SAML:2.0:protocol", "samlp");
valContext.putNamespacePrefix("urn:oasis:names:tc:SAML:2.0:assertion", "saml");
valContext.setIdAttributeNS(doc.getDocumentElement(), null, "ID");
// Unmarshal the XMLSignature.
valContext.setProperty("javax.xml.crypto.dsig.cacheReference", Boolean.TRUE);

View File

@ -24,7 +24,8 @@ public class XmlSignHelperTest {
@BeforeClass
public static void beforeClass() {
helper = new XmlDomSigner(new File("src/test/resources/test.jks"), "client", "changeit".toCharArray());
helper = new XmlDomSigner(new File("src/test/resources/test.jks"), "client", "server",
"changeit".toCharArray());
}
@Test
@ -58,6 +59,7 @@ public class XmlSignHelperTest {
File signedXmlFile = new File("src/test/resources/SignedXmlFile.xml");
Document document = XmlDomSigner.parse(signedXmlFile);
setIdAttr(document);
helper.validate(document);
}
@ -66,9 +68,28 @@ public class XmlSignHelperTest {
File signedXmlFile = new File("src/test/resources/SignedXmlFileWithNamespaces.xml");
Document document = XmlDomSigner.parse(signedXmlFile);
setIdAttrNs(document);
helper.validate(document);
}
private void setIdAttr(Document document) {
NodeList authnRequestNodes = document.getElementsByTagName("AuthnRequest");
if (authnRequestNodes.getLength() != 1)
throw new IllegalStateException("Multiple or no AuthnRequest Node found in document!");
Element authnRequestNode = (Element) authnRequestNodes.item(0);
authnRequestNode.setIdAttribute("ID", true);
}
private void setIdAttrNs(Document document) {
NodeList authnRequestNodes = document.getElementsByTagNameNS("urn:oasis:names:tc:SAML:2.0:protocol",
"AuthnRequest");
if (authnRequestNodes.getLength() != 1)
throw new IllegalStateException("Multiple or no AuthnRequest Node found in document!");
Element authnRequestNode = (Element) authnRequestNodes.item(0);
authnRequestNode.setIdAttribute("ID", true);
}
@Test
public void shouldSignAndValidate() {

Binary file not shown.