summaryrefslogtreecommitdiff
path: root/utils/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'utils/src/main')
-rw-r--r--utils/src/main/java/at/gv/egiz/idlink/CompressedIdentityLinkFactory.java800
-rw-r--r--utils/src/main/java/at/gv/egiz/idlink/IdentityLinkFactory.java6
-rw-r--r--utils/src/main/java/at/gv/egiz/marshal/MarshallerFactory.java52
-rw-r--r--utils/src/main/java/at/gv/egiz/marshal/NamespacePrefixMapperImpl.java86
-rw-r--r--utils/src/main/java/at/gv/egiz/xades/QualifyingPropertiesFactory.java418
5 files changed, 750 insertions, 612 deletions
diff --git a/utils/src/main/java/at/gv/egiz/idlink/CompressedIdentityLinkFactory.java b/utils/src/main/java/at/gv/egiz/idlink/CompressedIdentityLinkFactory.java
index 5f4e5d92..31e5163a 100644
--- a/utils/src/main/java/at/gv/egiz/idlink/CompressedIdentityLinkFactory.java
+++ b/utils/src/main/java/at/gv/egiz/idlink/CompressedIdentityLinkFactory.java
@@ -14,403 +14,403 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package at.gv.egiz.idlink;
-
-import java.io.BufferedReader;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.security.PublicKey;
-import java.security.cert.X509Certificate;
-import java.util.List;
-
-import javax.xml.bind.JAXBContext;
-import javax.xml.bind.JAXBElement;
-import javax.xml.bind.JAXBException;
-import javax.xml.bind.Marshaller;
-import javax.xml.bind.PropertyException;
-import javax.xml.bind.Unmarshaller;
-import javax.xml.transform.Source;
-import javax.xml.transform.dom.DOMResult;
-
-import org.w3._2000._09.xmldsig_.KeyValueType;
-import org.w3c.dom.Attr;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-import at.buergerkarte.namespaces.personenbindung._20020506_.CompressedIdentityLinkType;
-import at.gv.e_government.reference.namespace.persondata._20020228_.AbstractPersonType;
-import at.gv.e_government.reference.namespace.persondata._20020228_.IdentificationType;
-import at.gv.e_government.reference.namespace.persondata._20020228_.PersonNameType;
-import at.gv.e_government.reference.namespace.persondata._20020228_.PhysicalPersonType;
-import at.gv.e_government.reference.namespace.persondata._20020228_.IdentificationType.Value;
-import at.gv.e_government.reference.namespace.persondata._20020228_.PersonNameType.FamilyName;
-import at.gv.egiz.idlink.ans1.CitizenPublicKey;
-import at.gv.egiz.idlink.ans1.IdentityLink;
-import at.gv.egiz.idlink.ans1.PersonData;
-import at.gv.egiz.idlink.ans1.PhysicalPersonData;
-import at.gv.egiz.xmldsig.KeyTypeNotSupportedException;
-import at.gv.egiz.xmldsig.KeyValueFactory;
-
-public class CompressedIdentityLinkFactory {
-
- /**
- * The instance returned by {@link #getInstance()}.
- */
- private static CompressedIdentityLinkFactory instance;
-
- /**
- * The <code>JAXBContext</code>.
- */
- private static JAXBContext jaxbContext;
-
- /**
- * The <code>KeyValueFactory</code>.
- */
- private static KeyValueFactory keyValueFactory;
-
- /**
- * Get an instance of this <code>CompressedIdentityLinkFactory</code>.
- *
- * @return an instance of this <code>CompressedIdentityLinkFactory</code>
- */
- public synchronized static CompressedIdentityLinkFactory getInstance() {
- if (instance == null) {
- instance = new CompressedIdentityLinkFactory();
- }
- return instance;
- }
-
- /**
- * Private constructor.
- */
- private CompressedIdentityLinkFactory() {
-
- keyValueFactory = new KeyValueFactory();
-
- StringBuffer packageNames = new StringBuffer();
- packageNames.append(at.gv.e_government.reference.namespace.persondata._20020228_.ObjectFactory.class.getPackage().getName());
- packageNames.append(":");
- packageNames.append(org.w3._2000._09.xmldsig_.ObjectFactory.class.getPackage().getName());
- packageNames.append(":");
- packageNames.append(org.w3._2001._04.xmldsig_more_.ObjectFactory.class.getPackage().getName());
- packageNames.append(":");
- packageNames.append(at.buergerkarte.namespaces.personenbindung._20020506_.ObjectFactory.class.getPackage().getName());
-
- try {
- jaxbContext = JAXBContext.newInstance(packageNames.toString());
- } catch (JAXBException e) {
- // we should not get an JAXBException initializing the JAXBContext
- throw new RuntimeException(e);
- }
-
- }
-
- public IdentityLink createIdLink(CompressedIdentityLinkType compressedIdentityLinkType) {
-
- // IssuerTemplate
- String issuerTemplate = compressedIdentityLinkType.getIssuerTemplate();
-
- // AssertionId
- String assertionID = compressedIdentityLinkType.getAssertionID();
-
- // IssueInstant
- String issueInstant = compressedIdentityLinkType.getIssueInstant();
-
- AbstractPersonType personDataType = compressedIdentityLinkType.getPersonData();
-
- String baseId = null;
-
- List<IdentificationType> identifications = personDataType.getIdentification();
- for (IdentificationType identificationType : identifications) {
- String type = identificationType.getType();
- if ("urn:publicid:gv.at:baseid".equals(type)) {
- baseId = identificationType.getValue().getValue();
- }
- }
-
- String givenName = null;
- String familyName = null;
- String dateOfBirth = null;
-
- if (personDataType instanceof PhysicalPersonType) {
- PhysicalPersonType physicalPersonType = (PhysicalPersonType) personDataType;
- PersonNameType name = physicalPersonType.getName();
- List<String> givenNames = name.getGivenName();
- if (!givenNames.isEmpty()) {
- givenName = givenNames.get(0);
- }
- List<FamilyName> familyNames = name.getFamilyName();
- if (!familyNames.isEmpty()) {
- familyName = familyNames.get(0).getValue();
- }
- dateOfBirth = physicalPersonType.getDateOfBirth();
- }
-
- PhysicalPersonData physicalPersonData = new PhysicalPersonData(baseId, givenName, familyName, dateOfBirth);
- PersonData personData = new PersonData(physicalPersonData);
-
- int numKeys = compressedIdentityLinkType.getCitizenPublicKey().size();
- CitizenPublicKey[] citizenPublicKeys = new CitizenPublicKey[numKeys];
- for (int i = 0; i < numKeys;) {
- citizenPublicKeys[i] = new CitizenPublicKey(++i);
- }
-
- byte[] signatureValue = compressedIdentityLinkType.getSignatureValue();
- byte[] referenceDigest = compressedIdentityLinkType.getReferenceDigest();
- byte[] referenceManifestDigest = compressedIdentityLinkType.getReferenceManifestDigest();
- byte[] manifestReferenceDigest = compressedIdentityLinkType.getManifestReferenceDigest();
-
- IdentityLink idLink = new IdentityLink(issuerTemplate, assertionID, issueInstant, personData, citizenPublicKeys, signatureValue);
- idLink.setReferenceDigest(referenceDigest);
- idLink.setReferenceManifestDigest(referenceManifestDigest);
- idLink.setManifestReferenceDigest(manifestReferenceDigest);
-
- return idLink;
-
- }
-
- /**
- * Creates a new <code>CompressedIdentityLink</code> element from the given
- * ASN.1 representation of an <code>idLink</code>.
- *
- * @param idLink
- * the ASN.1 representation of an <code>IdentityLink</code>
- * @param certificates
- * a list of {@link X509Certificate}s containing the corresponding
- * public keys
- * @param domainId TODO
- * @return a new <code>CompressedIdentityLink</code> element
- *
- * @throws NullPointerException
- * if <code>idLink</code> or <code>certificates</code> is
- * <code>null</code>
- * @throws IllegalArgumentException
- * if <code>idLink</code> references certificates not in the range
- * of the <code>certificates</code> list
- */
- public JAXBElement<CompressedIdentityLinkType> createCompressedIdentityLink(
- at.gv.egiz.idlink.ans1.IdentityLink idLink,
- List<X509Certificate> certificates, String domainId) {
-
- at.gv.e_government.reference.namespace.persondata._20020228_.ObjectFactory prFactory =
- new at.gv.e_government.reference.namespace.persondata._20020228_.ObjectFactory();
-
- at.buergerkarte.namespaces.personenbindung._20020506_.ObjectFactory pbFactory =
- new at.buergerkarte.namespaces.personenbindung._20020506_.ObjectFactory();
-
- org.w3._2000._09.xmldsig_.ObjectFactory dsFactory = new org.w3._2000._09.xmldsig_.ObjectFactory();
-
- // PersonData
- PhysicalPersonData __physicalPersonData = idLink.getPersonData()
- .getPhysicalPerson();
-
- Value identificationTypeValue = prFactory.createIdentificationTypeValue();
- identificationTypeValue.setValue(__physicalPersonData.getBaseId());
- IdentificationType identificationType = prFactory
- .createIdentificationType();
- identificationType.setValue(identificationTypeValue);
- if (domainId != null) {
- identificationType.setType(domainId);
- } else {
- identificationType.setType("urn:publicid:gv.at:baseid");
- }
-
- PersonNameType personNameType = prFactory.createPersonNameType();
- FamilyName personNameTypeFamilyName = prFactory
- .createPersonNameTypeFamilyName();
- personNameTypeFamilyName.setValue(__physicalPersonData.getFamilyName());
- personNameType.getFamilyName().add(personNameTypeFamilyName);
- personNameType.getGivenName().add(__physicalPersonData.getGivenName());
-
- PhysicalPersonType physicalPersonType = prFactory
- .createPhysicalPersonType();
- physicalPersonType.getIdentification().add(identificationType);
- physicalPersonType.setName(personNameType);
- physicalPersonType.setDateOfBirth(__physicalPersonData.getDateOfBirth());
-
- // CompressedIdentityLink
- CompressedIdentityLinkType compressedIdentityLinkType = pbFactory
- .createCompressedIdentityLinkType();
- compressedIdentityLinkType.setIssuerTemplate(idLink.getIssuerTemplate());
- compressedIdentityLinkType.setAssertionID(idLink.getAssertionID());
- compressedIdentityLinkType.setIssueInstant(idLink.getIssueInstant());
- compressedIdentityLinkType.setPersonData(physicalPersonType);
-
- // CitizenPublicKey
- CitizenPublicKey[] __citizenPublicKeys = idLink.getCitizenPublicKeys();
- for (CitizenPublicKey __citizenPublicKey : __citizenPublicKeys) {
-
- X509Certificate certificate = certificates.get(__citizenPublicKey.getOnToken());
- PublicKey publicKey = certificate.getPublicKey();
-
- JAXBElement<?> keyValue;
- try {
- keyValue = keyValueFactory.createKeyValue(publicKey);
- } catch (KeyTypeNotSupportedException e) {
- // TODO: handle exception properly
- throw new RuntimeException(e);
- }
-
- KeyValueType keyValueType = dsFactory.createKeyValueType();
- keyValueType.getContent().add(keyValue);
-
- compressedIdentityLinkType.getCitizenPublicKey().add(keyValueType);
- }
-
- compressedIdentityLinkType.setSignatureValue(idLink.getSignatureValue());
- compressedIdentityLinkType.setReferenceDigest(idLink.getReferenceDigest());
- compressedIdentityLinkType.setReferenceManifestDigest(idLink
- .getReferenceManifestDigest());
- compressedIdentityLinkType.setManifestReferenceDigest(idLink
- .getManifestReferenceDigest());
- JAXBElement<CompressedIdentityLinkType> compressedIdentityLink = pbFactory
- .createCompressedIdentityLink(compressedIdentityLinkType);
-
- return compressedIdentityLink;
-
- }
-
- /**
- * Marshall the given <code>compressedIdentityLink</code> into a DOM document
- * with the given Nodes as <code>parent</code> and <code>nextSibling</code>
- * nodes.
- *
- * @param compressedIdentityLink
- * the <code>CompressedIdentityLink</code> element
- * @param parent
- * the parent node
- * @param nextSibling
- * the next sibling node (may be <code>null</code>)
- * @param applyWorkarounds
- * apply workarounds as spefiyed by
- * {@link #applyWorkarounds(Element, int)}
- *
- * @throws JAXBException
- * if an unexpected error occurs while marshalling
- * @throws NullPointerException
- * if <code>compressdIdentityLink</code> or <code>parent</code> is
- * <code>null</code>
- */
- public void marshallCompressedIdentityLink(
- JAXBElement<CompressedIdentityLinkType> compressedIdentityLink,
- Node parent, Node nextSibling, boolean applyWorkarounds) throws JAXBException {
-
- DOMResult result = new DOMResult(parent, nextSibling);
-
-
- try {
- Marshaller marshaller = jaxbContext.createMarshaller();
-
- marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
-
- marshaller.marshal(compressedIdentityLink, result);
- } catch (PropertyException e) {
- throw new RuntimeException(e);
- }
-
- if (applyWorkarounds) {
- Element element = (Element) ((nextSibling != null)
- ? nextSibling.getPreviousSibling()
- : parent.getFirstChild());
- applyWorkarounds(element, 76);
- }
-
- }
-
- @SuppressWarnings("unchecked")
- public CompressedIdentityLinkType unmarshallCompressedIdentityLink(Source source) throws JAXBException {
-
- Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
-
- return ((JAXBElement<CompressedIdentityLinkType>) unmarshaller.unmarshal(source)).getValue();
-
- }
-
- /**
- * Apply some workarounds to the given CompressedIdentityLink
- * <code>element</code> to achieve compatibility with IdentityLink
- * transformation stylesheets that have been designed for a (buggy) form of
- * the CompressedIdentityLink as produced by a well-known citizen card
- * environment implementation.
- *
- * <ol>
- * <li>Replace the attribute node <code>URN</code> of the
- * <code>NamedCurve</code> element of an <code>ECDSAKeyValue</code> element by
- * a child text-node with the same content.</li>
- * <li>Replace the attribute nodes <code>Value</code> of the <code>X</code>
- * and <code>Y</code> elements of an <code>ECDSAKeyValue</code> element by a
- * child text-node with the same content.</li>
- * <li>Insert &quot;\n&quot; at <code>base64LineLength</code> into the Base64
- * content of the <code>Modulus</code> element of an <code>RSAKeyValue</code>
- * element.
- * </ol>
- *
- * @param element
- * the <code>CompressedIdentityLink</code> element
- * @param base64LineLength
- * the line length of Base64 content
- */
- public void applyWorkarounds(Element element, int base64LineLength) {
-
- Document document = element.getOwnerDocument();
-
- NodeList nodeList = element.getElementsByTagNameNS(
- "http://www.w3.org/2001/04/xmldsig-more#", "NamedCurve");
- for (int i = 0; i < nodeList.getLength(); i++) {
- Node ecdsaNameCurve = nodeList.item(i);
- Attr attrNode = ((Element) ecdsaNameCurve).getAttributeNodeNS(null,
- "URN");
- ecdsaNameCurve
- .appendChild(document.createTextNode(attrNode.getValue()));
- ((Element) ecdsaNameCurve).removeAttributeNode(attrNode);
- }
- nodeList = document.getElementsByTagNameNS(
- "http://www.w3.org/2001/04/xmldsig-more#", "X");
- for (int i = 0; i < nodeList.getLength(); i++) {
- Node x = nodeList.item(i);
- Attr attrNode = ((Element) x).getAttributeNodeNS(null, "Value");
- x.appendChild(document.createTextNode(attrNode.getValue()));
- ((Element) x).removeAttributeNode(attrNode);
- }
- nodeList = document.getElementsByTagNameNS(
- "http://www.w3.org/2001/04/xmldsig-more#", "Y");
- for (int i = 0; i < nodeList.getLength(); i++) {
- Node y = nodeList.item(i);
- Attr attrNode = ((Element) y).getAttributeNodeNS(null, "Value");
- y.appendChild(document.createTextNode(attrNode.getValue()));
- ((Element) y).removeAttributeNode(attrNode);
- }
-
- if (base64LineLength > 0) {
- nodeList = document.getElementsByTagNameNS(
- "http://www.w3.org/2000/09/xmldsig#", "Modulus");
- for (int i = 0; i < nodeList.getLength(); i++) {
- Node modulus = nodeList.item(i);
- String value = ((Element) modulus).getTextContent();
- BufferedReader reader = new BufferedReader(new InputStreamReader(
- new ByteArrayInputStream(value.getBytes())));
- char[] buff = new char[base64LineLength];
- StringBuffer newValue = new StringBuffer();
- int found = 0;
- try {
- while ((found = reader.read(buff)) > 0) {
- newValue.append(buff, 0, found);
- if (found == base64LineLength)
- newValue.append('\n');
- }
- } catch (IOException e) {
- // this should never happen, as we are reading from a ByteArrayInputStream
- throw new RuntimeException(e);
- }
- ((Element) modulus).setTextContent(newValue.toString());
- }
-
- }
-
-
- }
-
-}
+package at.gv.egiz.idlink;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.security.PublicKey;
+import java.security.cert.X509Certificate;
+import java.util.List;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.PropertyException;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.transform.Source;
+import javax.xml.transform.dom.DOMResult;
+
+import org.w3._2000._09.xmldsig_.KeyValueType;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import at.buergerkarte.namespaces.personenbindung._20020506_.CompressedIdentityLinkType;
+import at.gv.e_government.reference.namespace.persondata._20020228_.AbstractPersonType;
+import at.gv.e_government.reference.namespace.persondata._20020228_.IdentificationType;
+import at.gv.e_government.reference.namespace.persondata._20020228_.PersonNameType;
+import at.gv.e_government.reference.namespace.persondata._20020228_.PhysicalPersonType;
+import at.gv.e_government.reference.namespace.persondata._20020228_.IdentificationType.Value;
+import at.gv.e_government.reference.namespace.persondata._20020228_.PersonNameType.FamilyName;
+import at.gv.egiz.idlink.ans1.CitizenPublicKey;
+import at.gv.egiz.idlink.ans1.IdentityLink;
+import at.gv.egiz.idlink.ans1.PersonData;
+import at.gv.egiz.idlink.ans1.PhysicalPersonData;
+import at.gv.egiz.marshal.MarshallerFactory;
+import at.gv.egiz.marshal.NamespacePrefixMapperImpl;
+import at.gv.egiz.xmldsig.KeyTypeNotSupportedException;
+import at.gv.egiz.xmldsig.KeyValueFactory;
+
+public class CompressedIdentityLinkFactory {
+
+ /**
+ * The instance returned by {@link #getInstance()}.
+ */
+ private static CompressedIdentityLinkFactory instance;
+
+ /**
+ * The <code>JAXBContext</code>.
+ */
+ private static JAXBContext jaxbContext;
+
+ /**
+ * The <code>KeyValueFactory</code>.
+ */
+ private static KeyValueFactory keyValueFactory;
+
+ /**
+ * Get an instance of this <code>CompressedIdentityLinkFactory</code>.
+ *
+ * @return an instance of this <code>CompressedIdentityLinkFactory</code>
+ */
+ public synchronized static CompressedIdentityLinkFactory getInstance() {
+ if (instance == null) {
+ instance = new CompressedIdentityLinkFactory();
+ }
+ return instance;
+ }
+
+ /**
+ * Private constructor.
+ */
+ private CompressedIdentityLinkFactory() {
+
+ keyValueFactory = new KeyValueFactory();
+
+ StringBuffer packageNames = new StringBuffer();
+ packageNames.append(at.gv.e_government.reference.namespace.persondata._20020228_.ObjectFactory.class.getPackage().getName());
+ packageNames.append(":");
+ packageNames.append(org.w3._2000._09.xmldsig_.ObjectFactory.class.getPackage().getName());
+ packageNames.append(":");
+ packageNames.append(org.w3._2001._04.xmldsig_more_.ObjectFactory.class.getPackage().getName());
+ packageNames.append(":");
+ packageNames.append(at.buergerkarte.namespaces.personenbindung._20020506_.ObjectFactory.class.getPackage().getName());
+
+ try {
+ jaxbContext = JAXBContext.newInstance(packageNames.toString());
+ } catch (JAXBException e) {
+ // we should not get an JAXBException initializing the JAXBContext
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ public IdentityLink createIdLink(CompressedIdentityLinkType compressedIdentityLinkType) {
+
+ // IssuerTemplate
+ String issuerTemplate = compressedIdentityLinkType.getIssuerTemplate();
+
+ // AssertionId
+ String assertionID = compressedIdentityLinkType.getAssertionID();
+
+ // IssueInstant
+ String issueInstant = compressedIdentityLinkType.getIssueInstant();
+
+ AbstractPersonType personDataType = compressedIdentityLinkType.getPersonData();
+
+ String baseId = null;
+
+ List<IdentificationType> identifications = personDataType.getIdentification();
+ for (IdentificationType identificationType : identifications) {
+ String type = identificationType.getType();
+ if ("urn:publicid:gv.at:baseid".equals(type)) {
+ baseId = identificationType.getValue().getValue();
+ }
+ }
+
+ String givenName = null;
+ String familyName = null;
+ String dateOfBirth = null;
+
+ if (personDataType instanceof PhysicalPersonType) {
+ PhysicalPersonType physicalPersonType = (PhysicalPersonType) personDataType;
+ PersonNameType name = physicalPersonType.getName();
+ List<String> givenNames = name.getGivenName();
+ if (!givenNames.isEmpty()) {
+ givenName = givenNames.get(0);
+ }
+ List<FamilyName> familyNames = name.getFamilyName();
+ if (!familyNames.isEmpty()) {
+ familyName = familyNames.get(0).getValue();
+ }
+ dateOfBirth = physicalPersonType.getDateOfBirth();
+ }
+
+ PhysicalPersonData physicalPersonData = new PhysicalPersonData(baseId, givenName, familyName, dateOfBirth);
+ PersonData personData = new PersonData(physicalPersonData);
+
+ int numKeys = compressedIdentityLinkType.getCitizenPublicKey().size();
+ CitizenPublicKey[] citizenPublicKeys = new CitizenPublicKey[numKeys];
+ for (int i = 0; i < numKeys;) {
+ citizenPublicKeys[i] = new CitizenPublicKey(++i);
+ }
+
+ byte[] signatureValue = compressedIdentityLinkType.getSignatureValue();
+ byte[] referenceDigest = compressedIdentityLinkType.getReferenceDigest();
+ byte[] referenceManifestDigest = compressedIdentityLinkType.getReferenceManifestDigest();
+ byte[] manifestReferenceDigest = compressedIdentityLinkType.getManifestReferenceDigest();
+
+ IdentityLink idLink = new IdentityLink(issuerTemplate, assertionID, issueInstant, personData, citizenPublicKeys, signatureValue);
+ idLink.setReferenceDigest(referenceDigest);
+ idLink.setReferenceManifestDigest(referenceManifestDigest);
+ idLink.setManifestReferenceDigest(manifestReferenceDigest);
+
+ return idLink;
+
+ }
+
+ /**
+ * Creates a new <code>CompressedIdentityLink</code> element from the given
+ * ASN.1 representation of an <code>idLink</code>.
+ *
+ * @param idLink
+ * the ASN.1 representation of an <code>IdentityLink</code>
+ * @param certificates
+ * a list of {@link X509Certificate}s containing the corresponding
+ * public keys
+ * @param domainId TODO
+ * @return a new <code>CompressedIdentityLink</code> element
+ *
+ * @throws NullPointerException
+ * if <code>idLink</code> or <code>certificates</code> is
+ * <code>null</code>
+ * @throws IllegalArgumentException
+ * if <code>idLink</code> references certificates not in the range
+ * of the <code>certificates</code> list
+ */
+ public JAXBElement<CompressedIdentityLinkType> createCompressedIdentityLink(
+ at.gv.egiz.idlink.ans1.IdentityLink idLink,
+ List<X509Certificate> certificates, String domainId) {
+
+ at.gv.e_government.reference.namespace.persondata._20020228_.ObjectFactory prFactory =
+ new at.gv.e_government.reference.namespace.persondata._20020228_.ObjectFactory();
+
+ at.buergerkarte.namespaces.personenbindung._20020506_.ObjectFactory pbFactory =
+ new at.buergerkarte.namespaces.personenbindung._20020506_.ObjectFactory();
+
+ org.w3._2000._09.xmldsig_.ObjectFactory dsFactory = new org.w3._2000._09.xmldsig_.ObjectFactory();
+
+ // PersonData
+ PhysicalPersonData __physicalPersonData = idLink.getPersonData()
+ .getPhysicalPerson();
+
+ Value identificationTypeValue = prFactory.createIdentificationTypeValue();
+ identificationTypeValue.setValue(__physicalPersonData.getBaseId());
+ IdentificationType identificationType = prFactory
+ .createIdentificationType();
+ identificationType.setValue(identificationTypeValue);
+ if (domainId != null) {
+ identificationType.setType(domainId);
+ } else {
+ identificationType.setType("urn:publicid:gv.at:baseid");
+ }
+
+ PersonNameType personNameType = prFactory.createPersonNameType();
+ FamilyName personNameTypeFamilyName = prFactory
+ .createPersonNameTypeFamilyName();
+ personNameTypeFamilyName.setValue(__physicalPersonData.getFamilyName());
+ personNameType.getFamilyName().add(personNameTypeFamilyName);
+ personNameType.getGivenName().add(__physicalPersonData.getGivenName());
+
+ PhysicalPersonType physicalPersonType = prFactory
+ .createPhysicalPersonType();
+ physicalPersonType.getIdentification().add(identificationType);
+ physicalPersonType.setName(personNameType);
+ physicalPersonType.setDateOfBirth(__physicalPersonData.getDateOfBirth());
+
+ // CompressedIdentityLink
+ CompressedIdentityLinkType compressedIdentityLinkType = pbFactory
+ .createCompressedIdentityLinkType();
+ compressedIdentityLinkType.setIssuerTemplate(idLink.getIssuerTemplate());
+ compressedIdentityLinkType.setAssertionID(idLink.getAssertionID());
+ compressedIdentityLinkType.setIssueInstant(idLink.getIssueInstant());
+ compressedIdentityLinkType.setPersonData(physicalPersonType);
+
+ // CitizenPublicKey
+ CitizenPublicKey[] __citizenPublicKeys = idLink.getCitizenPublicKeys();
+ for (CitizenPublicKey __citizenPublicKey : __citizenPublicKeys) {
+
+ X509Certificate certificate = certificates.get(__citizenPublicKey.getOnToken());
+ PublicKey publicKey = certificate.getPublicKey();
+
+ JAXBElement<?> keyValue;
+ try {
+ keyValue = keyValueFactory.createKeyValue(publicKey);
+ } catch (KeyTypeNotSupportedException e) {
+ // TODO: handle exception properly
+ throw new RuntimeException(e);
+ }
+
+ KeyValueType keyValueType = dsFactory.createKeyValueType();
+ keyValueType.getContent().add(keyValue);
+
+ compressedIdentityLinkType.getCitizenPublicKey().add(keyValueType);
+ }
+
+ compressedIdentityLinkType.setSignatureValue(idLink.getSignatureValue());
+ compressedIdentityLinkType.setReferenceDigest(idLink.getReferenceDigest());
+ compressedIdentityLinkType.setReferenceManifestDigest(idLink
+ .getReferenceManifestDigest());
+ compressedIdentityLinkType.setManifestReferenceDigest(idLink
+ .getManifestReferenceDigest());
+ JAXBElement<CompressedIdentityLinkType> compressedIdentityLink = pbFactory
+ .createCompressedIdentityLink(compressedIdentityLinkType);
+
+ return compressedIdentityLink;
+
+ }
+
+ /**
+ * Marshall the given <code>compressedIdentityLink</code> into a DOM document
+ * with the given Nodes as <code>parent</code> and <code>nextSibling</code>
+ * nodes.
+ *
+ * @param compressedIdentityLink
+ * the <code>CompressedIdentityLink</code> element
+ * @param parent
+ * the parent node
+ * @param nextSibling
+ * the next sibling node (may be <code>null</code>)
+ * @param applyWorkarounds
+ * apply workarounds as spefiyed by
+ * {@link #applyWorkarounds(Element, int)}
+ *
+ * @throws JAXBException
+ * if an unexpected error occurs while marshalling
+ * @throws NullPointerException
+ * if <code>compressdIdentityLink</code> or <code>parent</code> is
+ * <code>null</code>
+ */
+ public void marshallCompressedIdentityLink(
+ JAXBElement<CompressedIdentityLinkType> compressedIdentityLink,
+ Node parent, Node nextSibling, boolean applyWorkarounds) throws JAXBException {
+
+ DOMResult result = new DOMResult(parent, nextSibling);
+
+
+ try {
+ Marshaller marshaller = MarshallerFactory.createMarshaller(jaxbContext);
+
+ marshaller.marshal(compressedIdentityLink, result);
+ } catch (PropertyException e) {
+ throw new RuntimeException(e);
+ }
+
+ if (applyWorkarounds) {
+ Element element = (Element) ((nextSibling != null)
+ ? nextSibling.getPreviousSibling()
+ : parent.getFirstChild());
+ applyWorkarounds(element, 76);
+ }
+
+ }
+
+ @SuppressWarnings("unchecked")
+ public CompressedIdentityLinkType unmarshallCompressedIdentityLink(Source source) throws JAXBException {
+
+ Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
+
+ return ((JAXBElement<CompressedIdentityLinkType>) unmarshaller.unmarshal(source)).getValue();
+
+ }
+
+ /**
+ * Apply some workarounds to the given CompressedIdentityLink
+ * <code>element</code> to achieve compatibility with IdentityLink
+ * transformation stylesheets that have been designed for a (buggy) form of
+ * the CompressedIdentityLink as produced by a well-known citizen card
+ * environment implementation.
+ *
+ * <ol>
+ * <li>Replace the attribute node <code>URN</code> of the
+ * <code>NamedCurve</code> element of an <code>ECDSAKeyValue</code> element by
+ * a child text-node with the same content.</li>
+ * <li>Replace the attribute nodes <code>Value</code> of the <code>X</code>
+ * and <code>Y</code> elements of an <code>ECDSAKeyValue</code> element by a
+ * child text-node with the same content.</li>
+ * <li>Insert &quot;\n&quot; at <code>base64LineLength</code> into the Base64
+ * content of the <code>Modulus</code> element of an <code>RSAKeyValue</code>
+ * element.
+ * </ol>
+ *
+ * @param element
+ * the <code>CompressedIdentityLink</code> element
+ * @param base64LineLength
+ * the line length of Base64 content
+ */
+ public void applyWorkarounds(Element element, int base64LineLength) {
+
+ Document document = element.getOwnerDocument();
+
+ NodeList nodeList = element.getElementsByTagNameNS(
+ "http://www.w3.org/2001/04/xmldsig-more#", "NamedCurve");
+ for (int i = 0; i < nodeList.getLength(); i++) {
+ Node ecdsaNameCurve = nodeList.item(i);
+ Attr attrNode = ((Element) ecdsaNameCurve).getAttributeNodeNS(null,
+ "URN");
+ ecdsaNameCurve
+ .appendChild(document.createTextNode(attrNode.getValue()));
+ ((Element) ecdsaNameCurve).removeAttributeNode(attrNode);
+ }
+ nodeList = document.getElementsByTagNameNS(
+ "http://www.w3.org/2001/04/xmldsig-more#", "X");
+ for (int i = 0; i < nodeList.getLength(); i++) {
+ Node x = nodeList.item(i);
+ Attr attrNode = ((Element) x).getAttributeNodeNS(null, "Value");
+ x.appendChild(document.createTextNode(attrNode.getValue()));
+ ((Element) x).removeAttributeNode(attrNode);
+ }
+ nodeList = document.getElementsByTagNameNS(
+ "http://www.w3.org/2001/04/xmldsig-more#", "Y");
+ for (int i = 0; i < nodeList.getLength(); i++) {
+ Node y = nodeList.item(i);
+ Attr attrNode = ((Element) y).getAttributeNodeNS(null, "Value");
+ y.appendChild(document.createTextNode(attrNode.getValue()));
+ ((Element) y).removeAttributeNode(attrNode);
+ }
+
+ if (base64LineLength > 0) {
+ nodeList = document.getElementsByTagNameNS(
+ "http://www.w3.org/2000/09/xmldsig#", "Modulus");
+ for (int i = 0; i < nodeList.getLength(); i++) {
+ Node modulus = nodeList.item(i);
+ String value = ((Element) modulus).getTextContent();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(
+ new ByteArrayInputStream(value.getBytes())));
+ char[] buff = new char[base64LineLength];
+ StringBuffer newValue = new StringBuffer();
+ int found = 0;
+ try {
+ while ((found = reader.read(buff)) > 0) {
+ newValue.append(buff, 0, found);
+ if (found == base64LineLength)
+ newValue.append('\n');
+ }
+ } catch (IOException e) {
+ // this should never happen, as we are reading from a ByteArrayInputStream
+ throw new RuntimeException(e);
+ }
+ ((Element) modulus).setTextContent(newValue.toString());
+ }
+
+ }
+
+
+ }
+
+}
diff --git a/utils/src/main/java/at/gv/egiz/idlink/IdentityLinkFactory.java b/utils/src/main/java/at/gv/egiz/idlink/IdentityLinkFactory.java
index fb7943dc..38597446 100644
--- a/utils/src/main/java/at/gv/egiz/idlink/IdentityLinkFactory.java
+++ b/utils/src/main/java/at/gv/egiz/idlink/IdentityLinkFactory.java
@@ -87,6 +87,8 @@ import at.gv.e_government.reference.namespace.persondata._20020228_.PersonNameTy
import at.gv.e_government.reference.namespace.persondata._20020228_.PhysicalPersonType;
import at.gv.e_government.reference.namespace.persondata._20020228_.IdentificationType.Value;
import at.gv.e_government.reference.namespace.persondata._20020228_.PersonNameType.FamilyName;
+import at.gv.egiz.marshal.MarshallerFactory;
+import at.gv.egiz.marshal.NamespacePrefixMapperImpl;
import at.gv.egiz.xmldsig.KeyTypeNotSupportedException;
import at.gv.egiz.xmldsig.KeyValueFactory;
import oasis.names.tc.saml._1_0.assertion.AnyType;
@@ -276,9 +278,7 @@ public class IdentityLinkFactory {
DOMResult result = new DOMResult(parent, nextSibling);
try {
- Marshaller marshaller = jaxbContext.createMarshaller();
-
- marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
+ Marshaller marshaller = MarshallerFactory.createMarshaller(jaxbContext, true);
marshaller.marshal(identityLink, result);
} catch (PropertyException e) {
diff --git a/utils/src/main/java/at/gv/egiz/marshal/MarshallerFactory.java b/utils/src/main/java/at/gv/egiz/marshal/MarshallerFactory.java
new file mode 100644
index 00000000..ccebcc81
--- /dev/null
+++ b/utils/src/main/java/at/gv/egiz/marshal/MarshallerFactory.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2008 Federal Chancellery Austria and
+ * Graz University of Technology
+ *
+ * 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 at.gv.egiz.marshal;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.PropertyException;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ *
+ * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>
+ */
+public class MarshallerFactory {
+
+ private static final Log log = LogFactory.getLog(MarshallerFactory.class);
+
+ public static Marshaller createMarshaller(JAXBContext ctx, boolean formattedOutput) throws JAXBException {
+ Marshaller m = ctx.createMarshaller();
+ try {
+ if (formattedOutput) {
+ log.trace("setting marshaller property FORMATTED_OUTPUT");
+ m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
+ }
+ log.trace("setting marshaller property NamespacePrefixMapper");
+ m.setProperty("com.sun.xml.bind.namespacePrefixMapper", new NamespacePrefixMapperImpl());
+ } catch (PropertyException ex) {
+ log.info("failed to set marshaller property: " + ex.getMessage());
+ }
+ return m;
+ }
+
+ public static Marshaller createMarshaller(JAXBContext ctx) throws JAXBException {
+ return createMarshaller(ctx, false);
+ }
+}
diff --git a/utils/src/main/java/at/gv/egiz/marshal/NamespacePrefixMapperImpl.java b/utils/src/main/java/at/gv/egiz/marshal/NamespacePrefixMapperImpl.java
new file mode 100644
index 00000000..a08c1188
--- /dev/null
+++ b/utils/src/main/java/at/gv/egiz/marshal/NamespacePrefixMapperImpl.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2008 Federal Chancellery Austria and
+ * Graz University of Technology
+ *
+ * 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 at.gv.egiz.marshal;
+
+//import com.sun.xml.internal.bind.marshaller.NamespacePrefixMapper;
+import com.sun.xml.bind.marshaller.NamespacePrefixMapper;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ *
+ * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>
+ */
+public class NamespacePrefixMapperImpl extends NamespacePrefixMapper {
+
+ private static final Log log = LogFactory.getLog(NamespacePrefixMapperImpl.class);
+
+ @Override
+ public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) {
+
+ if (log.isTraceEnabled()) {
+ log.trace("prefix for namespace " + namespaceUri + " requested");
+ }
+ if ("http://www.w3.org/2001/XMLSchema-instance".equals(namespaceUri)) {
+ return "xsi";
+ }
+
+ if ("http://www.w3.org/2000/09/xmldsig#".equals(namespaceUri)) {
+ return "dsig";
+ }
+
+ if ("http://www.buergerkarte.at/namespaces/securitylayer/1.2#".equals(namespaceUri)) {
+ return "sl";
+ }
+
+ if ("http://www.buergerkarte.at/cardchannel".equals(namespaceUri)) {
+ return "cc";
+ }
+
+ if ("http://www.w3.org/2001/04/xmldsig-more#".equals(namespaceUri)) {
+ return "ecdsa";
+ }
+
+ if ("http://reference.e-government.gv.at/namespace/persondata/20020228#".equals(namespaceUri)) {
+ return "pr";
+ }
+
+ if ("urn:oasis:names:tc:SAML:1.0:assertion".equals(namespaceUri)) {
+ return "saml";
+ }
+
+ if ("http://uri.etsi.org/01903/v1.1.1#".equals(namespaceUri)) {
+ return "xades";
+ }
+
+ return suggestion;
+ }
+
+ /**
+ * Returns a list of namespace URIs that should be declared
+ * at the root element.
+ * <p>
+ * By default, the JAXB RI produces namespace declarations only when
+ * they are necessary, only at where they are used. Because of this
+ * lack of look-ahead, sometimes the marshaller produces a lot of
+ * namespace declarations that look redundant to human eyes. For example,
+ */
+ @Override
+ public String[] getPreDeclaredNamespaceUris() {
+ return new String[]{ "http://www.buergerkarte.at/namespaces/securitylayer/1.2#" };
+ }
+}
diff --git a/utils/src/main/java/at/gv/egiz/xades/QualifyingPropertiesFactory.java b/utils/src/main/java/at/gv/egiz/xades/QualifyingPropertiesFactory.java
index ae159215..71ca1db9 100644
--- a/utils/src/main/java/at/gv/egiz/xades/QualifyingPropertiesFactory.java
+++ b/utils/src/main/java/at/gv/egiz/xades/QualifyingPropertiesFactory.java
@@ -14,212 +14,212 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package at.gv.egiz.xades;
-
-import java.math.BigInteger;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.cert.CertificateEncodingException;
-import java.security.cert.X509Certificate;
-import java.util.Date;
-import java.util.GregorianCalendar;
-import java.util.List;
-import java.util.TimeZone;
-
-import javax.xml.bind.JAXBContext;
-import javax.xml.bind.JAXBElement;
-import javax.xml.bind.JAXBException;
-import javax.xml.bind.Marshaller;
-import javax.xml.bind.PropertyException;
-import javax.xml.crypto.dsig.DigestMethod;
-import javax.xml.datatype.DatatypeConfigurationException;
-import javax.xml.datatype.DatatypeFactory;
-import javax.xml.datatype.XMLGregorianCalendar;
-
-import org.etsi.uri._01903.v1_1.CertIDListType;
-import org.etsi.uri._01903.v1_1.CertIDType;
-import org.etsi.uri._01903.v1_1.DataObjectFormatType;
-import org.etsi.uri._01903.v1_1.DigestAlgAndValueType;
-import org.etsi.uri._01903.v1_1.QualifyingPropertiesType;
-import org.etsi.uri._01903.v1_1.SignaturePolicyIdentifierType;
-import org.etsi.uri._01903.v1_1.SignedDataObjectPropertiesType;
-import org.etsi.uri._01903.v1_1.SignedPropertiesType;
-import org.etsi.uri._01903.v1_1.SignedSignaturePropertiesType;
-import org.w3._2000._09.xmldsig_.DigestMethodType;
-import org.w3._2000._09.xmldsig_.X509IssuerSerialType;
-import org.w3c.dom.Node;
-
-public class QualifyingPropertiesFactory {
-
- public static String NS_URI_V1_1_1 = "http://uri.etsi.org/01903/v1.1.1#";
-
- public static String SIGNED_PROPERTIES_REFERENCE_TYPE_V1_1_1 = NS_URI_V1_1_1 + "SignedProperties";
-
- private static QualifyingPropertiesFactory instance;
-
- /**
- * The <code>JAXBContext</code>.
- */
- private static JAXBContext jaxbContext;
-
- public static synchronized QualifyingPropertiesFactory getInstance() {
- if (instance == null) {
- instance = new QualifyingPropertiesFactory();
- }
- return instance;
- }
-
- private DatatypeFactory datatypeFactory;
-
- private org.etsi.uri._01903.v1_1.ObjectFactory qpFactory;
-
- private org.w3._2000._09.xmldsig_.ObjectFactory dsFactory;
-
- public QualifyingPropertiesFactory() {
-
- try {
- datatypeFactory = DatatypeFactory.newInstance();
- } catch (DatatypeConfigurationException e) {
- throw new RuntimeException(e);
- }
-
- qpFactory = new org.etsi.uri._01903.v1_1.ObjectFactory();
-
- dsFactory = new org.w3._2000._09.xmldsig_.ObjectFactory();
-
- StringBuffer packageNames = new StringBuffer();
-
- packageNames.append(org.etsi.uri._01903.v1_1.ObjectFactory.class.getPackage().getName());
- packageNames.append(":");
- packageNames.append(org.w3._2000._09.xmldsig_.ObjectFactory.class.getPackage().getName());
-
- try {
- jaxbContext = JAXBContext.newInstance(packageNames.toString());
- } catch (JAXBException e) {
- // we should not get an JAXBException initializing the JAXBContext
- throw new RuntimeException(e);
- }
-
- }
-
- public DigestAlgAndValueType createDigestAlgAndValueType(X509Certificate certificate) throws QualifyingPropertiesException {
-
- DigestMethodType digestMethodType = dsFactory.createDigestMethodType();
- digestMethodType.setAlgorithm(DigestMethod.SHA1);
-
- byte[] digest;
- try {
- MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
- digest = messageDigest.digest(certificate.getEncoded());
- } catch (CertificateEncodingException e) {
- throw new QualifyingPropertiesException(e);
- } catch (NoSuchAlgorithmException e) {
- throw new QualifyingPropertiesException(e);
- }
-
- DigestAlgAndValueType digestAlgAndValueType = qpFactory.createDigestAlgAndValueType();
- digestAlgAndValueType.setDigestMethod(digestMethodType);
- digestAlgAndValueType.setDigestValue(digest);
-
- return digestAlgAndValueType;
-
- }
-
- public X509IssuerSerialType createX509IssuerSerialType(X509Certificate certificate) {
-
- String name = certificate.getIssuerX500Principal().getName("RFC2253");
- BigInteger serialNumber = certificate.getSerialNumber();
-
- X509IssuerSerialType issuerSerialType = dsFactory.createX509IssuerSerialType();
- issuerSerialType.setX509IssuerName(name);
- issuerSerialType.setX509SerialNumber(serialNumber);
-
- return issuerSerialType;
-
- }
-
- public DataObjectFormatType createDataObjectFormatType(String objectReference, String mimeType, String description) {
-
- DataObjectFormatType dataObjectFormatType = qpFactory.createDataObjectFormatType();
- dataObjectFormatType.setObjectReference(objectReference);
-
- if (mimeType != null) {
- dataObjectFormatType.setMimeType(mimeType);
- }
- if (description != null) {
- dataObjectFormatType.setDescription(description);
- }
-
- return dataObjectFormatType;
- }
-
- public JAXBElement<QualifyingPropertiesType> createQualifyingProperties111(Date signingTime, List<X509Certificate> certificates, String idValue, List<DataObjectFormatType> dataObjectFormats) throws QualifyingPropertiesException {
-
- GregorianCalendar gregorianCalendar = new GregorianCalendar();
- gregorianCalendar.setTimeZone(TimeZone.getTimeZone("UTC"));
- gregorianCalendar.setTime(signingTime);
-
- SignedSignaturePropertiesType signedSignaturePropertiesType = qpFactory.createSignedSignaturePropertiesType();
-
- // SigningTime
- XMLGregorianCalendar xmlGregorianCalendar = datatypeFactory.newXMLGregorianCalendar(gregorianCalendar);
- xmlGregorianCalendar.setFractionalSecond(null);
- signedSignaturePropertiesType.setSigningTime(xmlGregorianCalendar);
-
- // SigningCertificate
- CertIDListType certIDListType = qpFactory.createCertIDListType();
- List<CertIDType> certIDs = certIDListType.getCert();
-
- for (X509Certificate certificate : certificates) {
-
- CertIDType certIDType = qpFactory.createCertIDType();
- certIDType.setCertDigest(createDigestAlgAndValueType(certificate));
- certIDType.setIssuerSerial(createX509IssuerSerialType(certificate));
-
- certIDs.add(certIDType);
-
- }
- signedSignaturePropertiesType.setSigningCertificate(certIDListType);
-
- // SignaturePolicy
- SignaturePolicyIdentifierType signaturePolicyIdentifierType = qpFactory.createSignaturePolicyIdentifierType();
- signaturePolicyIdentifierType.setSignaturePolicyImplied(new SignaturePolicyIdentifierType.SignaturePolicyImplied());
- signedSignaturePropertiesType.setSignaturePolicyIdentifier(signaturePolicyIdentifierType);
-
- // SignedProperties
- SignedPropertiesType signedPropertiesType = qpFactory.createSignedPropertiesType();
- signedPropertiesType.setSignedSignatureProperties(signedSignaturePropertiesType);
-
- // DataObjectFormat
- if (dataObjectFormats != null && !dataObjectFormats.isEmpty()) {
- SignedDataObjectPropertiesType signedDataObjectPropertiesType = qpFactory.createSignedDataObjectPropertiesType();
- List<DataObjectFormatType> dataObjectFormatTypes = signedDataObjectPropertiesType.getDataObjectFormat();
- dataObjectFormatTypes.addAll(dataObjectFormats);
- signedPropertiesType.setSignedDataObjectProperties(signedDataObjectPropertiesType);
- }
-
- signedPropertiesType.setId(idValue);
-
- // QualifyingProperties
- QualifyingPropertiesType qualifyingPropertiesType = qpFactory.createQualifyingPropertiesType();
- qualifyingPropertiesType.setSignedProperties(signedPropertiesType);
-
- return qpFactory.createQualifyingProperties(qualifyingPropertiesType);
-
- }
-
- public void marshallQualifyingProperties(JAXBElement<QualifyingPropertiesType> qualifyingProperties, Node parent) throws JAXBException {
-
- try {
- Marshaller marshaller = jaxbContext.createMarshaller();
-
- marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
-
- marshaller.marshal(qualifyingProperties, parent);
- } catch (PropertyException e) {
- throw new RuntimeException(e);
- }
-
- }
-
-}
+package at.gv.egiz.xades;
+
+import at.gv.egiz.marshal.MarshallerFactory;
+import at.gv.egiz.marshal.NamespacePrefixMapperImpl;
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.List;
+import java.util.TimeZone;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.PropertyException;
+import javax.xml.crypto.dsig.DigestMethod;
+import javax.xml.datatype.DatatypeConfigurationException;
+import javax.xml.datatype.DatatypeFactory;
+import javax.xml.datatype.XMLGregorianCalendar;
+
+import org.etsi.uri._01903.v1_1.CertIDListType;
+import org.etsi.uri._01903.v1_1.CertIDType;
+import org.etsi.uri._01903.v1_1.DataObjectFormatType;
+import org.etsi.uri._01903.v1_1.DigestAlgAndValueType;
+import org.etsi.uri._01903.v1_1.QualifyingPropertiesType;
+import org.etsi.uri._01903.v1_1.SignaturePolicyIdentifierType;
+import org.etsi.uri._01903.v1_1.SignedDataObjectPropertiesType;
+import org.etsi.uri._01903.v1_1.SignedPropertiesType;
+import org.etsi.uri._01903.v1_1.SignedSignaturePropertiesType;
+import org.w3._2000._09.xmldsig_.DigestMethodType;
+import org.w3._2000._09.xmldsig_.X509IssuerSerialType;
+import org.w3c.dom.Node;
+
+public class QualifyingPropertiesFactory {
+
+ public static String NS_URI_V1_1_1 = "http://uri.etsi.org/01903/v1.1.1#";
+
+ public static String SIGNED_PROPERTIES_REFERENCE_TYPE_V1_1_1 = NS_URI_V1_1_1 + "SignedProperties";
+
+ private static QualifyingPropertiesFactory instance;
+
+ /**
+ * The <code>JAXBContext</code>.
+ */
+ private static JAXBContext jaxbContext;
+
+ public static synchronized QualifyingPropertiesFactory getInstance() {
+ if (instance == null) {
+ instance = new QualifyingPropertiesFactory();
+ }
+ return instance;
+ }
+
+ private DatatypeFactory datatypeFactory;
+
+ private org.etsi.uri._01903.v1_1.ObjectFactory qpFactory;
+
+ private org.w3._2000._09.xmldsig_.ObjectFactory dsFactory;
+
+ public QualifyingPropertiesFactory() {
+
+ try {
+ datatypeFactory = DatatypeFactory.newInstance();
+ } catch (DatatypeConfigurationException e) {
+ throw new RuntimeException(e);
+ }
+
+ qpFactory = new org.etsi.uri._01903.v1_1.ObjectFactory();
+
+ dsFactory = new org.w3._2000._09.xmldsig_.ObjectFactory();
+
+ StringBuffer packageNames = new StringBuffer();
+
+ packageNames.append(org.etsi.uri._01903.v1_1.ObjectFactory.class.getPackage().getName());
+ packageNames.append(":");
+ packageNames.append(org.w3._2000._09.xmldsig_.ObjectFactory.class.getPackage().getName());
+
+ try {
+ jaxbContext = JAXBContext.newInstance(packageNames.toString());
+ } catch (JAXBException e) {
+ // we should not get an JAXBException initializing the JAXBContext
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ public DigestAlgAndValueType createDigestAlgAndValueType(X509Certificate certificate) throws QualifyingPropertiesException {
+
+ DigestMethodType digestMethodType = dsFactory.createDigestMethodType();
+ digestMethodType.setAlgorithm(DigestMethod.SHA1);
+
+ byte[] digest;
+ try {
+ MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
+ digest = messageDigest.digest(certificate.getEncoded());
+ } catch (CertificateEncodingException e) {
+ throw new QualifyingPropertiesException(e);
+ } catch (NoSuchAlgorithmException e) {
+ throw new QualifyingPropertiesException(e);
+ }
+
+ DigestAlgAndValueType digestAlgAndValueType = qpFactory.createDigestAlgAndValueType();
+ digestAlgAndValueType.setDigestMethod(digestMethodType);
+ digestAlgAndValueType.setDigestValue(digest);
+
+ return digestAlgAndValueType;
+
+ }
+
+ public X509IssuerSerialType createX509IssuerSerialType(X509Certificate certificate) {
+
+ String name = certificate.getIssuerX500Principal().getName("RFC2253");
+ BigInteger serialNumber = certificate.getSerialNumber();
+
+ X509IssuerSerialType issuerSerialType = dsFactory.createX509IssuerSerialType();
+ issuerSerialType.setX509IssuerName(name);
+ issuerSerialType.setX509SerialNumber(serialNumber);
+
+ return issuerSerialType;
+
+ }
+
+ public DataObjectFormatType createDataObjectFormatType(String objectReference, String mimeType, String description) {
+
+ DataObjectFormatType dataObjectFormatType = qpFactory.createDataObjectFormatType();
+ dataObjectFormatType.setObjectReference(objectReference);
+
+ if (mimeType != null) {
+ dataObjectFormatType.setMimeType(mimeType);
+ }
+ if (description != null) {
+ dataObjectFormatType.setDescription(description);
+ }
+
+ return dataObjectFormatType;
+ }
+
+ public JAXBElement<QualifyingPropertiesType> createQualifyingProperties111(Date signingTime, List<X509Certificate> certificates, String idValue, List<DataObjectFormatType> dataObjectFormats) throws QualifyingPropertiesException {
+
+ GregorianCalendar gregorianCalendar = new GregorianCalendar();
+ gregorianCalendar.setTimeZone(TimeZone.getTimeZone("UTC"));
+ gregorianCalendar.setTime(signingTime);
+
+ SignedSignaturePropertiesType signedSignaturePropertiesType = qpFactory.createSignedSignaturePropertiesType();
+
+ // SigningTime
+ XMLGregorianCalendar xmlGregorianCalendar = datatypeFactory.newXMLGregorianCalendar(gregorianCalendar);
+ xmlGregorianCalendar.setFractionalSecond(null);
+ signedSignaturePropertiesType.setSigningTime(xmlGregorianCalendar);
+
+ // SigningCertificate
+ CertIDListType certIDListType = qpFactory.createCertIDListType();
+ List<CertIDType> certIDs = certIDListType.getCert();
+
+ for (X509Certificate certificate : certificates) {
+
+ CertIDType certIDType = qpFactory.createCertIDType();
+ certIDType.setCertDigest(createDigestAlgAndValueType(certificate));
+ certIDType.setIssuerSerial(createX509IssuerSerialType(certificate));
+
+ certIDs.add(certIDType);
+
+ }
+ signedSignaturePropertiesType.setSigningCertificate(certIDListType);
+
+ // SignaturePolicy
+ SignaturePolicyIdentifierType signaturePolicyIdentifierType = qpFactory.createSignaturePolicyIdentifierType();
+ signaturePolicyIdentifierType.setSignaturePolicyImplied(new SignaturePolicyIdentifierType.SignaturePolicyImplied());
+ signedSignaturePropertiesType.setSignaturePolicyIdentifier(signaturePolicyIdentifierType);
+
+ // SignedProperties
+ SignedPropertiesType signedPropertiesType = qpFactory.createSignedPropertiesType();
+ signedPropertiesType.setSignedSignatureProperties(signedSignaturePropertiesType);
+
+ // DataObjectFormat
+ if (dataObjectFormats != null && !dataObjectFormats.isEmpty()) {
+ SignedDataObjectPropertiesType signedDataObjectPropertiesType = qpFactory.createSignedDataObjectPropertiesType();
+ List<DataObjectFormatType> dataObjectFormatTypes = signedDataObjectPropertiesType.getDataObjectFormat();
+ dataObjectFormatTypes.addAll(dataObjectFormats);
+ signedPropertiesType.setSignedDataObjectProperties(signedDataObjectPropertiesType);
+ }
+
+ signedPropertiesType.setId(idValue);
+
+ // QualifyingProperties
+ QualifyingPropertiesType qualifyingPropertiesType = qpFactory.createQualifyingPropertiesType();
+ qualifyingPropertiesType.setSignedProperties(signedPropertiesType);
+
+ return qpFactory.createQualifyingProperties(qualifyingPropertiesType);
+
+ }
+
+ public void marshallQualifyingProperties(JAXBElement<QualifyingPropertiesType> qualifyingProperties, Node parent) throws JAXBException {
+
+ try {
+ Marshaller marshaller = MarshallerFactory.createMarshaller(jaxbContext, true);
+
+ marshaller.marshal(qualifyingProperties, parent);
+ } catch (PropertyException e) {
+ throw new RuntimeException(e);
+ }
+
+ }
+
+}