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