diff options
Diffstat (limited to 'utils/src/main/java')
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 "\n" 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 "\n" 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); +    }  +     +  } +   +} | 
