KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > org > apache > xml > internal > security > signature > XMLSignature


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */

17 package com.sun.org.apache.xml.internal.security.signature;
18
19
20
21 import java.io.IOException JavaDoc;
22 import java.io.OutputStream JavaDoc;
23 import java.security.Key JavaDoc;
24 import java.security.PublicKey JavaDoc;
25 import java.security.cert.X509Certificate JavaDoc;
26
27 import javax.crypto.SecretKey;
28
29 import com.sun.org.apache.xml.internal.security.algorithms.SignatureAlgorithm;
30 import com.sun.org.apache.xml.internal.security.c14n.CanonicalizationException;
31 import com.sun.org.apache.xml.internal.security.c14n.Canonicalizer;
32 import com.sun.org.apache.xml.internal.security.c14n.InvalidCanonicalizerException;
33 import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException;
34 import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException;
35 import com.sun.org.apache.xml.internal.security.keys.KeyInfo;
36 import com.sun.org.apache.xml.internal.security.keys.content.X509Data;
37 import com.sun.org.apache.xml.internal.security.transforms.Transforms;
38 import com.sun.org.apache.xml.internal.security.utils.Base64;
39 import com.sun.org.apache.xml.internal.security.utils.Constants;
40 import com.sun.org.apache.xml.internal.security.utils.I18n;
41 import com.sun.org.apache.xml.internal.security.utils.IdResolver;
42 import com.sun.org.apache.xml.internal.security.utils.SignatureElementProxy;
43 import com.sun.org.apache.xml.internal.security.utils.SignerOutputStream;
44 import com.sun.org.apache.xml.internal.security.utils.UnsyncBufferedOutputStream;
45 import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
46 import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolver;
47 import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverSpi;
48 import org.w3c.dom.Document JavaDoc;
49 import org.w3c.dom.Element JavaDoc;
50 import org.w3c.dom.Node JavaDoc;
51 import org.w3c.dom.Text JavaDoc;
52
53
54 /**
55  * Handles <code>&lt;ds:Signature&gt;</code> elements.
56  * This is the main class that deals with creating and verifying signatures.
57  *
58  * <p>There are 2 types of constructors for this class. The ones that take a
59  * document, baseURI and 1 or more Java Objects. This is mostly used for
60  * signing purposes.
61  * The other constructor is the one that takes a DOM Element and a BaseURI.
62  * This is used mostly with for verifying, when you have a SignatureElement.
63  *
64  * There are a few different types of methods:
65  * <ul><li>The addDocument* methods are used to add References with optional
66  * transforms during signing. </li>
67  * <li>addKeyInfo* methods are to add Certificates and Keys to the
68  * KeyInfo tags during signing. </li>
69  * <li>appendObject allows a user to add any XML Structure as an
70  * ObjectContainer during signing.</li>
71  * <li>sign and checkSignatureValue methods are used to sign and validate the
72  * signature. </li></ul>
73  *
74  * @author $Author: raul $
75  */

