View Javadoc
1   /*
2    * reserved comment block
3    * DO NOT REMOVE OR ALTER!
4    */
5   /**
6    * Licensed to the Apache Software Foundation (ASF) under one
7    * or more contributor license agreements. See the NOTICE file
8    * distributed with this work for additional information
9    * regarding copyright ownership. The ASF licenses this file
10   * to you under the Apache License, Version 2.0 (the
11   * "License"); you may not use this file except in compliance
12   * with the License. You may obtain a copy of the License at
13   *
14   * http://www.apache.org/licenses/LICENSE-2.0
15   *
16   * Unless required by applicable law or agreed to in writing,
17   * software distributed under the License is distributed on an
18   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
19   * KIND, either express or implied. See the License for the
20   * specific language governing permissions and limitations
21   * under the License.
22   */
23  package com.sun.org.apache.xml.internal.security.keys;
24  
25  import java.security.PrivateKey;
26  import java.security.PublicKey;
27  import java.security.cert.X509Certificate;
28  import java.util.ArrayList;
29  import java.util.Iterator;
30  import java.util.List;
31  
32  import javax.crypto.SecretKey;
33  
34  import com.sun.org.apache.xml.internal.security.encryption.EncryptedKey;
35  import com.sun.org.apache.xml.internal.security.encryption.XMLCipher;
36  import com.sun.org.apache.xml.internal.security.encryption.XMLEncryptionException;
37  import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException;
38  import com.sun.org.apache.xml.internal.security.keys.content.DEREncodedKeyValue;
39  import com.sun.org.apache.xml.internal.security.keys.content.KeyInfoReference;
40  import com.sun.org.apache.xml.internal.security.keys.content.KeyName;
41  import com.sun.org.apache.xml.internal.security.keys.content.KeyValue;
42  import com.sun.org.apache.xml.internal.security.keys.content.MgmtData;
43  import com.sun.org.apache.xml.internal.security.keys.content.PGPData;
44  import com.sun.org.apache.xml.internal.security.keys.content.RetrievalMethod;
45  import com.sun.org.apache.xml.internal.security.keys.content.SPKIData;
46  import com.sun.org.apache.xml.internal.security.keys.content.X509Data;
47  import com.sun.org.apache.xml.internal.security.keys.content.keyvalues.DSAKeyValue;
48  import com.sun.org.apache.xml.internal.security.keys.content.keyvalues.RSAKeyValue;
49  import com.sun.org.apache.xml.internal.security.keys.keyresolver.KeyResolver;
50  import com.sun.org.apache.xml.internal.security.keys.keyresolver.KeyResolverException;
51  import com.sun.org.apache.xml.internal.security.keys.keyresolver.KeyResolverSpi;
52  import com.sun.org.apache.xml.internal.security.keys.storage.StorageResolver;
53  import com.sun.org.apache.xml.internal.security.transforms.Transforms;
54  import com.sun.org.apache.xml.internal.security.utils.Constants;
55  import com.sun.org.apache.xml.internal.security.utils.EncryptionConstants;
56  import com.sun.org.apache.xml.internal.security.utils.SignatureElementProxy;
57  import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
58  import org.w3c.dom.Attr;
59  import org.w3c.dom.Document;
60  import org.w3c.dom.Element;
61  import org.w3c.dom.Node;
62  import org.w3c.dom.NodeList;
63  
64  /**
65   * This class stand for KeyInfo Element that may contain keys, names,
66   * certificates and other public key management information,
67   * such as in-band key distribution or key agreement data.
68   * <BR />
69   * KeyInfo Element has two basic functions:
70   * One is KeyResolve for getting the public key in signature validation processing.
71   * the other one is toElement for getting the element in signature generation processing.
72   * <BR />
73   * The <CODE>lengthXXX()</CODE> methods provide access to the internal Key
74   * objects:
75   * <UL>
76   * <LI>If the <CODE>KeyInfo</CODE> was constructed from an Element
77   * (Signature verification), the <CODE>lengthXXX()</CODE> methods searches
78   * for child elements of <CODE>ds:KeyInfo</CODE> for known types. </LI>
79   * <LI>If the <CODE>KeyInfo</CODE> was constructed from scratch (during
80   * Signature generation), the <CODE>lengthXXX()</CODE> methods return the number
81   * of <CODE>XXXs</CODE> objects already passed to the KeyInfo</LI>
82   * </UL>
83   * <BR />
84   * The <CODE>addXXX()</CODE> methods are used for adding Objects of the
85   * appropriate type to the <CODE>KeyInfo</CODE>. This is used during signature
86   * generation.
87   * <BR />
88   * The <CODE>itemXXX(int i)</CODE> methods return the i'th object of the
89   * corresponding type.
90   * <BR />
91   * The <CODE>containsXXX()</CODE> methods return <I>whether</I> the KeyInfo
92   * contains the corresponding type.
93   *
94   */
95  public class KeyInfo extends SignatureElementProxy {
96  
97      /** {@link org.apache.commons.logging} logging facility */
98      private static java.util.logging.Logger log =
99          java.util.logging.Logger.getLogger(KeyInfo.class.getName());
100 
101     // We need at least one StorageResolver otherwise
102     // the KeyResolvers would not be called.
103     // The default StorageResolver is null.
104 
105     private List<X509Data> x509Datas = null;
106     private List<EncryptedKey> encryptedKeys = null;
107 
108     private static final List<StorageResolver> nullList;
109     static {
110         List<StorageResolver> list = new ArrayList<StorageResolver>(1);
111         list.add(null);
112         nullList = java.util.Collections.unmodifiableList(list);
113     }
114 
115     /** Field storageResolvers */
116     private List<StorageResolver> storageResolvers = nullList;
117 
118     /**
119      * Stores the individual (per-KeyInfo) {@link KeyResolverSpi}s
120      */
121     private List<KeyResolverSpi> internalKeyResolvers = new ArrayList<KeyResolverSpi>();
122 
123     private boolean secureValidation;
124 
125     /**
126      * Constructor KeyInfo
127      * @param doc
128      */
129     public KeyInfo(Document doc) {
130         super(doc);
131 
132         XMLUtils.addReturnToElement(this.constructionElement);
133     }
134 
135     /**
136      * Constructor KeyInfo
137      *
138      * @param element
139      * @param baseURI
140      * @throws XMLSecurityException
141      */
142     public KeyInfo(Element element, String baseURI) throws XMLSecurityException {
143         super(element, baseURI);
144 
145         Attr attr = element.getAttributeNodeNS(null, "Id");
146         if (attr != null) {
147             element.setIdAttributeNode(attr, true);
148         }
149     }
150 
151     /**
152      * Set whether secure processing is enabled or not. The default is false.
153      */
154     public void setSecureValidation(boolean secureValidation) {
155         this.secureValidation = secureValidation;
156     }
157 
158     /**
159      * Sets the <code>Id</code> attribute
160      *
161      * @param Id ID
162      */
163     public void setId(String id) {
164         if (id != null) {
165             this.constructionElement.setAttributeNS(null, Constants._ATT_ID, id);
166             this.constructionElement.setIdAttributeNS(null, Constants._ATT_ID, true);
167         }
168     }
169 
170     /**
171      * Returns the <code>Id</code> attribute
172      *
173      * @return the <code>Id</code> attribute
174      */
175     public String getId() {
176         return this.constructionElement.getAttributeNS(null, Constants._ATT_ID);
177     }
178 
179     /**
180      * Method addKeyName
181      *
182      * @param keynameString
183      */
184     public void addKeyName(String keynameString) {
185         this.add(new KeyName(this.doc, keynameString));
186     }
187 
188     /**
189      * Method add
190      *
191      * @param keyname
192      */
193     public void add(KeyName keyname) {
194         this.constructionElement.appendChild(keyname.getElement());
195         XMLUtils.addReturnToElement(this.constructionElement);
196     }
197 
198     /**
199      * Method addKeyValue
200      *
201      * @param pk
202      */
203     public void addKeyValue(PublicKey pk) {
204         this.add(new KeyValue(this.doc, pk));
205     }
206 
207     /**
208      * Method addKeyValue
209      *
210      * @param unknownKeyValueElement
211      */
212     public void addKeyValue(Element unknownKeyValueElement) {
213         this.add(new KeyValue(this.doc, unknownKeyValueElement));
214     }
215 
216     /**
217      * Method add
218      *
219      * @param dsakeyvalue
220      */
221     public void add(DSAKeyValue dsakeyvalue) {
222         this.add(new KeyValue(this.doc, dsakeyvalue));
223     }
224 
225     /**
226      * Method add
227      *
228      * @param rsakeyvalue
229      */
230     public void add(RSAKeyValue rsakeyvalue) {
231         this.add(new KeyValue(this.doc, rsakeyvalue));
232     }
233 
234     /**
235      * Method add
236      *
237      * @param pk
238      */
239     public void add(PublicKey pk) {
240         this.add(new KeyValue(this.doc, pk));
241     }
242 
243     /**
244      * Method add
245      *
246      * @param keyvalue
247      */
248     public void add(KeyValue keyvalue) {
249         this.constructionElement.appendChild(keyvalue.getElement());
250         XMLUtils.addReturnToElement(this.constructionElement);
251     }
252 
253     /**
254      * Method addMgmtData
255      *
256      * @param mgmtdata
257      */
258     public void addMgmtData(String mgmtdata) {
259         this.add(new MgmtData(this.doc, mgmtdata));
260     }
261 
262     /**
263      * Method add
264      *
265      * @param mgmtdata
266      */
267     public void add(MgmtData mgmtdata) {
268         this.constructionElement.appendChild(mgmtdata.getElement());
269         XMLUtils.addReturnToElement(this.constructionElement);
270     }
271 
272     /**
273      * Method addPGPData
274      *
275      * @param pgpdata
276      */
277     public void add(PGPData pgpdata) {
278         this.constructionElement.appendChild(pgpdata.getElement());
279         XMLUtils.addReturnToElement(this.constructionElement);
280     }
281 
282     /**
283      * Method addRetrievalMethod
284      *
285      * @param uri
286      * @param transforms
287      * @param Type
288      */
289     public void addRetrievalMethod(String uri, Transforms transforms, String Type) {
290         this.add(new RetrievalMethod(this.doc, uri, transforms, Type));
291     }
292 
293     /**
294      * Method add
295      *
296      * @param retrievalmethod
297      */
298     public void add(RetrievalMethod retrievalmethod) {
299         this.constructionElement.appendChild(retrievalmethod.getElement());
300         XMLUtils.addReturnToElement(this.constructionElement);
301     }
302 
303     /**
304      * Method add
305      *
306      * @param spkidata
307      */
308     public void add(SPKIData spkidata) {
309         this.constructionElement.appendChild(spkidata.getElement());
310         XMLUtils.addReturnToElement(this.constructionElement);
311     }
312 
313     /**
314      * Method addX509Data
315      *
316      * @param x509data
317      */
318     public void add(X509Data x509data) {
319         if (x509Datas == null) {
320             x509Datas = new ArrayList<X509Data>();
321         }
322         x509Datas.add(x509data);
323         this.constructionElement.appendChild(x509data.getElement());
324         XMLUtils.addReturnToElement(this.constructionElement);
325     }
326 
327     /**
328      * Method addEncryptedKey
329      *
330      * @param encryptedKey
331      * @throws XMLEncryptionException
332      */
333 
334     public void add(EncryptedKey encryptedKey) throws XMLEncryptionException {
335         if (encryptedKeys == null) {
336             encryptedKeys = new ArrayList<EncryptedKey>();
337         }
338         encryptedKeys.add(encryptedKey);
339         XMLCipher cipher = XMLCipher.getInstance();
340         this.constructionElement.appendChild(cipher.martial(encryptedKey));
341     }
342 
343     /**
344      * Method addDEREncodedKeyValue
345      *
346      * @param pk
347      * @throws XMLSecurityException
348      */
349     public void addDEREncodedKeyValue(PublicKey pk) throws XMLSecurityException {
350         this.add(new DEREncodedKeyValue(this.doc, pk));
351     }
352 
353     /**
354      * Method add
355      *
356      * @param derEncodedKeyValue
357      */
358     public void add(DEREncodedKeyValue derEncodedKeyValue) {
359         this.constructionElement.appendChild(derEncodedKeyValue.getElement());
360         XMLUtils.addReturnToElement(this.constructionElement);
361     }
362 
363     /**
364      * Method addKeyInfoReference
365      *
366      * @param URI
367      * @throws XMLSecurityException
368      */
369     public void addKeyInfoReference(String URI) throws XMLSecurityException {
370         this.add(new KeyInfoReference(this.doc, URI));
371     }
372 
373     /**
374      * Method add
375      *
376      * @param keyInfoReference
377      */
378     public void add(KeyInfoReference keyInfoReference) {
379         this.constructionElement.appendChild(keyInfoReference.getElement());
380         XMLUtils.addReturnToElement(this.constructionElement);
381     }
382 
383     /**
384      * Method addUnknownElement
385      *
386      * @param element
387      */
388     public void addUnknownElement(Element element) {
389         this.constructionElement.appendChild(element);
390         XMLUtils.addReturnToElement(this.constructionElement);
391     }
392 
393     /**
394      * Method lengthKeyName
395      *
396      * @return the number of the KeyName tags
397      */
398     public int lengthKeyName() {
399         return this.length(Constants.SignatureSpecNS, Constants._TAG_KEYNAME);
400     }
401 
402     /**
403      * Method lengthKeyValue
404      *
405      *@return the number of the KeyValue tags
406      */
407     public int lengthKeyValue() {
408         return this.length(Constants.SignatureSpecNS, Constants._TAG_KEYVALUE);
409     }
410 
411     /**
412      * Method lengthMgmtData
413      *
414      *@return the number of the MgmtData tags
415      */
416     public int lengthMgmtData() {
417         return this.length(Constants.SignatureSpecNS, Constants._TAG_MGMTDATA);
418     }
419 
420     /**
421      * Method lengthPGPData
422      *
423      *@return the number of the PGPDat. tags
424      */
425     public int lengthPGPData() {
426         return this.length(Constants.SignatureSpecNS, Constants._TAG_PGPDATA);
427     }
428 
429     /**
430      * Method lengthRetrievalMethod
431      *
432      *@return the number of the RetrievalMethod tags
433      */
434     public int lengthRetrievalMethod() {
435         return this.length(Constants.SignatureSpecNS, Constants._TAG_RETRIEVALMETHOD);
436     }
437 
438     /**
439      * Method lengthSPKIData
440      *
441      *@return the number of the SPKIData tags
442      */
443     public int lengthSPKIData() {
444         return this.length(Constants.SignatureSpecNS, Constants._TAG_SPKIDATA);
445     }
446 
447     /**
448      * Method lengthX509Data
449      *
450      *@return the number of the X509Data tags
451      */
452     public int lengthX509Data() {
453         if (x509Datas != null) {
454             return x509Datas.size();
455         }
456         return this.length(Constants.SignatureSpecNS, Constants._TAG_X509DATA);
457     }
458 
459     /**
460      * Method lengthDEREncodedKeyValue
461      *
462      *@return the number of the DEREncodedKeyValue tags
463      */
464     public int lengthDEREncodedKeyValue() {
465         return this.length(Constants.SignatureSpec11NS, Constants._TAG_DERENCODEDKEYVALUE);
466     }
467 
468     /**
469      * Method lengthKeyInfoReference
470      *
471      *@return the number of the KeyInfoReference tags
472      */
473     public int lengthKeyInfoReference() {
474         return this.length(Constants.SignatureSpec11NS, Constants._TAG_KEYINFOREFERENCE);
475     }
476 
477     /**
478      * Method lengthUnknownElement
479      * NOTE possibly buggy.
480      * @return the number of the UnknownElement tags
481      */
482     public int lengthUnknownElement() {
483         int res = 0;
484         NodeList nl = this.constructionElement.getChildNodes();
485 
486         for (int i = 0; i < nl.getLength(); i++) {
487             Node current = nl.item(i);
488 
489             /**
490              * $todo$ using this method, we don't see unknown Elements
491              *  from Signature NS; revisit
492              */
493             if ((current.getNodeType() == Node.ELEMENT_NODE)
494                 && current.getNamespaceURI().equals(Constants.SignatureSpecNS)) {
495                 res++;
496             }
497         }
498 
499         return res;
500     }
501 
502     /**
503      * Method itemKeyName
504      *
505      * @param i
506      * @return the asked KeyName element, null if the index is too big
507      * @throws XMLSecurityException
508      */
509     public KeyName itemKeyName(int i) throws XMLSecurityException {
510         Element e =
511             XMLUtils.selectDsNode(
512                 this.constructionElement.getFirstChild(), Constants._TAG_KEYNAME, i);
513 
514         if (e != null) {
515             return new KeyName(e, this.baseURI);
516         }
517         return null;
518     }
519 
520     /**
521      * Method itemKeyValue
522      *
523      * @param i
524      * @return the asked KeyValue element, null if the index is too big
525      * @throws XMLSecurityException
526      */
527     public KeyValue itemKeyValue(int i) throws XMLSecurityException {
528         Element e =
529             XMLUtils.selectDsNode(
530                 this.constructionElement.getFirstChild(), Constants._TAG_KEYVALUE, i);
531 
532         if (e != null) {
533             return new KeyValue(e, this.baseURI);
534         }
535         return null;
536     }
537 
538     /**
539      * Method itemMgmtData
540      *
541      * @param i
542      * @return the asked MgmtData element, null if the index is too big
543      * @throws XMLSecurityException
544      */
545     public MgmtData itemMgmtData(int i) throws XMLSecurityException {
546         Element e =
547             XMLUtils.selectDsNode(
548                 this.constructionElement.getFirstChild(), Constants._TAG_MGMTDATA, i);
549 
550         if (e != null) {
551             return new MgmtData(e, this.baseURI);
552         }
553         return null;
554     }
555 
556     /**
557      * Method itemPGPData
558      *
559      * @param i
560      * @return the asked PGPData element, null if the index is too big
561      * @throws XMLSecurityException
562      */
563     public PGPData itemPGPData(int i) throws XMLSecurityException {
564         Element e =
565             XMLUtils.selectDsNode(
566                 this.constructionElement.getFirstChild(), Constants._TAG_PGPDATA, i);
567 
568         if (e != null) {
569             return new PGPData(e, this.baseURI);
570         }
571         return null;
572     }
573 
574     /**
575      * Method itemRetrievalMethod
576      *
577      * @param i
578      *@return the asked RetrievalMethod element, null if the index is too big
579      * @throws XMLSecurityException
580      */
581     public RetrievalMethod itemRetrievalMethod(int i) throws XMLSecurityException {
582         Element e =
583             XMLUtils.selectDsNode(
584                 this.constructionElement.getFirstChild(), Constants._TAG_RETRIEVALMETHOD, i);
585 
586         if (e != null) {
587             return new RetrievalMethod(e, this.baseURI);
588         }
589         return null;
590     }
591 
592     /**
593      * Method itemSPKIData
594      *
595      * @param i
596      * @return the asked SPKIData element, null if the index is too big
597      * @throws XMLSecurityException
598      */
599     public SPKIData itemSPKIData(int i) throws XMLSecurityException {
600         Element e =
601             XMLUtils.selectDsNode(
602                 this.constructionElement.getFirstChild(), Constants._TAG_SPKIDATA, i);
603 
604         if (e != null) {
605             return new SPKIData(e, this.baseURI);
606         }
607         return null;
608     }
609 
610     /**
611      * Method itemX509Data
612      *
613      * @param i
614      * @return the asked X509Data element, null if the index is too big
615      * @throws XMLSecurityException
616      */
617     public X509Data itemX509Data(int i) throws XMLSecurityException {
618         if (x509Datas != null) {
619             return x509Datas.get(i);
620         }
621         Element e =
622             XMLUtils.selectDsNode(
623                 this.constructionElement.getFirstChild(), Constants._TAG_X509DATA, i);
624 
625         if (e != null) {
626             return new X509Data(e, this.baseURI);
627         }
628         return null;
629     }
630 
631     /**
632      * Method itemEncryptedKey
633      *
634      * @param i
635      * @return the asked EncryptedKey element, null if the index is too big
636      * @throws XMLSecurityException
637      */
638     public EncryptedKey itemEncryptedKey(int i) throws XMLSecurityException {
639         if (encryptedKeys != null) {
640             return encryptedKeys.get(i);
641         }
642         Element e =
643             XMLUtils.selectXencNode(
644                 this.constructionElement.getFirstChild(), EncryptionConstants._TAG_ENCRYPTEDKEY, i);
645 
646         if (e != null) {
647             XMLCipher cipher = XMLCipher.getInstance();
648             cipher.init(XMLCipher.UNWRAP_MODE, null);
649             return cipher.loadEncryptedKey(e);
650         }
651         return null;
652     }
653 
654     /**
655      * Method itemDEREncodedKeyValue
656      *
657      * @param i
658      * @return the asked DEREncodedKeyValue element, null if the index is too big
659      * @throws XMLSecurityException
660      */
661     public DEREncodedKeyValue itemDEREncodedKeyValue(int i) throws XMLSecurityException {
662         Element e =
663             XMLUtils.selectDs11Node(
664                 this.constructionElement.getFirstChild(), Constants._TAG_DERENCODEDKEYVALUE, i);
665 
666         if (e != null) {
667             return new DEREncodedKeyValue(e, this.baseURI);
668         }
669         return null;
670     }
671 
672     /**
673      * Method itemKeyInfoReference
674      *
675      * @param i
676      * @return the asked KeyInfoReference element, null if the index is too big
677      * @throws XMLSecurityException
678      */
679     public KeyInfoReference itemKeyInfoReference(int i) throws XMLSecurityException {
680         Element e =
681             XMLUtils.selectDs11Node(
682                 this.constructionElement.getFirstChild(), Constants._TAG_KEYINFOREFERENCE, i);
683 
684         if (e != null) {
685             return new KeyInfoReference(e, this.baseURI);
686         }
687         return null;
688     }
689 
690     /**
691      * Method itemUnknownElement
692      *
693      * @param i index
694      * @return the element number of the unknown elements
695      */
696     public Element itemUnknownElement(int i) {
697         NodeList nl = this.constructionElement.getChildNodes();
698         int res = 0;
699 
700         for (int j = 0; j < nl.getLength(); j++) {
701             Node current = nl.item(j);
702 
703             /**
704              * $todo$ using this method, we don't see unknown Elements
705              *  from Signature NS; revisit
706              */
707             if ((current.getNodeType() == Node.ELEMENT_NODE)
708                 && current.getNamespaceURI().equals(Constants.SignatureSpecNS)) {
709                 res++;
710 
711                 if (res == i) {
712                     return (Element) current;
713                 }
714             }
715         }
716 
717         return null;
718     }
719 
720     /**
721      * Method isEmpty
722      *
723      * @return true if the element has no descendants.
724      */
725     public boolean isEmpty() {
726         return this.constructionElement.getFirstChild() == null;
727     }
728 
729     /**
730      * Method containsKeyName
731      *
732      * @return If the KeyInfo contains a KeyName node
733      */
734     public boolean containsKeyName() {
735         return this.lengthKeyName() > 0;
736     }
737 
738     /**
739      * Method containsKeyValue
740      *
741      * @return If the KeyInfo contains a KeyValue node
742      */
743     public boolean containsKeyValue() {
744         return this.lengthKeyValue() > 0;
745     }
746 
747     /**
748      * Method containsMgmtData
749      *
750      * @return If the KeyInfo contains a MgmtData node
751      */
752     public boolean containsMgmtData() {
753         return this.lengthMgmtData() > 0;
754     }
755 
756     /**
757      * Method containsPGPData
758      *
759      * @return If the KeyInfo contains a PGPData node
760      */
761     public boolean containsPGPData() {
762         return this.lengthPGPData() > 0;
763     }
764 
765     /**
766      * Method containsRetrievalMethod
767      *
768      * @return If the KeyInfo contains a RetrievalMethod node
769      */
770     public boolean containsRetrievalMethod() {
771         return this.lengthRetrievalMethod() > 0;
772     }
773 
774     /**
775      * Method containsSPKIData
776      *
777      * @return If the KeyInfo contains a SPKIData node
778      */
779     public boolean containsSPKIData() {
780         return this.lengthSPKIData() > 0;
781     }
782 
783     /**
784      * Method containsUnknownElement
785      *
786      * @return If the KeyInfo contains a UnknownElement node
787      */
788     public boolean containsUnknownElement() {
789         return this.lengthUnknownElement() > 0;
790     }
791 
792     /**
793      * Method containsX509Data
794      *
795      * @return If the KeyInfo contains a X509Data node
796      */
797     public boolean containsX509Data() {
798         return this.lengthX509Data() > 0;
799     }
800 
801     /**
802      * Method containsDEREncodedKeyValue
803      *
804      * @return If the KeyInfo contains a DEREncodedKeyValue node
805      */
806     public boolean containsDEREncodedKeyValue() {
807         return this.lengthDEREncodedKeyValue() > 0;
808     }
809 
810     /**
811      * Method containsKeyInfoReference
812      *
813      * @return If the KeyInfo contains a KeyInfoReference node
814      */
815     public boolean containsKeyInfoReference() {
816         return this.lengthKeyInfoReference() > 0;
817     }
818 
819     /**
820      * This method returns the public key.
821      *
822      * @return If the KeyInfo contains a PublicKey node
823      * @throws KeyResolverException
824      */
825     public PublicKey getPublicKey() throws KeyResolverException {
826         PublicKey pk = this.getPublicKeyFromInternalResolvers();
827 
828         if (pk != null) {
829             if (log.isLoggable(java.util.logging.Level.FINE)) {
830                 log.log(java.util.logging.Level.FINE, "I could find a key using the per-KeyInfo key resolvers");
831             }
832 
833             return pk;
834         }
835         if (log.isLoggable(java.util.logging.Level.FINE)) {
836             log.log(java.util.logging.Level.FINE, "I couldn't find a key using the per-KeyInfo key resolvers");
837         }
838 
839         pk = this.getPublicKeyFromStaticResolvers();
840 
841         if (pk != null) {
842             if (log.isLoggable(java.util.logging.Level.FINE)) {
843                 log.log(java.util.logging.Level.FINE, "I could find a key using the system-wide key resolvers");
844             }
845 
846             return pk;
847         }
848         if (log.isLoggable(java.util.logging.Level.FINE)) {
849             log.log(java.util.logging.Level.FINE, "I couldn't find a key using the system-wide key resolvers");
850         }
851 
852         return null;
853     }
854 
855     /**
856      * Searches the library wide KeyResolvers for public keys
857      *
858      * @return The public key contained in this Node.
859      * @throws KeyResolverException
860      */
861     PublicKey getPublicKeyFromStaticResolvers() throws KeyResolverException {
862         Iterator<KeyResolverSpi> it = KeyResolver.iterator();
863         while (it.hasNext()) {
864             KeyResolverSpi keyResolver = it.next();
865             keyResolver.setSecureValidation(secureValidation);
866             Node currentChild = this.constructionElement.getFirstChild();
867             String uri = this.getBaseURI();
868             while (currentChild != null) {
869                 if (currentChild.getNodeType() == Node.ELEMENT_NODE) {
870                     for (StorageResolver storage : storageResolvers) {
871                         PublicKey pk =
872                             keyResolver.engineLookupAndResolvePublicKey(
873                                 (Element) currentChild, uri, storage
874                             );
875 
876                         if (pk != null) {
877                             return pk;
878                         }
879                     }
880                 }
881                 currentChild = currentChild.getNextSibling();
882             }
883         }
884         return null;
885     }
886 
887     /**
888      * Searches the per-KeyInfo KeyResolvers for public keys
889      *
890      * @return The public key contained in this Node.
891      * @throws KeyResolverException
892      */
893     PublicKey getPublicKeyFromInternalResolvers() throws KeyResolverException {
894         for (KeyResolverSpi keyResolver : internalKeyResolvers) {
895             if (log.isLoggable(java.util.logging.Level.FINE)) {
896                 log.log(java.util.logging.Level.FINE, "Try " + keyResolver.getClass().getName());
897             }
898             keyResolver.setSecureValidation(secureValidation);
899             Node currentChild = this.constructionElement.getFirstChild();
900             String uri = this.getBaseURI();
901             while (currentChild != null)      {
902                 if (currentChild.getNodeType() == Node.ELEMENT_NODE) {
903                     for (StorageResolver storage : storageResolvers) {
904                         PublicKey pk =
905                             keyResolver.engineLookupAndResolvePublicKey(
906                                 (Element) currentChild, uri, storage
907                             );
908 
909                         if (pk != null) {
910                             return pk;
911                         }
912                     }
913                 }
914                 currentChild = currentChild.getNextSibling();
915             }
916         }
917 
918         return null;
919     }
920 
921     /**
922      * Method getX509Certificate
923      *
924      * @return The certificate contained in this KeyInfo
925      * @throws KeyResolverException
926      */
927     public X509Certificate getX509Certificate() throws KeyResolverException {
928         // First search using the individual resolvers from the user
929         X509Certificate cert = this.getX509CertificateFromInternalResolvers();
930 
931         if (cert != null) {
932             if (log.isLoggable(java.util.logging.Level.FINE)) {
933                 log.log(java.util.logging.Level.FINE, "I could find a X509Certificate using the per-KeyInfo key resolvers");
934             }
935 
936             return cert;
937         }
938         if (log.isLoggable(java.util.logging.Level.FINE)) {
939             log.log(java.util.logging.Level.FINE, "I couldn't find a X509Certificate using the per-KeyInfo key resolvers");
940         }
941 
942         // Then use the system-wide Resolvers
943         cert = this.getX509CertificateFromStaticResolvers();
944 
945         if (cert != null) {
946             if (log.isLoggable(java.util.logging.Level.FINE)) {
947                 log.log(java.util.logging.Level.FINE, "I could find a X509Certificate using the system-wide key resolvers");
948             }
949 
950             return cert;
951         }
952         if (log.isLoggable(java.util.logging.Level.FINE)) {
953             log.log(java.util.logging.Level.FINE, "I couldn't find a X509Certificate using the system-wide key resolvers");
954         }
955 
956         return null;
957     }
958 
959     /**
960      * This method uses each System-wide {@link KeyResolver} to search the
961      * child elements. Each combination of {@link KeyResolver} and child element
962      * is checked against all {@link StorageResolver}s.
963      *
964      * @return The certificate contained in this KeyInfo
965      * @throws KeyResolverException
966      */
967     X509Certificate getX509CertificateFromStaticResolvers()
968         throws KeyResolverException {
969         if (log.isLoggable(java.util.logging.Level.FINE)) {
970             log.log(java.util.logging.Level.FINE,
971                 "Start getX509CertificateFromStaticResolvers() with " + KeyResolver.length()
972                 + " resolvers"
973             );
974         }
975         String uri = this.getBaseURI();
976         Iterator<KeyResolverSpi> it = KeyResolver.iterator();
977         while (it.hasNext()) {
978             KeyResolverSpi keyResolver = it.next();
979             keyResolver.setSecureValidation(secureValidation);
980             X509Certificate cert = applyCurrentResolver(uri, keyResolver);
981             if (cert != null) {
982                 return cert;
983             }
984         }
985         return null;
986     }
987 
988     private X509Certificate applyCurrentResolver(
989         String uri, KeyResolverSpi keyResolver
990     ) throws KeyResolverException {
991         Node currentChild = this.constructionElement.getFirstChild();
992         while (currentChild != null)      {
993             if (currentChild.getNodeType() == Node.ELEMENT_NODE) {
994                 for (StorageResolver storage : storageResolvers) {
995                     X509Certificate cert =
996                         keyResolver.engineLookupResolveX509Certificate(
997                             (Element) currentChild, uri, storage
998                         );
999 
1000                     if (cert != null) {
1001                         return cert;
1002                     }
1003                 }
1004             }
1005             currentChild = currentChild.getNextSibling();
1006         }
1007         return null;
1008     }
1009 
1010     /**
1011      * Method getX509CertificateFromInternalResolvers
1012      *
1013      * @return The certificate contained in this KeyInfo
1014      * @throws KeyResolverException
1015      */
1016     X509Certificate getX509CertificateFromInternalResolvers()
1017         throws KeyResolverException {
1018         if (log.isLoggable(java.util.logging.Level.FINE)) {
1019             log.log(java.util.logging.Level.FINE,
1020                 "Start getX509CertificateFromInternalResolvers() with "
1021                 + this.lengthInternalKeyResolver() + " resolvers"
1022             );
1023         }
1024         String uri = this.getBaseURI();
1025         for (KeyResolverSpi keyResolver : internalKeyResolvers) {
1026             if (log.isLoggable(java.util.logging.Level.FINE)) {
1027                 log.log(java.util.logging.Level.FINE, "Try " + keyResolver.getClass().getName());
1028             }
1029             keyResolver.setSecureValidation(secureValidation);
1030             X509Certificate cert = applyCurrentResolver(uri, keyResolver);
1031             if (cert != null) {
1032                 return cert;
1033             }
1034         }
1035 
1036         return null;
1037     }
1038 
1039     /**
1040      * This method returns a secret (symmetric) key. This is for XML Encryption.
1041      * @return the secret key contained in this KeyInfo
1042      * @throws KeyResolverException
1043      */
1044     public SecretKey getSecretKey() throws KeyResolverException {
1045         SecretKey sk = this.getSecretKeyFromInternalResolvers();
1046 
1047         if (sk != null) {
1048             if (log.isLoggable(java.util.logging.Level.FINE)) {
1049                 log.log(java.util.logging.Level.FINE, "I could find a secret key using the per-KeyInfo key resolvers");
1050             }
1051 
1052             return sk;
1053         }
1054         if (log.isLoggable(java.util.logging.Level.FINE)) {
1055             log.log(java.util.logging.Level.FINE, "I couldn't find a secret key using the per-KeyInfo key resolvers");
1056         }
1057 
1058         sk = this.getSecretKeyFromStaticResolvers();
1059 
1060         if (sk != null) {
1061             if (log.isLoggable(java.util.logging.Level.FINE)) {
1062                 log.log(java.util.logging.Level.FINE, "I could find a secret key using the system-wide key resolvers");
1063             }
1064 
1065             return sk;
1066         }
1067         if (log.isLoggable(java.util.logging.Level.FINE)) {
1068             log.log(java.util.logging.Level.FINE, "I couldn't find a secret key using the system-wide key resolvers");
1069         }
1070 
1071         return null;
1072     }
1073 
1074     /**
1075      * Searches the library wide KeyResolvers for Secret keys
1076      *
1077      * @return the secret key contained in this KeyInfo
1078      * @throws KeyResolverException
1079      */
1080     SecretKey getSecretKeyFromStaticResolvers() throws KeyResolverException {
1081         Iterator<KeyResolverSpi> it = KeyResolver.iterator();
1082         while (it.hasNext()) {
1083             KeyResolverSpi keyResolver = it.next();
1084             keyResolver.setSecureValidation(secureValidation);
1085 
1086             Node currentChild = this.constructionElement.getFirstChild();
1087             String uri = this.getBaseURI();
1088             while (currentChild != null)      {
1089                 if (currentChild.getNodeType() == Node.ELEMENT_NODE) {
1090                     for (StorageResolver storage : storageResolvers) {
1091                         SecretKey sk =
1092                             keyResolver.engineLookupAndResolveSecretKey(
1093                                 (Element) currentChild, uri, storage
1094                             );
1095 
1096                         if (sk != null) {
1097                             return sk;
1098                         }
1099                     }
1100                 }
1101                 currentChild = currentChild.getNextSibling();
1102             }
1103         }
1104         return null;
1105     }
1106 
1107     /**
1108      * Searches the per-KeyInfo KeyResolvers for secret keys
1109      *
1110      * @return the secret key contained in this KeyInfo
1111      * @throws KeyResolverException
1112      */
1113 
1114     SecretKey getSecretKeyFromInternalResolvers() throws KeyResolverException {
1115         for (KeyResolverSpi keyResolver : internalKeyResolvers) {
1116             if (log.isLoggable(java.util.logging.Level.FINE)) {
1117                 log.log(java.util.logging.Level.FINE, "Try " + keyResolver.getClass().getName());
1118             }
1119             keyResolver.setSecureValidation(secureValidation);
1120             Node currentChild = this.constructionElement.getFirstChild();
1121             String uri = this.getBaseURI();
1122             while (currentChild != null)      {
1123                 if (currentChild.getNodeType() == Node.ELEMENT_NODE) {
1124                     for (StorageResolver storage : storageResolvers) {
1125                         SecretKey sk =
1126                             keyResolver.engineLookupAndResolveSecretKey(
1127                                 (Element) currentChild, uri, storage
1128                             );
1129 
1130                         if (sk != null) {
1131                             return sk;
1132                         }
1133                     }
1134                 }
1135                 currentChild = currentChild.getNextSibling();
1136             }
1137         }
1138 
1139         return null;
1140     }
1141 
1142     /**
1143      * This method returns a private key. This is for Key Transport in XML Encryption.
1144      * @return the private key contained in this KeyInfo
1145      * @throws KeyResolverException
1146      */
1147     public PrivateKey getPrivateKey() throws KeyResolverException {
1148         PrivateKey pk = this.getPrivateKeyFromInternalResolvers();
1149 
1150         if (pk != null) {
1151             if (log.isLoggable(java.util.logging.Level.FINE)) {
1152                 log.log(java.util.logging.Level.FINE, "I could find a private key using the per-KeyInfo key resolvers");
1153             }
1154             return pk;
1155         }
1156         if (log.isLoggable(java.util.logging.Level.FINE)) {
1157             log.log(java.util.logging.Level.FINE, "I couldn't find a secret key using the per-KeyInfo key resolvers");
1158         }
1159 
1160         pk = this.getPrivateKeyFromStaticResolvers();
1161         if (pk != null) {
1162             if (log.isLoggable(java.util.logging.Level.FINE)) {
1163                 log.log(java.util.logging.Level.FINE, "I could find a private key using the system-wide key resolvers");
1164             }
1165             return pk;
1166         }
1167         if (log.isLoggable(java.util.logging.Level.FINE)) {
1168             log.log(java.util.logging.Level.FINE, "I couldn't find a private key using the system-wide key resolvers");
1169         }
1170 
1171         return null;
1172     }
1173 
1174     /**
1175      * Searches the library wide KeyResolvers for Private keys
1176      *
1177      * @return the private key contained in this KeyInfo
1178      * @throws KeyResolverException
1179      */
1180     PrivateKey getPrivateKeyFromStaticResolvers() throws KeyResolverException {
1181         Iterator<KeyResolverSpi> it = KeyResolver.iterator();
1182         while (it.hasNext()) {
1183             KeyResolverSpi keyResolver = it.next();
1184             keyResolver.setSecureValidation(secureValidation);
1185 
1186             Node currentChild = this.constructionElement.getFirstChild();
1187             String uri = this.getBaseURI();
1188             while (currentChild != null)      {
1189                 if (currentChild.getNodeType() == Node.ELEMENT_NODE) {
1190                     // not using StorageResolvers at the moment
1191                     // since they cannot return private keys
1192                     PrivateKey pk =
1193                         keyResolver.engineLookupAndResolvePrivateKey(
1194                             (Element) currentChild, uri, null
1195                         );
1196 
1197                     if (pk != null) {
1198                         return pk;
1199                     }
1200                 }
1201                 currentChild = currentChild.getNextSibling();
1202             }
1203         }
1204         return null;
1205     }
1206 
1207     /**
1208      * Searches the per-KeyInfo KeyResolvers for private keys
1209      *
1210      * @return the private key contained in this KeyInfo
1211      * @throws KeyResolverException
1212      */
1213     PrivateKey getPrivateKeyFromInternalResolvers() throws KeyResolverException {
1214         for (KeyResolverSpi keyResolver : internalKeyResolvers) {
1215             if (log.isLoggable(java.util.logging.Level.FINE)) {
1216                 log.log(java.util.logging.Level.FINE, "Try " + keyResolver.getClass().getName());
1217             }
1218             keyResolver.setSecureValidation(secureValidation);
1219             Node currentChild = this.constructionElement.getFirstChild();
1220             String uri = this.getBaseURI();
1221             while (currentChild != null) {
1222                 if (currentChild.getNodeType() == Node.ELEMENT_NODE) {
1223                     // not using StorageResolvers at the moment
1224                     // since they cannot return private keys
1225                     PrivateKey pk =
1226                         keyResolver.engineLookupAndResolvePrivateKey(
1227                             (Element) currentChild, uri, null
1228                         );
1229 
1230                     if (pk != null) {
1231                         return pk;
1232                     }
1233                 }
1234                 currentChild = currentChild.getNextSibling();
1235             }
1236         }
1237 
1238         return null;
1239     }
1240 
1241     /**
1242      * This method is used to add a custom {@link KeyResolverSpi} to a KeyInfo
1243      * object.
1244      *
1245      * @param realKeyResolver
1246      */
1247     public void registerInternalKeyResolver(KeyResolverSpi realKeyResolver) {
1248         this.internalKeyResolvers.add(realKeyResolver);
1249     }
1250 
1251     /**
1252      * Method lengthInternalKeyResolver
1253      * @return the length of the key
1254      */
1255     int lengthInternalKeyResolver() {
1256         return this.internalKeyResolvers.size();
1257     }
1258 
1259     /**
1260      * Method itemInternalKeyResolver
1261      *
1262      * @param i the index
1263      * @return the KeyResolverSpi for the index.
1264      */
1265     KeyResolverSpi itemInternalKeyResolver(int i) {
1266         return this.internalKeyResolvers.get(i);
1267     }
1268 
1269     /**
1270      * Method addStorageResolver
1271      *
1272      * @param storageResolver
1273      */
1274     public void addStorageResolver(StorageResolver storageResolver) {
1275         if (storageResolvers == nullList) {
1276             // Replace the default null StorageResolver
1277             storageResolvers = new ArrayList<StorageResolver>();
1278         }
1279         this.storageResolvers.add(storageResolver);
1280     }
1281 
1282 
1283     /** @inheritDoc */
1284     public String getBaseLocalName() {
1285         return Constants._TAG_KEYINFO;
1286     }
1287 }