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