76 public final class XMLSignature extends SignatureElementProxy {
77
78    /** {@link java.util.logging} logging facility */
79    static java.util.logging.Logger JavaDoc log =
80         java.util.logging.Logger.getLogger(XMLSignature.class.getName());
81    
82    //J-
83
/** MAC - Required HMAC-SHA1 */
84    public static final String JavaDoc ALGO_ID_MAC_HMAC_SHA1 = Constants.SignatureSpecNS + "hmac-sha1";
85
86    /** Signature - Required DSAwithSHA1 (DSS) */
87    public static final String JavaDoc ALGO_ID_SIGNATURE_DSA = Constants.SignatureSpecNS + "dsa-sha1";
88
89    /** Signature - Recommended RSAwithSHA1 */
90    public static final String JavaDoc ALGO_ID_SIGNATURE_RSA = Constants.SignatureSpecNS + "rsa-sha1";
91    /** Signature - Recommended RSAwithSHA1 */
92    public static final String JavaDoc ALGO_ID_SIGNATURE_RSA_SHA1 = Constants.SignatureSpecNS + "rsa-sha1";
93    /** Signature - NOT Recommended RSAwithMD5 */
94    public static final String JavaDoc ALGO_ID_SIGNATURE_NOT_RECOMMENDED_RSA_MD5 = Constants.MoreAlgorithmsSpecNS + "rsa-md5";
95    /** Signature - Optional RSAwithRIPEMD160 */
96    public static final String JavaDoc ALGO_ID_SIGNATURE_RSA_RIPEMD160 = Constants.MoreAlgorithmsSpecNS + "rsa-ripemd160";
97    /** Signature - Optional RSAwithSHA256 */
98    public static final String JavaDoc ALGO_ID_SIGNATURE_RSA_SHA256 = Constants.MoreAlgorithmsSpecNS + "rsa-sha256";
99    /** Signature - Optional RSAwithSHA384 */
100    public static final String JavaDoc ALGO_ID_SIGNATURE_RSA_SHA384 = Constants.MoreAlgorithmsSpecNS + "rsa-sha384";
101    /** Signature - Optional RSAwithSHA512 */
102    public static final String JavaDoc ALGO_ID_SIGNATURE_RSA_SHA512 = Constants.MoreAlgorithmsSpecNS + "rsa-sha512";
103
104    /** HMAC - NOT Recommended HMAC-MD5 */
105    public static final String JavaDoc ALGO_ID_MAC_HMAC_NOT_RECOMMENDED_MD5 = Constants.MoreAlgorithmsSpecNS + "hmac-md5";
106    /** HMAC - Optional HMAC-RIPEMD160 */
107    public static final String JavaDoc ALGO_ID_MAC_HMAC_RIPEMD160 = Constants.MoreAlgorithmsSpecNS + "hmac-ripemd160";
108    /** HMAC - Optional HMAC-SHA256 */
109    public static final String JavaDoc ALGO_ID_MAC_HMAC_SHA256 = Constants.MoreAlgorithmsSpecNS + "hmac-sha256";
110    /** HMAC - Optional HMAC-SHA284 */
111    public static final String JavaDoc ALGO_ID_MAC_HMAC_SHA384 = Constants.MoreAlgorithmsSpecNS + "hmac-sha384";
112    /** HMAC - Optional HMAC-SHA512 */
113    public static final String JavaDoc ALGO_ID_MAC_HMAC_SHA512 = Constants.MoreAlgorithmsSpecNS + "hmac-sha512";
114    //J+
115

116    /** ds:Signature.ds:SignedInfo element */
117    private SignedInfo _signedInfo = null;
118
119    /** ds:Signature.ds:KeyInfo */
120    private KeyInfo _keyInfo = null;
121
122    /**
123     * Checking the digests in References in a Signature are mandatory, but for
124     * References inside a Manifest it is application specific. This boolean is
125     * to indicate that the References inside Manifests should be validated.
126     */

127    private boolean _followManifestsDuringValidation = false;
128
129   /**
130     * This creates a new <CODE>ds:Signature</CODE> Element and adds an empty
131     * <CODE>ds:SignedInfo</CODE>.
132     * The <code>ds:SignedInfo</code> is initialized with the specified Signature
133     * algorithm and Canonicalizer.ALGO_ID_C14N_OMIT_COMMENTS which is REQUIRED
134     * by the spec. This method's main use is for creating a new signature.
135     *
136     * @param doc Document in which the signature will be appended after creation.
137     * @param BaseURI URI to be used as context for all relative URIs.
138     * @param SignatureMethodURI signature algorithm to use.
139     * @throws XMLSecurityException
140     */

141    public XMLSignature(Document JavaDoc doc, String JavaDoc BaseURI, String JavaDoc SignatureMethodURI)
142            throws XMLSecurityException {
143       this(doc, BaseURI, SignatureMethodURI, 0,
144            Canonicalizer.ALGO_ID_C14N_OMIT_COMMENTS);
145    }
146
147    /**
148     * Constructor XMLSignature
149     *
150     * @param doc
151     * @param BaseURI
152     * @param SignatureMethodURI the Signature method to be used.
153     * @param HMACOutputLength
154     * @throws XMLSecurityException
155     */

156    public XMLSignature(
157            Document JavaDoc doc, String JavaDoc BaseURI, String JavaDoc SignatureMethodURI, int HMACOutputLength)
158               throws XMLSecurityException {
159       this(doc, BaseURI, SignatureMethodURI, HMACOutputLength,
160            Canonicalizer.ALGO_ID_C14N_OMIT_COMMENTS);
161    }
162
163    /**
164     * Constructor XMLSignature
165     *
166     * @param doc
167     * @param BaseURI
168     * @param SignatureMethodURI the Signature method to be used.
169     * @param CanonicalizationMethodURI the canonicalization algorithm to be used to c14nize the SignedInfo element.
170     * @throws XMLSecurityException
171     */

172    public XMLSignature(
173            Document JavaDoc doc, String JavaDoc BaseURI, String JavaDoc SignatureMethodURI, String JavaDoc CanonicalizationMethodURI)
174               throws XMLSecurityException {
175       this(doc, BaseURI, SignatureMethodURI, 0, CanonicalizationMethodURI);
176    }
177
178    /**
179     * Constructor XMLSignature
180     *
181     * @param doc
182     * @param BaseURI
183     * @param SignatureMethodURI
184     * @param HMACOutputLength
185     * @param CanonicalizationMethodURI
186     * @throws XMLSecurityException
187     */

188    public XMLSignature(
189            Document JavaDoc doc, String JavaDoc BaseURI, String JavaDoc SignatureMethodURI, int HMACOutputLength, String JavaDoc CanonicalizationMethodURI)
190               throws XMLSecurityException {
191
192       super(doc);
193
194       XMLUtils.addReturnToElement(this._constructionElement);
195
196       this._baseURI = BaseURI;
197       this._signedInfo = new SignedInfo(this._doc, SignatureMethodURI,
198                                         HMACOutputLength,
199                                         CanonicalizationMethodURI);
200
201       this._constructionElement.appendChild(this._signedInfo.getElement());
202       XMLUtils.addReturnToElement(this._constructionElement);
203
204       // create an empty SignatureValue; this is filled by setSignatureValueElement
205
Element JavaDoc signatureValueElement =
206          XMLUtils.createElementInSignatureSpace(this._doc,
207                                                 Constants._TAG_SIGNATUREVALUE);
208
209       this._constructionElement.appendChild(signatureValueElement);
210       XMLUtils.addReturnToElement(this._constructionElement);
211    }
212    /**
213     * Creates a XMLSignature in a Document
214     * @param doc
215     * @param BaseURI
216     * @param SignatureMethodElem
217     * @param CanonicalizationMethodElem
218     * @throws XMLSecurityException
219     */

220    public XMLSignature(
221            Document JavaDoc doc, String JavaDoc BaseURI, Element JavaDoc SignatureMethodElem, Element JavaDoc CanonicalizationMethodElem)
222               throws XMLSecurityException {
223
224       super(doc);
225
226       XMLUtils.addReturnToElement(this._constructionElement);
227
228       this._baseURI = BaseURI;
229       this._signedInfo = new SignedInfo(this._doc, SignatureMethodElem, CanonicalizationMethodElem);
230
231       this._constructionElement.appendChild(this._signedInfo.getElement());
232       XMLUtils.addReturnToElement(this._constructionElement);
233
234       // create an empty SignatureValue; this is filled by setSignatureValueElement
235
Element JavaDoc signatureValueElement =
236          XMLUtils.createElementInSignatureSpace(this._doc,
237                                                 Constants._TAG_SIGNATUREVALUE);
238
239       this._constructionElement.appendChild(signatureValueElement);
240       XMLUtils.addReturnToElement(this._constructionElement);
241    }
242
243    /**
244     * This will parse the element and construct the Java Objects.
245     * That will allow a user to validate the signature.
246     *
247     * @param element ds:Signature element that contains the whole signature
248     * @param BaseURI URI to be prepended to all relative URIs
249     * @throws XMLSecurityException
250     * @throws XMLSignatureException if the signature is badly formatted
251     */

252    public XMLSignature(Element JavaDoc element, String JavaDoc BaseURI)
253            throws XMLSignatureException, XMLSecurityException {
254
255       super(element, BaseURI);
256
257       // check out SignedInfo child
258
Element JavaDoc signedInfoElem = XMLUtils.selectDsNode(this._constructionElement.getFirstChild(),
259                                   Constants._TAG_SIGNEDINFO,0);
260
261       // check to see if it is there
262
if (signedInfoElem == null) {
263          Object JavaDoc exArgs[] = { Constants._TAG_SIGNEDINFO,
264                              Constants._TAG_SIGNATURE };
265
266          throw new XMLSignatureException("xml.WrongContent", exArgs);
267       }
268
269       // create a SignedInfo object from that element
270
this._signedInfo = new SignedInfo(signedInfoElem, BaseURI);
271
272       // check out SignatureValue child
273
Element JavaDoc signatureValueElement = XMLUtils.selectDsNode(this._constructionElement.getFirstChild(),
274                                          Constants._TAG_SIGNATUREVALUE,0);
275
276       // check to see if it exists
277
if (signatureValueElement == null) {
278          Object JavaDoc exArgs[] = { Constants._TAG_SIGNATUREVALUE,
279                              Constants._TAG_SIGNATURE };
280
281          throw new XMLSignatureException("xml.WrongContent", exArgs);
282       }
283
284       // <element ref="ds:KeyInfo" minOccurs="0"/>
285
Element JavaDoc keyInfoElem =XMLUtils.selectDsNode(this._constructionElement.getFirstChild(),
286                                Constants._TAG_KEYINFO,0);
287
288       // If it exists use it, but it's not mandatory
289
if (keyInfoElem != null) {
290          this._keyInfo = new KeyInfo(keyInfoElem, BaseURI);
291       }
292    }
293
294    /**
295     * Sets the <code>Id</code> attribute
296     *
297     * @param Id Id value to be used by the id attribute on the Signature Element
298     */

299    public void setId(String JavaDoc Id) {
300
301       if ((this._state == MODE_SIGN) && (Id != null)) {
302          this._constructionElement.setAttributeNS(null, Constants._ATT_ID, Id);
303          IdResolver.registerElementById(this._constructionElement, Id);
304       }
305    }
306
307    /**
308     * Returns the <code>Id</code> attribute
309     *
310     * @return the <code>Id</code> attribute
311     */

312    public String JavaDoc getId() {
313       return this._constructionElement.getAttributeNS(null, Constants._ATT_ID);
314    }
315
316    /**
317     * Returns the completely parsed <code>SignedInfo</code> object.
318     *
319     * @return the completely parsed <code>SignedInfo</code> object.
320     */

321    public SignedInfo getSignedInfo() {
322       return this._signedInfo;
323    }
324
325    /**
326     * Returns the octet value of the SignatureValue element.
327     * Throws an XMLSignatureException if it has no or wrong content.
328     *
329     * @return the value of the SignatureValue element.
330     * @throws XMLSignatureException If there is no content
331     */

332    public byte[] getSignatureValue() throws XMLSignatureException {
333
334       try {
335          Element JavaDoc signatureValueElem = XMLUtils.selectDsNode(this._constructionElement.getFirstChild(),
336                                          Constants._TAG_SIGNATUREVALUE,0);
337          byte[] signatureValue = Base64.decode(signatureValueElem);
338
339          return signatureValue;
340       } catch (Base64DecodingException ex) {
341          throw new XMLSignatureException("empty", ex);
342       }
343    }
344
345    /**
346     * Base64 encodes and sets the bytes as the content of the SignatureValue
347     * Node.
348     *
349     * @param bytes bytes to be used by SignatureValue before Base64 encoding
350     */

351    private void setSignatureValueElement(byte[] bytes)
352    {
353
354       if (this._state == MODE_SIGN) {
355          Element JavaDoc signatureValueElem = XMLUtils.selectDsNode(this._constructionElement.getFirstChild(),
356                                          Constants._TAG_SIGNATUREVALUE,0);
357          while (signatureValueElem.hasChildNodes()) {
358             signatureValueElem.removeChild(signatureValueElem.getFirstChild());
359          }
360
361          String JavaDoc base64codedValue = Base64.encode(bytes);
362
363          if (base64codedValue.length() > 76) {
364             base64codedValue = "\n" + base64codedValue + "\n";
365          }
366
367          Text JavaDoc t = this._doc.createTextNode(base64codedValue);
368
369          signatureValueElem.appendChild(t);
370       }
371    }
372
373    /**
374     * Returns the KeyInfo child. If we are in signing mode and the KeyInfo
375     * does not exist yet, it is created on demand and added to the Signature.
376     * <br>
377     * This allows to add arbitrary content to the KeyInfo during signing.
378     *
379     * @return the KeyInfo object
380     */

381    public KeyInfo getKeyInfo() {
382
383       // check to see if we are signing and if we have to create a keyinfo
384
if ((this._state == MODE_SIGN) && (this._keyInfo == null)) {
385
386          // create the KeyInfo
387
this._keyInfo = new KeyInfo(this._doc);
388
389          // get the Element from KeyInfo
390
Element JavaDoc keyInfoElement = this._keyInfo.getElement();
391          Element JavaDoc firstObject=null;
392          Node JavaDoc sibling= this._constructionElement.getFirstChild();
393          firstObject = XMLUtils.selectDsNode(sibling,Constants._TAG_OBJECT,0);
394              
395             if (firstObject != null) {
396
397                // add it before the object
398
this._constructionElement.insertBefore(keyInfoElement,
399                                                       firstObject);
400                this._constructionElement
401                   .insertBefore(this._doc.createTextNode("\n"), firstObject);
402             } else {
403
404                // add it as the last element to the signature
405
this._constructionElement.appendChild(keyInfoElement);
406                XMLUtils.addReturnToElement(this._constructionElement);
407             }
408       }
409
410       return this._keyInfo;
411    }
412
413    /**
414     * Appends an Object (not a <code>java.lang.Object</code> but an Object
415     * element) to the Signature. Please note that this is only possible
416     * when signing.
417     *
418     * @param object ds:Object to be appended.
419     * @throws XMLSignatureException When this object is used to verify.
420     */

421    public void appendObject(ObjectContainer object)
422            throws XMLSignatureException {
423
424       try {
425          if (this._state != MODE_SIGN) {
426             throw new XMLSignatureException(
427                "signature.operationOnlyBeforeSign");
428          }
429
430          this._constructionElement.appendChild(object.getElement());
431          XMLUtils.addReturnToElement(this._constructionElement);
432       } catch (XMLSecurityException ex) {
433          throw new XMLSignatureException("empty", ex);
434       }
435    }
436
437    /**
438     * Returns the <code>i<code>th <code>ds:Object</code> child of the signature
439     * or null if no such <code>ds:Object</code> element exists.
440     *
441     * @param i
442     * @return the <code>i<code>th <code>ds:Object</code> child of the signature or null if no such <code>ds:Object</code> element exists.
443     */

444    public ObjectContainer getObjectItem(int i) {
445
446       Element JavaDoc objElem = XMLUtils.selectDsNode(this._constructionElement.getFirstChild(),
447             Constants._TAG_OBJECT,i);
448
449       try {
450          return new ObjectContainer(objElem, this._baseURI);
451       } catch (XMLSecurityException ex) {
452          return null;
453       }
454    }
455
456    /**
457     * Returns the number of all <code>ds:Object</code> elements.
458     *
459     * @return the number of all <code>ds:Object</code> elements.
460     */

461    public int getObjectLength() {
462       return this.length(Constants.SignatureSpecNS, Constants._TAG_OBJECT);
463    }
464
465    /**
466     * Digests all References in the SignedInfo, calculates the signature value and
467     * sets it in the SignatureValue Element.
468     *
469     * @param signingKey the {@link java.security.PrivateKey} or {@link javax.crypto.SecretKey} that is used to sign.
470     * @throws XMLSignatureException
471     */

472    public void sign(Key JavaDoc signingKey) throws XMLSignatureException {
473
474       if (signingKey instanceof PublicKey JavaDoc) {
475          throw new IllegalArgumentException JavaDoc(I18n
476             .translate("algorithms.operationOnlyVerification"));
477       }
478
479       try {
480          if (this._state == MODE_SIGN) {
481
482             // XMLUtils.indentSignature(this._constructionElement, " ", 0);
483
// get the SignatureMethodElement
484
Element JavaDoc signatureMethodElement =
485                this._signedInfo.getSignatureMethodElement();
486
487             //Create a SignatureAlgorithm object
488
SignatureAlgorithm sa =
489                new SignatureAlgorithm(signatureMethodElement,
490                                       this.getBaseURI());
491
492             // initialize SignatureAlgorithm for signing
493
sa.initSign(signingKey);
494
495             SignedInfo si = this.getSignedInfo();
496
497             // generate digest values for all References in this SignedInfo
498
si.generateDigestValues();
499             OutputStream JavaDoc so=new UnsyncBufferedOutputStream(new SignerOutputStream(sa));
500             try {
501                 so.close();
502             } catch (IOException JavaDoc e) {
503                 //Imposible
504
}
505             // get the canonicalized bytes from SignedInfo
506
si.signInOctectStream(so);
507
508             byte jcebytes[] = sa.sign();
509
510             // set them on the SignateValue element
511
this.setSignatureValueElement(jcebytes);
512          }
513       } catch (CanonicalizationException ex) {
514          throw new XMLSignatureException("empty", ex);
515       } catch (InvalidCanonicalizerException ex) {
516          throw new XMLSignatureException("empty", ex);
517       } catch (XMLSecurityException ex) {
518          throw new XMLSignatureException("empty", ex);
519       }
520    }
521
522    /**
523     * Adds a {@link ResourceResolver} to enable the retrieval of resources.
524     *
525     * @param resolver
526     */

527    public void addResourceResolver(ResourceResolver resolver) {
528       this.getSignedInfo().addResourceResolver(resolver);
529    }
530
531    /**
532     * Adds a {@link ResourceResolverSpi} to enable the retrieval of resources.
533     *
534     * @param resolver
535     */

536    public void addResourceResolver(ResourceResolverSpi resolver) {
537       this.getSignedInfo().addResourceResolver(resolver);
538    }
539
540    /**
541     * Extracts the public key from the certificate and verifies if the signature
542     * is valid by re-digesting all References, comparing those against the
543     * stored DigestValues and then checking to see if the Signatures match on
544     * the SignedInfo.
545     *
546     * @param cert Certificate that contains the public key part of the keypair that was used to sign.
547     * @return true if the signature is valid, false otherwise
548     * @throws XMLSignatureException
549     */

550    public boolean checkSignatureValue(X509Certificate JavaDoc cert)
551            throws XMLSignatureException {
552
553       // see if cert is null
554
if (cert != null) {
555
556          //check the values with the public key from the cert
557
return this.checkSignatureValue(cert.getPublicKey());
558       }
559       
560       Object JavaDoc exArgs[] = { "Didn't get a certificate" };
561       throw new XMLSignatureException("empty", exArgs);
562       
563    }
564
565    /**
566     * Verifies if the signature is valid by redigesting all References,
567     * comparing those against the stored DigestValues and then checking to see
568     * if the Signatures match on the SignedInfo.
569     *
570     * @param pk {@link java.security.PublicKey} part of the keypair or {@link javax.crypto.SecretKey} that was used to sign
571     * @return true if the signature is valid, false otherwise
572     * @throws XMLSignatureException
573     */

574    public boolean checkSignatureValue(Key JavaDoc pk) throws XMLSignatureException {
575
576       //COMMENT: pk suggests it can only be a public key?
577
//check to see if the key is not null
578
if (pk == null) {
579          Object JavaDoc exArgs[] = { "Didn't get a key" };
580
581          throw new XMLSignatureException("empty", exArgs);
582       }
583
584       try {
585
586          //create a SignatureAlgorithms from the SignatureMethod inside
587
//SignedInfo. This is used to validate the signature.
588
SignatureAlgorithm sa =
589             new SignatureAlgorithm(this.getSignedInfo()
590                .getSignatureMethodElement(), this.getBaseURI());
591          if (true) {
592             if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "SignatureMethodURI = " + sa.getAlgorithmURI());
593             if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "jceSigAlgorithm = " + sa.getJCEAlgorithmString());
594             if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "jceSigProvider = " + sa.getJCEProviderName());
595             if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "PublicKey = " + pk);
596          }
597          sa.initVerify(pk);
598
599          // Get the canonicalized (normalized) SignedInfo
600
SignerOutputStream so=new SignerOutputStream(sa);
601          OutputStream JavaDoc bos=new UnsyncBufferedOutputStream(so);
602          this._signedInfo.signInOctectStream(bos);
603          try {
604             bos.close();
605         } catch (IOException JavaDoc e) {
606             //Imposible
607
}
608          
609          //retrieve the byte[] from the stored signature
610
byte sigBytes[] = this.getSignatureValue();
611
612
613          //Have SignatureAlgorithm sign the input bytes and compare them to the
614
//bytes that were stored in the signature.
615
if (!sa.verify(sigBytes)) {
616         return false;
617      }
618
619          // all references inside the signedinfo need to be dereferenced and
620
// digested again to see if the outcome matches the stored value in the
621
// SignedInfo.
622
// If _followManifestsDuringValidation is true it will do the same for
623
// References inside a Manifest.
624
return this.getSignedInfo().verify
625         (this._followManifestsDuringValidation);
626       } catch (XMLSecurityException ex) {
627          throw new XMLSignatureException("empty", ex);
628       }
629    }
630
631    /**
632     * Add a Reference with full parameters to this Signature
633     *
634     * @param referenceURI URI of the resource to be signed. Can be null in which
635     * case the dereferencing is application specific. Can be "" in which it's
636     * the parent node (or parent document?). There can only be one "" in each
637     * signature.
638     * @param trans Optional list of transformations to be done before digesting
639     * @param digestURI Mandatory URI of the digesting algorithm to use.
640     * @param ReferenceId Optional id attribute for this Reference
641     * @param ReferenceType Optional mimetype for the URI
642     * @throws XMLSignatureException
643     */

