src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/SignedInfo.java
changeset 50614 3810c9a2efa1
parent 47216 71c04702a3d5
child 59240 b3116877866f
equal deleted inserted replaced
50613:0f93a75b9213 50614:3810c9a2efa1
    22  */
    22  */
    23 package com.sun.org.apache.xml.internal.security.signature;
    23 package com.sun.org.apache.xml.internal.security.signature;
    24 
    24 
    25 import java.io.ByteArrayInputStream;
    25 import java.io.ByteArrayInputStream;
    26 import java.io.IOException;
    26 import java.io.IOException;
       
    27 import java.io.InputStream;
    27 import java.io.OutputStream;
    28 import java.io.OutputStream;
       
    29 
    28 import javax.crypto.SecretKey;
    30 import javax.crypto.SecretKey;
    29 import javax.crypto.spec.SecretKeySpec;
    31 import javax.crypto.spec.SecretKeySpec;
    30 import javax.xml.XMLConstants;
       
    31 import javax.xml.parsers.ParserConfigurationException;
    32 import javax.xml.parsers.ParserConfigurationException;
    32 
    33 
    33 import com.sun.org.apache.xml.internal.security.algorithms.SignatureAlgorithm;
    34 import com.sun.org.apache.xml.internal.security.algorithms.SignatureAlgorithm;
    34 import com.sun.org.apache.xml.internal.security.c14n.CanonicalizationException;
    35 import com.sun.org.apache.xml.internal.security.c14n.CanonicalizationException;
    35 import com.sun.org.apache.xml.internal.security.c14n.Canonicalizer;
    36 import com.sun.org.apache.xml.internal.security.c14n.Canonicalizer;
    36 import com.sun.org.apache.xml.internal.security.c14n.InvalidCanonicalizerException;
    37 import com.sun.org.apache.xml.internal.security.c14n.InvalidCanonicalizerException;
    37 import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException;
    38 import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException;
       
    39 import com.sun.org.apache.xml.internal.security.transforms.params.InclusiveNamespaces;
    38 import com.sun.org.apache.xml.internal.security.utils.Constants;
    40 import com.sun.org.apache.xml.internal.security.utils.Constants;
    39 import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
    41 import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
    40 import com.sun.org.apache.xml.internal.security.transforms.params.InclusiveNamespaces;
       
    41 import org.w3c.dom.Document;
    42 import org.w3c.dom.Document;
    42 import org.w3c.dom.Element;
    43 import org.w3c.dom.Element;
    43 import org.w3c.dom.Node;
    44 import org.w3c.dom.Node;
    44 import org.xml.sax.SAXException;
    45 import org.xml.sax.SAXException;
    45 
    46 
    46 /**
    47 /**
    47  * Handles <code>&lt;ds:SignedInfo&gt;</code> elements
    48  * Handles {@code &lt;ds:SignedInfo&gt;} elements
    48  * This <code>SignedInfo<code> element includes the canonicalization algorithm,
    49  * This {@code SignedInfo} element includes the canonicalization algorithm,
    49  * a signature algorithm, and one or more references.
    50  * a signature algorithm, and one or more references.
    50  *
    51  *
    51  * @author Christian Geuer-Pollmann
       
    52  */
    52  */
    53 public class SignedInfo extends Manifest {
    53 public class SignedInfo extends Manifest {
    54 
    54 
    55     /** Field signatureAlgorithm */
    55     /** Field signatureAlgorithm */
    56     private SignatureAlgorithm signatureAlgorithm = null;
    56     private SignatureAlgorithm signatureAlgorithm;
    57 
    57 
    58     /** Field c14nizedBytes           */
    58     /** Field c14nizedBytes           */
    59     private byte[] c14nizedBytes = null;
    59     private byte[] c14nizedBytes;
    60 
    60 
    61     private Element c14nMethod;
    61     private Element c14nMethod;
    62     private Element signatureMethod;
    62     private Element signatureMethod;
    63 
    63 
    64     /**
    64     /**
    65      * Overwrites {@link Manifest#addDocument} because it creates another
    65      * Overwrites {@link Manifest#addDocument} because it creates another
    66      * Element.
    66      * Element.
    67      *
    67      *
    68      * @param doc the {@link Document} in which <code>XMLsignature</code> will
    68      * @param doc the {@link Document} in which {@code XMLsignature} will
    69      *    be placed
    69      *    be placed
    70      * @throws XMLSecurityException
    70      * @throws XMLSecurityException
    71      */
    71      */
    72     public SignedInfo(Document doc) throws XMLSecurityException {
    72     public SignedInfo(Document doc) throws XMLSecurityException {
    73         this(doc, XMLSignature.ALGO_ID_SIGNATURE_DSA,
    73         this(doc, XMLSignature.ALGO_ID_SIGNATURE_DSA,
    76 
    76 
    77     /**
    77     /**
    78      * Constructs {@link SignedInfo} using given Canonicalization algorithm and
    78      * Constructs {@link SignedInfo} using given Canonicalization algorithm and
    79      * Signature algorithm.
    79      * Signature algorithm.
    80      *
    80      *
    81      * @param doc <code>SignedInfo</code> is placed in this document
    81      * @param doc {@code SignedInfo} is placed in this document
    82      * @param signatureMethodURI URI representation of the Digest and
    82      * @param signatureMethodURI URI representation of the Digest and
    83      *    Signature algorithm
    83      *    Signature algorithm
    84      * @param canonicalizationMethodURI URI representation of the
    84      * @param canonicalizationMethodURI URI representation of the
    85      *    Canonicalization method
    85      *    Canonicalization method
    86      * @throws XMLSecurityException
    86      * @throws XMLSecurityException
    92     }
    92     }
    93 
    93 
    94     /**
    94     /**
    95      * Constructor SignedInfo
    95      * Constructor SignedInfo
    96      *
    96      *
    97      * @param doc <code>SignedInfo</code> is placed in this document
    97      * @param doc {@code SignedInfo} is placed in this document
    98      * @param signatureMethodURI URI representation of the Digest and
    98      * @param signatureMethodURI URI representation of the Digest and
    99      *    Signature algorithm
    99      *    Signature algorithm
   100      * @param hMACOutputLength
   100      * @param hMACOutputLength
   101      * @param canonicalizationMethodURI URI representation of the
   101      * @param canonicalizationMethodURI URI representation of the
   102      *    Canonicalization method
   102      *    Canonicalization method
   107         int hMACOutputLength, String canonicalizationMethodURI
   107         int hMACOutputLength, String canonicalizationMethodURI
   108     ) throws XMLSecurityException {
   108     ) throws XMLSecurityException {
   109         super(doc);
   109         super(doc);
   110 
   110 
   111         c14nMethod =
   111         c14nMethod =
   112             XMLUtils.createElementInSignatureSpace(this.doc, Constants._TAG_CANONICALIZATIONMETHOD);
   112             XMLUtils.createElementInSignatureSpace(getDocument(), Constants._TAG_CANONICALIZATIONMETHOD);
   113 
   113 
   114         c14nMethod.setAttributeNS(null, Constants._ATT_ALGORITHM, canonicalizationMethodURI);
   114         c14nMethod.setAttributeNS(null, Constants._ATT_ALGORITHM, canonicalizationMethodURI);
   115         this.constructionElement.appendChild(c14nMethod);
   115         appendSelf(c14nMethod);
   116         XMLUtils.addReturnToElement(this.constructionElement);
   116         addReturnToSelf();
   117 
   117 
   118         if (hMACOutputLength > 0) {
   118         if (hMACOutputLength > 0) {
   119             this.signatureAlgorithm =
   119             this.signatureAlgorithm =
   120                 new SignatureAlgorithm(this.doc, signatureMethodURI, hMACOutputLength);
   120                 new SignatureAlgorithm(getDocument(), signatureMethodURI, hMACOutputLength);
   121         } else {
   121         } else {
   122             this.signatureAlgorithm = new SignatureAlgorithm(this.doc, signatureMethodURI);
   122             this.signatureAlgorithm = new SignatureAlgorithm(getDocument(), signatureMethodURI);
   123         }
   123         }
   124 
   124 
   125         signatureMethod = this.signatureAlgorithm.getElement();
   125         signatureMethod = this.signatureAlgorithm.getElement();
   126         this.constructionElement.appendChild(signatureMethod);
   126         appendSelf(signatureMethod);
   127         XMLUtils.addReturnToElement(this.constructionElement);
   127         addReturnToSelf();
   128     }
   128     }
   129 
   129 
   130     /**
   130     /**
   131      * @param doc
   131      * @param doc
   132      * @param signatureMethodElem
   132      * @param signatureMethodElem
   137         Document doc, Element signatureMethodElem, Element canonicalizationMethodElem
   137         Document doc, Element signatureMethodElem, Element canonicalizationMethodElem
   138     ) throws XMLSecurityException {
   138     ) throws XMLSecurityException {
   139         super(doc);
   139         super(doc);
   140         // Check this?
   140         // Check this?
   141         this.c14nMethod = canonicalizationMethodElem;
   141         this.c14nMethod = canonicalizationMethodElem;
   142         this.constructionElement.appendChild(c14nMethod);
   142         appendSelf(c14nMethod);
   143         XMLUtils.addReturnToElement(this.constructionElement);
   143         addReturnToSelf();
   144 
   144 
   145         this.signatureAlgorithm =
   145         this.signatureAlgorithm =
   146             new SignatureAlgorithm(signatureMethodElem, null);
   146             new SignatureAlgorithm(signatureMethodElem, null);
   147 
   147 
   148         signatureMethod = this.signatureAlgorithm.getElement();
   148         signatureMethod = this.signatureAlgorithm.getElement();
   149         this.constructionElement.appendChild(signatureMethod);
   149         appendSelf(signatureMethod);
   150 
   150 
   151         XMLUtils.addReturnToElement(this.constructionElement);
   151         addReturnToSelf();
   152     }
   152     }
   153 
   153 
   154     /**
   154     /**
   155      * Build a {@link SignedInfo} from an {@link Element}
   155      * Build a {@link SignedInfo} from an {@link Element}
   156      *
   156      *
   157      * @param element <code>SignedInfo</code>
   157      * @param element {@code SignedInfo}
   158      * @param baseURI the URI of the resource where the XML instance was stored
   158      * @param baseURI the URI of the resource where the XML instance was stored
   159      * @throws XMLSecurityException
   159      * @throws XMLSecurityException
   160      * @see <A HREF="http://lists.w3.org/Archives/Public/w3c-ietf-xmldsig/2001OctDec/0033.html">
   160      * @see <A HREF="http://lists.w3.org/Archives/Public/w3c-ietf-xmldsig/2001OctDec/0033.html">
   161      * Question</A>
   161      * Question</A>
   162      * @see <A HREF="http://lists.w3.org/Archives/Public/w3c-ietf-xmldsig/2001OctDec/0054.html">
   162      * @see <A HREF="http://lists.w3.org/Archives/Public/w3c-ietf-xmldsig/2001OctDec/0054.html">
   163      * Answer</A>
   163      * Answer</A>
   164      */
   164      */
   165     public SignedInfo(Element element, String baseURI) throws XMLSecurityException {
   165     public SignedInfo(Element element, String baseURI) throws XMLSecurityException {
   166         this(element, baseURI, false);
   166         this(element, baseURI, true);
   167     }
   167     }
   168 
   168 
   169     /**
   169     /**
   170      * Build a {@link SignedInfo} from an {@link Element}
   170      * Build a {@link SignedInfo} from an {@link Element}
   171      *
   171      *
   172      * @param element <code>SignedInfo</code>
   172      * @param element {@code SignedInfo}
   173      * @param baseURI the URI of the resource where the XML instance was stored
   173      * @param baseURI the URI of the resource where the XML instance was stored
   174      * @param secureValidation whether secure validation is enabled or not
   174      * @param secureValidation whether secure validation is enabled or not
   175      * @throws XMLSecurityException
   175      * @throws XMLSecurityException
   176      * @see <A HREF="http://lists.w3.org/Archives/Public/w3c-ietf-xmldsig/2001OctDec/0033.html">
   176      * @see <A HREF="http://lists.w3.org/Archives/Public/w3c-ietf-xmldsig/2001OctDec/0033.html">
   177      * Question</A>
   177      * Question</A>
   180      */
   180      */
   181     public SignedInfo(
   181     public SignedInfo(
   182         Element element, String baseURI, boolean secureValidation
   182         Element element, String baseURI, boolean secureValidation
   183     ) throws XMLSecurityException {
   183     ) throws XMLSecurityException {
   184         // Parse the Reference children and Id attribute in the Manifest
   184         // Parse the Reference children and Id attribute in the Manifest
   185         super(reparseSignedInfoElem(element), baseURI, secureValidation);
   185         super(reparseSignedInfoElem(element, secureValidation), baseURI, secureValidation);
   186 
   186 
   187         c14nMethod = XMLUtils.getNextElement(element.getFirstChild());
   187         c14nMethod = XMLUtils.getNextElement(element.getFirstChild());
   188         signatureMethod = XMLUtils.getNextElement(c14nMethod.getNextSibling());
   188         signatureMethod = XMLUtils.getNextElement(c14nMethod.getNextSibling());
   189         this.signatureAlgorithm =
   189         this.signatureAlgorithm =
   190             new SignatureAlgorithm(signatureMethod, this.getBaseURI(), secureValidation);
   190             new SignatureAlgorithm(signatureMethod, this.getBaseURI(), secureValidation);
   191     }
   191     }
   192 
   192 
   193     private static Element reparseSignedInfoElem(Element element)
   193     private static Element reparseSignedInfoElem(Element element, boolean secureValidation)
   194         throws XMLSecurityException {
   194         throws XMLSecurityException {
   195         /*
   195         /*
   196          * If a custom canonicalizationMethod is used, canonicalize
   196          * If a custom canonicalizationMethod is used, canonicalize
   197          * ds:SignedInfo, reparse it into a new document
   197          * ds:SignedInfo, reparse it into a new document
   198          * and replace the original not-canonicalized ds:SignedInfo by
   198          * and replace the original not-canonicalized ds:SignedInfo by
   210             // the c14n is not a secure one and can rewrite the URIs or like
   210             // the c14n is not a secure one and can rewrite the URIs or like
   211             // so reparse the SignedInfo to be sure
   211             // so reparse the SignedInfo to be sure
   212             try {
   212             try {
   213                 Canonicalizer c14nizer =
   213                 Canonicalizer c14nizer =
   214                     Canonicalizer.getInstance(c14nMethodURI);
   214                     Canonicalizer.getInstance(c14nMethodURI);
       
   215                 c14nizer.setSecureValidation(secureValidation);
   215 
   216 
   216                 byte[] c14nizedBytes = c14nizer.canonicalizeSubtree(element);
   217                 byte[] c14nizedBytes = c14nizer.canonicalizeSubtree(element);
   217                 javax.xml.parsers.DocumentBuilderFactory dbf =
   218                 javax.xml.parsers.DocumentBuilder db =
   218                     javax.xml.parsers.DocumentBuilderFactory.newInstance();
   219                     XMLUtils.createDocumentBuilder(false, secureValidation);
   219                 dbf.setNamespaceAware(true);
   220                 try (InputStream is = new ByteArrayInputStream(c14nizedBytes)) {
   220                 dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE);
   221                     Document newdoc = db.parse(is);
   221                 javax.xml.parsers.DocumentBuilder db = dbf.newDocumentBuilder();
   222                     Node imported = element.getOwnerDocument().importNode(
   222                 Document newdoc =
   223                             newdoc.getDocumentElement(), true);
   223                     db.parse(new ByteArrayInputStream(c14nizedBytes));
   224                     element.getParentNode().replaceChild(imported, element);
   224                 Node imported =
   225                     return (Element) imported;
   225                     element.getOwnerDocument().importNode(newdoc.getDocumentElement(), true);
   226                 }
   226 
       
   227                 element.getParentNode().replaceChild(imported, element);
       
   228 
       
   229                 return (Element) imported;
       
   230             } catch (ParserConfigurationException ex) {
   227             } catch (ParserConfigurationException ex) {
   231                 throw new XMLSecurityException("empty", ex);
   228                 throw new XMLSecurityException(ex);
   232             } catch (IOException ex) {
   229             } catch (IOException ex) {
   233                 throw new XMLSecurityException("empty", ex);
   230                 throw new XMLSecurityException(ex);
   234             } catch (SAXException ex) {
   231             } catch (SAXException ex) {
   235                 throw new XMLSecurityException("empty", ex);
   232                 throw new XMLSecurityException(ex);
   236             }
   233             }
   237         }
   234         }
   238         return element;
   235         return element;
   239     }
   236     }
   240 
   237 
   251     }
   248     }
   252 
   249 
   253     /**
   250     /**
   254      * Tests core validation process
   251      * Tests core validation process
   255      *
   252      *
   256      * @param followManifests defines whether the verification process has to verify referenced <CODE>ds:Manifest</CODE>s, too
   253      * @param followManifests defines whether the verification process has to verify referenced {@code ds:Manifest}s, too
   257      * @return true if verification was successful
   254      * @return true if verification was successful
   258      * @throws MissingResourceFailureException
   255      * @throws MissingResourceFailureException
   259      * @throws XMLSecurityException
   256      * @throws XMLSecurityException
   260      */
   257      */
   261     public boolean verify(boolean followManifests)
   258     public boolean verify(boolean followManifests)
   264     }
   261     }
   265 
   262 
   266     /**
   263     /**
   267      * Returns getCanonicalizedOctetStream
   264      * Returns getCanonicalizedOctetStream
   268      *
   265      *
   269      * @return the canonicalization result octet stream of <code>SignedInfo</code> element
   266      * @return the canonicalization result octet stream of {@code SignedInfo} element
   270      * @throws CanonicalizationException
   267      * @throws CanonicalizationException
   271      * @throws InvalidCanonicalizerException
   268      * @throws InvalidCanonicalizerException
   272      * @throws XMLSecurityException
   269      * @throws XMLSecurityException
   273      */
   270      */
   274     public byte[] getCanonicalizedOctetStream()
   271     public byte[] getCanonicalizedOctetStream()
   275         throws CanonicalizationException, InvalidCanonicalizerException, XMLSecurityException {
   272         throws CanonicalizationException, InvalidCanonicalizerException, XMLSecurityException {
   276         if (this.c14nizedBytes == null) {
   273         if (this.c14nizedBytes == null) {
   277             Canonicalizer c14nizer =
   274             Canonicalizer c14nizer =
   278                 Canonicalizer.getInstance(this.getCanonicalizationMethodURI());
   275                 Canonicalizer.getInstance(this.getCanonicalizationMethodURI());
   279 
   276             c14nizer.setSecureValidation(isSecureValidation());
   280             this.c14nizedBytes =
   277 
   281                 c14nizer.canonicalizeSubtree(this.constructionElement);
   278             String inclusiveNamespaces = this.getInclusiveNamespaces();
       
   279             if (inclusiveNamespaces == null) {
       
   280                 this.c14nizedBytes = c14nizer.canonicalizeSubtree(getElement());
       
   281             } else {
       
   282                 this.c14nizedBytes = c14nizer.canonicalizeSubtree(getElement(), inclusiveNamespaces);
       
   283             }
   282         }
   284         }
   283 
   285 
   284         // make defensive copy
   286         // make defensive copy
   285         return this.c14nizedBytes.clone();
   287         return this.c14nizedBytes.clone();
   286     }
   288     }
   295     public void signInOctetStream(OutputStream os)
   297     public void signInOctetStream(OutputStream os)
   296         throws CanonicalizationException, InvalidCanonicalizerException, XMLSecurityException {
   298         throws CanonicalizationException, InvalidCanonicalizerException, XMLSecurityException {
   297         if (this.c14nizedBytes == null) {
   299         if (this.c14nizedBytes == null) {
   298             Canonicalizer c14nizer =
   300             Canonicalizer c14nizer =
   299                 Canonicalizer.getInstance(this.getCanonicalizationMethodURI());
   301                 Canonicalizer.getInstance(this.getCanonicalizationMethodURI());
       
   302             c14nizer.setSecureValidation(isSecureValidation());
   300             c14nizer.setWriter(os);
   303             c14nizer.setWriter(os);
   301             String inclusiveNamespaces = this.getInclusiveNamespaces();
   304             String inclusiveNamespaces = this.getInclusiveNamespaces();
   302 
   305 
   303             if (inclusiveNamespaces == null) {
   306             if (inclusiveNamespaces == null) {
   304                 c14nizer.canonicalizeSubtree(this.constructionElement);
   307                 c14nizer.canonicalizeSubtree(getElement());
   305             } else {
   308             } else {
   306                 c14nizer.canonicalizeSubtree(this.constructionElement, inclusiveNamespaces);
   309                 c14nizer.canonicalizeSubtree(getElement(), inclusiveNamespaces);
   307             }
   310             }
   308         } else {
   311         } else {
   309             try {
   312             try {
   310                 os.write(this.c14nizedBytes);
   313                 os.write(this.c14nizedBytes);
   311             } catch (IOException e) {
   314             } catch (IOException e) {
   356      */
   359      */
   357     public SecretKey createSecretKey(byte[] secretKeyBytes) {
   360     public SecretKey createSecretKey(byte[] secretKeyBytes) {
   358         return new SecretKeySpec(secretKeyBytes, this.signatureAlgorithm.getJCEAlgorithmString());
   361         return new SecretKeySpec(secretKeyBytes, this.signatureAlgorithm.getJCEAlgorithmString());
   359     }
   362     }
   360 
   363 
   361     protected SignatureAlgorithm getSignatureAlgorithm() {
   364     public SignatureAlgorithm getSignatureAlgorithm() {
   362         return signatureAlgorithm;
   365         return signatureAlgorithm;
   363     }
   366     }
   364 
   367 
   365     /**
   368     /**
   366      * Method getBaseLocalName
   369      * Method getBaseLocalName
   367      * @inheritDoc
   370      * {@inheritDoc}
   368      *
   371      *
   369      */
   372      */
   370     public String getBaseLocalName() {
   373     public String getBaseLocalName() {
   371         return Constants._TAG_SIGNEDINFO;
   374         return Constants._TAG_SIGNEDINFO;
   372     }
   375     }
   373 
   376 
   374     public String getInclusiveNamespaces() {
   377     public String getInclusiveNamespaces() {
   375         String c14nMethodURI = c14nMethod.getAttributeNS(null, Constants._ATT_ALGORITHM);
   378         String c14nMethodURI = getCanonicalizationMethodURI();
   376         if (!(c14nMethodURI.equals("http://www.w3.org/2001/10/xml-exc-c14n#") ||
   379         if (!(c14nMethodURI.equals("http://www.w3.org/2001/10/xml-exc-c14n#") ||
   377             c14nMethodURI.equals("http://www.w3.org/2001/10/xml-exc-c14n#WithComments"))) {
   380             c14nMethodURI.equals("http://www.w3.org/2001/10/xml-exc-c14n#WithComments"))) {
   378             return null;
   381             return null;
   379         }
   382         }
   380 
   383