3 Replies Latest reply on Feb 6, 2019 9:44 PM by 3878978

    XML Digital Signature throws NAMESPACE_ERR exception under OpenJDK 11 that works under Java SE 8

    3878978

      My XML Digital Signature code runs fine under Java 8 (1.8.0_161), but on upgrading to OpenJDK 11 (11.0.2, ), it now traps with an NAMESPACE_ERR exception:

       

      org.w3c.dom.DOMException: NAMESPACE_ERR: An attempt is made to create or change an object in a way which is incorrect with regard to namespaces.

      at java.xml/com.sun.org.apache.xerces.internal.dom.ElementNSImpl.setName(ElementNSImpl.java:109)

      at java.xml/com.sun.org.apache.xerces.internal.dom.ElementNSImpl.<init>(ElementNSImpl.java:84)

      at java.xml/com.sun.org.apache.xerces.internal.dom.CoreDocumentImpl.createElementNS(CoreDocumentImpl.java:2089)

      at java.xml.crypto/org.jcp.xml.dsig.internal.dom.XmlWriterToTree.writeStartElement(XmlWriterToTree.java:99)

      at java.xml.crypto/org.jcp.xml.dsig.internal.dom.Marshaller.marshalGenericNode(Marshaller.java:303)

      at java.xml.crypto/org.jcp.xml.dsig.internal.dom.Marshaller.marshalGenericNode(Marshaller.java:286)

      at java.xml.crypto/org.jcp.xml.dsig.internal.dom.Marshaller$14.marshalObject(Marshaller.java:251)

      at java.xml.crypto/org.jcp.xml.dsig.internal.dom.Marshaller$14.marshalObject(Marshaller.java:247)

      at java.xml.crypto/org.jcp.xml.dsig.internal.dom.XmlWriterToTree.marshalStructure(XmlWriterToTree.java:200)

      at java.xml.crypto/org.jcp.xml.dsig.internal.dom.DOMXMLObject.marshal(DOMXMLObject.java:180)

      at java.xml.crypto/org.jcp.xml.dsig.internal.dom.DOMXMLSignature.marshal(DOMXMLSignature.java:233)

      at java.xml.crypto/org.jcp.xml.dsig.internal.dom.DOMXMLSignature.sign(DOMXMLSignature.java:325)

      at com.esignforms.open.crypto.XmlDigitalSignature.sign(XmlDigitalSignature.java:208)

       

      If I revert back to Java 8, it works again. 

      I noted that our XML digital signature code makes no direct references to namespaces.  Basic code does set the DocumentBuildFactory to be namespace aware:

       

        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

        dbf.setNamespaceAware(true);

       

      When we sign under Java 8, this is the resulting digitally signed output for our XML <snapshot> element, which does have a namespace of our own:

       

      <snapshot xmlns="http://open.esignforms.com/XMLSchema/2011" timestamp="2019-01-30T12:40:46-08:00" type="document"><![CDATA[<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

      <html xmlns="http://www.w3.org/1999/xhtml">

      <head>

      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

      <title>Date Doc 1</title>

      <meta name="robots" content="noindex, nofollow" />

      <meta name="Description" content="Confidential document" />

      <meta name="viewport" content="width=device-width, initial-scale=1" />

      <meta name="Generator" content="Yozons Open eSignForms document generator version 19.1.19_p0129_1657" />

      <meta name="DeploymentId" content="bbfe9bed-918d-446b-9518-8ec303bafb83" />

      <meta name="TransactionId" content="5163276c-d8aa-436f-8a96-5bc0c9eca931" />

      <meta name="TransactionTemplateId" content="d15a91a3-87b8-457e-84bc-0b56ac7ebb10" />

      <meta name="TransactionMode" content="Test" />

      <meta name="PackageId" content="60301b59-ca07-429e-bb76-7083bfd6e642" />

      <meta name="PackageVersionId" content="61afd6f3-b79e-4d14-844d-3a38541020ea" />

      <meta name="PackageVersionPartyName" content="FirstParty" />

      <meta name="DocumentId" content="e105af31-4b37-4092-9795-48b7c762ae97" />

      <meta name="DocumentName" content="Date Doc 1" />

      <meta name="DocumentVersionId" content="52248c28-187e-43f0-8de8-98357fa63654" />

      <meta name="DocumentVersionPageId" content="62edfd59-be00-435a-9bd5-583cc84d220a" />

      <meta name="DocumentVersionPartyName" content="FirstParty" />

      <meta name="DocumentPageMode" content="REVIEW" />

      <meta name="HtmlRenderTimestamp" content="2019-01-30 12:40:43.041 PST" />

      <meta name="RequestIpAddr" content="50-46-115-249.evrt.wa.frontiernet.net (50.46.115.249)" />

      <meta name="RequestUserAgent" content="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0.3 Safari/605.1.15" />

      <base href="https://open.esignforms.com/demo/" />

      <style type="text/css">

      /* platform esf.css */

      @import url(//fonts.googleapis.com/css?family=Pacifico);

       

      body.esf { font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 1em; }

       

      .esf a img { border: none; }

       

      .esf table.center, .esf div.center { margin-left: auto; margin-right: auto; }

       

      .esf p.left, .esf span.left, .esf div.left, .esf th.left, .esf td.left { text-align: left; }

      .esf p.right, .esf span.right, .esf div.right, .esf th.right, .esf td.right { text-align: right; }

      .esf p.center, .esf span.center, .esf th.center, .esf td.center { text-align: center; }

      .esf p.justify, .esf span.justify, .esf div.justify { text-align: justify; }

       

      .esf .bottom { vertical-align: bottom; }

      .esf .top { vertical-align: top; }

      .esf .middle { vertical-align: middle; }

       

      .esf .w5 { width: 5%; }

      .esf .w10 { width: 10%; }

      .esf .w15 { width: 15%; }

      .esf .w20 { width: 20%; }

      .esf .w25 { width: 25%; }

      .esf .w30 { width: 30%; }

      .esf .w33 { width: 33%; }

      .esf .w34 { width: 34%; }

      .esf .w35 { width: 35%; }

      .esf .w40 { width: 40%; }

      .esf .w45 { width: 45%; }

      .esf .w48 { width: 48%; }

      .esf .w50 { width: 50%; }

      .esf .w60 { width: 60%; }

      .esf .w70 { width: 70%; }

      .esf .w75 { width: 75%; }

      .esf .w80 { width: 80%; }

      .esf .w85 { width: 85%; }

      .esf .w90 { width: 90%; }

      .esf .w95 { width: 95%; }

      .esf .w98 { width: 98%; }

      .esf .w100 { width: 100%; }

       

      .esf .boT { border-top: 1px solid black; }

      .esf .boB { border-bottom: 1px solid black; }

      .esf .boTB { border-top: 1px solid black; border-bottom: 1px solid black; }

      .esf .boL { border-left: 1px solid black; }

      .esf .boR { border-right: 1px solid black; }

      .esf .boLR { border-left: 1px solid black; border-right: 1px solid black; }

      .esf .boBdash { border-bottom: 1px dashed black; }

      .esf .boBdot { border-bottom: 1px dotted black; }

      .esf .boBthick { border-bottom: 4px solid black; }

       

      .esf .box { border: 1px solid black; }

      .esf .boxthicker { border: 2px solid black; }

      .esf .boxthick { border: 4px solid black; }

       

      .esf .underline { text-decoration: underline; }

      .esf .bold { font-weight: bold; }

      .esf .italic { font-style: italic; }

       

      .esf ::-webkit-input-placeholder { font-style: italic; }

      .esf :-moz-placeholder { font-style: italic; }

      .esf ::-moz-placeholder { font-style: italic; }

      .esf :-ms-input-placeholder { font-style: italic; }

       

      .esf .caps { text-transform: uppercase; }

      .esf .smallcaps { font-variant: small-caps; }

      .esf .lowercase { text-transform: lowercase; }

       

      .esf .f6 { font-size: 6pt; }

      .esf .f7 { font-size: 7pt; }

      .esf .f8 { font-size: 8pt; }

      .esf .f9 { font-size: 9pt; }

      .esf .f10 { font-size: 10pt; }

      .esf .f11 { font-size: 11pt; }

      .esf .f12 { font-size: 12pt; }

      .esf .f14 { font-size: 14pt; }

      .esf .f16 { font-size: 16pt; }

      .esf .f18 { font-size: 18pt; }

      .esf .f20 { font-size: 20pt; }

      .esf .f22 { font-size: 22pt; }

      .esf .f24 { font-size: 24pt; }

      .esf .f28 { font-size: 28pt; }

      .esf .f32 { font-size: 32pt; }

      .esf .f36 { font-size: 36pt; }

      .esf .f40 { font-size: 40pt; }

      .esf .f48 { font-size: 48pt; }

      .esf .f60 { font-size: 60pt; }

      .esf .f72 { font-size: 72pt; }

      .esf .f96 { font-size: 96pt; }

       

      .esf .red {color: red;}

      .esf .green {color: green;}

      .esf .blue {color: blue;}

      .esf .white {color: white;}

      .esf .black {color: black;}

      .esf .gray  {color: gray;}

       

      .esf .nomargin { margin: 0; }

      .esf .nomarginT { margin-top: 0; }

      .esf .nomarginB { margin-bottom: 0; }

      .esf .nomarginTB { margin-top: 0; margin-bottom: 0; }

      .esf .nomarginL { margin-left: 0; }

      .esf .nomarginR { margin-right: 0; }

      .esf .nomarginLR { margin-left: 0; margin-right: 0; }

      .esf .nowrap { white-space: nowrap; }

       

      /* HTML5 versions for table cellpadding="0" through cellpadding="5" */

      .esf table.cellpadding0 th, .esf table.cellpadding0 td { padding: 0; }

      .esf table.cellpadding1 th, .esf table.cellpadding1 td { padding: 1px; }

      .esf table.cellpadding2 th, .esf table.cellpadding2 td { padding: 2px; }

      .esf table.cellpadding3 th, .esf table.cellpadding3 td { padding: 3px; }

      .esf table.cellpadding4 th, .esf table.cellpadding4 td { padding: 4px; }

      .esf table.cellpadding5 th, .esf table.cellpadding5 td { padding: 5px; }

       

      /* HTML5 versions for table cellspacing="0" through cellspacing="5" */

      .esf table.cellspacing0 { border-spacing: 0; }

      .esf table.cellspacing1 { border-spacing: 1px; }

      .esf table.cellspacing2 { border-spacing: 2px; }

      .esf table.cellspacing3 { border-spacing: 3px; }

      .esf table.cellspacing4 { border-spacing: 4px; }

      .esf table.cellspacing5 { border-spacing: 5px; }

       

      /* HTML5 version of border="1" through border="2" */

      table.gridBorder { border-top: 1px solid black; border-left: 1px solid black; }

      table.gridBorder th, table.gridBorder td { border-bottom: 1px solid black; border-right: 1px solid black; }

      table.gridBorder2 { border-top: 2px solid black; border-left: 2px solid black; }

      table.gridBorder2 th, table.gridBorder2 td { border-bottom: 2px solid black; border-right: 2px solid black; }

       

      .esf div.newPage { border-top: 1px dotted gray; }

      .esf .doNotPrint { } /* do nothing normally, but we override in @print so suppress the element */

      .esf div.pagediv { } /* do nothing, but allows you to style as each page is wrapped in a div */

       

      .esf div.inline { display: inline-block; }

      .esf span.inlineblock { display: inline-block; }

       

      /* The following are generally not useful for a document, but are used in the auto-rendering of fields, labels, errors, etc. Many of these can be set via DocumentStyles in Open ESF. */

       

      /* For the Field Label rendering */

      .esf label.normal { }

      .esf label.normal-error { color: red; font-weight: bold; background-color: yellow; }

      .esf label.small { font-size: 8pt; }

      .esf label.small-error { font-size: 8pt; color: red; font-weight: bold; background-color: yellow; }

       

      .esf span.viewFieldData { width: inherit; } /* when viewing field data -- not in input mode */

      .esf span.viewFieldData-error { font-weight: bold; font-style: italic; background-color: pink; border: 2px dashed red; } /* when viewing data that was not known -- not in input mode */

       

      .esf span.labelFieldArea { display: inline-block; } /* sets the width for the label and field area */

       

      .esf span.labelFieldArea span.labelAreaStacked { display: block; white-space: nowrap; }

      .esf span.labelFieldArea span.labelAreaRightStacked { display: block; text-align: right; white-space: nowrap; }

      .esf span.labelFieldArea span.labelAreaCenterStacked { display: block; text-align: center; white-space: nowrap; }

      .esf span.labelFieldArea span.labelArea { display: inline-block; white-space: nowrap; }

      .esf span.labelFieldArea span.labelAreaRight { display: inline-block; text-align: right; white-space: nowrap; }

      .esf span.labelFieldArea span.labelAreaCenter { display: inline-block; text-align: center; white-space: nowrap; }

       

      .esf span.labelFieldArea span.fieldAreaStacked { display: block; width: 100%; }

      .esf span.labelFieldArea span.fieldAreaLeftStacked { display: block; width: 100%; text-align: left; }

      .esf span.labelFieldArea span.fieldAreaRightStacked { display: block; width: 100%; text-align: right; }

      .esf span.labelFieldArea span.fieldAreaCenterStacked { display: block; width: 100%; text-align: center; }

      .esf span.labelFieldArea span.fieldArea { display: inline-block; width: 100%; }

      .esf span.labelFieldArea span.fieldAreaLeft { display: inline-block; width: 100%; text-align: left; }

      .esf span.labelFieldArea span.fieldAreaRight { display: inline-block; width: 100%; text-align: right; }

      .esf span.labelFieldArea span.fieldAreaCenter { display: inline-block; width: 100%; text-align: center; }

       

      .esf span.labelFieldArea span.fieldAreaStackedAuto { display: block; width: auto; }

      .esf span.labelFieldArea span.fieldAreaLeftStackedAuto { display: block; width: auto; text-align: left; }

      .esf span.labelFieldArea span.fieldAreaRightStackedAuto { display: block; width: auto; text-align: right; }

      .esf span.labelFieldArea span.fieldAreaCenterStackedAuto { display: block; width: auto; text-align: center; }

      .esf span.labelFieldArea span.fieldAreaAuto { display: inline-block; width: auto; }

      .esf span.labelFieldArea span.fieldAreaLeftAuto { display: inline-block; width: auto; text-align: left; }

      .esf span.labelFieldArea span.fieldAreaRightAuto { display: inline-block; width: auto; text-align: right; }

      .esf span.labelFieldArea span.fieldAreaCenterAuto { display: inline-block; width: auto; text-align: center; }

       

      .esf span.fieldArea { display: inline-block; }

      .esf span.fieldAreaLeft { display: inline-block; text-align: left; }

      .esf span.fieldAreaRight { display: inline-block; text-align: right; }

      .esf span.fieldAreaCenter { display: inline-block; text-align: center; }

       

      .esf span.fieldAreaAuto { display: inline; }

      /* Auto widths do not make sense really with alignment as the field should be no bigger than the contents; we'll keep it inline-blocked */

      .esf span.fieldAreaLeftAuto { display: inline-block; text-align: left; }

      .esf span.fieldAreaRightAuto { display: inline-block; text-align: right; }

      .esf span.fieldAreaCenterAuto { display: inline-block; text-align: center; }

       

      /* For signature/initials display */

      .esf .signature, .esf .signature input { font-family: 'Pacifico', 'Bradley Hand ITC', 'Lucida Handwriting', 'Comic Sans MS', cursive; font-size: 14pt; color: blue; white-space: nowrap; }

      .esf div.signatureBlock { border: 3px solid #9899c4; border-radius: 10px; background-color: #efffff; padding: 0px 3px 3px 12px; width: 720px; page-break-inside: avoid; }

      .esf div.signatureBlock p.signatureHeader { font-size: 11pt; font-weight: bold; text-decoration: underline; margin-bottom: 0px; }

      .esf .signatureMetadata { font-size: 8pt; font-family: 'Courier New', Courier, monospace; white-space: nowrap; }

       

      /* For optional/required/error input fields; uses span.viewFieldData for showing the data when in non-edit mode */

      .esf input.required { background-color: #FFFFE7; font-weight: bold; border: 1px solid #7F9DB9; width: inherit; }

      .esf input.optional { background-color: white; font-weight: bold; border: 1px solid #7F9DB9; width: inherit; }

      .esf input.error { background-color: #FFC0CB; font-weight: bold; border: 1px solid red; width: inherit; }

      .esf select.required { background-color: #FFFFE7; font-weight: bold; border: 1px solid #7F9DB9; width: inherit; }

      .esf select.optional { background-color: white; font-weight: bold; border: 1px solid #7F9DB9; width: inherit; }

      .esf select.error { background-color: #FFC0CB; font-weight: bold; border: 1px solid red; width: inherit; }

      .esf textarea.required { background-color: #FFFFE7; font-weight: bold; border: 1px solid #7F9DB9; width: inherit; }

      .esf textarea.optional { background-color: white; font-weight: bold; border: 1px solid #7F9DB9; width: inherit; }

      .esf textarea.error { background-color: #FFC0CB; font-weight: bold; border: 1px solid red; width: inherit; }

      /* Special override for optional checkboxes to not have a border around them */

      .esf input[type="checkbox"].required { border: 0 none !important; outline-color: #FFFFE7; outline-style: solid; outline-width: medium; }

      .esf input[type="checkbox"].optional { border: 0 none !important; }

      .esf input[type="checkbox"].error { outline: 1px solid red; }

      /* Special override for optional radio to not have a border around them */

      .esf input[type="radio"].required { border: 0 none !important; outline-color: #FFFFE7; outline-style: solid; outline-width: medium; }

      .esf input[type="radio"].optional { border: 0 none !important; }

      .esf input[type="radio"].error { outline: 1px solid red; }

      .esf input[type="radio"] { margin-bottom: 3px; } /* push it up a bit so fits with label better */

       

      /* For buttons */

      .esf p.buttons { margin-top: 2em; margin-left: 2em; }

      .esf p.buttons input { margin-right: 2em; font-size: 1.1em; padding: 5px 10px; margin-top: 5px; }

      .esf p.buttons input.caution { color: #FF8000; }

      .esf p.buttons input.preferredFlow { font-weight: bold; color: green; font-size: 1.3em; padding: 8px 15px; }

       

      .esf p.extraButtons { text-align: right; margin-top: -3em; }

      .esf p.extraButtons input { color: blue; font-size: 0.6em; padding: 2px 3px; margin-right: 1em; }

       

      .esf div.documentAndPageNumbersInfo { font-family: 'Courier New', Courier, monospace; font-size: 8pt; text-align: right; color: lightgray; }

       

      /* For image overlays */

      .esf div.imageOverlay { position: relative; display: inline-block; }

      .esf div.imageOverlay img { margin: 0; padding: 0; }

      .esf div.imageOverlay span.imageOverlayFieldArea { position: absolute; margin: 0; padding: 0; }

      .esf div.imageOverlay span.imageOverlayFieldArea input[type="radio"] { margin: 0; padding: 0; }

      .esf div.imageOverlay span.imageOverlayFieldArea input[type="checkbox"] { margin: 0; padding: 0; }

       

      .esf input.small { font-size: 8pt; }

      .esf input.upload { color: green; }

       

      /* For file uploads of images displayed inline */

      .esf img.fileUploadInlineImage200 { max-width: 200px; border: 2px solid black; page-break-inside: avoid; }

      .esf img.fileUploadInlineImage400 { max-width: 400px; border: 2px solid black; page-break-inside: avoid; }

      .esf img.fileUploadInlineImage600 { max-width: 800px; border: 2px solid black; page-break-inside: avoid; }

      .esf img.fileUploadInlineImage800 { max-width: 800px; border: 2px solid black; page-break-inside: avoid; }

       

      /* For standard display of ErrorEntry[] arrays from Errors */

      .esf table.errorEntryArea { margin-left: 1em; border: 1px solid #FBD777; border-radius: 5px; background-color: #FDE8A5; width: 95%; padding-top: 2px; padding-bottom: 2px; }

      .esf ul.errorEntryArea { padding-left: 20px; }

      .esf li.error-ErrorEntry { list-style-type: circle; font-size: 1em; font-weight: bold; color: red; margin-left: 0px; margin-right: 1em; }

      .esf li.warning-ErrorEntry { list-style-type: circle; font-size: 1em; font-weight: bold; color: blue; margin-left: 0px; margin-right: 1em; }

      .esf li.success-ErrorEntry { list-style-type: circle; font-size: 1em; font-weight: bold; color: green; margin-left: 0px; margin-right: 1em; }

      .esf li.info-ErrorEntry { list-style-type: circle; font-size: 1em; font-weight: bold; color: black; margin-left: 0px; margin-right: 1em; }

       

      /* Used for multi-line reports to separate them like "greenbar paper" of old */

      .esf .bgGreenbarLight { background-color: transparent; }

      .esf .bgGreenbarDark { background-color: #E8E6E6; }

       

      .esf span.jspfooter { font-size: 8pt; color: gray; }

       

      .esf div.jspErrorPageMessage { margin-left: 1em; width: 700px; font-weight: bold; background-color: pink; border: 1px solid black; border-radius: 10px; padding: 0px 1em 0px 1em; }

       

      @media print {

        body.esf { margin: 0; padding: 0; font-size: 80% !important; }

        .esf div.newPage { border-top: none; page-break-after: always; }

        .esf a.showURL:link:after, a.showURL:visited:after { content: " (" attr(href) ")"; font-size: 80%; }

        .esf .doNotPrint { display: none; }

      }

       

       

      /* Begin document style id: 9a000404-5f56-4a1c-ad4a-be6382c67d97, version id: 86f339d5-81e2-4117-95c2-8f747f5a6fe3 */

      body.esf { font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 11pt;    }

      .esf .X86f339d5_81e2_4117_95c2_8f747f5a6fe3 span.signature { font-family: Pacifico, cursive; font-size: 14pt; color: blue; font-style: normal; font-weight: normal; font-variant: normal; text-transform: inherit;  }

      .esf .X86f339d5_81e2_4117_95c2_8f747f5a6fe3 span.signature input { font-family: Pacifico, cursive; font-size: 14pt; color: blue; font-style: normal; font-weight: normal; font-variant: normal; text-transform: inherit;  }

      .esf .X86f339d5_81e2_4117_95c2_8f747f5a6fe3 span.viewFieldData {      }

      .esf .X86f339d5_81e2_4117_95c2_8f747f5a6fe3 input[type='checkbox'].required { border: 0 none !important; outline-color: #FFFFE7; outline-style: solid; outline-width: medium; }

      .esf .X86f339d5_81e2_4117_95c2_8f747f5a6fe3 input[type='radio'].required { border: 0 none !important; outline-color: #FFFFE7; outline-style: solid; outline-width: medium; }

      .esf .X86f339d5_81e2_4117_95c2_8f747f5a6fe3 input.required {    font-style: normal; font-weight: bold; font-variant: normal; text-transform: inherit; background-color: #FFFFE7; border: 1px solid #7F9DB9; }

      .esf .X86f339d5_81e2_4117_95c2_8f747f5a6fe3 select.required {    font-style: normal; font-weight: bold; font-variant: normal; text-transform: inherit; background-color: #FFFFE7; border: 1px solid #7F9DB9; }

      .esf .X86f339d5_81e2_4117_95c2_8f747f5a6fe3 textarea.required {    font-style: normal; font-weight: bold; font-variant: normal; text-transform: inherit; background-color: #FFFFE7; border: 1px solid #7F9DB9; }

      .esf .X86f339d5_81e2_4117_95c2_8f747f5a6fe3 input.optional {    font-style: normal; font-weight: bold; font-variant: normal; text-transform: inherit; background-color: white; border: 1px solid #7F9DB9; }

      .esf .X86f339d5_81e2_4117_95c2_8f747f5a6fe3 select.optional {    font-style: normal; font-weight: bold; font-variant: normal; text-transform: inherit; background-color: white; border: 1px solid #7F9DB9; }

      .esf .X86f339d5_81e2_4117_95c2_8f747f5a6fe3 textarea.optional {    font-style: normal; font-weight: bold; font-variant: normal; text-transform: inherit; background-color: white; border: 1px solid #7F9DB9; }

      .esf .X86f339d5_81e2_4117_95c2_8f747f5a6fe3 input[type='checkbox'].error { border: 0 none !important; outline: 1px solid red; }

      .esf .X86f339d5_81e2_4117_95c2_8f747f5a6fe3 input[type='radio'].error { border: 0 none !important; outline: 1px solid red; }

      .esf .X86f339d5_81e2_4117_95c2_8f747f5a6fe3 input.error {    font-style: normal; font-weight: bold; font-variant: normal; text-transform: inherit; background-color: #FFC0CB; border: 1px solid red; }

      .esf .X86f339d5_81e2_4117_95c2_8f747f5a6fe3 select.error {    font-style: normal; font-weight: bold; font-variant: normal; text-transform: inherit; background-color: #FFC0CB; border: 1px solid red; }

      .esf .X86f339d5_81e2_4117_95c2_8f747f5a6fe3 textarea.error {    font-style: normal; font-weight: bold; font-variant: normal; text-transform: inherit; background-color: #FFC0CB; border: 1px solid red; }

      .esf .X86f339d5_81e2_4117_95c2_8f747f5a6fe3 label.normal {      }

      .esf .X86f339d5_81e2_4117_95c2_8f747f5a6fe3 label.normal-error {   color: red; font-style: normal; font-weight: bold; font-variant: normal; text-transform: inherit; background-color: yellow; }

      .esf .X86f339d5_81e2_4117_95c2_8f747f5a6fe3 label.small {  font-size: 8pt;    }

      .esf .X86f339d5_81e2_4117_95c2_8f747f5a6fe3 label.small-error {  font-size: 8pt; color: red; font-style: normal; font-weight: bold; font-variant: normal; text-transform: inherit; background-color: yellow; }

      /* End document style */

      </style>

      <script type="text/javascript">

      (function() {

        // If not defined yet, ensure our top "JavaScript namespace" variable 'esf' is created.

        if ( typeof esf == "undefined" ) {

        esf = {

        version: {

        major: 19, minor: 1, update: '19',

        toString: function(){

        with(esf.version){

        return major + "." + minor + "." + update;

        }

        }

        },

        appname: 'Open eSignForms',

        htmlCopyright: '&copy; 2019 Yozons, Inc.',

        textCopyright: 'Copyright (c) 2009-2019 Yozons, Inc.'

        };

       

        esf.getRelease = function() {

        return this.appname + " " + this.version.toString();

        };

       

        if ( typeof console != "undefined") console.log(esf.getRelease() + ' - ' + esf.textCopyright);

       

        esf.saveScrollPosition = function(elem) {

        var currLeft = window.pageXOffset || document.documentElement.scrollLeft;

        var currTop  = window.pageYOffset || document.documentElement.scrollTop;

        elem.form.ESF_PAGE_SCROLLLEFT.value = currLeft;  // form field name must match DocumentPageBean.HIDDEN_PAGE_SCROLLLEFT

        elem.form.ESF_PAGE_SCROLLTOP.value  = currTop;   // form field name must match DocumentPageBean.HIDDEN_PAGE_SCROLLTOP

        }

       

        esf.autoPost = function(inputField) {

        esf.confirmOnPageUnloadMessage = null; // do not block leaving page for autopost

        esf.hideAllSubmitInputFields();

        inputField.form.ESF_AUTO_POST_FIELD_ID.value = inputField.id; // form field name must match DocumentPageBean.HIDDEN_AUTO_POST_FIELD_ID

        esf.saveScrollPosition(inputField);

        inputField.form.submit();

        };

       

        esf.blockEnterKeyViaInputFields = function(e) {

        var evt = e || window.event;

        var node = (evt.target) ? evt.target : ((evt.srcElement) ? evt.srcElement : null);

        if ((evt.keyCode == 13) && (node.type=="text")) {

        return false;

        }

        };

       

        esf.checkConfirmOnPageUnload = function(confirm,durationMsec) {

        if (! confirm) {

        window.onbeforeunload = null;

        }

        if ( durationMsec && durationMsec > 0 )

        esf.hideAllSubmitInputFieldsTemporarily(durationMsec);

        else

        esf.hideAllSubmitInputFields();

        };

       

        // For links, we don't hide buttons and we don't clear the unload unless requested AND the target is _top or _self (or no target set)

        esf.checkLinkConfirmOnPageUnload = function(confirm,atag) {

        if (! confirm && (atag.target == "_top" || atag.target == "_self" || atag.target == "") ) {

        window.onbeforeunload = null;

        }

        };

       

        // Default is no message to display on page unload

        esf.confirmOnPageUnloadMessage = null;

       

        esf.confirmOnPageUnload = function(e) {

        e = e || window.event;

       

                if ( esf.confirmOnPageUnloadMessage ) {

                if (e) {

                e.returnValue = esf.confirmOnPageUnloadMessage;

                }

                    return esf.confirmOnPageUnloadMessage;

                }

        };

       

        esf.hideAllSubmitInputFields = function() {

          if ( document.getElementsByTagName ) {

          var inputFields = document.getElementsByTagName("input");

          for( var i=0; i < inputFields.length; ++i ) {

            if ( inputFields[i].type == "submit" )

                esf.makeInvisible(inputFields[i]);

          }

          var buttonFields = document.getElementsByTagName("button");

          for( var i=0; i < buttonFields.length; ++i ) {

          esf.makeInvisible(buttonFields[i]);

          }

          return true;

          }

        };

       

        esf.showAllSubmitInputFields = function() {

          if ( document.getElementsByTagName ) {

            var inputFields = document.getElementsByTagName("input");

          for( var i=0; i < inputFields.length; ++i ) {

            if ( inputFields[i].type == "submit" )

                esf.makeVisible(inputFields[i]);

          }

          var buttonFields = document.getElementsByTagName("button");

          for( var i=0; i < buttonFields.length; ++i ) {

          esf.makeVisible(buttonFields[i]);

          }

          return true;

          }

        };

       

        esf.hideAllSubmitInputFieldsTemporarily = function(durationMsec) {

        esf.hideAllSubmitInputFields();

        setTimeout( esf.showAllSubmitInputFields, durationMsec );

        };

       

        esf.displayById = function(id) {

        if ( document.getElementById && document.getElementById(id) )

        esf.display(document.getElementById(id));

        };

       

        esf.display = function(elem) {

        if ( elem && elem.style )

        elem.style.display = "block";

        };

       

        esf.hideById = function(id) {

        if ( document.getElementById && document.getElementById(id) )

        esf.hide(document.getElementById(id));

        };

       

        esf.hide = function(elem) {

        if ( elem && elem.style )

        elem.style.display = "none";

        };

       

        esf.makeVisibleById = function(id) {

        if ( document.getElementById && document.getElementById(id) )

        esf.makeVisible(document.getElementById(id));

        };

       

        esf.makeVisible = function(elem) {

          if ( elem && elem.style )

          elem.style.visibility = 'visible';

        };

       

        esf.makeInvisibleById = function(id) {

        if ( document.getElementById && document.getElementById(id) )

        esf.makeInvisible(document.getElementById(id));

        };

       

        esf.makeInvisible = function(elem) {

          if ( elem && elem.style )

          elem.style.visibility = 'hidden';

        };

       

        esf.makeTemporarilyInvisible = function(elem, durationMsec) {

        esf.makeInvisible(elem);

            setTimeout( function(){esf.makeVisible(elem);}, durationMsec );

        };

       

        esf.ensureTopWindow = function() {

          if (window != window.top)

        top.location.href = location.href;

        };

       

        esf.getElementsByFieldName = function(fieldName) {

          if ( document.getElementsByName ) {

          return document.getElementsByName(fieldName.toLowerCase()); // Field names are all lowercase in the HTML DOM

          }

          return []; // not really an empty node list, but an empty array so it has a 'length' property to query before accessing

        };

       

        esf.getElementByFieldName = function(fieldName) {

          var elemNL = esf.getElementsByFieldName(fieldName);

          return elemNL.length > 0 ? elemNL[0] : null;

        };

       

        esf.setAllCheckboxesByName = function(name,b) {

          var checkboxes = esf.getElementsByFieldName(name);

          for( var i=0; i < checkboxes.length; ++i ) {

            if ( checkboxes[i].type == "checkbox" )

                checkboxes[i].checked = b;

          }

        };

        esf.checkAllCheckboxesByName = function(name) {

            esf.setAllCheckboxesByName(name,true);

        };

        esf.uncheckAllCheckboxesByName = function(name) {

            esf.setAllCheckboxesByName(name,false);

        };

       

        /* Expects two radiobuttons to be laid out as [] Yes  [] No order -- can also be stacked as long as Yes is first */

        esf.setupDisplayIfYesNoRadioButtonGroupIsYes = function(yesNoRadioButtonGroupName,elemIdToShowIfYes,currentRadioButtonGroupFieldValue) {

          var rbYesNoElems = document.getElementsByName(yesNoRadioButtonGroupName.toLowerCase());

          if ( rbYesNoElems && rbYesNoElems.length == 2 ) { /* radio buttons will only exist in EDIT mode */

          rbYesNoElems[0].onclick = function() { esf.displayById(elemIdToShowIfYes); }; /* yes rb */

          rbYesNoElems[1].onclick = function() { esf.hideById(elemIdToShowIfYes); }; /* no rb */

          }

          var lowerValue = currentRadioButtonGroupFieldValue.toLowerCase();

          if ( lowerValue.startsWith('y') || lowerValue.startsWith('t') || lowerValue == '1' )

              esf.displayById(elemIdToShowIfYes);

          else

              esf.hideById(elemIdToShowIfYes);

        };

       

        /* Expects two radiobuttons to be laid out as [] Yes  [] No order -- can also be stacked as long as Yes is first */

        esf.setupDisplayIfYesNoRadioButtonGroupIsNo = function(yesNoRadioButtonGroupName,elemIdToShowIfNo,currentRadioButtonGroupFieldValue) {

              var rbYesNoElems = document.getElementsByName(yesNoRadioButtonGroupName.toLowerCase());

          if ( rbYesNoElems && rbYesNoElems.length == 2 ) { /* radio buttons will only exist in EDIT mode */

          rbYesNoElems[0].onclick = function() { esf.hideById(elemIdToShowIfNo); }; /* yes rb */

          rbYesNoElems[1].onclick = function() { esf.displayById(elemIdToShowIfNo); }; /* no rb */

          }

          var lowerValue = currentRadioButtonGroupFieldValue.toLowerCase();

          if ( lowerValue.startsWith('n') || lowerValue.startsWith('f') || lowerValue == '0' )

          esf.displayById(elemIdToShowIfNo);

          else

          esf.hideById(elemIdToShowIfNo);

            };

       

        esf.setupDisplayIfChecked = function(checkboxName,elemIdToShowIfChecked,currentCheckboxFieldValue,checkboxValueWhenChecked) {

          var cbElems = document.getElementsByName(checkboxName.toLowerCase());

          if ( cbElems && cbElems.length == 1 ) { /* checkboxes will only exist in EDIT mode */

          cbElems[0].onchange = function() {

          if ( this.checked )

          esf.displayById(elemIdToShowIfChecked);

          else

          esf.hideById(elemIdToShowIfChecked);

          };

          }

          if ( currentCheckboxFieldValue == checkboxValueWhenChecked )

              esf.displayById(elemIdToShowIfChecked);

          else

              esf.hideById(elemIdToShowIfChecked);

        };

       

       

        esf.containsSpace = function(s) {

        if ( s == null )

        return false;

        i = 0;

        while( i < s.length ) {

        if ( s.charAt(i) == ' ' )

        return true;

        ++i;

        }

       

        return false;

        };

       

        esf.isOnlyNumbers = function(s) {

        if ( s == null )

        return false;

        var i = 0;

        while( i < s.length ) {

        if ( "0123456789".indexOf(s.charAt(i)) < 0 )

        return false;

        i++;

        }

        return true;

        };

       

        // Trims whitespace from the front and end of a string

        esf.trimSpace = function(s) {

        if ( s == null || s.length == 0 )

        return s;

       

        var beginIndex = 0;

        var endIndex   = s.length - 1;

        while( beginIndex < s.length && s.charAt(beginIndex) == ' ' )

        ++beginIndex;

        while( endIndex >= 0 && s.charAt(endIndex) == ' ' )

        --endIndex;

        ++endIndex;

       

        if ( beginIndex >= endIndex )

        return '';

       

        return s.substring(beginIndex,endIndex);

        };

       

        // Opens a window -- for a given name, width and height

        esf.showWindow = function(url,name,width,height) {

        var win = window.open(url,name,'width='+width+',height='+height+',scrollbars=yes,resizable=yes');

        win.focus();

        return false;

        };

       

        }

      })();

       

      /* Workaround for IE, the only browser in the world that doesn't support standard JavaScript String.startsWith() */

      if ( ! String.prototype.startsWith ) {

        String.prototype.startsWith = function(searchString, position) {

        position = position || 0;

        return this.indexOf(searchString, position) === position;

        };

      }

       

       

      </script>

      </head>

      <body class="esf">

      <div id="X52248c28_187e_43f0_8de8_98357fa63654" class="X86f339d5_81e2_4117_95c2_8f747f5a6fe3 pagediv">

      <div id="ESF_TEST_TRANSACTION_HEADER" style="background-color: pink; text-align: center; width: 100%;">* * *   T E S T   T R A N S A C T I O N   * * *</div>

       

       

       

      <div id="X62edfd59_be00_435a_9bd5_583cc84d220a" class="Page1">

       

      <p><span class="labelFieldArea bottom" style="width: 10em;"><span class="labelAreaStacked"><label class="small">Current Date: </label></span><span class="bottom fieldArea viewFieldData " >January 30, 2019</span></span></p>

       

      </div>

       

       

       

      </div>

      </body>

      </html>

      ]]><Signature xmlns="http://www.w3.org/2000/09/xmldsig#" Id="OpenESignForms_Seal"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/2006/12/xml-c14n11#WithComments"/><SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha512"/><Reference Id="Payload_Reference_ID" URI=""><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/></Transforms><DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha512"/><DigestValue>82PhK9E99GBG/pq5PSLRIGqpz0QbwwN8wlYQJsR3e4r5g1M8yhD3J0XhxNcMHmJIyyyb7yzo947O

      y2T9M/EHQw==</DigestValue></Reference><Reference URI="#KeyInfo_ID"><DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha512"/><DigestValue>zqVVsv0tdx1Fp/c1rrj5b7aKdVtwtq2u0R0RsUnwCja3aMXGjsfqA68lZawt5wCtZqLWsKllPUom

      Z5quVeBVBg==</DigestValue></Reference><Reference URI="#QualifyingProperties_ID"><DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha512"/><DigestValue>AKs1UqheswdoyC7xfofmnZoCOF8dmFISw0Cnqfp9n294EgvP5dnZAWWXH+yspvhnNr3qOJmcaP3N

      ZYoN6rG5XA==</DigestValue></Reference><Reference URI="#OpenESignForms_Seal_ID"><DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha512"/><DigestValue>PzDq2Q3GpkgsnMmD//3bp5q+IksCxpR106yL1hx+WdxNvZWeAdT3SFAoHgLZtx4KL814iqLbiL5U

      kwwmI2q8DA==</DigestValue></Reference></SignedInfo><SignatureValue>ID9zJVDWmIjJzv2TWdq3RjZ4MdF3+gX2LX2du7uRw0A2BJ7u8DAg33Wzlg0EnGNyOFC/P8obaegE

      xCaomRhZXqrLdCoyobe5zWxAFZ+cEHvUY4IwZKdf06i8UEgWiREdHTLfmqqbrhWrnXSnyFoSzAR3

      pn4WssvP4LlJqoMPVQfHtO2aPJQpBBbnQe9wa8K0DgEpAy3ge6OwTtOZ48F27AweZPnFQOBhcmw4

      Rfsri9CmZKUWI46RmLuSBv5uyxSwaZIX88uGPd4bG2zXcHd2VBxDyKblpGgIU+xcG+nxuSYNN8Y6

      rs5o9/XoMM6T8x8LTdNWIgMRf11VhJ1bCh6uF8nEi/QYnV5GcRys/14a8J1oq7l/RNwEk1rMU1m/

      VWDWhQT591S8hD4ZCVx7tokHdqtPg7hGHBbNdpcDYDKAhwRm3PJJBJ9XBHTgByrxnCqVk1W7D50f

      bSiITGvsOIp3ooX3wsq44zv/GVl6BamUPMLhgDq30YZmMNDobJsZxY+CoxQPINfv325R4solQ6s0

      WXqg5RzHHjRTfTK6uNNX931iCb9o3HzKZhtyfZcLygUY69og0etvVpUXjMc2m590eUFUs14ekKwU

      hvB8rN0Qz+FVFH/jwR7AsNgDwE2KGaHEgypEOG5m3vLfLlJXP9ocGuCTp8IpOetx3GAndDFmizU=</SignatureValue><KeyInfo Id="KeyInfo_ID"><KeyName>021eddcd-ebd0-4603-8b26-24b3f7fee682</KeyName><KeyValue><RSAKeyValue><Modulus>iSEKAXeyDOq1RKCwypjN5iuU2uR//YM4ssMBGBCtfpq7eF6pXm0rU5Zz4LnmoptUyu4IcnrStgRr

      JP3NPOeHgibR8i/Ef9frzd4rCwX2JpY3tztCGYByzk93ln7tzRYnMug9q0IVk6Far7JxBIuMy/eg

      LOyptCZGnRU8wV6D+gydsdoFsaR+zghMtBmoZ8sArGd81rzq28B3NDdqrd4camU7viI+5mMTRGJn

      UtBzU/4p7kxv2gePzUc2vJ76+8I1eUGbqc7Co12q8vS+wGpQ4a0lUiWJwj7BRXR21oPz+Qo5fiqb

      a/mSo0gv11s3T2oHTTzWSyvTPb2wbwyBSFAVVaoqJ0g01UEjU2Lv2RkTi/YZpyyPPUDh4OA1KMfX

      f3M7wxzS0+tJFfE4O4ELsaYlcRElVIor1y98LPKmqWgTg0olfU8H00igjbJdU37SzyqygqNadZlC

      ocTtaMvveNIkDURAPPZS/Llp1KUm4YY29m+Of0JK0ZoEBLIj5R0uEIpOBe0MWhH4d8l5mxn8IKpR

      chGgxgJ4P7bNpPQmPUH2rpFukV0NIPe946X7oJE/NubjePyQxpQwwE6zzavz0rf9s4OQpW7tdG/+

      fyubGHXq4H/DH4ZZt0KBuIhLfqjEd3mgyzp4waihnkn4bhcRFm8s5UJEuszp6BkD0EHcPfN76Uk=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue></KeyValue><X509Data><X509Certificate>MIIKkDCCCHigAwIBAgIIXjPAnc0XFeIwDQYJKoZIhvcNAQENBQAwgcIxOTA3BgNVBAMMME9wZW5f

      ZVNpZ25Gb3Jtc19odHRwczovL29wZW4uZXNpZ25mb3Jtcy5jb20vZGVtbzE6MDgGA1UECgwxRGVw

      bG95bWVudElEL2JiZmU5YmVkLTkxOGQtNDQ2Yi05NTE4LThlYzMwM2JhZmI4MzE8MDoGA1UECwwz

      U2lnbmF0dXJlS2V5SUQvMDIxZWRkY2QtZWJkMC00NjAzLThiMjYtMjRiM2Y3ZmVlNjgyMQswCQYD

      VQQGEwJVUzAeFw0xMTA0MTYwMzIxMzhaFw0yMTA0MTYwMzIxMzhaMIHCMTkwNwYDVQQDDDBPcGVu

      X2VTaWduRm9ybXNfaHR0cHM6Ly9vcGVuLmVzaWduZm9ybXMuY29tL2RlbW8xOjA4BgNVBAoMMURl

      cGxveW1lbnRJRC9iYmZlOWJlZC05MThkLTQ0NmItOTUxOC04ZWMzMDNiYWZiODMxPDA6BgNVBAsM

      M1NpZ25hdHVyZUtleUlELzAyMWVkZGNkLWViZDAtNDYwMy04YjI2LTI0YjNmN2ZlZTY4MjELMAkG

      A1UEBhMCVVMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCJIQoBd7IM6rVEoLDKmM3m

      K5Ta5H/9gziywwEYEK1+mrt4XqlebStTlnPgueaim1TK7ghyetK2BGsk/c0854eCJtHyL8R/1+vN

      3isLBfYmlje3O0IZgHLOT3eWfu3NFicy6D2rQhWToVqvsnEEi4zL96As7Km0JkadFTzBXoP6DJ2x

      2gWxpH7OCEy0GahnywCsZ3zWvOrbwHc0N2qt3hxqZTu+Ij7mYxNEYmdS0HNT/inuTG/aB4/NRza8

      nvr7wjV5QZupzsKjXary9L7AalDhrSVSJYnCPsFFdHbWg/P5Cjl+Kptr+ZKjSC/XWzdPagdNPNZL

      K9M9vbBvDIFIUBVVqionSDTVQSNTYu/ZGROL9hmnLI89QOHg4DUox9d/czvDHNLT60kV8Tg7gQux

      piVxESVUiivXL3ws8qapaBODSiV9TwfTSKCNsl1TftLPKrKCo1p1mUKhxO1oy+940iQNREA89lL8

      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

      9zGxY4cvR4vn4VtWcebg9AVMJCwhV85c7l0P0uU=</X509Certificate></X509Data></KeyInfo><Object><QualifyingProperties Id="QualifyingProperties_ID"><SignedProperties><SignedSignatureProperties><SigningTime>2019-01-30T12:40:46-08:00</SigningTime></SignedSignatureProperties><SignedDataObjectProperties><DataObjectFormat ObjectReference="#Payload_Reference_ID"><Description>document.html</Description><MimeType>text/html</MimeType></DataObjectFormat></SignedDataObjectProperties></SignedProperties></QualifyingProperties></Object><Object><SignatureProperties><SignatureProperty Id="OpenESignForms_Seal_ID" Target="#OpenESignForms_Seal"><OpenESignForms_XmlDigitalSignatureSeal DeploymentHostAddress="104.239.136.116" DeploymentHostName="open.esignforms.com" DeploymentId="bbfe9bed-918d-446b-9518-8ec303bafb83" SignerAddress="50-46-115-249.evrt.wa.frontiernet.net (50.46.115.249)" SignerAgent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0.3 Safari/605.1.15" Timestamp="2019-01-30T12:40:46-08:00" Version="19.1.19_p0129_1657"/></SignatureProperty></SignatureProperties></Object></Signature></snapshot>

        • 1. Re: XML Digital Signature throws NAMESPACE_ERR exception under OpenJDK 11 that works under Java SE 8
          3878978

          A quick update if it helps.  We were able to test under Java 10, and it also works fine.  So the issue starts with OpenJDK 11.

           

          Works Java 8:

          java version "1.8.0_161"

          Java(TM) SE Runtime Environment (build 1.8.0_161-b12)

          Java HotSpot(TM) 64-Bit Server VM (build 25.161-b12, mixed mode)

           

           

          Works Java 10:

          java version "10.0.2" 2018-07-17

          Java(TM) SE Runtime Environment 18.3 (build 10.0.2+13)

          Java HotSpot(TM) 64-Bit Server VM 18.3 (build 10.0.2+13, mixed mode)

           

          Broken on Java 11:

          openjdk version "11.0.2" 2019-01-15

          OpenJDK Runtime Environment 18.9 (build 11.0.2+9)

          OpenJDK 64-Bit Server VM 18.9 (build 11.0.2+9, mixed mode)

          • 2. Re: XML Digital Signature throws NAMESPACE_ERR exception under OpenJDK 11 that works under Java SE 8
            3878978

            The last bit we've discovered is that under OpenJDK 11, it appears that the XML digitally signed documents are verified fine; it's just creating new digitally signed that throws the NAMESPACE_ERR issue.  When we retrieve XML digitally signed documents, we verify that the signature is valid, and that code appears to work and find the prior signature to be valid.

            • 3. Re: XML Digital Signature throws NAMESPACE_ERR exception under OpenJDK 11 that works under Java SE 8
              3878978

              I have a test version of the code that can run standalone and shows the bug.  I'm not sure how best to transfer this information to the forum for those to play with.

               

              Note that we use the BouncyCastle BC used in our code, but if you don't have or want to use the BC provider JAR, it will fallback to the SunRsaSign provider that appears to be bundled with JDKs. 

               

              I get the same results with BC or SunRsaSign providers.  It's just the Java version that causes the issue.

               

              In testing with or without the BC provider, the Java 10 version runs and produces the signed XML, while the Java 11 fails.

               

              java version "10.0.2" 2018-07-17
              Java(TM) SE Runtime Environment 18.3 (build 10.0.2+13)
              Java HotSpot(TM) 64-Bit Server VM 18.3 (build 10.0.2+13, mixed mode)

               

              openjdk version "11.0.2" 2019-01-15
              OpenJDK Runtime Environment 18.9 (build 11.0.2+9)
              OpenJDK 64-Bit Server VM 18.9 (build 11.0.2+9, mixed mode)

               

              The Java 11 exception:

              XmlDigitalSignature.main() exception: NAMESPACE_ERR: An attempt is made to create or change an object in a way which is incorrect with regard to namespaces.
              org.w3c.dom.DOMException: NAMESPACE_ERR: An attempt is made to create or change an object in a way which is incorrect with regard to namespaces.
                  at java.xml/com.sun.org.apache.xerces.internal.dom.ElementNSImpl.setName(ElementNSImpl.java:109)
                  at java.xml/com.sun.org.apache.xerces.internal.dom.ElementNSImpl.<init>(ElementNSImpl.java:84)
                  at java.xml/com.sun.org.apache.xerces.internal.dom.CoreDocumentImpl.createElementNS(CoreDocumentImpl.java:2089)
                  at java.xml.crypto/org.jcp.xml.dsig.internal.dom.XmlWriterToTree.writeStartElement(XmlWriterToTree.java:99)
                  at java.xml.crypto/org.jcp.xml.dsig.internal.dom.Marshaller.marshalGenericNode(Marshaller.java:303)
                  at java.xml.crypto/org.jcp.xml.dsig.internal.dom.Marshaller.marshalGenericNode(Marshaller.java:286)
                  at java.xml.crypto/org.jcp.xml.dsig.internal.dom.Marshaller$14.marshalObject(Marshaller.java:251)
                  at java.xml.crypto/org.jcp.xml.dsig.internal.dom.Marshaller$14.marshalObject(Marshaller.java:247)
                  at java.xml.crypto/org.jcp.xml.dsig.internal.dom.XmlWriterToTree.marshalStructure(XmlWriterToTree.java:200)
                  at java.xml.crypto/org.jcp.xml.dsig.internal.dom.DOMXMLObject.marshal(DOMXMLObject.java:180)
                  at java.xml.crypto/org.jcp.xml.dsig.internal.dom.DOMXMLSignature.marshal(DOMXMLSignature.java:233)
                  at java.xml.crypto/org.jcp.xml.dsig.internal.dom.DOMXMLSignature.sign(DOMXMLSignature.java:325)
                  at com.esignforms.open.xmldsigbug.XmlDigitalSignature.sign(XmlDigitalSignature.java:212)
                  at com.esignforms.open.xmldsigbug.XmlDigitalSignature.main(XmlDigitalSignature.java:732)

               

              Under Java 10, the signed XML:

              <snapshot xmlns="http://open.esignforms.com/XMLSchema/2011" timestamp="2019-02-06T13:29:02-08:00" type="document"><![CDATA[<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body><p>Dummy HTML document</p></body></html>]]><Signature xmlns="http://www.w3.org/2000/09/xmldsig#" Id="OpenESignForms_Seal"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/2006/12/xml-c14n11#WithComments"/><SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha512"/><Reference Id="Payload_Reference_ID" URI=""><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/></Transforms><DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha512"/><DigestValue>xbX6EvkJBIDySHYJizqf4rNkEi5eQRyWfpD5TX1xaSI7pez0isMTFwho7/F+fJioI2eHEBPpujhn
              wvIlHvvCOg==</DigestValue></Reference><Reference URI="#KeyInfo_ID"><DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha512"/><DigestValue>D6WsZi/HzkmfZCT3tg7rvoo8S3mkNx5WkEp71OiOJ+JVYG+UAF6aVadY55Jt/tR3BF/wDntWOraK
              gmAXZ2ifHQ==</DigestValue></Reference><Reference URI="#QualifyingProperties_ID"><DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha512"/><DigestValue>1tOD+n70iPIcUM0gylw5Wu4LpFQUyEi0L+aq0Z5RgdvO4xsoypumooQRPWWxn/esiisbbRSEbCxs
              11jaahDUGQ==</DigestValue></Reference><Reference URI="#OpenESignForms_Seal_ID"><DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha512"/><DigestValue>A9REglXLHIr8M5xFHIR8o93pNKMiCoOQTW/58WOXLnQ/8Gaw4txOTwIsnclKxG+5bkQ76/KR/It+
              /ljnjdlmFw==</DigestValue></Reference></SignedInfo><SignatureValue>FxFXp98EIK2+NoHlwE6ewE9En+X02tz0Fb4IBlHKLh/aRYbGQn8ceexq27nbfA3wKXYgLM5aG9Mv
              n+nvkLQfP+U0jXtW6En0hGnbmCa2sBevEB0l31HItXW6+KocAJBio8FT1Sps0mAn7eAAfKbuVyTu
              Xy+SOcJZWrTzSkI7V323+TwRv4i6NbIpVJsH/Cj7AfuqWocWenPAmBNDfzmgjohnL8vN1OFNPdXz
              RN6rkVbPl+yvjhUtX2XgGkHiMvYmrd64XGGfGv80Iu052+CUoe5ZHEIe1M26hK995ffotVzPbHov
              2O2cCIXJI1xWIHpS926KTvtpMVHEiWtDqGbh2mKmG7zD2AHEJY2d/u34pOauLkeU5Yk87BK0Dt9Q
              jiDxJy28wMbO0eyoiMfWwf5VWeiyzbPkDGzCqUvQEbXmGuvkhxRuztE7cELF2dWdvx/8rRjc7Imh
              OJ4pwgaxHS4Ek5C8mP6MCPfdiztCO4z08iKbnXOBaG1oe1+SyvecksLy2vF8UxQwPfV6LVU7cxhy
              C51R3nXZcsgNNTvxLyO8npKKlLtJj4O1D3cfhgKUWNZCKg9HCh1J6VKyEg3KFXWN//vD8QPSDhmx
              BPKLq+QZQw8SW4bMTrI5xIgY5FYiwMex5lyezGcjFzWAp64m8lehpW889wi2A18j6ccQ2K8+PN4=</SignatureValue><KeyInfo Id="KeyInfo_ID"><KeyName>5c585e1f-634a-4ddb-bbe0-9b110e38d3a6</KeyName><KeyValue><RSAKeyValue><Modulus>kPCr+Fy0NInaICpnzDpGLkNQ93kd0NzZfTBfQOb3PUH1Bt4OrBWcvYoch7wUm6k1Il3apsi7s2B9
              Geqbh7tzF41MwvTWBNCQg3Kw3FKcF0jzKZ7D+na8Ndc52YPmsjU9zjpf+SDfKqb0NIDe3Bo3csWW
              I42CkF3sI9AFknogovrfRM7ITJatA6WRHU8Kv6Qee8VfXZ1XAdKzWcc9EWbj74Kagiz8bMeATujU
              MCI/XQb1luwvlrVxZUtnfLL9WD6Nvmj3uDYK52z5E80vqTKIq7EJvmlR7kcEdH1NuxDQSWCJQgQX
              oU2TzuB0Nmov7P/pZ40JPF72Knb18Rgu4aRSMiaKKw+jzFHpw75VlQn2YkdfjNMwfUaEaZ4wuHoJ
              Qjud79jilbam++eUQFRxjcXK9Nl/z01KtmuV1mPhm97LRaKQlsbBxa56pncrkAmF0cuIipPzo9aB
              snJZkUQuwQtD/moDkUm84v5SOU1hn4RpWdGAkaJ1ubIrnKfF0qKmbCOcO69SEL5zP0JXEgSZ+D6z
              Vv7VkAJizdJ91KKs4y/ypel4lurNcyBd3hzw8xpz9joMl8DOTLCcLhGp350Vrccbh9vauAcRcK/n
              C+yaPI/mghmN2D2yZ3LZ3Z6k78Jl9BUV7PL5YyuxQmZjVP07lJvi6glLUm23o+c3c4D7rgHL4gM=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue></KeyValue><X509Data><X509Certificate>MIIKvTCCCKWgAwIBAgIJAPaU10x5GhRQMA0GCSqGSIb3DQEBDQUAMIHYMU0wSwYDVQQDDERPcGVu
              X2VTaWduRm9ybXNfaHR0cHM6Ly9sb2NhbGhvc3QubG9jYWxkb21haW4vb3Blbi1lU2lnbkZvcm1z
              VmFhZGluNzE6MDgGA1UECgwxRGVwbG95bWVudElEL2FhMGUyYjllLWM5ZDItNDk0NS04ZWVmLWI2
              NDhiZDYzYWFjNDE8MDoGA1UECwwzU2lnbmF0dXJlS2V5SUQvMDJkYmMwMDktMTAyYi00ZWE3LTlh
              YzgtNzYwZThiMzY4NTlmMQ0wCwYDVQQGEwRudWxsMB4XDTE0MTIxNjAzMjc1NVoXDTI0MTIxNjAz
              Mjc1NVowgdgxTTBLBgNVBAMMRE9wZW5fZVNpZ25Gb3Jtc19odHRwczovL2xvY2FsaG9zdC5sb2Nh
              bGRvbWFpbi9vcGVuLWVTaWduRm9ybXNWYWFkaW43MTowOAYDVQQKDDFEZXBsb3ltZW50SUQvYWEw
              ZTJiOWUtYzlkMi00OTQ1LThlZWYtYjY0OGJkNjNhYWM0MTwwOgYDVQQLDDNTaWduYXR1cmVLZXlJ
              RC8wMmRiYzAwOS0xMDJiLTRlYTctOWFjOC03NjBlOGIzNjg1OWYxDTALBgNVBAYTBG51bGwwggIi
              MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCQ8Kv4XLQ0idogKmfMOkYuQ1D3eR3Q3Nl9MF9A
              5vc9QfUG3g6sFZy9ihyHvBSbqTUiXdqmyLuzYH0Z6puHu3MXjUzC9NYE0JCDcrDcUpwXSPMpnsP6
              drw11znZg+ayNT3OOl/5IN8qpvQ0gN7cGjdyxZYjjYKQXewj0AWSeiCi+t9EzshMlq0DpZEdTwq/
              pB57xV9dnVcB0rNZxz0RZuPvgpqCLPxsx4BO6NQwIj9dBvWW7C+WtXFlS2d8sv1YPo2+aPe4Ngrn
              bPkTzS+pMoirsQm+aVHuRwR0fU27ENBJYIlCBBehTZPO4HQ2ai/s/+lnjQk8XvYqdvXxGC7hpFIy
              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
              VMfem/JPPYT/veThnefIgQk=</X509Certificate></X509Data></KeyInfo><Object><QualifyingProperties Id="QualifyingProperties_ID"><SignedProperties><SignedSignatureProperties><SigningTime>2019-02-06T13:29:03-08:00</SigningTime></SignedSignatureProperties><SignedDataObjectProperties><DataObjectFormat ObjectReference="#Payload_Reference_ID"><Description>description</Description><MimeType>text/html</MimeType></DataObjectFormat></SignedDataObjectProperties></SignedProperties></QualifyingProperties></Object><Object><SignatureProperties><SignatureProperty Id="OpenESignForms_Seal_ID" Target="#OpenESignForms_Seal"><OpenESignForms_XmlDigitalSignatureSeal DeploymentHostAddress="192.1.1.1" DeploymentHostName="open.esignforms.com" DeploymentId="1.1.1.1" SignerAddress="192.1.1.1" SignerAgent="No-Browser-Test" Timestamp="2019-02-06T13:29:03-08:00" Version="19.1.19"/></SignatureProperty></SignatureProperties></Object></Signature></snapshot>

               

              XML Digital Signature code used:

               

              // Copyright (C) 2011-2019 Yozons, Inc.

              // Open eSignForms - Web-based electronic contracting software

              //

              // This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License

              // as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

              //

              // This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;

              // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

              // See the GNU Affero General Public License for more details.

              //

              // You should have received a copy of the GNU Affero General Public License along with this program. 

              // If not, see <http://open.esignforms.com/agpl.txt> or <http://www.gnu.org/licenses/>.

              // Contact information is via the public forums at http://open.esignforms.com or via private email to open-esign@yozons.com.

              //

              package com.esignforms.open.xmldsigbug;

               

              import java.io.BufferedInputStream;

              import java.io.ByteArrayInputStream;

              import java.io.StringWriter;

              import java.io.Writer;

              import java.nio.charset.StandardCharsets;

              import java.security.Key;

              import java.security.KeyException;

              import java.security.KeyFactory;

              import java.security.KeyPair;

              import java.security.NoSuchProviderException;

              import java.security.PrivateKey;

              import java.security.PublicKey;

              import java.security.cert.Certificate;

              import java.security.cert.CertificateFactory;

              import java.security.cert.X509Certificate;

              import java.security.spec.PKCS8EncodedKeySpec;

              import java.security.spec.X509EncodedKeySpec;

              import java.time.ZonedDateTime;

              import java.time.format.DateTimeFormatter;

              import java.util.Collections;

              import java.util.Iterator;

              import java.util.LinkedList;

              import java.util.List;

              import java.util.UUID;

               

              import javax.xml.crypto.AlgorithmMethod;

              import javax.xml.crypto.KeySelector;

              import javax.xml.crypto.KeySelectorException;

              import javax.xml.crypto.KeySelectorResult;

              import javax.xml.crypto.XMLCryptoContext;

              import javax.xml.crypto.XMLStructure;

              import javax.xml.crypto.dom.DOMStructure;

              import javax.xml.crypto.dsig.DigestMethod;

              import javax.xml.crypto.dsig.Reference;

              import javax.xml.crypto.dsig.SignatureMethod;

              import javax.xml.crypto.dsig.SignatureProperties;

              import javax.xml.crypto.dsig.SignatureProperty;

              import javax.xml.crypto.dsig.SignedInfo;

              import javax.xml.crypto.dsig.Transform;

              import javax.xml.crypto.dsig.XMLObject;

              import javax.xml.crypto.dsig.XMLSignature;

              import javax.xml.crypto.dsig.XMLSignatureFactory;

              import javax.xml.crypto.dsig.dom.DOMSignContext;

              import javax.xml.crypto.dsig.dom.DOMValidateContext;

              import javax.xml.crypto.dsig.keyinfo.KeyInfo;

              import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;

              import javax.xml.crypto.dsig.keyinfo.KeyName;

              import javax.xml.crypto.dsig.keyinfo.KeyValue;

              import javax.xml.crypto.dsig.keyinfo.X509Data;

              import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;

              import javax.xml.crypto.dsig.spec.TransformParameterSpec;

              import javax.xml.parsers.DocumentBuilderFactory;

              import javax.xml.transform.OutputKeys;

              import javax.xml.transform.Transformer;

              import javax.xml.transform.TransformerFactory;

              import javax.xml.transform.dom.DOMSource;

              import javax.xml.transform.stream.StreamResult;

               

              import org.w3c.dom.Document;

              import org.w3c.dom.Element;

              import org.w3c.dom.NodeList;

               

               

              /**

              * This code is adapted from the Open eSignForms source file com.esignforms.open.crypto.XmlDigitalSignature, with all platform hooks removed.

              *

              * XmlDigitalSignature provides our interface to XML Digital Signatures.

              *

              * Much of the code understanding came from Oracle's technotes:

              * http://download.oracle.com/javase/6/docs/technotes/guides/security/xmldsig/XMLDigitalSignature.html

              *

              * @author Yozons, Inc.

              */

              public final class XmlDigitalSignature {

                // These literals are supported as of Java 7, but are not defined in the API yet...

                private static final String SignatureMethod_RSA_SHA512 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512";

                private static final String CanonicalizationMethod_INCLUSIVE_C14N11_WITH_COMMENTS = "http://www.w3.org/2006/12/xml-c14n11#WithComments";

               

                private XMLSignatureFactory xmlSignatureFactory;

               

                public XmlDigitalSignature() {

                xmlSignatureFactory = XMLSignatureFactory.getInstance("DOM");

                }

               

                public String sign(String xmlToSign, String description, String contentType, SignatureKey signatureKey) throws Exception {

                return sign(xmlToSign, description, contentType, signatureKey, null, null);

                }

               

                public String sign(String xmlToSign, String description, String contentType, SignatureKey signatureKey, String signerIpHost, String signerUserAgent) throws Exception {

                if (isBlank(xmlToSign))

                throw new Exception("Missing XML string to be signed.");

                if (signatureKey == null)

                throw new Exception("Missing the signature key needed to sign.");

               

                try {

                // Our KeyInfo section will have a KeyName that is our signature key's id, as well as the public key itself,

                // and our self-sign X.509 certificate.

                KeyInfoFactory keyInfoFactory = xmlSignatureFactory.getKeyInfoFactory();

                List<XMLStructure> keyInfoList = new LinkedList<XMLStructure>();

                KeyName keyName = keyInfoFactory.newKeyName(signatureKey.id.toString());

                keyInfoList.add(keyName);

                KeyValue keyValue = keyInfoFactory.newKeyValue(signatureKey.keyPair.getPublic());

                keyInfoList.add(keyValue);

                X509Data keyX409Data = keyInfoFactory.newX509Data(Collections.singletonList(signatureKey.cert));

                keyInfoList.add(keyX409Data);

                KeyInfo keyInfo = keyInfoFactory.newKeyInfo(keyInfoList, "KeyInfo_ID");

               

                // Instantiate the document to be signed

                DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

                dbf.setNamespaceAware(true);

                Document document = dbf.newDocumentBuilder().parse(new BufferedInputStream(new ByteArrayInputStream(stringToBytes(xmlToSign))));

               

                // Create a DOMSignContext and specify the RSA PrivateKey and

                // location of the resulting XMLSignature's parent element.

                DOMSignContext domSignContext = new DOMSignContext(signatureKey.keyPair.getPrivate(), document.getDocumentElement());

               

                // Add in the EU Directive extras: http://uri.etsi.org/01903/v1.4.1/ts_101903v010401p.pdf

                String signingTime = toXmlWithTz(ZonedDateTime.now());

                Element qualifyingPropertiesElement = document.createElement("QualifyingProperties");

                qualifyingPropertiesElement.setAttribute("Id", "QualifyingProperties_ID");

                qualifyingPropertiesElement.setIdAttribute("Id", true); // mark our id as the "Id" attribute

                Element signedPropertiesElement = document.createElement("SignedProperties");

                Element signedSignaturePropertiesElement = document.createElement("SignedSignatureProperties");

                Element signingTimeElement = document.createElement("SigningTime");

                signingTimeElement.setTextContent(signingTime);

               

                Element signedDataObjectPropertiesElement = document.createElement("SignedDataObjectProperties");

                Element dataObjectFormatElement = document.createElement("DataObjectFormat");

                dataObjectFormatElement.setAttribute("ObjectReference", "#Payload_Reference_ID");

                Element dataObjectDescriptionElement = document.createElement("Description");

                dataObjectDescriptionElement.setTextContent(toEscapedXml(description));

                dataObjectFormatElement.appendChild(dataObjectDescriptionElement);

                Element dataObjectMimeTypeElement = document.createElement("MimeType");

                dataObjectMimeTypeElement.setTextContent(toEscapedXml(contentType));

                dataObjectFormatElement.appendChild(dataObjectMimeTypeElement);

               

                qualifyingPropertiesElement.appendChild(signedPropertiesElement);

                signedPropertiesElement.appendChild(signedSignaturePropertiesElement);

                signedPropertiesElement.appendChild(signedDataObjectPropertiesElement);

                signedSignaturePropertiesElement.appendChild(signingTimeElement);

                signedDataObjectPropertiesElement.appendChild(dataObjectFormatElement);

               

                DOMStructure qualifyingPropertiesObject = new DOMStructure(qualifyingPropertiesElement);

                XMLObject qualifyingPropertiesXMLObject = xmlSignatureFactory.newXMLObject(Collections.singletonList(qualifyingPropertiesObject), null, null, null);

               

                // Our signature includes the deployment id, and the current timestamp

                Element esignformsElement = document.createElement("OpenESignForms_XmlDigitalSignatureSeal");

                esignformsElement.setAttribute("Version", toEscapedXml("19.1.19"));

                esignformsElement.setAttribute("Timestamp", signingTime);

                esignformsElement.setAttribute("DeploymentId", "1.1.1.1");

                esignformsElement.setAttribute("DeploymentHostName", "open.esignforms.com");

                esignformsElement.setAttribute("DeploymentHostAddress", "192.1.1.1");

                if (!isBlank(signerIpHost))

                esignformsElement.setAttribute("SignerAddress", toEscapedXml(signerIpHost));

                if (!isBlank(signerUserAgent))

                esignformsElement.setAttribute("SignerAgent", toEscapedXml(signerUserAgent));

               

                DOMStructure signatureObject = new DOMStructure(esignformsElement);

               

                SignatureProperty signatureProperty = xmlSignatureFactory.newSignatureProperty(Collections.singletonList(signatureObject), "#OpenESignForms_Seal",

                "OpenESignForms_Seal_ID");

                SignatureProperties signatureProperties = xmlSignatureFactory.newSignatureProperties(Collections.singletonList(signatureProperty), null);

                XMLObject signaturePropertiesXMLObject = xmlSignatureFactory.newXMLObject(Collections.singletonList(signatureProperties), null, null, null);

               

                // Sign the main payload

                Reference referencePayload = xmlSignatureFactory.newReference("", xmlSignatureFactory.newDigestMethod(DigestMethod.SHA512, null),

                Collections.singletonList(xmlSignatureFactory.newTransform(Transform.ENVELOPED, (TransformParameterSpec) null)), null, "Payload_Reference_ID");

                // Sign the KeyInfo per the EU spec

                Reference referenceKeyInfo = xmlSignatureFactory.newReference("#KeyInfo_ID", xmlSignatureFactory.newDigestMethod(DigestMethod.SHA512, null));

                // Sign the EU qualifying properties

                Reference referenceQualifyingProperties = xmlSignatureFactory.newReference("#QualifyingProperties_ID",

                xmlSignatureFactory.newDigestMethod(DigestMethod.SHA512, null));

                // Sign our seal

                Reference referenceSignatureProperties = xmlSignatureFactory.newReference("#OpenESignForms_Seal_ID",

                xmlSignatureFactory.newDigestMethod(DigestMethod.SHA512, null));

               

                List<Reference> referenceList = new LinkedList<Reference>();

                referenceList.add(referencePayload);

                referenceList.add(referenceKeyInfo);

                referenceList.add(referenceQualifyingProperties);

                referenceList.add(referenceSignatureProperties);

               

                SignedInfo signedInfo = xmlSignatureFactory

                .newSignedInfo(

                xmlSignatureFactory.newCanonicalizationMethod(

                CanonicalizationMethod_INCLUSIVE_C14N11_WITH_COMMENTS/* CanonicalizationMethod.INCLUSIVE_WITH_COMMENTS */, (C14NMethodParameterSpec) null),

                xmlSignatureFactory.newSignatureMethod(SignatureMethod_RSA_SHA512, null), referenceList);

               

                // Create the XMLSignature, but don't sign it yet.

                List<XMLObject> signingXMLObjects = new LinkedList<XMLObject>();

                signingXMLObjects.add(qualifyingPropertiesXMLObject);

                signingXMLObjects.add(signaturePropertiesXMLObject);

                XMLSignature xmlSignature = xmlSignatureFactory.newXMLSignature(signedInfo, keyInfo, signingXMLObjects, "OpenESignForms_Seal", null);

               

                // Marshal, generate, and sign the enveloped signature.

                xmlSignature.sign(domSignContext);

               

                Writer writer = new StringWriter(xmlToSign.length() + 8000); // add in overhead for Signature element

                TransformerFactory tf = TransformerFactory.newInstance();

                Transformer transformer = tf.newTransformer();

                // we don't want <?xml version="1.0" encoding="UTF-8" standalone="no"?> at the top since we embed our signed XML in other XML structures

                // (it's not a standalone document at all)

                transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");

                transformer.transform(new DOMSource(document), new StreamResult(writer));

               

                return writer.toString();

                } catch (Exception e) {

                System.err.println("XmlDigitalSignature.sign() SERIOUS-ERROR exception: " + e.getMessage());

                e.printStackTrace();

                throw e;

                }

                }

               

                public void verify(String signedXml, SignatureKey signatureKey) throws Exception {

                if (isBlank(signedXml) || signatureKey == null)

                throw new Exception("Missing required parameter signedXml and/or signatureKey");

               

                try {

                DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

                dbf.setNamespaceAware(true);

                Document document = dbf.newDocumentBuilder().parse(new BufferedInputStream(new ByteArrayInputStream(stringToBytes(signedXml))));

               

                NodeList qualifyingPropertiesNodeList = document.getElementsByTagName("QualifyingProperties");

                if (qualifyingPropertiesNodeList != null) {

                for (int i = 0; i < qualifyingPropertiesNodeList.getLength(); ++i) {

                Element qualifyingPropertiesElement = (Element) qualifyingPropertiesNodeList.item(i);

                if (qualifyingPropertiesElement != null)

                qualifyingPropertiesElement.setIdAttribute("Id", true); // mark our id as the "Id" attribute

                }

                }

               

                NodeList nl = document.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");

                if (nl.getLength() == 0) {

                System.err.println("XmlDigitalSignature.verify(SignatureKey) SERIOUS-ERROR no Signature element");

                throw new Exception("The signedXML has no Signature element");

                }

               

                // The embedded key must match our signatureKey's values or the validation will fail.

                DOMValidateContext valContext = new DOMValidateContext(new VerifyingKeySelector(signatureKey), nl.item(0));

               

                XMLSignature signature = xmlSignatureFactory.unmarshalXMLSignature(valContext);

                if (!signature.validate(valContext)) {

                boolean isSignatureValueValid = signature.getSignatureValue().validate(valContext);

                System.err.println("XmlDigitalSignature.verify(SignatureKey) SERIOUS-ERROR Failed core validation; SignatureValue validated: " + isSignatureValueValid);

                StringBuilder exceptionText = new StringBuilder();

                exceptionText.append("Invalid signature. SignatureValue ").append(isSignatureValueValid ? "validated" : "INVALID");

                Iterator<?> i = signature.getSignedInfo().getReferences().iterator();

                for (int j = 0; i.hasNext(); j++) {

                boolean refValid = ((Reference) i.next()).validate(valContext);

                System.err.println(" -> Reference[" + j + "] validated: " + refValid);

                exceptionText.append("; ").append(getReferenceName(j)).append(refValid ? " validated" : " INVALID");

                }

                throw new Exception(exceptionText.toString());

                }

                } catch (Exception e) {

                System.err.println("XmlDigitalSignature.verify(SignatureKey) SERIOUS-ERROR exception: " + e.getMessage());

                e.printStackTrace();

                throw e;

                }

               

                }

               

                private static String getReferenceName(int i) {

                if (i == 0)

                return "XML data payload";

                if (i == 1)

                return "OpenESignForms Seal";

                return "Unexpected Reference[" + i + "]";

                }

               

                public void verify(String signedXml, PublicKey publicKey) throws Exception {

                if (isBlank(signedXml) || publicKey == null)

                throw new Exception("Missing required parameter signedXml and/or publicKey");

               

                try {

                DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

                dbf.setNamespaceAware(true);

                Document document = dbf.newDocumentBuilder().parse(new BufferedInputStream(new ByteArrayInputStream(stringToBytes(signedXml))));

               

                NodeList qualifyingPropertiesNodeList = document.getElementsByTagName("QualifyingProperties");

                if (qualifyingPropertiesNodeList != null) {

                for (int i = 0; i < qualifyingPropertiesNodeList.getLength(); ++i) {

                Element qualifyingPropertiesElement = (Element) qualifyingPropertiesNodeList.item(i);

                if (qualifyingPropertiesElement != null)

                qualifyingPropertiesElement.setIdAttribute("Id", true); // mark our id as the "Id" attribute

                }

                }

               

                NodeList nl = document.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");

                if (nl.getLength() == 0) {

                System.err.println("XmlDigitalSignature.verify(PublicKey) SERIOUS-ERROR no Signature element");

                throw new Exception("The signedXML has no Signature element");

                }

               

                DOMValidateContext valContext = new DOMValidateContext(publicKey, nl.item(0));

                // DOMValidateContext valContext = new DOMValidateContext(KeySelector.singletonKeySelector(publicKey), nl.item(0));

               

                XMLSignature signature = xmlSignatureFactory.unmarshalXMLSignature(valContext);

                if (!signature.validate(valContext)) {

                boolean isSignatureValueValid = signature.getSignatureValue().validate(valContext);

                System.err.println("XmlDigitalSignature.verify(PublicKey) SERIOUS-ERROR Failed core validation; SignatureValue validated; " + isSignatureValueValid);

                StringBuilder exceptionText = new StringBuilder();

                exceptionText.append("Invalid signature. SignatureValue ").append(isSignatureValueValid ? "validated" : "INVALID");

                Iterator<?> i = signature.getSignedInfo().getReferences().iterator();

                for (int j = 0; i.hasNext(); j++) {

                boolean refValid = ((Reference) i.next()).validate(valContext);

                System.err.println(" -> Reference[" + j + "] validated: " + refValid);

                exceptionText.append("; ").append(getReferenceName(j)).append(refValid ? " validated" : " INVALID");

                }

                throw new Exception(exceptionText.toString());

                }

                } catch (Exception e) {

                System.err.println("XmlDigitalSignature.verify(PublicKey) SERIOUS-ERROR exception: " + e.getMessage());

                e.printStackTrace();

                throw e;

                }

               

                }

               

                public void verifyAcceptEmbeddedKeysIfKeyIdNotFound(String signedXml) throws Exception {

                if (isBlank(signedXml))

                throw new Exception("Missing required parameter signedXml");

               

                try {

                DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

                dbf.setNamespaceAware(true);

                Document document = dbf.newDocumentBuilder().parse((new BufferedInputStream(new ByteArrayInputStream(stringToBytes(signedXml)))));

               

                NodeList qualifyingPropertiesNodeList = document.getElementsByTagName("QualifyingProperties");

                if (qualifyingPropertiesNodeList != null) {

                for (int i = 0; i < qualifyingPropertiesNodeList.getLength(); ++i) {

                Element qualifyingPropertiesElement = (Element) qualifyingPropertiesNodeList.item(i);

                if (qualifyingPropertiesElement != null)

                qualifyingPropertiesElement.setIdAttribute("Id", true); // mark our id as the "Id" attribute

                }

                }

               

                NodeList nl = document.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");

                if (nl.getLength() == 0) {

                System.err.println("XmlDigitalSignature.verifyAcceptEmbeddedKeysIfKeyIdNotFound() SERIOUS-ERROR no Signature element");

                throw new Exception("The signedXML has no Signature element");

                }

               

                // The embedded key must match our signatureKey's values or the validation will fail.

                DOMValidateContext valContext = new DOMValidateContext(new AcceptEmbeddedKeySelector(), nl.item(0));

               

                XMLSignature signature = xmlSignatureFactory.unmarshalXMLSignature(valContext);

                if (!signature.validate(valContext)) {

                boolean isSignatureValueValid = signature.getSignatureValue().validate(valContext);

                System.err.println("XmlDigitalSignature.verifyAcceptEmbeddedKeysIfKeyIdNotFound() SERIOUS-ERROR Failed core validation; SignatureValue validated; "

                + isSignatureValueValid);

                StringBuilder exceptionText = new StringBuilder();

                exceptionText.append("Invalid signature. SignatureValue ").append(isSignatureValueValid ? "validated" : "INVALID");

                Iterator<?> i = signature.getSignedInfo().getReferences().iterator();

                for (int j = 0; i.hasNext(); j++) {

                boolean refValid = ((Reference) i.next()).validate(valContext);

                System.err.println(" -> Reference[" + j + "] validated: " + refValid);

                exceptionText.append("; ").append(getReferenceName(j)).append(refValid ? " validated" : " INVALID");

                }

                throw new Exception(exceptionText.toString());

                }

                } catch (Exception e) {

                System.err.println("XmlDigitalSignature.verifyAcceptEmbeddedKeysIfKeyIdNotFound() SERIOUS-ERROR exception: " + e.getMessage());

                e.printStackTrace();

                throw e;

                }

                }

               

                protected static class VerifyingKeySelector extends KeySelector {

                SignatureKey signatureKey;

               

                public VerifyingKeySelector(SignatureKey signatureKey) {

                this.signatureKey = signatureKey;

                }

               

                public VerifyingKeySelector() {

                this.signatureKey = null;

                }

               

                @Override

                public KeySelectorResult select(KeyInfo keyInfo, Purpose purpose, AlgorithmMethod method, XMLCryptoContext context) throws KeySelectorException {

                if (keyInfo == null)

                throw new KeySelectorException("NULL KeyInfo");

               

                SignatureMethod sm = (SignatureMethod) method;

                List<?> list = keyInfo.getContent();

               

                UUID keyId = null;

                PublicKey publicKey = null;

                for (int i = 0; i < list.size(); i++) {

                XMLStructure xmlStructure = (XMLStructure) list.get(i);

                if (xmlStructure instanceof KeyName) {

                String name = ((KeyName) xmlStructure).getName();

                keyId = UUID.fromString(name);

                } else if (xmlStructure instanceof KeyValue) {

                try {

                publicKey = ((KeyValue) xmlStructure).getPublicKey();

                } catch (KeyException ke) {

                throw new KeySelectorException(ke);

                }

                }

                }

               

                if (keyId == null || publicKey == null)

                throw new KeySelectorException("XML Signature element needs KeyName and KeyValue to verify");

               

                // If we don't have a signatureKey set, let's see if we can find it by the id

                if (signatureKey == null)

                signatureKey = new SignatureKey(keyId);

               

                if (signatureKey == null)

                throw new KeySelectorException("KeyName and KeyValue cannot be verified without a SignatureKey");

               

                if (keyId.equals(signatureKey.id) && publicKey.equals(signatureKey.keyPair.getPublic()) && algEquals(sm.getAlgorithm(), publicKey.getAlgorithm()))

                return new SimpleKeySelectorResult(publicKey);

               

                throw new KeySelectorException("KeyName and KeyValue are not correct and do not match the expected SignatureKey");

                }

                }

               

                protected static class AcceptEmbeddedKeySelector extends KeySelector {

                public AcceptEmbeddedKeySelector() {

                }

               

                @Override

                public KeySelectorResult select(KeyInfo keyInfo, Purpose purpose, AlgorithmMethod method, XMLCryptoContext context) throws KeySelectorException {

                if (keyInfo == null)

                throw new KeySelectorException("NULL KeyInfo");

               

                SignatureMethod sm = (SignatureMethod) method;

                List<?> list = keyInfo.getContent();

               

                UUID keyId = null;

                PublicKey publicKey = null;

                for (int i = 0; i < list.size(); i++) {

                XMLStructure xmlStructure = (XMLStructure) list.get(i);

                if (xmlStructure instanceof KeyName) {

                String name = ((KeyName) xmlStructure).getName();

                keyId = UUID.fromString(name);

                } else if (xmlStructure instanceof KeyValue) {

                try {

                publicKey = ((KeyValue) xmlStructure).getPublicKey();

                } catch (KeyException ke) {

                throw new KeySelectorException(ke);

                }

                }

                }

               

                if (keyId == null || publicKey == null)

                throw new KeySelectorException("XML Signature element needs KeyName and KeyValue as these are always present when valid, even if not trusted");

               

                // If we can find the key that uses the keyid specified, we'll ensure the public key is valid, but if not found,

                // we'll implicitly trust it for this method's purpose.

                SignatureKey signatureKey = new SignatureKey(keyId);

                if (signatureKey == null) {

                if (algEquals(sm.getAlgorithm(), publicKey.getAlgorithm()))

                return new SimpleKeySelectorResult(publicKey);

                } else {

                if (publicKey.equals(signatureKey.keyPair.getPublic()) && algEquals(sm.getAlgorithm(), publicKey.getAlgorithm()))

                return new SimpleKeySelectorResult(publicKey);

               

                }

                throw new KeySelectorException("KeyName and KeyValue are not correct");

                }

               

                }

               

                public static class SimpleKeySelectorResult implements KeySelectorResult {

                PublicKey publicKey;

               

                SimpleKeySelectorResult(PublicKey publicKey) {

                this.publicKey = publicKey;

                }

               

                public Key getKey() {

                return publicKey;

                }

                }

               

                static boolean algEquals(String algURI, String algName) {

                return (algName.equalsIgnoreCase("DSA") && algURI.equalsIgnoreCase(SignatureMethod.DSA_SHA1))

                || (algName.equalsIgnoreCase("RSA") && (algURI.equalsIgnoreCase(SignatureMethod_RSA_SHA512) || algURI.equalsIgnoreCase(SignatureMethod.RSA_SHA1)));

                }

               

                // End of original code

               

                // Various utility routines added to replace OpenESF logic

                static boolean isBlank(String v) {

                if (v == null)

                return true;

                for (int i = 0; i < v.length(); ++i) {

                if (!Character.isWhitespace(v.charAt(i)))

                return false;

                }

                return true;

                }

               

                static final byte[] stringToBytes(String v) {

                if (v == null)

                return null;

                return v.getBytes(StandardCharsets.UTF_8);

                }

               

                static final String bytesToString(byte[] v) {

                if (v == null)

                return null;

                return new String(v, StandardCharsets.UTF_8);

                }

               

                static String toXmlWithTz(ZonedDateTime date) {

                if (date == null)

                return "";

                // XML TZ is like -08:00, but Java Z format wants -0800

                DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ");

                // If we have a 4 digit TZ, make it HH:MM format rather than HHMM format Java gives us

                String xml = fmt.format(date);

                xml = xml.substring(0, 22) + ":" + xml.substring(22);

                return xml;

                }

               

                static boolean isUnexpectedISOControlCharacter(char c) {

                if (c == '\n' || c == '\r' || c == '\t')

                return false;

                return Character.isISOControl(c);

                }

               

                static String toEscapedXml(String s) {

                if (s == null)

                return "";

               

                // The gamble here is that most strings will not contain the special characters,

                // so we optimize things in that case by appending the original string without

                // creating any new objects.

                int length = s.length();

                int currentPos;

               

                for (currentPos = 0; currentPos < length; ++currentPos) {

                char c = s.charAt(currentPos);

               

                if (c == '"' || c == '<' || c == '>' || c == '&' || c == '\'' || isUnexpectedISOControlCharacter(c))

                break; // we'll need to escape this one

                }

               

                // No quoting necessary, so just append the original string into the buffer.

                if (currentPos >= length) {

                return s;

                }

               

                StringBuilder buf = new StringBuilder(s.length());

               

                buf.append(s.substring(0, currentPos));

               

                for (; currentPos < length; ++currentPos) {

                char c = s.charAt(currentPos);

               

                switch (c) {

                case '"':

                buf.append("&quot;");

                break;

               

                case '\'':

                buf.append("&apos;"); // aka: &#039; but we don't do any of these codes here

                break;

               

                case '<':

                buf.append("&lt;");

                break;

               

                case '>':

                buf.append("&gt;");

                break;

               

                case '&': {

                buf.append("&amp;");

                break;

                }

               

                default:

                if (!isUnexpectedISOControlCharacter(c)) // we won't allow these in our XML data

                buf.append(c);

                break;

                }

                }

               

                return buf.toString();

                }

               

                static X509Certificate toX509CertificateFromBase64Encoded(String base64EncodeCert) {

                try {

                byte[] encodedCert = java.util.Base64.getDecoder().decode(base64EncodeCert);

                if (encodedCert == null) {

                System.err.println("toX509CertificateFromBase64Encoded() - Failed to Base64 decode.");

                return null;

                }

               

                CertificateFactory factory = CertificateFactory.getInstance("X.509");

                if (factory == null) {

                System.err.println("toX509CertificateFromBase64Encoded() - Failed to get an X.509 certificate factory.");

                return null;

                }

               

                ByteArrayInputStream bais = new ByteArrayInputStream(encodedCert);

                Certificate cert = (X509Certificate) factory.generateCertificate(bais);

                if (cert instanceof X509Certificate)

                return (X509Certificate) cert;

               

                System.err.println("toX509CertificateFromBase64Encoded() certficate is not X.509 as expected. Type is: " + cert.getType());

                return null;

                } catch (java.security.cert.CertificateException e) {

                System.err.println("toX509CertificateFromBase64Encoded() exception: " + e.getMessage());

                e.printStackTrace();

                return null;

                }

                }

               

                static PublicKey getPublicFromX509Encoded(KeyFactory keyFactory, byte[] x509EncodedPublicKey) {

                try {

                X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(x509EncodedPublicKey);

                return keyFactory.generatePublic(pubKeySpec);

                } catch (Exception e) {

                System.err.println("getPublicFromX509Encoded() Failed to decode: " + e.getMessage());

                return null;

                }

                }

               

                static PrivateKey getPrivateFromPkcs8Encoded(KeyFactory keyFactory, byte[] pkcs8EncodedPrivateKey) {

                try {

                PKCS8EncodedKeySpec privKeySpec = new java.security.spec.PKCS8EncodedKeySpec(pkcs8EncodedPrivateKey);

                return keyFactory.generatePrivate(privKeySpec);

                } catch (Exception e) {

                System.err.println("getPrivateFromPkcs8Encoded() Failed to decode: " + e.getMessage());

                return null;

                }

                }

               

               

                static final String CERT = "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";

                static final String PUBKEY = "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAkPCr+Fy0NInaICpnzDpGLkNQ93kd0NzZfTBfQOb3PUH1Bt4OrBWcvYoch7wUm6k1Il3apsi7s2B9Geqbh7tzF41MwvTWBNCQg3Kw3FKcF0jzKZ7D+na8Ndc52YPmsjU9zjpf+SDfKqb0NIDe3Bo3csWWI42CkF3sI9AFknogovrfRM7ITJatA6WRHU8Kv6Qee8VfXZ1XAdKzWcc9EWbj74Kagiz8bMeATujUMCI/XQb1luwvlrVxZUtnfLL9WD6Nvmj3uDYK52z5E80vqTKIq7EJvmlR7kcEdH1NuxDQSWCJQgQXoU2TzuB0Nmov7P/pZ40JPF72Knb18Rgu4aRSMiaKKw+jzFHpw75VlQn2YkdfjNMwfUaEaZ4wuHoJQjud79jilbam++eUQFRxjcXK9Nl/z01KtmuV1mPhm97LRaKQlsbBxa56pncrkAmF0cuIipPzo9aBsnJZkUQuwQtD/moDkUm84v5SOU1hn4RpWdGAkaJ1ubIrnKfF0qKmbCOcO69SEL5zP0JXEgSZ+D6zVv7VkAJizdJ91KKs4y/ypel4lurNcyBd3hzw8xpz9joMl8DOTLCcLhGp350Vrccbh9vauAcRcK/nC+yaPI/mghmN2D2yZ3LZ3Z6k78Jl9BUV7PL5YyuxQmZjVP07lJvi6glLUm23o+c3c4D7rgHL4gMCAwEAAQ==";

                static final String PRIVKEY = "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";

               

                public static class SignatureKey {

                public UUID id;

                public KeyPair keyPair;

                public X509Certificate cert;

               

                public SignatureKey(UUID id) {

                this.id = id;

               

                String base64Cert = CERT;

                String base64PublicKey = PUBKEY;

                String base64PrivateKey = PRIVKEY;

               

                try {

                KeyFactory keyFactory = null;

               

                try {

                keyFactory = KeyFactory.getInstance("RSA", "BC");

                System.err.println("SignatureKey: Using BC provider on RSA KeyFactory");

                } catch (NoSuchProviderException e) {

                try {

                keyFactory = KeyFactory.getInstance("RSA", "SunRsaSign");

                System.err.println("SignatureKey: Using SunRsaSign provider on RSA KeyFactory");

                } catch (NoSuchProviderException e2) {

                System.err.println("SignatureKey -- no KeyFactory provider found exception: " + e.getMessage());

                e.printStackTrace();

                System.exit(2);

                }

                }

               

                cert = toX509CertificateFromBase64Encoded(base64Cert);

                byte[] encodedPublicKey = java.util.Base64.getDecoder().decode(base64PublicKey);

                PublicKey publicKey = getPublicFromX509Encoded(keyFactory,encodedPublicKey);

               

                byte[] encodedPrivateKey = java.util.Base64.getDecoder().decode(base64PrivateKey);

                PrivateKey privateKey = getPrivateFromPkcs8Encoded(keyFactory,encodedPrivateKey);

                keyPair = new KeyPair(publicKey, privateKey);

                } catch( Exception e ) {

                System.err.println("SignatureKey - exception: " + e.getMessage());

                e.printStackTrace();

                }

               

               

                }

                }

               

                static final String html = "<html xmlns=\"http://www.w3.org/1999/xhtml\"><head></head><body><p>Dummy HTML document</p></body></html>";

                static final String XML_NAMESPACE_2011 = "http://open.esignforms.com/XMLSchema/2011";

               

                // Added main so can run the test under different JDKs.

                public static void main(String[] args) {

                try {

                java.security.Security.setProperty("crypto.policy", "unlimited"); // Should work in Java 9 to allow unlimited crypto strength.

               

                try {

                Class<?> jceProvider = Class.forName("org.bouncycastle.jce.provider.BouncyCastleProvider");

                java.security.Provider p = (java.security.Provider) jceProvider.newInstance();

                java.security.Security.addProvider(p);

                p = java.security.Security.getProvider("BC");

                if (p == null)

                System.err.println("Could not find the BC JCE provider; hoping that the SunRsaSign is in there!");

                else

                System.err.println("Found BC Provider: " + p.getInfo());

                } catch(ClassNotFoundException e) {

                System.err.println("ClassNotFoundException: Could not find the BC JCE provider");

                } catch (InstantiationException e) {

                System.err.println("InstantiationException: Could not find the BC JCE provider");

                } catch (IllegalAccessException e) {

                System.err.println("IllegalAccessException: Could not find the BC JCE provider");

                }

               

                String namespaceTimestampAttributes = "xmlns=\"" + XML_NAMESPACE_2011 + "\" timestamp=\"" + toXmlWithTz(ZonedDateTime.now()) + "\"";

                String xml = "<snapshot type=\"document\" " + namespaceTimestampAttributes + "><![CDATA[" + html + "]]></snapshot>";

               

                SignatureKey signatureKey = new SignatureKey(UUID.randomUUID());

                XmlDigitalSignature xmldsig = new XmlDigitalSignature();

                String signedXml = xmldsig.sign(xml, "description", "text/html", signatureKey, "192.1.1.1", "No-Browser-Test");

                System.out.println("Signed XML:");

                System.out.println(signedXml);

                } catch (Exception e) {

                System.err.println("XmlDigitalSignature.main() exception: " + e.getMessage());

                e.printStackTrace();

                System.exit(1);

                }

               

                System.exit(0);

                }

              }