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}