001/*
002 * nimbus-jose-jwt
003 *
004 * Copyright 2012-2019, Connect2id Ltd.
005 *
006 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use
007 * this file except in compliance with the License. You may obtain a copy of the
008 * License at
009 *
010 *    http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software distributed
013 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
014 * CONDITIONS OF ANY KIND, either express or implied. See the License for the
015 * specific language governing permissions and limitations under the License.
016 */
017
018package com.nimbusds.jose.jwk;
019
020
021import java.security.cert.CertificateException;
022import java.security.cert.X509Certificate;
023import java.util.*;
024
025import net.jcip.annotations.Immutable;
026
027import com.nimbusds.jose.Algorithm;
028import com.nimbusds.jose.JWEHeader;
029import com.nimbusds.jose.JWSAlgorithm;
030import com.nimbusds.jose.JWSHeader;
031import com.nimbusds.jose.util.Base64URL;
032import com.nimbusds.jose.util.X509CertUtils;
033
034
035/**
036 * JSON Web Key (JWK) matcher. May be used to ensure a JWK matches a set of
037 * application-specific criteria.
038 *
039 * <p>Supported key matching criteria:
040 *
041 * <ul>
042 *     <li>Any, unspecified, one or more key types (typ).
043 *     <li>Any, unspecified, one or more key uses (use).
044 *     <li>Any, unspecified, one or more key operations (key_ops).
045 *     <li>Any, unspecified, one or more key algorithms (alg).
046 *     <li>Any, unspecified, one or more key identifiers (kid).
047 *     <li>Private key only.
048 *     <li>Public key only.
049 *     <li>Non-revoked key only.
050 *     <li>Revoked key only.
051 *     <li>Minimum, maximum or exact key sizes.
052 *     <li>Any, unspecified, one or more curves for EC and OKP keys (crv).
053 *     <li>X.509 certificate SHA-256 thumbprint.
054 *     <li>With X.509 certificate only.
055 * </ul>
056 *
057 * <p>Matching by JWK thumbprint (RFC 7638), X.509 certificate URL and X.509
058 * certificate chain is not supported.
059 *
060 * @author Vladimir Dzhuvinov
061 * @author Josh Cummings
062 * @author Ben Arena
063 * @version 2024-11-01
064 */
065@Immutable
066public class JWKMatcher {
067
068
069        /**
070         * The key types to match.
071         */
072        private final Set<KeyType> types;
073
074
075        /**
076         * The public key uses to match.
077         */
078        private final Set<KeyUse> uses;
079
080
081        /**
082         * The key operations to match.
083         */
084        private final Set<KeyOperation> ops;
085
086
087        /**
088         * The algorithms to match.
089         */
090        private final Set<Algorithm> algs;
091
092
093        /**
094         * The key IDs to match.
095         */
096        private final Set<String> ids;
097        
098        
099        /**
100         * {@code true} to match a key with a specified use only.
101         */
102        private final boolean withUseOnly;
103        
104        
105        /**
106         * {@code true} to match a key with a specified ID only.
107         */
108        private final boolean withIDOnly;
109
110
111        /**
112         * {@code true} to match a private key only.
113         */
114        private final boolean privateOnly;
115
116
117        /**
118         * {@code true} to match a public key only.
119         */
120        private final boolean publicOnly;
121
122
123        /**
124         * {@code true} to match a non-revoked key only.
125         */
126        private final boolean nonRevokedOnly;
127
128
129        /**
130         * {@code true} to match a revoked key only.
131         */
132        private final boolean revokedOnly;
133
134
135        /**
136         * The minimum key size in bits, zero implies no minimum size.
137         */
138        private final int minSizeBits;
139
140
141        /**
142         * The maximum key size in bits, zero implies no maximum size.
143         */
144        private final int maxSizeBits;
145        
146        
147        /**
148         * The key sizes in bits.
149         */
150        private final Set<Integer> sizesBits;
151        
152        
153        /**
154         * The curves to match (for EC and OKP keys).
155         */
156        private final Set<Curve> curves;
157
158        
159        /**
160         * The X.509 certificate SHA-256 thumbprints to match.
161         */
162        private final Set<Base64URL> x5tS256s;
163        
164        
165        /**
166         * {@code true} to match a key with a specified X.509 certificate chain
167         * only.
168         */
169        private final boolean withX5COnly;
170
171        
172        /**
173         * Builder for constructing JWK matchers.
174         *
175         * <p>Example usage:
176         *
177         * <pre>
178         * JWKMatcher matcher = new JWKMatcher().keyID("123").build();
179         * </pre>
180         */
181        public static class Builder {
182
183                
184                /**
185                 * The key types to match.
186                 */
187                private Set<KeyType> types;
188
189
190                /**
191                 * The public key uses to match.
192                 */
193                private Set<KeyUse> uses;
194
195
196                /**
197                 * The key operations to match.
198                 */
199                private Set<KeyOperation> ops;
200
201
202                /**
203                 * The algorithms to match.
204                 */
205                private Set<Algorithm> algs;
206
207
208                /**
209                 * The key IDs to match.
210                 */
211                private Set<String> ids;
212                
213                
214                /**
215                 * {@code true} to match a key with specified use only.
216                 */
217                private boolean withUseOnly = false;
218                
219                
220                /**
221                 * {@code true} to match a key with a specified ID only.
222                 */
223                private boolean withIDOnly = false;
224
225
226                /**
227                 * {@code true} to match a private key only.
228                 */
229                private boolean privateOnly = false;
230
231
232                /**
233                 * {@code true} to match a public key only.
234                 */
235                private boolean publicOnly = false;
236
237
238                /**
239                 * {@code true} to match a non-revoked key only.
240                 */
241                private boolean nonRevokedOnly = false;
242
243
244                /**
245                 * {@code true} to match a revoked key only.
246                 */
247                private boolean revokedOnly = false;
248
249
250                /**
251                 * The minimum key size in bits, zero implies no minimum size
252                 * limit.
253                 */
254                private int minSizeBits = 0;
255
256
257                /**
258                 * The maximum key size in bits, zero implies no maximum size
259                 * limit.
260                 */
261                private int maxSizeBits = 0;
262                
263                
264                /**
265                 * The key sizes in bits.
266                 */
267                private Set<Integer> sizesBits;
268                
269                
270                /**
271                 * The curves to match (for EC and OKP keys).
272                 */
273                private Set<Curve> curves;
274
275                
276                /**
277                 * The X.509 certificate SHA-256 thumbprints to match.
278                 */
279                private Set<Base64URL> x5tS256s;
280                
281                
282                /**
283                 * {@code true} to match a key with a specified X.509
284                 * certificate chain only.
285                 */
286                private boolean withX5COnly = false;
287
288
289                /**
290                 * Creates a new builder for constructing JWK matchers.
291                 */
292                public Builder() {
293                }
294
295
296                /**
297                 * Creates a new builder for constructing JWK matchers using
298                 * the specified matcher.
299                 *
300                 * @param jwkMatcher The JWK matcher to use. Must not be
301                 *                   {@code null}.
302                 */
303                public Builder(final JWKMatcher jwkMatcher) {
304                        types = jwkMatcher.getKeyTypes();
305                        uses = jwkMatcher.getKeyUses();
306                        ops = jwkMatcher.getKeyOperations();
307                        algs = jwkMatcher.getAlgorithms();
308                        ids = jwkMatcher.getKeyIDs();
309                        withUseOnly = jwkMatcher.isWithKeyUseOnly();
310                        withIDOnly = jwkMatcher.isWithKeyIDOnly();
311                        privateOnly = jwkMatcher.isPrivateOnly();
312                        publicOnly = jwkMatcher.isPublicOnly();
313                        nonRevokedOnly = jwkMatcher.isNonRevokedOnly();
314                        revokedOnly = jwkMatcher.isNonRevokedOnly();
315                        minSizeBits = jwkMatcher.getMinKeySize();
316                        maxSizeBits = jwkMatcher.getMaxKeySize();
317                        sizesBits = jwkMatcher.getKeySizes();
318                        curves = jwkMatcher.getCurves();
319                        x5tS256s = jwkMatcher.getX509CertSHA256Thumbprints();
320                        withX5COnly = jwkMatcher.isWithX509CertChainOnly();
321                }
322
323
324                /**
325                 * Sets a single key type to match.
326                 *
327                 * @param kty The key type, {@code null} if not specified.
328                 *            
329                 * @return This builder.            
330                 */
331                public Builder keyType(final KeyType kty) {
332
333                        if (kty == null) {
334                                types = null;
335                        } else {
336                                types = new HashSet<>(Collections.singletonList(kty));
337                        }
338                        
339                        return this;
340                }
341
342
343                /**
344                 * Sets multiple key types to match.
345                 *
346                 * @param types The key types.
347                 *
348                 * @return This builder.
349                 */
350                public Builder keyTypes(final KeyType ... types) {
351
352                        keyTypes(new LinkedHashSet<>(Arrays.asList(types)));
353                        return this;
354                }
355
356
357                /**
358                 * Sets multiple key types to match.
359                 *
360                 * @param types The key types, {@code null} if not specified.
361                 *
362                 * @return This builder.
363                 */
364                public Builder keyTypes(final Set<KeyType> types) {
365
366                        this.types = types;
367                        return this;
368                }
369
370
371                /**
372                 * Sets a single public key use to match.
373                 *
374                 * @param use The public key use, {@code null} if not 
375                 *            specified.
376                 *
377                 * @return This builder.
378                 */
379                public Builder keyUse(final KeyUse use) {
380
381                        if (use == null) {
382                                uses = null;
383                        } else {
384                                uses = new HashSet<>(Collections.singletonList(use));
385                        }
386                        return this;
387                }
388
389
390                /**
391                 * Sets multiple public key uses to match.
392                 *
393                 * @param uses The public key uses.
394                 *
395                 * @return This builder.
396                 */
397                public Builder keyUses(final KeyUse... uses) {
398
399                        keyUses(new LinkedHashSet<>(Arrays.asList(uses)));
400                        return this;
401                }
402
403
404                /**
405                 * Sets multiple public key uses to match.
406                 *
407                 * @param uses The public key uses, {@code null} if not
408                 *             specified.
409                 *
410                 * @return This builder.
411                 */
412                public Builder keyUses(final Set<KeyUse> uses) {
413
414                        this.uses = uses;
415                        return this;
416                }
417
418
419                /**
420                 * Sets a single key operation to match.
421                 *
422                 * @param op The key operation, {@code null} if not specified.
423                 *
424                 * @return This builder.
425                 */
426                public Builder keyOperation(final KeyOperation op) {
427
428                        if (op == null) {
429                                ops = null;
430                        } else {
431                                ops = new HashSet<>(Collections.singletonList(op));
432                        }
433                        return this;
434                }
435
436
437                /**
438                 * Sets multiple key operations to match.
439                 *
440                 * @param ops The key operations.
441                 *
442                 * @return This builder.
443                 */
444                public Builder keyOperations(final KeyOperation... ops) {
445
446                        keyOperations(new LinkedHashSet<>(Arrays.asList(ops)));
447                        return this;
448                }
449
450
451                /**
452                 * Sets multiple key operations to match.
453                 *
454                 * @param ops The key operations, {@code null} if not
455                 *            specified.
456                 *
457                 * @return This builder.
458                 */
459                public Builder keyOperations(final Set<KeyOperation> ops) {
460
461                        this.ops = ops;
462                        return this;
463                }
464
465
466                /**
467                 * Sets a single JOSE algorithm to match.
468                 *
469                 * @param alg The JOSE algorithm, {@code null} if not
470                 *            specified.
471                 *
472                 * @return This builder.
473                 */
474                public Builder algorithm(final Algorithm alg) {
475
476                        if (alg == null) {
477                                algs = null;
478                        } else {
479                                algs = new HashSet<>(Collections.singletonList(alg));
480                        }
481                        return this;
482                }
483
484
485                /**
486                 * Sets multiple JOSE algorithms to match.
487                 *
488                 * @param algs The JOSE algorithms.
489                 *
490                 * @return This builder.
491                 */
492                public Builder algorithms(final Algorithm ... algs) {
493
494                        algorithms(new LinkedHashSet<>(Arrays.asList(algs)));
495                        return this;
496                }
497
498
499                /**
500                 * Sets multiple JOSE algorithms to match.
501                 *
502                 * @param algs The JOSE algorithms, {@code null} if not
503                 *             specified.
504                 *
505                 * @return This builder.
506                 */
507                public Builder algorithms(final Set<Algorithm> algs) {
508
509                        this.algs = algs;
510                        return this;
511                }
512
513
514                /**
515                 * Sets a single key ID to match.
516                 *
517                 * @param id The key ID, {@code null} if not specified.
518                 *
519                 * @return This builder.
520                 */
521                public Builder keyID(final String id) {
522
523                        if (id == null) {
524                                ids = null;
525                        } else {
526                                ids = new HashSet<>(Collections.singletonList(id));
527                        }
528                        return this;
529                }
530
531
532                /**
533                 * Sets multiple key IDs to match.
534                 *
535                 * @param ids The key IDs.
536                 *
537                 * @return This builder.
538                 */
539                public Builder keyIDs(final String ... ids) {
540
541                        keyIDs(new LinkedHashSet<>(Arrays.asList(ids)));
542                        return this;
543                }
544
545
546                /**
547                 * Sets multiple key IDs to match.
548                 *
549                 * @param ids The key IDs, {@code null} if not specified.
550                 *
551                 * @return This builder.
552                 */
553                public Builder keyIDs(final Set<String> ids) {
554
555                        this.ids = ids;
556                        return this;
557                }
558                
559                
560                /**
561                 * Sets the key use presence matching.
562                 *
563                 * @param hasUse {@code true} to match a key with a specified
564                 *               use only.
565                 *
566                 * @return This builder.
567                 */
568                @Deprecated
569                public Builder hasKeyUse(final boolean hasUse) {
570                        
571                        return withKeyUseOnly(hasUse);
572                }
573
574
575                /**
576                 * Sets the key use presence matching.
577                 *
578                 * @param withUseOnly {@code true} to match a key with a
579                 *                    specified use only.
580                 *
581                 * @return This builder.
582                 */
583                public Builder withKeyUseOnly(final boolean withUseOnly) {
584
585                        this.withUseOnly = withUseOnly;
586                        return this;
587                }
588                
589                
590                /**
591                 * Sets the key ID presence matching.
592                 *
593                 * @param hasID {@code true} to match a key a specified ID
594                 *              only.
595                 *
596                 * @return This builder.
597                 */
598                @Deprecated
599                public Builder hasKeyID(final boolean hasID) {
600                        
601                        return withKeyIDOnly(hasID);
602                }
603
604
605                /**
606                 * Sets the key ID presence matching.
607                 *
608                 * @param withIDOnly {@code true} to match a key a specified ID
609                 *                   only.
610                 *
611                 * @return This builder.
612                 */
613                public Builder withKeyIDOnly(final boolean withIDOnly) {
614
615                        this.withIDOnly = withIDOnly;
616                        return this;
617                }
618
619
620                /**
621                 * Sets the private key matching.
622                 *
623                 * @param privateOnly {@code true} to match a private key only.
624                 *
625                 * @return This builder.
626                 */
627                public Builder privateOnly(final boolean privateOnly) {
628
629                        this.privateOnly = privateOnly;
630                        return this;
631                }
632
633
634                /**
635                 * Sets the public key matching.
636                 *
637                 * @param publicOnly {@code true} to match a public key only.
638                 *
639                 * @return This builder.
640                 */
641                public Builder publicOnly(final boolean publicOnly) {
642
643                        this.publicOnly = publicOnly;
644                        return this;
645                }
646
647
648                /**
649                 * Sets the non-revoked key matching.
650                 *
651                 * @param nonRevokedOnly {@code true} to match a non-revoked
652                 *                       key only.
653                 *
654                 * @return This builder.
655                 */
656                public Builder nonRevokedOnly(final boolean nonRevokedOnly) {
657
658                        this.nonRevokedOnly = nonRevokedOnly;
659                        return this;
660                }
661
662
663                /**
664                 * Sets the revoked key matching.
665                 *
666                 * @param revokedOnly {@code true} to match a revoked key only.
667                 *
668                 * @return This builder.
669                 */
670                public Builder revokedOnly(final boolean revokedOnly) {
671
672                        this.revokedOnly = revokedOnly;
673                        return this;
674                }
675
676
677                /**
678                 * Sets the minimal key size.
679                 *
680                 * @param minSizeBits The minimum key size in bits, zero
681                 *                    implies no minimum key size limit.
682                 *
683                 * @return This builder.
684                 */
685                public Builder minKeySize(final int minSizeBits) {
686
687                        this.minSizeBits = minSizeBits;
688                        return this;
689                }
690
691
692                /**
693                 * Sets the maximum key size.
694                 *
695                 * @param maxSizeBits The maximum key size in bits, zero
696                 *                    implies no maximum key size limit.
697                 *
698                 * @return This builder.
699                 */
700                public Builder maxKeySize(final int maxSizeBits) {
701
702                        this.maxSizeBits = maxSizeBits;
703                        return this;
704                }
705                
706                
707                /**
708                 * Sets the key size.
709                 *
710                 * @param keySizeBits The key size in bits, zero if not
711                 *                    specified.
712                 *
713                 * @return This builder.
714                 */
715                public Builder keySize(final int keySizeBits) {
716                        if (keySizeBits <= 0) {
717                                sizesBits = null;
718                        } else {
719                                sizesBits = Collections.singleton(keySizeBits);
720                        }
721                        return this;
722                }
723                
724                
725                /**
726                 * Sets the key sizes.
727                 *
728                 * @param keySizesBits The key sizes in bits.
729                 *
730                 * @return This builder.
731                 */
732                public Builder keySizes(final int... keySizesBits) {
733                        Set<Integer> sizesSet = new LinkedHashSet<>();
734                        for (int keySize: keySizesBits) {
735                                sizesSet.add(keySize);
736                        }
737                        keySizes(sizesSet);
738                        return this;
739                }
740                
741                
742                /**
743                 * Sets the key sizes.
744                 *
745                 * @param keySizesBits The key sizes in bits.
746                 *
747                 * @return This builder.
748                 */
749                public Builder keySizes(final Set<Integer> keySizesBits) {
750                        
751                        this.sizesBits = keySizesBits;
752                        return this;
753                }
754                
755                
756                /**
757                 * Sets a single curve to match (for EC and OKP keys).
758                 *
759                 * @param curve The curve, {@code null} if not specified.
760                 *
761                 * @return This builder.
762                 */
763                public Builder curve(final Curve curve) {
764                        
765                        if (curve == null) {
766                                curves = null;
767                        } else {
768                                curves = Collections.singleton(curve);
769                        }
770                        return this;
771                }
772                
773                
774                /**
775                 * Sets multiple curves to match (for EC and OKP keys).
776                 *
777                 * @param curves The curves.
778                 *
779                 * @return This builder.
780                 */
781                public Builder curves(final Curve... curves) {
782                        
783                        curves(new LinkedHashSet<>(Arrays.asList(curves)));
784                        return this;
785                }
786                
787                
788                /**
789                 * Sets multiple curves to match (for EC and OKP keys).
790                 *
791                 * @param curves The curves, {@code null} if not specified.
792                 *
793                 * @return This builder.
794                 */
795                public Builder curves(final Set<Curve> curves) {
796                        
797                        this.curves = curves;
798                        return this;
799                }
800
801                
802                /**
803                 * Sets a single X.509 certificate SHA-256 thumbprint to match.
804                 *
805                 * @param x5tS256 The thumbprint, {@code null} if not
806                 *                specified.
807                 *
808                 * @return This builder.
809                 */
810                public Builder x509CertSHA256Thumbprint(final Base64URL x5tS256) {
811
812                        if (x5tS256 == null) {
813                                x5tS256s = null;
814                        } else {
815                                x5tS256s = Collections.singleton(x5tS256);
816                        }
817                        return this;
818                }
819
820                
821                /**
822                 * Sets multiple X.509 certificate SHA-256 thumbprints to
823                 * match.
824                 *
825                 * @param x5tS256s The thumbprints.
826                 *
827                 * @return This builder.
828                 */
829                public Builder x509CertSHA256Thumbprints(final Base64URL... x5tS256s) {
830                        return x509CertSHA256Thumbprints(new LinkedHashSet<>(Arrays.asList(x5tS256s)));
831                }
832
833                
834                /**
835                 * Sets multiple X.509 certificate SHA-256 thumbprints to
836                 * match.
837                 *
838                 * @param x5tS256s The thumbprints, {@code null} if not
839                 *                 specified.
840                 *
841                 * @return This builder.
842                 */
843                public Builder x509CertSHA256Thumbprints(final Set<Base64URL> x5tS256s) {
844                        this.x5tS256s = x5tS256s;
845                        return this;
846                }
847                
848                
849                /**
850                 * Sets the X.509 certificate chain presence matching.
851                 *
852                 * @param hasX5C {@code true} to match a key with a specified
853                 *               X.509 certificate chain only.
854                 *
855                 * @return This builder.
856                 */
857                @Deprecated
858                public Builder hasX509CertChain(final boolean hasX5C) {
859
860                        return withX509CertChainOnly(hasX5C);
861                }
862
863
864                /**
865                 * Sets the X.509 certificate chain presence matching.
866                 *
867                 * @param withX5CONly {@code true} to match a key with a
868                 *                    specified X.509 certificate chain only.
869                 *
870                 * @return This builder.
871                 */
872                public Builder withX509CertChainOnly(final boolean withX5CONly) {
873
874                        this.withX5COnly = withX5CONly;
875                        return this;
876                }
877
878                
879                /**
880                 * Builds a new JWK matcher.
881                 *
882                 * @return The JWK matcher.
883                 */
884                public JWKMatcher build() {
885
886                        return new JWKMatcher(
887                                types, uses, ops, algs, ids,
888                                withUseOnly, withIDOnly,
889                                privateOnly, publicOnly,
890                                nonRevokedOnly, revokedOnly,
891                                minSizeBits, maxSizeBits, sizesBits,
892                                curves,
893                                x5tS256s, withX5COnly);
894                }
895        }
896
897
898        /**
899         * Creates a new JSON Web Key (JWK) matcher.
900         *
901         * @param types       The key types to match, {@code null} if not
902         *                    specified.
903         * @param uses        The public key uses to match, {@code null} if not
904         *                    specified.
905         * @param ops         The key operations to match, {@code null} if not
906         *                    specified.
907         * @param algs        The JOSE algorithms to match, {@code null} if not
908         *                    specified.
909         * @param ids         The key IDs to match, {@code null} if not
910         *                    specified.
911         * @param privateOnly {@code true} to match a private key.
912         * @param publicOnly  {@code true} to match a public only key.
913         */
914        @Deprecated
915        public JWKMatcher(final Set<KeyType> types,
916                          final Set<KeyUse> uses,
917                          final Set<KeyOperation> ops,
918                          final Set<Algorithm> algs,
919                          final Set<String> ids,
920                          final boolean privateOnly,
921                          final boolean publicOnly) {
922
923                this(types, uses, ops, algs, ids, privateOnly, publicOnly, 0, 0);
924        }
925
926
927        /**
928         * Creates a new JSON Web Key (JWK) matcher.
929         *
930         * @param types       The key types to match, {@code null} if not
931         *                    specified.
932         * @param uses        The public key uses to match, {@code null} if not
933         *                    specified.
934         * @param ops         The key operations to match, {@code null} if not
935         *                    specified.
936         * @param algs        The JOSE algorithms to match, {@code null} if not
937         *                    specified.
938         * @param ids         The key IDs to match, {@code null} if not
939         *                    specified.
940         * @param privateOnly {@code true} to match a private key.
941         * @param publicOnly  {@code true} to match a public only key.
942         * @param minSizeBits The minimum key size in bits, zero implies no
943         *                    minimum size limit.
944         * @param maxSizeBits The maximum key size in bits, zero implies no
945         *                    maximum size limit.
946         */
947        @Deprecated
948        public JWKMatcher(final Set<KeyType> types,
949                          final Set<KeyUse> uses,
950                          final Set<KeyOperation> ops,
951                          final Set<Algorithm> algs,
952                          final Set<String> ids,
953                          final boolean privateOnly,
954                          final boolean publicOnly,
955                          final int minSizeBits,
956                          final int maxSizeBits) {
957                
958                this(types, uses, ops, algs, ids, privateOnly, publicOnly, minSizeBits, maxSizeBits, null);
959        }
960
961
962        /**
963         * Creates a new JSON Web Key (JWK) matcher.
964         *
965         * @param types       The key types to match, {@code null} if not
966         *                    specified.
967         * @param uses        The public key uses to match, {@code null} if not
968         *                    specified.
969         * @param ops         The key operations to match, {@code null} if not
970         *                    specified.
971         * @param algs        The JOSE algorithms to match, {@code null} if not
972         *                    specified.
973         * @param ids         The key IDs to match, {@code null} if not
974         *                    specified.
975         * @param privateOnly {@code true} to match a private key.
976         * @param publicOnly  {@code true} to match a public only key.
977         * @param minSizeBits The minimum key size in bits, zero implies no
978         *                    minimum size limit.
979         * @param maxSizeBits The maximum key size in bits, zero implies no
980         *                    maximum size limit.
981         * @param curves      The curves to match (for EC keys), {@code null}
982         *                    if not specified.
983         */
984        @Deprecated
985        public JWKMatcher(final Set<KeyType> types,
986                          final Set<KeyUse> uses,
987                          final Set<KeyOperation> ops,
988                          final Set<Algorithm> algs,
989                          final Set<String> ids,
990                          final boolean privateOnly,
991                          final boolean publicOnly,
992                          final int minSizeBits,
993                          final int maxSizeBits,
994                          final Set<Curve> curves) {
995                
996                this(types, uses, ops, algs, ids, privateOnly, publicOnly, minSizeBits, maxSizeBits, null, curves);
997        }
998
999
1000        /**
1001         * Creates a new JSON Web Key (JWK) matcher.
1002         *
1003         * @param types       The key types to match, {@code null} if not
1004         *                    specified.
1005         * @param uses        The public key uses to match, {@code null} if not
1006         *                    specified.
1007         * @param ops         The key operations to match, {@code null} if not
1008         *                    specified.
1009         * @param algs        The JOSE algorithms to match, {@code null} if not
1010         *                    specified.
1011         * @param ids         The key IDs to match, {@code null} if not
1012         *                    specified.
1013         * @param privateOnly {@code true} to match a private key.
1014         * @param publicOnly  {@code true} to match a public only key.
1015         * @param minSizeBits The minimum key size in bits, zero implies no
1016         *                    minimum size limit.
1017         * @param maxSizeBits The maximum key size in bits, zero implies no
1018         *                    maximum size limit.
1019         * @param sizesBits   The key sizes in bits, {@code null} if not
1020         *                    specified.
1021         * @param curves      The curves to match (for EC and OKP keys),
1022         *                    {@code null} if not specified.
1023         */
1024        @Deprecated
1025        public JWKMatcher(final Set<KeyType> types,
1026                          final Set<KeyUse> uses,
1027                          final Set<KeyOperation> ops,
1028                          final Set<Algorithm> algs,
1029                          final Set<String> ids,
1030                          final boolean privateOnly,
1031                          final boolean publicOnly,
1032                          final int minSizeBits,
1033                          final int maxSizeBits,
1034                          final Set<Integer> sizesBits,
1035                          final Set<Curve> curves) {
1036                
1037                this(types, uses, ops, algs, ids, false, false, privateOnly, publicOnly, minSizeBits, maxSizeBits, sizesBits, curves);
1038        }
1039
1040
1041        /**
1042         * Creates a new JSON Web Key (JWK) matcher.
1043         *
1044         * @param types       The key types to match, {@code null} if not
1045         *                    specified.
1046         * @param uses        The public key uses to match, {@code null} if not
1047         *                    specified.
1048         * @param ops         The key operations to match, {@code null} if not
1049         *                    specified.
1050         * @param algs        The JOSE algorithms to match, {@code null} if not
1051         *                    specified.
1052         * @param ids         The key IDs to match, {@code null} if not
1053         *                    specified.
1054         * @param withUseOnly      {@code true} to match a key with a set use.
1055         * @param withIDOnly       {@code true} to match a key with a set ID.
1056         * @param privateOnly {@code true} to match a private key.
1057         * @param publicOnly  {@code true} to match a public only key.
1058         * @param minSizeBits The minimum key size in bits, zero implies no
1059         *                    minimum size limit.
1060         * @param maxSizeBits The maximum key size in bits, zero implies no
1061         *                    maximum size limit.
1062         * @param sizesBits   The key sizes in bits, {@code null} if not
1063         *                    specified.
1064         * @param curves      The curves to match (for EC and OKP keys),
1065         *                    {@code null} if not specified.
1066         */
1067        @Deprecated
1068        public JWKMatcher(final Set<KeyType> types,
1069                          final Set<KeyUse> uses,
1070                          final Set<KeyOperation> ops,
1071                          final Set<Algorithm> algs,
1072                          final Set<String> ids,
1073                          final boolean withUseOnly,
1074                          final boolean withIDOnly,
1075                          final boolean privateOnly,
1076                          final boolean publicOnly,
1077                          final int minSizeBits,
1078                          final int maxSizeBits,
1079                          final Set<Integer> sizesBits,
1080                          final Set<Curve> curves) {
1081
1082                this(types, uses, ops, algs, ids, withUseOnly, withIDOnly, privateOnly, publicOnly, minSizeBits, maxSizeBits, sizesBits, curves, null);
1083        }
1084
1085        
1086        /**
1087         * Creates a new JSON Web Key (JWK) matcher.
1088         *
1089         * @param types       The key types to match, {@code null} if not
1090         *                    specified.
1091         * @param uses        The public key uses to match, {@code null} if not
1092         *                    specified.
1093         * @param ops         The key operations to match, {@code null} if not
1094         *                    specified.
1095         * @param algs        The JOSE algorithms to match, {@code null} if not
1096         *                    specified.
1097         * @param ids         The key IDs to match, {@code null} if not
1098         *                    specified.
1099         * @param withUseOnly      {@code true} to match a key with a set use.
1100         * @param withIDOnly       {@code true} to match a key with a set ID.
1101         * @param privateOnly {@code true} to match a private key.
1102         * @param publicOnly  {@code true} to match a public only key.
1103         * @param minSizeBits The minimum key size in bits, zero implies no
1104         *                    minimum size limit.
1105         * @param maxSizeBits The maximum key size in bits, zero implies no
1106         *                    maximum size limit.
1107         * @param sizesBits   The key sizes in bits, {@code null} if not
1108         *                    specified.
1109         * @param curves      The curves to match (for EC and OKP keys),
1110         *                    {@code null} if not specified.
1111         * @param x5tS256s    The X.509 certificate thumbprints to match,
1112         *                    {@code null} if not specified.
1113         */
1114        @Deprecated
1115        public JWKMatcher(final Set<KeyType> types,
1116                          final Set<KeyUse> uses,
1117                          final Set<KeyOperation> ops,
1118                          final Set<Algorithm> algs,
1119                          final Set<String> ids,
1120                          final boolean withUseOnly,
1121                          final boolean withIDOnly,
1122                          final boolean privateOnly,
1123                          final boolean publicOnly,
1124                          final int minSizeBits,
1125                          final int maxSizeBits,
1126                          final Set<Integer> sizesBits,
1127                          final Set<Curve> curves,
1128                          final Set<Base64URL> x5tS256s) {
1129
1130                this(types, uses, ops, algs, ids, withUseOnly, withIDOnly, privateOnly, publicOnly, minSizeBits, maxSizeBits, sizesBits, curves, x5tS256s, false);
1131        }
1132
1133        
1134        /**
1135         * Creates a new JSON Web Key (JWK) matcher.
1136         *
1137         * @param types       The key types to match, {@code null} if not
1138         *                    specified.
1139         * @param uses        The public key uses to match, {@code null} if not
1140         *                    specified.
1141         * @param ops         The key operations to match, {@code null} if not
1142         *                    specified.
1143         * @param algs        The JOSE algorithms to match, {@code null} if not
1144         *                    specified.
1145         * @param ids         The key IDs to match, {@code null} if not
1146         *                    specified.
1147         * @param withUseOnly      {@code true} to match a key with a set use.
1148         * @param withIDOnly       {@code true} to match a key with a set ID.
1149         * @param privateOnly {@code true} to match a private key.
1150         * @param publicOnly  {@code true} to match a public only key.
1151         * @param minSizeBits The minimum key size in bits, zero implies no
1152         *                    minimum size limit.
1153         * @param maxSizeBits The maximum key size in bits, zero implies no
1154         *                    maximum size limit.
1155         * @param sizesBits   The key sizes in bits, {@code null} if not
1156         *                    specified.
1157         * @param curves      The curves to match (for EC and OKP keys),
1158         *                    {@code null} if not specified.
1159         * @param x5tS256s    The X.509 certificate thumbprints to match,
1160         *                    {@code null} if not specified.
1161         * @param withX5COnly      {@code true} to match a key with a set X.509
1162         *                    certificate chain.
1163         */
1164        @Deprecated
1165        public JWKMatcher(final Set<KeyType> types,
1166                                          final Set<KeyUse> uses,
1167                                          final Set<KeyOperation> ops,
1168                                          final Set<Algorithm> algs,
1169                                          final Set<String> ids,
1170                                          final boolean withUseOnly,
1171                                          final boolean withIDOnly,
1172                                          final boolean privateOnly,
1173                                          final boolean publicOnly,
1174                                          final int minSizeBits,
1175                                          final int maxSizeBits,
1176                                          final Set<Integer> sizesBits,
1177                                          final Set<Curve> curves,
1178                                          final Set<Base64URL> x5tS256s,
1179                                          final boolean withX5COnly) {
1180
1181                this(types, uses, ops, algs, ids, withUseOnly, withIDOnly, privateOnly, publicOnly, false, false, minSizeBits, maxSizeBits, sizesBits, curves, x5tS256s, withX5COnly);
1182        }
1183
1184
1185        /**
1186         * Creates a new JSON Web Key (JWK) matcher.
1187         *
1188         * @param types          The key types to match, {@code null} if not
1189         *                       specified.
1190         * @param uses           The public key uses to match, {@code null} if
1191         *                       not specified.
1192         * @param ops            The key operations to match, {@code null} if
1193         *                       not specified.
1194         * @param algs           The JOSE algorithms to match, {@code null} if
1195         *                       not specified.
1196         * @param ids            The key IDs to match, {@code null} if not
1197         *                       specified.
1198         * @param withUseOnly         {@code true} to match a key with a set use.
1199         * @param withIDOnly          {@code true} to match a key with a set ID.
1200         * @param privateOnly    {@code true} to match a private key only.
1201         * @param publicOnly     {@code true} to match a public key only.
1202         * @param nonRevokedOnly {@code true} to match a non-revoked key only.
1203         * @param revokedOnly    {@code true} to match a revoked key only.
1204         * @param minSizeBits    The minimum key size in bits, zero implies no
1205         *                       minimum size.
1206         * @param maxSizeBits    The maximum key size in bits, zero implies no
1207         *                       maximum size.
1208         * @param sizesBits      The key sizes in bits, {@code null} if not
1209         *                       specified.
1210         * @param curves         The curves to match (for EC and OKP keys),
1211         *                       {@code null} if not specified.
1212         * @param x5tS256s       The X.509 certificate thumbprints to match,
1213         *                       {@code null} if not specified.
1214         * @param withX5COnly         {@code true} to match a key with a set X.509
1215         *                       certificate chain.
1216         */
1217        public JWKMatcher(final Set<KeyType> types,
1218                          final Set<KeyUse> uses,
1219                          final Set<KeyOperation> ops,
1220                          final Set<Algorithm> algs,
1221                          final Set<String> ids,
1222                          final boolean withUseOnly,
1223                          final boolean withIDOnly,
1224                          final boolean privateOnly,
1225                          final boolean publicOnly,
1226                          final boolean nonRevokedOnly,
1227                          final boolean revokedOnly,
1228                          final int minSizeBits,
1229                          final int maxSizeBits,
1230                          final Set<Integer> sizesBits,
1231                          final Set<Curve> curves,
1232                          final Set<Base64URL> x5tS256s,
1233                          final boolean withX5COnly) {
1234
1235                this.types = types;
1236                this.uses = uses;
1237                this.ops = ops;
1238                this.algs = algs;
1239                this.ids = ids;
1240                this.withUseOnly = withUseOnly;
1241                this.withIDOnly = withIDOnly;
1242                this.privateOnly = privateOnly;
1243                this.publicOnly = publicOnly;
1244                this.nonRevokedOnly = nonRevokedOnly;
1245                this.revokedOnly = revokedOnly;
1246                this.minSizeBits = minSizeBits;
1247                this.maxSizeBits = maxSizeBits;
1248                this.sizesBits = sizesBits;
1249                this.curves = curves;
1250                this.x5tS256s = x5tS256s;
1251                this.withX5COnly = withX5COnly;
1252        }
1253
1254        
1255        /**
1256         * Returns a {@link JWKMatcher} based on the given {@link JWEHeader}.
1257         *
1258         * <p>The {@link JWKMatcher} is configured as follows:
1259         *
1260         * <ul>
1261         *     <li>The key type to match is determined by the JWE algorithm
1262         *         (alg).
1263         *     <li>The key ID to match is set by the JWE header key ID (kid)
1264         *         parameter (if set).
1265         *     <li>The key uses to match are set to encryption or not
1266         *         specified.
1267         *     <li>The key algorithm to match is set to the JWE algorithm (alg)
1268         *         or not specified.
1269         * </ul>
1270         *
1271         * <p>Other JWE header parameters are not taken into account.
1272         *
1273         * @param jweHeader The header to use.
1274         *
1275         * @return A {@code JWKMatcher} based on the given header.
1276         */
1277        public static JWKMatcher forJWEHeader(final JWEHeader jweHeader) {
1278
1279                return new JWKMatcher.Builder()
1280                        .keyType(KeyType.forAlgorithm(jweHeader.getAlgorithm()))
1281                        .keyID(jweHeader.getKeyID())
1282                        .keyUses(KeyUse.ENCRYPTION, null)
1283                        .algorithms(jweHeader.getAlgorithm(), null)
1284                        .build();
1285        }
1286
1287        
1288        /**
1289         * Returns a {@link JWKMatcher} based on the given {@link JWSHeader}.
1290         *
1291         * <p>The {@link JWKMatcher} is configured as follows:
1292         *
1293         * <ul>
1294         *     <li>The key type to match is determined by the JWS algorithm
1295         *         (alg).
1296         *     <li>The key ID to match is set by the JWS header key ID (kid)
1297         *         parameter (if set).
1298         *     <li>The key uses to match are set to signature or not specified.
1299         *     <li>The key algorithm to match is set to the JWS algorithm (alg)
1300         *         or not specified.
1301         *     <li>The X.509 certificate SHA-256 thumbprint to match is set to
1302         *         the x5t#S256 parameter (if set).
1303         * </ul>
1304         *
1305         * <p>Other JWS header parameters are not taken into account.
1306         *
1307         * @param jwsHeader The header to use.
1308         *
1309         * @return A {@code JWKMatcher} based on the given header, {@code null}
1310         *         if the JWS algorithm is not supported.
1311         */
1312        public static JWKMatcher forJWSHeader(final JWSHeader jwsHeader) {
1313
1314                JWSAlgorithm algorithm = jwsHeader.getAlgorithm();
1315                if (JWSAlgorithm.Family.RSA.contains(algorithm) || JWSAlgorithm.Family.EC.contains(algorithm)) {
1316                        // RSA or EC key matcher
1317                        return new JWKMatcher.Builder()
1318                                .keyType(KeyType.forAlgorithm(algorithm))
1319                                .keyID(jwsHeader.getKeyID())
1320                                .keyUses(KeyUse.SIGNATURE, null)
1321                                .algorithms(algorithm, null)
1322                                .x509CertSHA256Thumbprint(jwsHeader.getX509CertSHA256Thumbprint())
1323                                .build();
1324                } else if (JWSAlgorithm.Family.HMAC_SHA.contains(algorithm)) {
1325                        // HMAC secret matcher
1326                        return new JWKMatcher.Builder()
1327                                .keyType(KeyType.forAlgorithm(algorithm))
1328                                .keyID(jwsHeader.getKeyID())
1329                                .privateOnly(true)
1330                                .algorithms(algorithm, null)
1331                                .build();
1332                } else if (JWSAlgorithm.Family.ED.contains(algorithm)) {
1333                        return new JWKMatcher.Builder()
1334                                .keyType(KeyType.forAlgorithm(algorithm))
1335                                .keyID(jwsHeader.getKeyID())
1336                                .keyUses(KeyUse.SIGNATURE, null)
1337                                .algorithms(algorithm, null)
1338                                .curves(Curve.forJWSAlgorithm(algorithm))
1339                                .build();
1340                } else {
1341                        return null; // Unsupported algorithm
1342                }
1343        }
1344        
1345
1346        /**
1347         * Returns the key types to match.
1348         *
1349         * @return The key types, {@code null} if not specified.
1350         */
1351        public Set<KeyType> getKeyTypes() {
1352
1353                return types;
1354        }
1355
1356
1357        /**
1358         * Returns the public key uses to match.
1359         *
1360         * @return The public key uses, {@code null} if not specified.
1361         */
1362        public Set<KeyUse> getKeyUses() {
1363
1364                return uses;
1365        }
1366
1367
1368        /**
1369         * Returns the key operations to match.
1370         *
1371         * @return The key operations, {@code null} if not specified.
1372         */
1373        public Set<KeyOperation> getKeyOperations() {
1374
1375                return ops;
1376        }
1377
1378
1379        /**
1380         * Returns the JOSE algorithms to match.
1381         *
1382         * @return The JOSE algorithms, {@code null} if not specified.
1383         */
1384        public Set<Algorithm> getAlgorithms() {
1385
1386                return algs;
1387        }
1388
1389
1390        /**
1391         * Returns the key IDs to match.
1392         *
1393         * @return The key IDs, {@code null} if not specified.
1394         */
1395        public Set<String> getKeyIDs() {
1396
1397                return ids;
1398        }
1399        
1400        
1401        /**
1402         * Returns {@code true} if keys with a specified use are matched.
1403         *
1404         * @return {@code true} if keys with a specified use are matched, else
1405         *         {@code false}.
1406         */
1407        @Deprecated
1408        public boolean hasKeyUse() {
1409                
1410                return isWithKeyUseOnly();
1411        }
1412
1413
1414        /**
1415         * Returns {@code true} if keys with a specified use are matched.
1416         *
1417         * @return {@code true} if keys with a specified use are matched, else
1418         *         {@code false}.
1419         */
1420        public boolean isWithKeyUseOnly() {
1421
1422                return withUseOnly;
1423        }
1424        
1425        
1426        /**
1427         * Returns {@code true} if keys with a specified ID are matched.
1428         *
1429         * @return {@code true} if keys with a specified ID are matched, else
1430         *         {@code false}.
1431         */
1432        @Deprecated
1433        public boolean hasKeyID() {
1434                
1435                return isWithKeyIDOnly();
1436        }
1437
1438
1439        /**
1440         * Returns {@code true} if keys with a specified ID are matched.
1441         *
1442         * @return {@code true} if keys with a specified ID are matched, else
1443         *         {@code false}.
1444         */
1445        public boolean isWithKeyIDOnly() {
1446
1447                return withIDOnly;
1448        }
1449
1450
1451        /**
1452         * Returns {@code true} if only private keys are matched.
1453         *
1454         * @return {@code true} if only private keys are matched, else 
1455         *         {@code false}.
1456         */
1457        public boolean isPrivateOnly() {
1458
1459                return privateOnly;
1460        }
1461
1462
1463        /**
1464         * Returns {@code true} if only public keys are matched.
1465         *
1466         * @return {@code true} if only public keys are matched, else
1467         *         {@code false}.
1468         */
1469        public boolean isPublicOnly() {
1470
1471                return publicOnly;
1472        }
1473
1474
1475        /**
1476         * Returns {@code true} if only non-revoked keys are matched.
1477         * 
1478         * @return {@code true} if only non-revoked keys are matched, else
1479         *         {@code false}.
1480         */
1481        public boolean isNonRevokedOnly() {
1482                
1483                return nonRevokedOnly;
1484        }
1485
1486
1487        /**
1488         * Returns {@code true} if only revoked keys are matched.
1489         *
1490         * @return {@code true} if only revoked keys are matched, else
1491         *         {@code false}.
1492         */
1493        public boolean isRevokedOnly() {
1494
1495                return revokedOnly;
1496        }
1497
1498
1499        /**
1500         * Returns the minimum key size. Use {@link #getMinKeySize()} instead.
1501         *
1502         * @return The minimum key size in bits, zero implies no minimum size
1503         *         limit.
1504         */
1505        @Deprecated
1506        public int getMinSize() {
1507
1508                return getMinKeySize();
1509        }
1510
1511
1512        /**
1513         * Returns the minimum key size.
1514         *
1515         * @return The minimum key size in bits, zero implies no minimum size
1516         *         limit.
1517         */
1518        public int getMinKeySize() {
1519
1520                return minSizeBits;
1521        }
1522
1523
1524        /**
1525         * Returns the maximum key size. Use {@link #getMaxKeySize()} instead.
1526         *
1527         * @return The maximum key size in bits, zero implies no maximum size
1528         *         limit.
1529         */
1530        @Deprecated
1531        public int getMaxSize() {
1532
1533                return getMaxKeySize();
1534        }
1535
1536
1537        /**
1538         * Returns the maximum key size.
1539         *
1540         * @return The maximum key size in bits, zero implies no maximum size
1541         *         limit.
1542         */
1543        public int getMaxKeySize() {
1544
1545                return maxSizeBits;
1546        }
1547        
1548        
1549        /**
1550         * Returns the key sizes.
1551         *
1552         * @return The key sizes in bits, {@code null} if not specified.
1553         */
1554        public Set<Integer> getKeySizes() {
1555                
1556                return sizesBits;
1557        }
1558        
1559        
1560        /**
1561         * Returns the curves to match (for EC and OKP keys).
1562         *
1563         * @return The curves, {@code null} if not specified.
1564         */
1565        public Set<Curve> getCurves() {
1566                
1567                return curves;
1568        }
1569
1570        /**
1571         * Returns the X.509 certificate SHA-256 thumbprints to match.
1572         *
1573         * @return The thumbprints, {@code null} if not specified.
1574         */
1575        public Set<Base64URL> getX509CertSHA256Thumbprints() {
1576                
1577                return x5tS256s;
1578        }
1579        
1580        
1581        /**
1582         * Returns {@code true} if keys with a specified X.509 certificate
1583         * chain are matched.
1584         *
1585         * @return {@code true} if keys with a specified X.509 certificate are
1586         *         matched, else {@code false}.
1587         */
1588        @Deprecated
1589        public boolean hasX509CertChain() {
1590                
1591                return isWithX509CertChainOnly();
1592        }
1593
1594
1595        /**
1596         * Returns {@code true} if keys with a specified X.509 certificate
1597         * chain are matched.
1598         *
1599         * @return {@code true} if keys with a specified X.509 certificate
1600         *         chain are matched, else {@code false}.
1601         */
1602        public boolean isWithX509CertChainOnly() {
1603
1604                return withX5COnly;
1605        }
1606        
1607
1608        /**
1609         * Returns {@code true} if the specified JWK matches.
1610         *
1611         * @param key The JSON Web Key (JWK). Must not  be {@code null}.
1612         *
1613         * @return {@code true} if the JWK matches, else {@code false}.
1614         */
1615        public boolean matches(final JWK key) {
1616                
1617                if (withUseOnly && key.getKeyUse() == null)
1618                        return false;
1619                
1620                if (withIDOnly && (key.getKeyID() == null || key.getKeyID().trim().isEmpty()))
1621                        return false;
1622
1623                if (privateOnly && ! key.isPrivate())
1624                        return false;
1625
1626                if (publicOnly && key.isPrivate())
1627                        return false;
1628
1629                if (nonRevokedOnly && key.getKeyRevocation() != null)
1630                        return false;
1631
1632                if (revokedOnly && key.getKeyRevocation() == null)
1633                        return false;
1634
1635                if (types != null && ! types.contains(key.getKeyType()))
1636                        return false;
1637
1638                if (uses != null && ! uses.contains(key.getKeyUse()))
1639                        return false;
1640
1641                if (ops != null) {
1642
1643                        if (ops.contains(null) && key.getKeyOperations() == null) {
1644                                // pass
1645                        } else if (key.getKeyOperations() != null && ops.containsAll(key.getKeyOperations())) {
1646                                // pass
1647                        } else {
1648                                return false;
1649                        }
1650                }
1651
1652                if (algs != null && ! algs.contains(key.getAlgorithm()))
1653                        return false;
1654
1655                if (ids != null && ! ids.contains(key.getKeyID()))
1656                        return false;
1657
1658                if (minSizeBits > 0) {
1659
1660                        if (key.size() < minSizeBits)
1661                                return false;
1662                }
1663
1664                if (maxSizeBits > 0) {
1665
1666                        if (key.size() > maxSizeBits)
1667                                return false;
1668                }
1669                
1670                if (sizesBits != null) {
1671                        if (! sizesBits.contains(key.size()))
1672                                return false;
1673                }
1674                
1675                if (curves != null) {
1676                        
1677                        if (! (key instanceof CurveBasedJWK))
1678                                return false;
1679                        
1680                        CurveBasedJWK curveBasedJWK = (CurveBasedJWK) key;
1681                        
1682                        if (! curves.contains(curveBasedJWK.getCurve()))
1683                                return false;
1684                }
1685
1686                if (x5tS256s != null) {
1687                        
1688                        boolean matchingCertFound = false;
1689                        
1690                        if (key.getX509CertChain() != null && ! key.getX509CertChain().isEmpty()) {
1691                                try {
1692                                        X509Certificate cert = X509CertUtils.parseWithException(key.getX509CertChain().get(0).decode());
1693                                        matchingCertFound = x5tS256s.contains(X509CertUtils.computeSHA256Thumbprint(cert));
1694                                } catch (CertificateException e) {
1695                                        // Ignore
1696                                }
1697                        }
1698                        
1699                        boolean matchingX5T256Found = x5tS256s.contains(key.getX509CertSHA256Thumbprint());
1700                        
1701                        if (! matchingCertFound && ! matchingX5T256Found) {
1702                                return false;
1703                        }
1704                }
1705                
1706                if (withX5COnly) {
1707                        return key.getX509CertChain() != null && !key.getX509CertChain().isEmpty();
1708                }
1709
1710                return true;
1711        }
1712        
1713        
1714        @Override
1715        public String toString() {
1716                StringBuilder sb = new StringBuilder();
1717                
1718                append(sb, JWKParameterNames.KEY_TYPE, types);
1719                append(sb, JWKParameterNames.PUBLIC_KEY_USE, uses);
1720                append(sb, JWKParameterNames.KEY_OPS, ops);
1721                append(sb, JWKParameterNames.ALGORITHM, algs);
1722                append(sb, JWKParameterNames.KEY_ID, ids);
1723                
1724                if (withUseOnly) {
1725                        sb.append("with_use_only=true ");
1726                }
1727                
1728                if (withIDOnly) {
1729                        sb.append("with_id_only=true ");
1730                }
1731                
1732                if (privateOnly) {
1733                        sb.append("private_only=true ");
1734                }
1735                
1736                if (publicOnly) {
1737                        sb.append("public_only=true ");
1738                }
1739
1740                if (nonRevokedOnly) {
1741                        sb.append("non_revoked_only=true ");
1742                }
1743
1744                if (revokedOnly) {
1745                        sb.append("revoked_only=true ");
1746                }
1747                
1748                if (minSizeBits > 0) {
1749                        sb.append("min_size=" + minSizeBits + " ");
1750                }
1751                
1752                if (maxSizeBits > 0) {
1753                        sb.append("max_size=" + maxSizeBits + " ");
1754                }
1755                
1756                append(sb, "size", sizesBits);
1757                append(sb, JWKParameterNames.ELLIPTIC_CURVE, curves);
1758                append(sb, JWKParameterNames.X_509_CERT_SHA_256_THUMBPRINT, x5tS256s);
1759                if (withX5COnly) {
1760                        sb.append("with_x5c_only=true" );
1761                }
1762                        
1763                return sb.toString().trim();
1764        }
1765        
1766        
1767        /**
1768         * Appends the specified JWK matcher parameter to a string builder.
1769         *
1770         * @param sb     The string builder. Must not be {@code null}.
1771         * @param key    The parameter key. Must not be {@code null}.
1772         * @param values The parameter value, {@code null} if not specified.
1773         */
1774        private static void append(final StringBuilder sb, final String key, final Set<?> values) {
1775                
1776                if (values != null) {
1777                        
1778                        sb.append(key);
1779                        sb.append('=');
1780                        if (values.size() == 1) {
1781                                Object value = values.iterator().next();
1782                                if (value == null) {
1783                                        sb.append("ANY");
1784                                } else {
1785                                        sb.append(value.toString().trim());
1786                                }
1787                        } else {
1788                                sb.append(values.toString().trim());
1789                        }
1790                        
1791                        sb.append(' ');
1792                }
1793        }
1794}