[Major] Changed XmlDomSigner to taked alias names for key finding
This commit is contained in:
parent
779bdbb3c1
commit
cd5f98225d
|
@ -10,6 +10,8 @@ import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.security.KeyStore;
|
import java.security.KeyStore;
|
||||||
import java.security.KeyStore.PrivateKeyEntry;
|
import java.security.KeyStore.PrivateKeyEntry;
|
||||||
|
import java.security.KeyStore.TrustedCertificateEntry;
|
||||||
|
import java.security.PrivateKey;
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -48,26 +50,33 @@ import org.w3c.dom.Element;
|
||||||
import org.w3c.dom.Node;
|
import org.w3c.dom.Node;
|
||||||
import org.w3c.dom.NodeList;
|
import org.w3c.dom.NodeList;
|
||||||
|
|
||||||
|
import ch.eitchnet.utils.dbc.DBC;
|
||||||
|
|
||||||
public class XmlDomSigner {
|
public class XmlDomSigner {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(XmlDomSigner.class);
|
private static final Logger logger = LoggerFactory.getLogger(XmlDomSigner.class);
|
||||||
|
|
||||||
private PrivateKeyEntry keyEntry;
|
private KeyStore keyStore;
|
||||||
private X509Certificate cert;
|
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 {
|
try {
|
||||||
|
|
||||||
KeyStore ks = KeyStore.getInstance("JKS");
|
KeyStore keyStore = KeyStore.getInstance("JKS");
|
||||||
ks.load(new FileInputStream(keyStorePath), password);
|
keyStore.load(new FileInputStream(keyStorePath), password);
|
||||||
this.keyEntry = (PrivateKeyEntry) ks.getEntry(ks.aliases().nextElement(),
|
this.keyStore = keyStore;
|
||||||
new KeyStore.PasswordProtection(password));
|
this.privateKeyAlias = privateKeyAlias;
|
||||||
|
this.trustAlias = trustAlias;
|
||||||
this.cert = (X509Certificate) this.keyEntry.getCertificate();
|
this.password = password;
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(
|
throw new RuntimeException("Failed to read keystore " + keyStorePath);
|
||||||
"Failed to read certificate and private key from keystore " + keyStorePath + " and alias " + alias);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +102,6 @@ public class XmlDomSigner {
|
||||||
transforms.add(fac.newTransform(CanonicalizationMethod.EXCLUSIVE, (TransformParameterSpec) null));
|
transforms.add(fac.newTransform(CanonicalizationMethod.EXCLUSIVE, (TransformParameterSpec) null));
|
||||||
DigestMethod digestMethod = fac.newDigestMethod(DigestMethod.SHA1, null);
|
DigestMethod digestMethod = fac.newDigestMethod(DigestMethod.SHA1, null);
|
||||||
Reference ref = fac.newReference("#" + id, digestMethod, transforms, null, null);
|
Reference ref = fac.newReference("#" + id, digestMethod, transforms, null, null);
|
||||||
//Reference ref = fac.newReference("", digestMethod, transforms, null, null);
|
|
||||||
|
|
||||||
// Create the SignedInfo.
|
// Create the SignedInfo.
|
||||||
SignedInfo signedInfo = fac.newSignedInfo(
|
SignedInfo signedInfo = fac.newSignedInfo(
|
||||||
|
@ -102,18 +110,23 @@ public class XmlDomSigner {
|
||||||
Collections.singletonList(ref));
|
Collections.singletonList(ref));
|
||||||
|
|
||||||
// Load the KeyStore and get the signing key and certificate.
|
// 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.
|
// Create the KeyInfo containing the X509Data.
|
||||||
KeyInfoFactory kif = fac.getKeyInfoFactory();
|
KeyInfoFactory kif = fac.getKeyInfoFactory();
|
||||||
List<Object> x509Content = new ArrayList<>();
|
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);
|
X509Data xd = kif.newX509Data(x509Content);
|
||||||
KeyInfo keyInfo = kif.newKeyInfo(Collections.singletonList(xd));
|
KeyInfo keyInfo = kif.newKeyInfo(Collections.singletonList(xd));
|
||||||
|
|
||||||
// Create a DOMSignContext and specify the RSA PrivateKey and
|
// Create a DOMSignContext and specify the RSA PrivateKey and
|
||||||
// location of the resulting XMLSignature's parent element.
|
// 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.setDefaultNamespacePrefix("samlp");
|
||||||
dsc.putNamespacePrefix(XMLSignature.XMLNS, "ds");
|
dsc.putNamespacePrefix(XMLSignature.XMLNS, "ds");
|
||||||
|
|
||||||
|
@ -145,17 +158,13 @@ public class XmlDomSigner {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the KeyStore and get the signing key and certificate.
|
// 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
|
// Create a DOMValidateContext and specify a KeySelector
|
||||||
// and document context.
|
// and document context.
|
||||||
Node signatureNode = nl.item(0);
|
Node signatureNode = nl.item(0);
|
||||||
DOMValidateContext valContext = new DOMValidateContext(publicKey, signatureNode);
|
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.
|
// Unmarshal the XMLSignature.
|
||||||
valContext.setProperty("javax.xml.crypto.dsig.cacheReference", Boolean.TRUE);
|
valContext.setProperty("javax.xml.crypto.dsig.cacheReference", Boolean.TRUE);
|
||||||
|
|
|
@ -24,7 +24,8 @@ public class XmlSignHelperTest {
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void 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
|
@Test
|
||||||
|
@ -58,6 +59,7 @@ public class XmlSignHelperTest {
|
||||||
|
|
||||||
File signedXmlFile = new File("src/test/resources/SignedXmlFile.xml");
|
File signedXmlFile = new File("src/test/resources/SignedXmlFile.xml");
|
||||||
Document document = XmlDomSigner.parse(signedXmlFile);
|
Document document = XmlDomSigner.parse(signedXmlFile);
|
||||||
|
setIdAttr(document);
|
||||||
helper.validate(document);
|
helper.validate(document);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,9 +68,28 @@ public class XmlSignHelperTest {
|
||||||
|
|
||||||
File signedXmlFile = new File("src/test/resources/SignedXmlFileWithNamespaces.xml");
|
File signedXmlFile = new File("src/test/resources/SignedXmlFileWithNamespaces.xml");
|
||||||
Document document = XmlDomSigner.parse(signedXmlFile);
|
Document document = XmlDomSigner.parse(signedXmlFile);
|
||||||
|
setIdAttrNs(document);
|
||||||
|
|
||||||
helper.validate(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
|
@Test
|
||||||
public void shouldSignAndValidate() {
|
public void shouldSignAndValidate() {
|
||||||
|
|
||||||
|
|
Binary file not shown.
Loading…
Reference in New Issue