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