644    public void addDocument(
645            String JavaDoc referenceURI, Transforms trans, String JavaDoc digestURI, String JavaDoc ReferenceId, String JavaDoc ReferenceType)
646               throws XMLSignatureException {
647       this._signedInfo.addDocument(this._baseURI, referenceURI, trans,
648                                    digestURI, ReferenceId, ReferenceType);
649    }
650
651    /**
652     * This method is a proxy method for the {@link Manifest#addDocument} method.
653     *
654     * @param referenceURI URI according to the XML Signature specification.
655     * @param trans List of transformations to be applied.
656     * @param digestURI URI of the digest algorithm to be used.
657     * @see Manifest#addDocument
658     * @throws XMLSignatureException
659     */

660    public void addDocument(
661            String JavaDoc referenceURI, Transforms trans, String JavaDoc digestURI)
662               throws XMLSignatureException {
663       this._signedInfo.addDocument(this._baseURI, referenceURI, trans,
664                                    digestURI, null, null);
665    }
666
667    /**
668     * Adds a Reference with just the URI and the transforms. This used the
669     * SHA1 algorithm as a default digest algorithm.
670     *
671     * @param referenceURI URI according to the XML Signature specification.
672     * @param trans List of transformations to be applied.
673     * @throws XMLSignatureException
674     */

