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