001/*
002 * nimbus-jose-jwt
003 *
004 * Copyright 2012-2016, 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.util.*;
022
023import com.nimbusds.jose.Algorithm;
024import com.nimbusds.jose.util.Base64URL;
025import net.jcip.annotations.Immutable;
026
027
028/**
029 * JSON Web Key (JWK) matcher. May be used to ensure a JWK matches a set of
030 * application-specific criteria.
031 *
032 * <p>Supported key matching criteria:
033 *
034 * <ul>
035 *     <li>Any, unspecified, one or more key types (typ).
036 *     <li>Any, unspecified, one or more key uses (use).
037 *     <li>Any, unspecified, one or more key operations (key_ops).
038 *     <li>Any, unspecified, one or more key algorithms (alg).
039 *     <li>Any, unspecified, one or more key identifiers (kid).
040 *     <li>Private only key.
041 *     <li>Public only key.
042 *     <li>Minimum, maximum or exact key sizes.
043 *     <li>Any, unspecified, one or more curves for EC and OKP keys (crv).
044 *     <li>X.509 certificate SHA-256 thumbprint.
045 * </ul>
046 *
047 * <p>Matching by JWK thumbprint (RFC 7638), X.509 certificate URL and X.509
048 * certificate chain is not supported.
049 *
050 * @author Vladimir Dzhuvinov
051 * @author Josh Cummings
052 * @version 2018-06-13
053 */
054@Immutable
055public class JWKMatcher {
056
057
058        /**
059         * The key types to match.
060         */
061        private final Set<KeyType> types;
062
063
064        /**
065         * The public key uses to match.
066         */
067        private final Set<KeyUse> uses;
068
069
070        /**
071         * The key operations to match.
072         */
073        private final Set<KeyOperation> ops;
074
075
076        /**
077         * The algorithms to match.
078         */
079        private final Set<Algorithm> algs;
080
081
082        /**
083         * The key IDs to match.
084         */
085        private final Set<String> ids;
086        
087        
088        /**
089         * {@code true} to match a key with a set use.
090         */
091        private final boolean hasUse;
092        
093        
094        /**
095         * {@code true} to match a key with a set ID.
096         */
097        private final boolean hasID;
098
099
100        /**
101         * {@code true} to match a private key.
102         */
103        private final boolean privateOnly;
104
105
106        /**
107         * {@code true} to match a public only key.
108         */
109        private final boolean publicOnly;
110
111
112        /**
113         * The minimum key size in bits, zero implies no minimum size limit.
114         */
115        private final int minSizeBits;
116
117
118        /**
119         * The maximum key size in bits, zero implies no maximum size limit.
120         */
121        private final int maxSizeBits;
122        
123        
124        /**
125         * The key sizes in bits.
126         */
127        private final Set<Integer> sizesBits;
128        
129        
130        /**
131         * The curves to match (for EC and OKP keys).
132         */
133        private final Set<Curve> curves;
134
135        
136        /**
137         * The X.509 certificate SHA-256 thumbprints to match.
138         */
139        private final Set<Base64URL> x5tS256s;
140
141        
142        /**
143         * Builder for constructing JWK matchers.
144         *
145         * <p>Example usage:
146         *
147         * <pre>
148         * JWKMatcher matcher = new JWKMatcher().keyID("123").build();
149         * </pre>
150         */
151        public static class Builder {
152
153                
154                /**
155                 * The key types to match.
156                 */
157                private Set<KeyType> types;
158
159
160                /**
161                 * The public key uses to match.
162                 */
163                private Set<KeyUse> uses;
164
165
166                /**
167                 * The key operations to match.
168                 */
169                private Set<KeyOperation> ops;
170
171
172                /**
173                 * The algorithms to match.
174                 */
175                private Set<Algorithm> algs;
176
177
178                /**
179                 * The key IDs to match.
180                 */
181                private Set<String> ids;
182                
183                
184                /**
185                 * {@code true} to match a key with a set use.
186                 */
187                private boolean hasUse = false;
188                
189                
190                /**
191                 * {@code true} to match a key with a set ID.
192                 */
193                private boolean hasID = false;
194
195
196                /**
197                 * {@code true} to match a private key.
198                 */
199                private boolean privateOnly = false;
200
201
202                /**
203                 * {@code true} to match a public only key.
204                 */
205                private boolean publicOnly = false;
206
207
208                /**
209                 * The minimum key size in bits, zero implies no minimum size
210                 * limit.
211                 */
212                private int minSizeBits = 0;
213
214
215                /**
216                 * The maximum key size in bits, zero implies no maximum size
217                 * limit.
218                 */
219                private int maxSizeBits = 0;
220                
221                
222                /**
223                 * The key sizes in bits.
224                 */
225                private Set<Integer> sizesBits;
226                
227                
228                /**
229                 * The curves to match (for EC and OKP keys).
230                 */
231                private Set<Curve> curves;
232
233                
234                /**
235                 * The X.509 certificate SHA-256 thumbprints to match.
236                 */
237                private Set<Base64URL> x5tS256s;
238
239                
240                /**
241                 * Sets a single key type to match.
242                 *
243                 * @param kty The key type, {@code null} if not specified.
244                 *            
245                 * @return This builder.            
246                 */
247                public Builder keyType(final KeyType kty) {
248
249                        if (kty == null) {
250                                types = null;
251                        } else {
252                                types = new HashSet<>(Collections.singletonList(kty));
253                        }
254                        
255                        return this;
256                }
257
258
259                /**
260                 * Sets multiple key types to match.
261                 *
262                 * @param types The key types.
263                 *
264                 * @return This builder.
265                 */
266                public Builder keyTypes(final KeyType ... types) {
267
268                        keyTypes(new LinkedHashSet<>(Arrays.asList(types)));
269                        return this;
270                }
271
272
273                /**
274                 * Sets multiple key types to match.
275                 *
276                 * @param types The key types, {@code null} if not specified.
277                 *
278                 * @return This builder.
279                 */
280                public Builder keyTypes(final Set<KeyType> types) {
281
282                        this.types = types;
283                        return this;
284                }
285
286
287                /**
288                 * Sets a single public key use to match.
289                 *
290                 * @param use The public key use, {@code null} if not 
291                 *            specified.
292                 *
293                 * @return This builder.
294                 */
295                public Builder keyUse(final KeyUse use) {
296
297                        if (use == null) {
298                                uses = null;
299                        } else {
300                                uses = new HashSet<>(Collections.singletonList(use));
301                        }
302                        return this;
303                }
304
305
306                /**
307                 * Sets multiple public key uses to match.
308                 *
309                 * @param uses The public key uses.
310                 *
311                 * @return This builder.
312                 */
313                public Builder keyUses(final KeyUse... uses) {
314
315                        keyUses(new LinkedHashSet<>(Arrays.asList(uses)));
316                        return this;
317                }
318
319
320                /**
321                 * Sets multiple public key uses to match.
322                 *
323                 * @param uses The public key uses, {@code null} if not
324                 *             specified.
325                 *
326                 * @return This builder.
327                 */
328                public Builder keyUses(final Set<KeyUse> uses) {
329
330                        this.uses = uses;
331                        return this;
332                }
333
334
335                /**
336                 * Sets a single key operation to match.
337                 *
338                 * @param op The key operation, {@code null} if not specified.
339                 *
340                 * @return This builder.
341                 */
342                public Builder keyOperation(final KeyOperation op) {
343
344                        if (op == null) {
345                                ops = null;
346                        } else {
347                                ops = new HashSet<>(Collections.singletonList(op));
348                        }
349                        return this;
350                }
351
352
353                /**
354                 * Sets multiple key operations to match.
355                 *
356                 * @param ops The key operations.
357                 *
358                 * @return This builder.
359                 */
360                public Builder keyOperations(final KeyOperation... ops) {
361
362                        keyOperations(new LinkedHashSet<>(Arrays.asList(ops)));
363                        return this;
364                }
365
366
367                /**
368                 * Sets multiple key operations to match.
369                 *
370                 * @param ops The key operations, {@code null} if not
371                 *            specified.
372                 *
373                 * @return This builder.
374                 */
375                public Builder keyOperations(final Set<KeyOperation> ops) {
376
377                        this.ops = ops;
378                        return this;
379                }
380
381
382                /**
383                 * Sets a single JOSE algorithm to match.
384                 *
385                 * @param alg The JOSE algorithm, {@code null} if not
386                 *            specified.
387                 *
388                 * @return This builder.
389                 */
390                public Builder algorithm(final Algorithm alg) {
391
392                        if (alg == null) {
393                                algs = null;
394                        } else {
395                                algs = new HashSet<>(Collections.singletonList(alg));
396                        }
397                        return this;
398                }
399
400
401                /**
402                 * Sets multiple JOSE algorithms to match.
403                 *
404                 * @param algs The JOSE algorithms.
405                 *
406                 * @return This builder.
407                 */
408                public Builder algorithms(final Algorithm ... algs) {
409
410                        algorithms(new LinkedHashSet<>(Arrays.asList(algs)));
411                        return this;
412                }
413
414
415                /**
416                 * Sets multiple JOSE algorithms to match.
417                 *
418                 * @param algs The JOSE algorithms, {@code null} if not
419                 *             specified.
420                 *
421                 * @return This builder.
422                 */
423                public Builder algorithms(final Set<Algorithm> algs) {
424
425                        this.algs = algs;
426                        return this;
427                }
428
429
430                /**
431                 * Sets a single key ID to match.
432                 *
433                 * @param id The key ID, {@code null} if not specified.
434                 *
435                 * @return This builder.
436                 */
437                public Builder keyID(final String id) {
438
439                        if (id == null) {
440                                ids = null;
441                        } else {
442                                ids = new HashSet<>(Collections.singletonList(id));
443                        }
444                        return this;
445                }
446
447
448                /**
449                 * Sets multiple key IDs to match.
450                 *
451                 * @param ids The key IDs.
452                 *
453                 * @return This builder.
454                 */
455                public Builder keyIDs(final String ... ids) {
456
457                        keyIDs(new LinkedHashSet<>(Arrays.asList(ids)));
458                        return this;
459                }
460
461
462                /**
463                 * Sets multiple key IDs to match.
464                 *
465                 * @param ids The key IDs, {@code null} if not specified.
466                 *
467                 * @return This builder.
468                 */
469                public Builder keyIDs(final Set<String> ids) {
470
471                        this.ids = ids;
472                        return this;
473                }
474                
475                
476                /**
477                 * Sets key use presence matching.
478                 *
479                 * @param hasUse {@code true} to match a key with a set use.
480                 *
481                 * @return This builder.
482                 */
483                public Builder hasKeyUse(final boolean hasUse) {
484                        
485                        this.hasUse = hasUse;
486                        return this;
487                }
488                
489                
490                /**
491                 * Sets key ID presence matching.
492                 *
493                 * @param hasID {@code true} to match a key with a set ID.
494                 *
495                 * @return This builder.
496                 */
497                public Builder hasKeyID(final boolean hasID) {
498                        
499                        this.hasID = hasID;
500                        return this;
501                }
502
503
504                /**
505                 * Sets the private key matching policy.
506                 *
507                 * @param privateOnly {@code true} to match a private key.
508                 *
509                 * @return This builder.
510                 */
511                public Builder privateOnly(final boolean privateOnly) {
512
513                        this.privateOnly = privateOnly;
514                        return this;
515                }
516
517
518                /**
519                 * Sets the public key matching policy.
520                 *
521                 * @param publicOnly {@code true} to match a public only key.
522                 *
523                 * @return This builder.
524                 */
525                public Builder publicOnly(final boolean publicOnly) {
526
527                        this.publicOnly = publicOnly;
528                        return this;
529                }
530
531
532                /**
533                 * Sets the minimal key size.
534                 *
535                 * @param minSizeBits The minimum key size in bits, zero
536                 *                    implies no minimum key size limit.
537                 *
538                 * @return This builder.
539                 */
540                public Builder minKeySize(final int minSizeBits) {
541
542                        this.minSizeBits = minSizeBits;
543                        return this;
544                }
545
546
547                /**
548                 * Sets the maximum key size.
549                 *
550                 * @param maxSizeBits The maximum key size in bits, zero
551                 *                    implies no maximum key size limit.
552                 *
553                 * @return This builder.
554                 */
555                public Builder maxKeySize(final int maxSizeBits) {
556
557                        this.maxSizeBits = maxSizeBits;
558                        return this;
559                }
560                
561                
562                /**
563                 * Sets the key size.
564                 *
565                 * @param keySizeBits The key size in bits, zero if not
566                 *                    specified.
567                 *
568                 * @return This builder.
569                 */
570                public Builder keySize(final int keySizeBits) {
571                        if (keySizeBits <= 0) {
572                                sizesBits = null;
573                        } else {
574                                sizesBits = Collections.singleton(keySizeBits);
575                        }
576                        return this;
577                }
578                
579                
580                /**
581                 * Sets the key sizes.
582                 *
583                 * @param keySizesBits The key sizes in bits.
584                 *
585                 * @return This builder.
586                 */
587                public Builder keySizes(final int... keySizesBits) {
588                        Set<Integer> sizesSet = new LinkedHashSet<>();
589                        for (int keySize: keySizesBits) {
590                                sizesSet.add(keySize);
591                        }
592                        keySizes(sizesSet);
593                        return this;
594                }
595                
596                
597                /**
598                 * Sets the key sizes.
599                 *
600                 * @param keySizesBits The key sizes in bits.
601                 *
602                 * @return This builder.
603                 */
604                public Builder keySizes(final Set<Integer> keySizesBits) {
605                        
606                        this.sizesBits = keySizesBits;
607                        return this;
608                }
609                
610                
611                /**
612                 * Sets a single curve to match (for EC and OKP keys).
613                 *
614                 * @param curve The curve, {@code null} if not specified.
615                 *
616                 * @return This builder.
617                 */
618                public Builder curve(final Curve curve) {
619                        
620                        if (curve == null) {
621                                curves = null;
622                        } else {
623                                curves = new HashSet<>(Collections.singletonList(curve));
624                        }
625                        return this;
626                }
627                
628                
629                /**
630                 * Sets multiple curves to match (for EC and OKP keys).
631                 *
632                 * @param curves The curves.
633                 *
634                 * @return This builder.
635                 */
636                public Builder curves(final Curve... curves) {
637                        
638                        curves(new LinkedHashSet<>(Arrays.asList(curves)));
639                        return this;
640                }
641                
642                
643                /**
644                 * Sets multiple curves to match (for EC and OKP keys).
645                 *
646                 * @param curves The curves, {@code null} if not specified.
647                 *
648                 * @return This builder.
649                 */
650                public Builder curves(final Set<Curve> curves) {
651                        
652                        this.curves = curves;
653                        return this;
654                }
655
656                
657                /**
658                 * Sets a single X.509 certificate SHA-256 thumbprint to match.
659                 *
660                 * @param x5tS256 The thumbprint, {@code null} if not
661                 *                specified.
662                 *
663                 * @return This builder.
664                 */
665                public Builder x509CertSHA256Thumbprint(final Base64URL x5tS256) {
666
667                        if (x5tS256 == null) {
668                                x5tS256s = null;
669                        } else {
670                                x5tS256s = Collections.singleton(x5tS256);
671                        }
672                        return this;
673                }
674
675                /**
676                 * Sets multiple X.509 certificate SHA-256 thumbprints to
677                 * match.
678                 *
679                 * @param x5tS256s The thumbprints.
680                 *
681                 * @return This builder.
682                 */
683                public Builder x509CertSHA256Thumbprints(final Base64URL... x5tS256s) {
684                        return x509CertSHA256Thumbprints(new LinkedHashSet<>(Arrays.asList(x5tS256s)));
685                }
686
687                
688                /**
689                 * Sets multiple X.509 certificate SHA-256 thumbprints to
690                 * match.
691                 *
692                 * @param x5tS256s The thumbprints, {@code null} if not
693                 *                 specified.
694                 *
695                 * @return This builder.
696                 */
697                public Builder x509CertSHA256Thumbprints(final Set<Base64URL> x5tS256s) {
698                        this.x5tS256s = x5tS256s;
699                        return this;
700                }
701
702                /**
703                 * Builds a new JWK matcher.
704                 *
705                 * @return The JWK matcher.
706                 */
707                public JWKMatcher build() {
708
709                        return new JWKMatcher(types, uses, ops, algs, ids, hasUse, hasID, privateOnly, publicOnly, minSizeBits, maxSizeBits, sizesBits, curves, x5tS256s);
710                }
711        }
712
713
714        /**
715         * Creates a new JSON Web Key (JWK) matcher.
716         *
717         * @param types       The key types to match, {@code null} if not
718         *                    specified.
719         * @param uses        The public key uses to match, {@code null} if not
720         *                    specified.
721         * @param ops         The key operations to match, {@code null} if not
722         *                    specified.
723         * @param algs        The JOSE algorithms to match, {@code null} if not
724         *                    specified.
725         * @param ids         The key IDs to match, {@code null} if not
726         *                    specified.
727         * @param privateOnly {@code true} to match a private key.
728         * @param publicOnly  {@code true} to match a public only key.
729         */
730        @Deprecated
731        public JWKMatcher(final Set<KeyType> types,
732                          final Set<KeyUse> uses,
733                          final Set<KeyOperation> ops,
734                          final Set<Algorithm> algs,
735                          final Set<String> ids,
736                          final boolean privateOnly,
737                          final boolean publicOnly) {
738
739                this(types, uses, ops, algs, ids, privateOnly, publicOnly, 0, 0);
740        }
741
742
743        /**
744         * Creates a new JSON Web Key (JWK) matcher.
745         *
746         * @param types       The key types to match, {@code null} if not
747         *                    specified.
748         * @param uses        The public key uses to match, {@code null} if not
749         *                    specified.
750         * @param ops         The key operations to match, {@code null} if not
751         *                    specified.
752         * @param algs        The JOSE algorithms to match, {@code null} if not
753         *                    specified.
754         * @param ids         The key IDs to match, {@code null} if not
755         *                    specified.
756         * @param privateOnly {@code true} to match a private key.
757         * @param publicOnly  {@code true} to match a public only key.
758         * @param minSizeBits The minimum key size in bits, zero implies no
759         *                    minimum size limit.
760         * @param maxSizeBits The maximum key size in bits, zero implies no
761         *                    maximum size limit.
762         */
763        @Deprecated
764        public JWKMatcher(final Set<KeyType> types,
765                          final Set<KeyUse> uses,
766                          final Set<KeyOperation> ops,
767                          final Set<Algorithm> algs,
768                          final Set<String> ids,
769                          final boolean privateOnly,
770                          final boolean publicOnly,
771                          final int minSizeBits,
772                          final int maxSizeBits) {
773                
774                this(types, uses, ops, algs, ids, privateOnly, publicOnly, minSizeBits, maxSizeBits, null);
775        }
776
777
778        /**
779         * Creates a new JSON Web Key (JWK) matcher.
780         *
781         * @param types       The key types to match, {@code null} if not
782         *                    specified.
783         * @param uses        The public key uses to match, {@code null} if not
784         *                    specified.
785         * @param ops         The key operations to match, {@code null} if not
786         *                    specified.
787         * @param algs        The JOSE algorithms to match, {@code null} if not
788         *                    specified.
789         * @param ids         The key IDs to match, {@code null} if not
790         *                    specified.
791         * @param privateOnly {@code true} to match a private key.
792         * @param publicOnly  {@code true} to match a public only key.
793         * @param minSizeBits The minimum key size in bits, zero implies no
794         *                    minimum size limit.
795         * @param maxSizeBits The maximum key size in bits, zero implies no
796         *                    maximum size limit.
797         * @param curves      The curves to match (for EC keys), {@code null}
798         *                    if not specified.
799         */
800        @Deprecated
801        public JWKMatcher(final Set<KeyType> types,
802                          final Set<KeyUse> uses,
803                          final Set<KeyOperation> ops,
804                          final Set<Algorithm> algs,
805                          final Set<String> ids,
806                          final boolean privateOnly,
807                          final boolean publicOnly,
808                          final int minSizeBits,
809                          final int maxSizeBits,
810                          final Set<Curve> curves) {
811                
812                this(types, uses, ops, algs, ids, privateOnly, publicOnly, minSizeBits, maxSizeBits, null, curves);
813        }
814
815
816        /**
817         * Creates a new JSON Web Key (JWK) matcher.
818         *
819         * @param types       The key types to match, {@code null} if not
820         *                    specified.
821         * @param uses        The public key uses to match, {@code null} if not
822         *                    specified.
823         * @param ops         The key operations to match, {@code null} if not
824         *                    specified.
825         * @param algs        The JOSE algorithms to match, {@code null} if not
826         *                    specified.
827         * @param ids         The key IDs to match, {@code null} if not
828         *                    specified.
829         * @param privateOnly {@code true} to match a private key.
830         * @param publicOnly  {@code true} to match a public only key.
831         * @param minSizeBits The minimum key size in bits, zero implies no
832         *                    minimum size limit.
833         * @param maxSizeBits The maximum key size in bits, zero implies no
834         *                    maximum size limit.
835         * @param sizesBits   The key sizes in bits, {@code null} if not
836         *                    specified.
837         * @param curves      The curves to match (for EC and OKP keys),
838         *                    {@code null} if not specified.
839         */
840        @Deprecated
841        public JWKMatcher(final Set<KeyType> types,
842                          final Set<KeyUse> uses,
843                          final Set<KeyOperation> ops,
844                          final Set<Algorithm> algs,
845                          final Set<String> ids,
846                          final boolean privateOnly,
847                          final boolean publicOnly,
848                          final int minSizeBits,
849                          final int maxSizeBits,
850                          final Set<Integer> sizesBits,
851                          final Set<Curve> curves) {
852                
853                this(types, uses, ops, algs, ids, false, false, privateOnly, publicOnly, minSizeBits, maxSizeBits, sizesBits, curves);
854        }
855
856
857        /**
858         * Creates a new JSON Web Key (JWK) matcher.
859         *
860         * @param types       The key types to match, {@code null} if not
861         *                    specified.
862         * @param uses        The public key uses to match, {@code null} if not
863         *                    specified.
864         * @param ops         The key operations to match, {@code null} if not
865         *                    specified.
866         * @param algs        The JOSE algorithms to match, {@code null} if not
867         *                    specified.
868         * @param ids         The key IDs to match, {@code null} if not
869         *                    specified.
870         * @param hasUse      {@code true} to match a key with a set use.
871         * @param hasID       {@code true} to match a key with a set ID.
872         * @param privateOnly {@code true} to match a private key.
873         * @param publicOnly  {@code true} to match a public only key.
874         * @param minSizeBits The minimum key size in bits, zero implies no
875         *                    minimum size limit.
876         * @param maxSizeBits The maximum key size in bits, zero implies no
877         *                    maximum size limit.
878         * @param sizesBits   The key sizes in bits, {@code null} if not
879         *                    specified.
880         * @param curves      The curves to match (for EC and OKP keys),
881         *                    {@code null} if not specified.
882         */
883        @Deprecated
884        public JWKMatcher(final Set<KeyType> types,
885                          final Set<KeyUse> uses,
886                          final Set<KeyOperation> ops,
887                          final Set<Algorithm> algs,
888                          final Set<String> ids,
889                          final boolean hasUse,
890                          final boolean hasID,
891                          final boolean privateOnly,
892                          final boolean publicOnly,
893                          final int minSizeBits,
894                          final int maxSizeBits,
895                          final Set<Integer> sizesBits,
896                          final Set<Curve> curves) {
897
898                this(types, uses, ops, algs, ids, hasUse, hasID, privateOnly, publicOnly, minSizeBits, maxSizeBits, sizesBits, curves, null);
899        }
900
901        /**
902         * Creates a new JSON Web Key (JWK) matcher.
903         *
904         * @param types       The key types to match, {@code null} if not
905         *                    specified.
906         * @param uses        The public key uses to match, {@code null} if not
907         *                    specified.
908         * @param ops         The key operations to match, {@code null} if not
909         *                    specified.
910         * @param algs        The JOSE algorithms to match, {@code null} if not
911         *                    specified.
912         * @param ids         The key IDs to match, {@code null} if not
913         *                    specified.
914         * @param hasUse      {@code true} to match a key with a set use.
915         * @param hasID       {@code true} to match a key with a set ID.
916         * @param privateOnly {@code true} to match a private key.
917         * @param publicOnly  {@code true} to match a public only key.
918         * @param minSizeBits The minimum key size in bits, zero implies no
919         *                    minimum size limit.
920         * @param maxSizeBits The maximum key size in bits, zero implies no
921         *                    maximum size limit.
922         * @param sizesBits   The key sizes in bits, {@code null} if not
923         *                    specified.
924         * @param curves      The curves to match (for EC and OKP keys),
925         *                    {@code null} if not specified.
926         * @param x5tS256s    The X.509 certificate thumbprints to match,
927         *                    {@code null} if not specified.
928         */
929        public JWKMatcher(final Set<KeyType> types,
930                                          final Set<KeyUse> uses,
931                                          final Set<KeyOperation> ops,
932                                          final Set<Algorithm> algs,
933                                          final Set<String> ids,
934                                          final boolean hasUse,
935                                          final boolean hasID,
936                                          final boolean privateOnly,
937                                          final boolean publicOnly,
938                                          final int minSizeBits,
939                                          final int maxSizeBits,
940                                          final Set<Integer> sizesBits,
941                                          final Set<Curve> curves,
942                                          final Set<Base64URL> x5tS256s) {
943
944                this.types = types;
945                this.uses = uses;
946                this.ops = ops;
947                this.algs = algs;
948                this.ids = ids;
949                this.hasUse = hasUse;
950                this.hasID = hasID;
951                this.privateOnly = privateOnly;
952                this.publicOnly = publicOnly;
953                this.minSizeBits = minSizeBits;
954                this.maxSizeBits = maxSizeBits;
955                this.sizesBits = sizesBits;
956                this.curves = curves;
957                this.x5tS256s = x5tS256s;
958        }
959        
960
961        /**
962         * Returns the key types to match.
963         *
964         * @return The key types, {@code null} if not specified.
965         */
966        public Set<KeyType> getKeyTypes() {
967
968                return types;
969        }
970
971
972        /**
973         * Returns the public key uses to match.
974         *
975         * @return The public key uses, {@code null} if not specified.
976         */
977        public Set<KeyUse> getKeyUses() {
978
979                return uses;
980        }
981
982
983        /**
984         * Returns the key operations to match.
985         *
986         * @return The key operations, {@code null} if not specified.
987         */
988        public Set<KeyOperation> getKeyOperations() {
989
990                return ops;
991        }
992
993
994        /**
995         * Returns the JOSE algorithms to match.
996         *
997         * @return The JOSE algorithms, {@code null} if not specified.
998         */
999        public Set<Algorithm> getAlgorithms() {
1000
1001                return algs;
1002        }
1003
1004
1005        /**
1006         * Returns the key IDs to match.
1007         *
1008         * @return The key IDs, {@code null} if not specified.
1009         */
1010        public Set<String> getKeyIDs() {
1011
1012                return ids;
1013        }
1014        
1015        
1016        /**
1017         * Returns {@code true} if keys with a set use are matched.
1018         *
1019         * @return {@code true} if keys with a set use are matched, else
1020         *         {@code false}.
1021         */
1022        public boolean hasKeyUse() {
1023                
1024                return hasUse;
1025        }
1026        
1027        
1028        /**
1029         * Returns {@code true} if keys with a set use are matched.
1030         *
1031         * @return {@code true} if keys with a set ID are matched, else
1032         *         {@code false}.
1033         */
1034        public boolean hasKeyID() {
1035                
1036                return hasID;
1037        }
1038
1039
1040        /**
1041         * Returns {@code true} if only private keys are matched.
1042         *
1043         * @return {@code true} if only private keys are matched, else 
1044         *         {@code false}.
1045         */
1046        public boolean isPrivateOnly() {
1047
1048                return privateOnly;
1049        }
1050
1051
1052        /**
1053         * Returns {@code true} if only public keys are matched.
1054         *
1055         * @return {@code true} if only public keys are selected, else
1056         *         {@code false}.
1057         */
1058        public boolean isPublicOnly() {
1059
1060                return publicOnly;
1061        }
1062
1063
1064        /**
1065         * Returns the minimum key size. Use {@link #getMinKeySize()} instead.
1066         *
1067         * @return The minimum key size in bits, zero implies no minimum size
1068         *         limit.
1069         */
1070        @Deprecated
1071        public int getMinSize() {
1072
1073                return getMinKeySize();
1074        }
1075
1076
1077        /**
1078         * Returns the minimum key size.
1079         *
1080         * @return The minimum key size in bits, zero implies no minimum size
1081         *         limit.
1082         */
1083        public int getMinKeySize() {
1084
1085                return minSizeBits;
1086        }
1087
1088
1089        /**
1090         * Returns the maximum key size. Use {@link #getMaxKeySize()} instead.
1091         *
1092         * @return The maximum key size in bits, zero implies no maximum size
1093         *         limit.
1094         */
1095        @Deprecated
1096        public int getMaxSize() {
1097
1098                return getMaxKeySize();
1099        }
1100
1101
1102        /**
1103         * Returns the maximum key size.
1104         *
1105         * @return The maximum key size in bits, zero implies no maximum size
1106         *         limit.
1107         */
1108        public int getMaxKeySize() {
1109
1110                return maxSizeBits;
1111        }
1112        
1113        
1114        /**
1115         * Returns the key sizes.
1116         *
1117         * @return The key sizes in bits, {@code null} if not specified.
1118         */
1119        public Set<Integer> getKeySizes() {
1120                
1121                return sizesBits;
1122        }
1123        
1124        
1125        /**
1126         * Returns the curves to match (for EC and OKP keys).
1127         *
1128         * @return The curves, {@code null} if not specified.
1129         */
1130        public Set<Curve> getCurves() {
1131                
1132                return curves;
1133        }
1134
1135        /**
1136         * Returns the X.509 certificate SHA-256 thumbprints to match.
1137         *
1138         * @return The thumbprints, {@code null} if not specified.
1139         */
1140        public Set<Base64URL> getX509CertSHA256Thumbprints() {
1141                
1142                return x5tS256s;
1143        }
1144
1145        /**
1146         * Returns {@code true} if the specified JWK matches.
1147         *
1148         * @param key The JSON Web Key (JWK). Must not  be {@code null}.
1149         *
1150         * @return {@code true} if the JWK matches, else {@code false}.
1151         */
1152        public boolean matches(final JWK key) {
1153                
1154                if (hasUse && key.getKeyUse() == null)
1155                        return false;
1156                
1157                if (hasID && (key.getKeyID() == null || key.getKeyID().trim().isEmpty()))
1158                        return false;
1159
1160                if (privateOnly && ! key.isPrivate())
1161                        return false;
1162
1163                if (publicOnly && key.isPrivate())
1164                        return false;
1165
1166                if (types != null && ! types.contains(key.getKeyType()))
1167                        return false;
1168
1169                if (uses != null && ! uses.contains(key.getKeyUse()))
1170                        return false;
1171
1172                if (ops != null) {
1173
1174                        if (ops.contains(null) && key.getKeyOperations() == null) {
1175                                // pass
1176                        } else if (key.getKeyOperations() != null && ops.containsAll(key.getKeyOperations())) {
1177                                // pass
1178                        } else {
1179                                return false;
1180                        }
1181                }
1182
1183                if (algs != null && ! algs.contains(key.getAlgorithm()))
1184                        return false;
1185
1186                if (ids != null && ! ids.contains(key.getKeyID()))
1187                        return false;
1188
1189                if (minSizeBits > 0) {
1190
1191                        if (key.size() < minSizeBits)
1192                                return false;
1193                }
1194
1195                if (maxSizeBits > 0) {
1196
1197                        if (key.size() > maxSizeBits)
1198                                return false;
1199                }
1200                
1201                if (sizesBits != null) {
1202                        if (! sizesBits.contains(key.size()))
1203                                return false;
1204                }
1205                
1206                if (curves != null) {
1207                        
1208                        if (! (key instanceof CurveBasedJWK))
1209                                return false;
1210                        
1211                        CurveBasedJWK curveBasedJWK = (CurveBasedJWK) key;
1212                        
1213                        if (! curves.contains(curveBasedJWK.getCurve()))
1214                                return false;
1215                }
1216
1217                if (x5tS256s != null) {
1218                        if (! x5tS256s.contains(key.getX509CertSHA256Thumbprint()) )
1219                                return false;
1220                }
1221
1222                return true;
1223        }
1224        
1225        @Override
1226        public String toString() {
1227                StringBuilder sb = new StringBuilder();
1228                
1229                append(sb, "kty", types);
1230                append(sb, "use", uses);
1231                append(sb, "key_ops", ops);
1232                append(sb, "alg", algs);
1233                append(sb, "kid", ids);
1234                
1235                if (hasUse) {
1236                        sb.append("has_use=true ");
1237                }
1238                
1239                if (hasID) {
1240                        sb.append("has_id=true ");
1241                }
1242                
1243                if (privateOnly) {
1244                        sb.append("private_only=true ");
1245                }
1246                
1247                if (publicOnly) {
1248                        sb.append("public_only=true ");
1249                }
1250                
1251                if (minSizeBits > 0) {
1252                        sb.append("min_size=" + minSizeBits + " ");
1253                }
1254                
1255                if (maxSizeBits > 0) {
1256                        sb.append("max_size=" + maxSizeBits + " ");
1257                }
1258                
1259                append(sb, "size", sizesBits);
1260                append(sb, "crv", curves);
1261                append(sb, "x5t#S256", x5tS256s);
1262                        
1263                return sb.toString().trim();
1264        }
1265        
1266        
1267        /**
1268         * Appends the specified JWK matcher parameter to a string builder.
1269         *
1270         * @param sb     The string builder. Must not be {@code null}.
1271         * @param key    The parameter key. Must not be {@code null}.
1272         * @param values The parameter value, {@code null} if not specified.
1273         */
1274        private static void append(final StringBuilder sb, final String key, final Set<?> values) {
1275                
1276                if (values != null) {
1277                        
1278                        sb.append(key);
1279                        sb.append('=');
1280                        if (values.size() == 1) {
1281                                Object value = values.iterator().next();
1282                                if (value == null) {
1283                                        sb.append("ANY");
1284                                } else {
1285                                        sb.append(value.toString().trim());
1286                                }
1287                        } else {
1288                                sb.append(values.toString().trim());
1289                        }
1290                        
1291                        sb.append(' ');
1292                }
1293        }
1294}