675    public void addDocument(String JavaDoc referenceURI, Transforms trans)
676            throws XMLSignatureException {
677       this._signedInfo.addDocument(this._baseURI, referenceURI, trans,
678                                    Constants.ALGO_ID_DIGEST_SHA1, null, null);
679    }
680
681    /**
682     * Add a Reference with just this URI. It uses SHA1 by default as the digest
683     * algorithm
684     *
685     * @param referenceURI URI according to the XML Signature specification.
686     * @throws XMLSignatureException
687     */

688    public void addDocument(String JavaDoc referenceURI) throws XMLSignatureException {
689       this._signedInfo.addDocument(this._baseURI, referenceURI, null,
690                                    Constants.ALGO_ID_DIGEST_SHA1, null, null);
691    }
692
693    /**
694     * Add an X509 Certificate to the KeyInfo. This will include the whole cert
695     * inside X509Data/X509Certificate tags.
696     *
697     * @param cert Certificate to be included. This should be the certificate of the key that was used to sign.
698     * @throws XMLSecurityException
699     */

700    public void addKeyInfo(X509Certificate JavaDoc cert) throws XMLSecurityException {
701
702       X509Data x509data = new X509Data(this._doc);
703
704       x509data.addCertificate(cert);
705       this.getKeyInfo().add(x509data);
706    }
707
708    /**
709     * Add this public key to the KeyInfo. This will include the complete key in
710     * the KeyInfo structure.
711     *
712     * @param pk
713     */

714    public void addKeyInfo(PublicKey JavaDoc pk) {
715       this.getKeyInfo().add(pk);
716    }
717
718    /**
719     * Proxy method for {@link SignedInfo#createSecretKey(byte[])}. If you want to
720     * create a MAC, this method helps you to obtain the {@link javax.crypto.SecretKey}
721     * from octets.
722     *
723     * @param secretKeyBytes
724     * @return the secret key created.
725     * @see SignedInfo#createSecretKey(byte[])
726     */

727    public SecretKey createSecretKey(byte[] secretKeyBytes)
728    {
729       return this.getSignedInfo().createSecretKey(secretKeyBytes);
730    }
731
732    /**
733     * Signal wether Manifest should be automatically validated.
734     * Checking the digests in References in a Signature are mandatory, but for
735     * References inside a Manifest it is application specific. This boolean is
736     * to indicate that the References inside Manifests should be validated.
737     *
738     * @param followManifests
739     * @see <a HREF="http://www.w3.org/TR/xmldsig-core/#sec-CoreValidation">Core validation section in the XML Signature Rec.</a>
740     */

741    public void setFollowNestedManifests(boolean followManifests) {
742       this._followManifestsDuringValidation = followManifests;
743    }
744
745    /**
746     * Get the local name of this element
747     *
748     * @return Constant._TAG_SIGNATURE
749     */

750    public String JavaDoc getBaseLocalName() {
751       return Constants._TAG_SIGNATURE;
752    }
753 }
754
Popular Tags