001/* 002 * nimbus-jose-jwt 003 * 004 * Copyright 2012-2019, Connect2id Ltd. 005 * 006 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 007 * this file except in compliance with the License. You may obtain a copy of the 008 * License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software distributed 013 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 014 * CONDITIONS OF ANY KIND, either express or implied. See the License for the 015 * specific language governing permissions and limitations under the License. 016 */ 017 018package com.nimbusds.jose.jwk; 019 020 021import java.security.cert.CertificateException; 022import java.security.cert.X509Certificate; 023import java.util.*; 024 025import net.jcip.annotations.Immutable; 026 027import com.nimbusds.jose.Algorithm; 028import com.nimbusds.jose.JWEHeader; 029import com.nimbusds.jose.JWSAlgorithm; 030import com.nimbusds.jose.JWSHeader; 031import com.nimbusds.jose.util.Base64URL; 032import com.nimbusds.jose.util.X509CertUtils; 033 034 035/** 036 * JSON Web Key (JWK) matcher. May be used to ensure a JWK matches a set of 037 * application-specific criteria. 038 * 039 * <p>Supported key matching criteria: 040 * 041 * <ul> 042 * <li>Any, unspecified, one or more key types (typ). 043 * <li>Any, unspecified, one or more key uses (use). 044 * <li>Any, unspecified, one or more key operations (key_ops). 045 * <li>Any, unspecified, one or more key algorithms (alg). 046 * <li>Any, unspecified, one or more key identifiers (kid). 047 * <li>Private key only. 048 * <li>Public key only. 049 * <li>Non-revoked key only. 050 * <li>Revoked key only. 051 * <li>Minimum, maximum or exact key sizes. 052 * <li>Any, unspecified, one or more curves for EC and OKP keys (crv). 053 * <li>X.509 certificate SHA-256 thumbprint. 054 * <li>With X.509 certificate only. 055 * </ul> 056 * 057 * <p>Matching by JWK thumbprint (RFC 7638), X.509 certificate URL and X.509 058 * certificate chain is not supported. 059 * 060 * @author Vladimir Dzhuvinov 061 * @author Josh Cummings 062 * @author Ben Arena 063 * @version 2024-11-01 064 */ 065@Immutable 066public class JWKMatcher { 067 068 069 /** 070 * The key types to match. 071 */ 072 private final Set<KeyType> types; 073 074 075 /** 076 * The public key uses to match. 077 */ 078 private final Set<KeyUse> uses; 079 080 081 /** 082 * The key operations to match. 083 */ 084 private final Set<KeyOperation> ops; 085 086 087 /** 088 * The algorithms to match. 089 */ 090 private final Set<Algorithm> algs; 091 092 093 /** 094 * The key IDs to match. 095 */ 096 private final Set<String> ids; 097 098 099 /** 100 * {@code true} to match a key with a specified use only. 101 */ 102 private final boolean withUseOnly; 103 104 105 /** 106 * {@code true} to match a key with a specified ID only. 107 */ 108 private final boolean withIDOnly; 109 110 111 /** 112 * {@code true} to match a private key only. 113 */ 114 private final boolean privateOnly; 115 116 117 /** 118 * {@code true} to match a public key only. 119 */ 120 private final boolean publicOnly; 121 122 123 /** 124 * {@code true} to match a non-revoked key only. 125 */ 126 private final boolean nonRevokedOnly; 127 128 129 /** 130 * {@code true} to match a revoked key only. 131 */ 132 private final boolean revokedOnly; 133 134 135 /** 136 * The minimum key size in bits, zero implies no minimum size. 137 */ 138 private final int minSizeBits; 139 140 141 /** 142 * The maximum key size in bits, zero implies no maximum size. 143 */ 144 private final int maxSizeBits; 145 146 147 /** 148 * The key sizes in bits. 149 */ 150 private final Set<Integer> sizesBits; 151 152 153 /** 154 * The curves to match (for EC and OKP keys). 155 */ 156 private final Set<Curve> curves; 157 158 159 /** 160 * The X.509 certificate SHA-256 thumbprints to match. 161 */ 162 private final Set<Base64URL> x5tS256s; 163 164 165 /** 166 * {@code true} to match a key with a specified X.509 certificate chain 167 * only. 168 */ 169 private final boolean withX5COnly; 170 171 172 /** 173 * Builder for constructing JWK matchers. 174 * 175 * <p>Example usage: 176 * 177 * <pre> 178 * JWKMatcher matcher = new JWKMatcher().keyID("123").build(); 179 * </pre> 180 */ 181 public static class Builder { 182 183 184 /** 185 * The key types to match. 186 */ 187 private Set<KeyType> types; 188 189 190 /** 191 * The public key uses to match. 192 */ 193 private Set<KeyUse> uses; 194 195 196 /** 197 * The key operations to match. 198 */ 199 private Set<KeyOperation> ops; 200 201 202 /** 203 * The algorithms to match. 204 */ 205 private Set<Algorithm> algs; 206 207 208 /** 209 * The key IDs to match. 210 */ 211 private Set<String> ids; 212 213 214 /** 215 * {@code true} to match a key with specified use only. 216 */ 217 private boolean withUseOnly = false; 218 219 220 /** 221 * {@code true} to match a key with a specified ID only. 222 */ 223 private boolean withIDOnly = false; 224 225 226 /** 227 * {@code true} to match a private key only. 228 */ 229 private boolean privateOnly = false; 230 231 232 /** 233 * {@code true} to match a public key only. 234 */ 235 private boolean publicOnly = false; 236 237 238 /** 239 * {@code true} to match a non-revoked key only. 240 */ 241 private boolean nonRevokedOnly = false; 242 243 244 /** 245 * {@code true} to match a revoked key only. 246 */ 247 private boolean revokedOnly = false; 248 249 250 /** 251 * The minimum key size in bits, zero implies no minimum size 252 * limit. 253 */ 254 private int minSizeBits = 0; 255 256 257 /** 258 * The maximum key size in bits, zero implies no maximum size 259 * limit. 260 */ 261 private int maxSizeBits = 0; 262 263 264 /** 265 * The key sizes in bits. 266 */ 267 private Set<Integer> sizesBits; 268 269 270 /** 271 * The curves to match (for EC and OKP keys). 272 */ 273 private Set<Curve> curves; 274 275 276 /** 277 * The X.509 certificate SHA-256 thumbprints to match. 278 */ 279 private Set<Base64URL> x5tS256s; 280 281 282 /** 283 * {@code true} to match a key with a specified X.509 284 * certificate chain only. 285 */ 286 private boolean withX5COnly = false; 287 288 289 /** 290 * Creates a new builder for constructing JWK matchers. 291 */ 292 public Builder() { 293 } 294 295 296 /** 297 * Creates a new builder for constructing JWK matchers using 298 * the specified matcher. 299 * 300 * @param jwkMatcher The JWK matcher to use. Must not be 301 * {@code null}. 302 */ 303 public Builder(final JWKMatcher jwkMatcher) { 304 types = jwkMatcher.getKeyTypes(); 305 uses = jwkMatcher.getKeyUses(); 306 ops = jwkMatcher.getKeyOperations(); 307 algs = jwkMatcher.getAlgorithms(); 308 ids = jwkMatcher.getKeyIDs(); 309 withUseOnly = jwkMatcher.isWithKeyUseOnly(); 310 withIDOnly = jwkMatcher.isWithKeyIDOnly(); 311 privateOnly = jwkMatcher.isPrivateOnly(); 312 publicOnly = jwkMatcher.isPublicOnly(); 313 nonRevokedOnly = jwkMatcher.isNonRevokedOnly(); 314 revokedOnly = jwkMatcher.isNonRevokedOnly(); 315 minSizeBits = jwkMatcher.getMinKeySize(); 316 maxSizeBits = jwkMatcher.getMaxKeySize(); 317 sizesBits = jwkMatcher.getKeySizes(); 318 curves = jwkMatcher.getCurves(); 319 x5tS256s = jwkMatcher.getX509CertSHA256Thumbprints(); 320 withX5COnly = jwkMatcher.isWithX509CertChainOnly(); 321 } 322 323 324 /** 325 * Sets a single key type to match. 326 * 327 * @param kty The key type, {@code null} if not specified. 328 * 329 * @return This builder. 330 */ 331 public Builder keyType(final KeyType kty) { 332 333 if (kty == null) { 334 types = null; 335 } else { 336 types = new HashSet<>(Collections.singletonList(kty)); 337 } 338 339 return this; 340 } 341 342 343 /** 344 * Sets multiple key types to match. 345 * 346 * @param types The key types. 347 * 348 * @return This builder. 349 */ 350 public Builder keyTypes(final KeyType ... types) { 351 352 keyTypes(new LinkedHashSet<>(Arrays.asList(types))); 353 return this; 354 } 355 356 357 /** 358 * Sets multiple key types to match. 359 * 360 * @param types The key types, {@code null} if not specified. 361 * 362 * @return This builder. 363 */ 364 public Builder keyTypes(final Set<KeyType> types) { 365 366 this.types = types; 367 return this; 368 } 369 370 371 /** 372 * Sets a single public key use to match. 373 * 374 * @param use The public key use, {@code null} if not 375 * specified. 376 * 377 * @return This builder. 378 */ 379 public Builder keyUse(final KeyUse use) { 380 381 if (use == null) { 382 uses = null; 383 } else { 384 uses = new HashSet<>(Collections.singletonList(use)); 385 } 386 return this; 387 } 388 389 390 /** 391 * Sets multiple public key uses to match. 392 * 393 * @param uses The public key uses. 394 * 395 * @return This builder. 396 */ 397 public Builder keyUses(final KeyUse... uses) { 398 399 keyUses(new LinkedHashSet<>(Arrays.asList(uses))); 400 return this; 401 } 402 403 404 /** 405 * Sets multiple public key uses to match. 406 * 407 * @param uses The public key uses, {@code null} if not 408 * specified. 409 * 410 * @return This builder. 411 */ 412 public Builder keyUses(final Set<KeyUse> uses) { 413 414 this.uses = uses; 415 return this; 416 } 417 418 419 /** 420 * Sets a single key operation to match. 421 * 422 * @param op The key operation, {@code null} if not specified. 423 * 424 * @return This builder. 425 */ 426 public Builder keyOperation(final KeyOperation op) { 427 428 if (op == null) { 429 ops = null; 430 } else { 431 ops = new HashSet<>(Collections.singletonList(op)); 432 } 433 return this; 434 } 435 436 437 /** 438 * Sets multiple key operations to match. 439 * 440 * @param ops The key operations. 441 * 442 * @return This builder. 443 */ 444 public Builder keyOperations(final KeyOperation... ops) { 445 446 keyOperations(new LinkedHashSet<>(Arrays.asList(ops))); 447 return this; 448 } 449 450 451 /** 452 * Sets multiple key operations to match. 453 * 454 * @param ops The key operations, {@code null} if not 455 * specified. 456 * 457 * @return This builder. 458 */ 459 public Builder keyOperations(final Set<KeyOperation> ops) { 460 461 this.ops = ops; 462 return this; 463 } 464 465 466 /** 467 * Sets a single JOSE algorithm to match. 468 * 469 * @param alg The JOSE algorithm, {@code null} if not 470 * specified. 471 * 472 * @return This builder. 473 */ 474 public Builder algorithm(final Algorithm alg) { 475 476 if (alg == null) { 477 algs = null; 478 } else { 479 algs = new HashSet<>(Collections.singletonList(alg)); 480 } 481 return this; 482 } 483 484 485 /** 486 * Sets multiple JOSE algorithms to match. 487 * 488 * @param algs The JOSE algorithms. 489 * 490 * @return This builder. 491 */ 492 public Builder algorithms(final Algorithm ... algs) { 493 494 algorithms(new LinkedHashSet<>(Arrays.asList(algs))); 495 return this; 496 } 497 498 499 /** 500 * Sets multiple JOSE algorithms to match. 501 * 502 * @param algs The JOSE algorithms, {@code null} if not 503 * specified. 504 * 505 * @return This builder. 506 */ 507 public Builder algorithms(final Set<Algorithm> algs) { 508 509 this.algs = algs; 510 return this; 511 } 512 513 514 /** 515 * Sets a single key ID to match. 516 * 517 * @param id The key ID, {@code null} if not specified. 518 * 519 * @return This builder. 520 */ 521 public Builder keyID(final String id) { 522 523 if (id == null) { 524 ids = null; 525 } else { 526 ids = new HashSet<>(Collections.singletonList(id)); 527 } 528 return this; 529 } 530 531 532 /** 533 * Sets multiple key IDs to match. 534 * 535 * @param ids The key IDs. 536 * 537 * @return This builder. 538 */ 539 public Builder keyIDs(final String ... ids) { 540 541 keyIDs(new LinkedHashSet<>(Arrays.asList(ids))); 542 return this; 543 } 544 545 546 /** 547 * Sets multiple key IDs to match. 548 * 549 * @param ids The key IDs, {@code null} if not specified. 550 * 551 * @return This builder. 552 */ 553 public Builder keyIDs(final Set<String> ids) { 554 555 this.ids = ids; 556 return this; 557 } 558 559 560 /** 561 * Sets the key use presence matching. 562 * 563 * @param hasUse {@code true} to match a key with a specified 564 * use only. 565 * 566 * @return This builder. 567 */ 568 @Deprecated 569 public Builder hasKeyUse(final boolean hasUse) { 570 571 return withKeyUseOnly(hasUse); 572 } 573 574 575 /** 576 * Sets the key use presence matching. 577 * 578 * @param withUseOnly {@code true} to match a key with a 579 * specified use only. 580 * 581 * @return This builder. 582 */ 583 public Builder withKeyUseOnly(final boolean withUseOnly) { 584 585 this.withUseOnly = withUseOnly; 586 return this; 587 } 588 589 590 /** 591 * Sets the key ID presence matching. 592 * 593 * @param hasID {@code true} to match a key a specified ID 594 * only. 595 * 596 * @return This builder. 597 */ 598 @Deprecated 599 public Builder hasKeyID(final boolean hasID) { 600 601 return withKeyIDOnly(hasID); 602 } 603 604 605 /** 606 * Sets the key ID presence matching. 607 * 608 * @param withIDOnly {@code true} to match a key a specified ID 609 * only. 610 * 611 * @return This builder. 612 */ 613 public Builder withKeyIDOnly(final boolean withIDOnly) { 614 615 this.withIDOnly = withIDOnly; 616 return this; 617 } 618 619 620 /** 621 * Sets the private key matching. 622 * 623 * @param privateOnly {@code true} to match a private key only. 624 * 625 * @return This builder. 626 */ 627 public Builder privateOnly(final boolean privateOnly) { 628 629 this.privateOnly = privateOnly; 630 return this; 631 } 632 633 634 /** 635 * Sets the public key matching. 636 * 637 * @param publicOnly {@code true} to match a public key only. 638 * 639 * @return This builder. 640 */ 641 public Builder publicOnly(final boolean publicOnly) { 642 643 this.publicOnly = publicOnly; 644 return this; 645 } 646 647 648 /** 649 * Sets the non-revoked key matching. 650 * 651 * @param nonRevokedOnly {@code true} to match a non-revoked 652 * key only. 653 * 654 * @return This builder. 655 */ 656 public Builder nonRevokedOnly(final boolean nonRevokedOnly) { 657 658 this.nonRevokedOnly = nonRevokedOnly; 659 return this; 660 } 661 662 663 /** 664 * Sets the revoked key matching. 665 * 666 * @param revokedOnly {@code true} to match a revoked key only. 667 * 668 * @return This builder. 669 */ 670 public Builder revokedOnly(final boolean revokedOnly) { 671 672 this.revokedOnly = revokedOnly; 673 return this; 674 } 675 676 677 /** 678 * Sets the minimal key size. 679 * 680 * @param minSizeBits The minimum key size in bits, zero 681 * implies no minimum key size limit. 682 * 683 * @return This builder. 684 */ 685 public Builder minKeySize(final int minSizeBits) { 686 687 this.minSizeBits = minSizeBits; 688 return this; 689 } 690 691 692 /** 693 * Sets the maximum key size. 694 * 695 * @param maxSizeBits The maximum key size in bits, zero 696 * implies no maximum key size limit. 697 * 698 * @return This builder. 699 */ 700 public Builder maxKeySize(final int maxSizeBits) { 701 702 this.maxSizeBits = maxSizeBits; 703 return this; 704 } 705 706 707 /** 708 * Sets the key size. 709 * 710 * @param keySizeBits The key size in bits, zero if not 711 * specified. 712 * 713 * @return This builder. 714 */ 715 public Builder keySize(final int keySizeBits) { 716 if (keySizeBits <= 0) { 717 sizesBits = null; 718 } else { 719 sizesBits = Collections.singleton(keySizeBits); 720 } 721 return this; 722 } 723 724 725 /** 726 * Sets the key sizes. 727 * 728 * @param keySizesBits The key sizes in bits. 729 * 730 * @return This builder. 731 */ 732 public Builder keySizes(final int... keySizesBits) { 733 Set<Integer> sizesSet = new LinkedHashSet<>(); 734 for (int keySize: keySizesBits) { 735 sizesSet.add(keySize); 736 } 737 keySizes(sizesSet); 738 return this; 739 } 740 741 742 /** 743 * Sets the key sizes. 744 * 745 * @param keySizesBits The key sizes in bits. 746 * 747 * @return This builder. 748 */ 749 public Builder keySizes(final Set<Integer> keySizesBits) { 750 751 this.sizesBits = keySizesBits; 752 return this; 753 } 754 755 756 /** 757 * Sets a single curve to match (for EC and OKP keys). 758 * 759 * @param curve The curve, {@code null} if not specified. 760 * 761 * @return This builder. 762 */ 763 public Builder curve(final Curve curve) { 764 765 if (curve == null) { 766 curves = null; 767 } else { 768 curves = Collections.singleton(curve); 769 } 770 return this; 771 } 772 773 774 /** 775 * Sets multiple curves to match (for EC and OKP keys). 776 * 777 * @param curves The curves. 778 * 779 * @return This builder. 780 */ 781 public Builder curves(final Curve... curves) { 782 783 curves(new LinkedHashSet<>(Arrays.asList(curves))); 784 return this; 785 } 786 787 788 /** 789 * Sets multiple curves to match (for EC and OKP keys). 790 * 791 * @param curves The curves, {@code null} if not specified. 792 * 793 * @return This builder. 794 */ 795 public Builder curves(final Set<Curve> curves) { 796 797 this.curves = curves; 798 return this; 799 } 800 801 802 /** 803 * Sets a single X.509 certificate SHA-256 thumbprint to match. 804 * 805 * @param x5tS256 The thumbprint, {@code null} if not 806 * specified. 807 * 808 * @return This builder. 809 */ 810 public Builder x509CertSHA256Thumbprint(final Base64URL x5tS256) { 811 812 if (x5tS256 == null) { 813 x5tS256s = null; 814 } else { 815 x5tS256s = Collections.singleton(x5tS256); 816 } 817 return this; 818 } 819 820 821 /** 822 * Sets multiple X.509 certificate SHA-256 thumbprints to 823 * match. 824 * 825 * @param x5tS256s The thumbprints. 826 * 827 * @return This builder. 828 */ 829 public Builder x509CertSHA256Thumbprints(final Base64URL... x5tS256s) { 830 return x509CertSHA256Thumbprints(new LinkedHashSet<>(Arrays.asList(x5tS256s))); 831 } 832 833 834 /** 835 * Sets multiple X.509 certificate SHA-256 thumbprints to 836 * match. 837 * 838 * @param x5tS256s The thumbprints, {@code null} if not 839 * specified. 840 * 841 * @return This builder. 842 */ 843 public Builder x509CertSHA256Thumbprints(final Set<Base64URL> x5tS256s) { 844 this.x5tS256s = x5tS256s; 845 return this; 846 } 847 848 849 /** 850 * Sets the X.509 certificate chain presence matching. 851 * 852 * @param hasX5C {@code true} to match a key with a specified 853 * X.509 certificate chain only. 854 * 855 * @return This builder. 856 */ 857 @Deprecated 858 public Builder hasX509CertChain(final boolean hasX5C) { 859 860 return withX509CertChainOnly(hasX5C); 861 } 862 863 864 /** 865 * Sets the X.509 certificate chain presence matching. 866 * 867 * @param withX5CONly {@code true} to match a key with a 868 * specified X.509 certificate chain only. 869 * 870 * @return This builder. 871 */ 872 public Builder withX509CertChainOnly(final boolean withX5CONly) { 873 874 this.withX5COnly = withX5CONly; 875 return this; 876 } 877 878 879 /** 880 * Builds a new JWK matcher. 881 * 882 * @return The JWK matcher. 883 */ 884 public JWKMatcher build() { 885 886 return new JWKMatcher( 887 types, uses, ops, algs, ids, 888 withUseOnly, withIDOnly, 889 privateOnly, publicOnly, 890 nonRevokedOnly, revokedOnly, 891 minSizeBits, maxSizeBits, sizesBits, 892 curves, 893 x5tS256s, withX5COnly); 894 } 895 } 896 897 898 /** 899 * Creates a new JSON Web Key (JWK) matcher. 900 * 901 * @param types The key types to match, {@code null} if not 902 * specified. 903 * @param uses The public key uses to match, {@code null} if not 904 * specified. 905 * @param ops The key operations to match, {@code null} if not 906 * specified. 907 * @param algs The JOSE algorithms to match, {@code null} if not 908 * specified. 909 * @param ids The key IDs to match, {@code null} if not 910 * specified. 911 * @param privateOnly {@code true} to match a private key. 912 * @param publicOnly {@code true} to match a public only key. 913 */ 914 @Deprecated 915 public JWKMatcher(final Set<KeyType> types, 916 final Set<KeyUse> uses, 917 final Set<KeyOperation> ops, 918 final Set<Algorithm> algs, 919 final Set<String> ids, 920 final boolean privateOnly, 921 final boolean publicOnly) { 922 923 this(types, uses, ops, algs, ids, privateOnly, publicOnly, 0, 0); 924 } 925 926 927 /** 928 * Creates a new JSON Web Key (JWK) matcher. 929 * 930 * @param types The key types to match, {@code null} if not 931 * specified. 932 * @param uses The public key uses to match, {@code null} if not 933 * specified. 934 * @param ops The key operations to match, {@code null} if not 935 * specified. 936 * @param algs The JOSE algorithms to match, {@code null} if not 937 * specified. 938 * @param ids The key IDs to match, {@code null} if not 939 * specified. 940 * @param privateOnly {@code true} to match a private key. 941 * @param publicOnly {@code true} to match a public only key. 942 * @param minSizeBits The minimum key size in bits, zero implies no 943 * minimum size limit. 944 * @param maxSizeBits The maximum key size in bits, zero implies no 945 * maximum size limit. 946 */ 947 @Deprecated 948 public JWKMatcher(final Set<KeyType> types, 949 final Set<KeyUse> uses, 950 final Set<KeyOperation> ops, 951 final Set<Algorithm> algs, 952 final Set<String> ids, 953 final boolean privateOnly, 954 final boolean publicOnly, 955 final int minSizeBits, 956 final int maxSizeBits) { 957 958 this(types, uses, ops, algs, ids, privateOnly, publicOnly, minSizeBits, maxSizeBits, null); 959 } 960 961 962 /** 963 * Creates a new JSON Web Key (JWK) matcher. 964 * 965 * @param types The key types to match, {@code null} if not 966 * specified. 967 * @param uses The public key uses to match, {@code null} if not 968 * specified. 969 * @param ops The key operations to match, {@code null} if not 970 * specified. 971 * @param algs The JOSE algorithms to match, {@code null} if not 972 * specified. 973 * @param ids The key IDs to match, {@code null} if not 974 * specified. 975 * @param privateOnly {@code true} to match a private key. 976 * @param publicOnly {@code true} to match a public only key. 977 * @param minSizeBits The minimum key size in bits, zero implies no 978 * minimum size limit. 979 * @param maxSizeBits The maximum key size in bits, zero implies no 980 * maximum size limit. 981 * @param curves The curves to match (for EC keys), {@code null} 982 * if not specified. 983 */ 984 @Deprecated 985 public JWKMatcher(final Set<KeyType> types, 986 final Set<KeyUse> uses, 987 final Set<KeyOperation> ops, 988 final Set<Algorithm> algs, 989 final Set<String> ids, 990 final boolean privateOnly, 991 final boolean publicOnly, 992 final int minSizeBits, 993 final int maxSizeBits, 994 final Set<Curve> curves) { 995 996 this(types, uses, ops, algs, ids, privateOnly, publicOnly, minSizeBits, maxSizeBits, null, curves); 997 } 998 999 1000 /** 1001 * Creates a new JSON Web Key (JWK) matcher. 1002 * 1003 * @param types The key types to match, {@code null} if not 1004 * specified. 1005 * @param uses The public key uses to match, {@code null} if not 1006 * specified. 1007 * @param ops The key operations to match, {@code null} if not 1008 * specified. 1009 * @param algs The JOSE algorithms to match, {@code null} if not 1010 * specified. 1011 * @param ids The key IDs to match, {@code null} if not 1012 * specified. 1013 * @param privateOnly {@code true} to match a private key. 1014 * @param publicOnly {@code true} to match a public only key. 1015 * @param minSizeBits The minimum key size in bits, zero implies no 1016 * minimum size limit. 1017 * @param maxSizeBits The maximum key size in bits, zero implies no 1018 * maximum size limit. 1019 * @param sizesBits The key sizes in bits, {@code null} if not 1020 * specified. 1021 * @param curves The curves to match (for EC and OKP keys), 1022 * {@code null} if not specified. 1023 */ 1024 @Deprecated 1025 public JWKMatcher(final Set<KeyType> types, 1026 final Set<KeyUse> uses, 1027 final Set<KeyOperation> ops, 1028 final Set<Algorithm> algs, 1029 final Set<String> ids, 1030 final boolean privateOnly, 1031 final boolean publicOnly, 1032 final int minSizeBits, 1033 final int maxSizeBits, 1034 final Set<Integer> sizesBits, 1035 final Set<Curve> curves) { 1036 1037 this(types, uses, ops, algs, ids, false, false, privateOnly, publicOnly, minSizeBits, maxSizeBits, sizesBits, curves); 1038 } 1039 1040 1041 /** 1042 * Creates a new JSON Web Key (JWK) matcher. 1043 * 1044 * @param types The key types to match, {@code null} if not 1045 * specified. 1046 * @param uses The public key uses to match, {@code null} if not 1047 * specified. 1048 * @param ops The key operations to match, {@code null} if not 1049 * specified. 1050 * @param algs The JOSE algorithms to match, {@code null} if not 1051 * specified. 1052 * @param ids The key IDs to match, {@code null} if not 1053 * specified. 1054 * @param withUseOnly {@code true} to match a key with a set use. 1055 * @param withIDOnly {@code true} to match a key with a set ID. 1056 * @param privateOnly {@code true} to match a private key. 1057 * @param publicOnly {@code true} to match a public only key. 1058 * @param minSizeBits The minimum key size in bits, zero implies no 1059 * minimum size limit. 1060 * @param maxSizeBits The maximum key size in bits, zero implies no 1061 * maximum size limit. 1062 * @param sizesBits The key sizes in bits, {@code null} if not 1063 * specified. 1064 * @param curves The curves to match (for EC and OKP keys), 1065 * {@code null} if not specified. 1066 */ 1067 @Deprecated 1068 public JWKMatcher(final Set<KeyType> types, 1069 final Set<KeyUse> uses, 1070 final Set<KeyOperation> ops, 1071 final Set<Algorithm> algs, 1072 final Set<String> ids, 1073 final boolean withUseOnly, 1074 final boolean withIDOnly, 1075 final boolean privateOnly, 1076 final boolean publicOnly, 1077 final int minSizeBits, 1078 final int maxSizeBits, 1079 final Set<Integer> sizesBits, 1080 final Set<Curve> curves) { 1081 1082 this(types, uses, ops, algs, ids, withUseOnly, withIDOnly, privateOnly, publicOnly, minSizeBits, maxSizeBits, sizesBits, curves, null); 1083 } 1084 1085 1086 /** 1087 * Creates a new JSON Web Key (JWK) matcher. 1088 * 1089 * @param types The key types to match, {@code null} if not 1090 * specified. 1091 * @param uses The public key uses to match, {@code null} if not 1092 * specified. 1093 * @param ops The key operations to match, {@code null} if not 1094 * specified. 1095 * @param algs The JOSE algorithms to match, {@code null} if not 1096 * specified. 1097 * @param ids The key IDs to match, {@code null} if not 1098 * specified. 1099 * @param withUseOnly {@code true} to match a key with a set use. 1100 * @param withIDOnly {@code true} to match a key with a set ID. 1101 * @param privateOnly {@code true} to match a private key. 1102 * @param publicOnly {@code true} to match a public only key. 1103 * @param minSizeBits The minimum key size in bits, zero implies no 1104 * minimum size limit. 1105 * @param maxSizeBits The maximum key size in bits, zero implies no 1106 * maximum size limit. 1107 * @param sizesBits The key sizes in bits, {@code null} if not 1108 * specified. 1109 * @param curves The curves to match (for EC and OKP keys), 1110 * {@code null} if not specified. 1111 * @param x5tS256s The X.509 certificate thumbprints to match, 1112 * {@code null} if not specified. 1113 */ 1114 @Deprecated 1115 public JWKMatcher(final Set<KeyType> types, 1116 final Set<KeyUse> uses, 1117 final Set<KeyOperation> ops, 1118 final Set<Algorithm> algs, 1119 final Set<String> ids, 1120 final boolean withUseOnly, 1121 final boolean withIDOnly, 1122 final boolean privateOnly, 1123 final boolean publicOnly, 1124 final int minSizeBits, 1125 final int maxSizeBits, 1126 final Set<Integer> sizesBits, 1127 final Set<Curve> curves, 1128 final Set<Base64URL> x5tS256s) { 1129 1130 this(types, uses, ops, algs, ids, withUseOnly, withIDOnly, privateOnly, publicOnly, minSizeBits, maxSizeBits, sizesBits, curves, x5tS256s, false); 1131 } 1132 1133 1134 /** 1135 * Creates a new JSON Web Key (JWK) matcher. 1136 * 1137 * @param types The key types to match, {@code null} if not 1138 * specified. 1139 * @param uses The public key uses to match, {@code null} if not 1140 * specified. 1141 * @param ops The key operations to match, {@code null} if not 1142 * specified. 1143 * @param algs The JOSE algorithms to match, {@code null} if not 1144 * specified. 1145 * @param ids The key IDs to match, {@code null} if not 1146 * specified. 1147 * @param withUseOnly {@code true} to match a key with a set use. 1148 * @param withIDOnly {@code true} to match a key with a set ID. 1149 * @param privateOnly {@code true} to match a private key. 1150 * @param publicOnly {@code true} to match a public only key. 1151 * @param minSizeBits The minimum key size in bits, zero implies no 1152 * minimum size limit. 1153 * @param maxSizeBits The maximum key size in bits, zero implies no 1154 * maximum size limit. 1155 * @param sizesBits The key sizes in bits, {@code null} if not 1156 * specified. 1157 * @param curves The curves to match (for EC and OKP keys), 1158 * {@code null} if not specified. 1159 * @param x5tS256s The X.509 certificate thumbprints to match, 1160 * {@code null} if not specified. 1161 * @param withX5COnly {@code true} to match a key with a set X.509 1162 * certificate chain. 1163 */ 1164 @Deprecated 1165 public JWKMatcher(final Set<KeyType> types, 1166 final Set<KeyUse> uses, 1167 final Set<KeyOperation> ops, 1168 final Set<Algorithm> algs, 1169 final Set<String> ids, 1170 final boolean withUseOnly, 1171 final boolean withIDOnly, 1172 final boolean privateOnly, 1173 final boolean publicOnly, 1174 final int minSizeBits, 1175 final int maxSizeBits, 1176 final Set<Integer> sizesBits, 1177 final Set<Curve> curves, 1178 final Set<Base64URL> x5tS256s, 1179 final boolean withX5COnly) { 1180 1181 this(types, uses, ops, algs, ids, withUseOnly, withIDOnly, privateOnly, publicOnly, false, false, minSizeBits, maxSizeBits, sizesBits, curves, x5tS256s, withX5COnly); 1182 } 1183 1184 1185 /** 1186 * Creates a new JSON Web Key (JWK) matcher. 1187 * 1188 * @param types The key types to match, {@code null} if not 1189 * specified. 1190 * @param uses The public key uses to match, {@code null} if 1191 * not specified. 1192 * @param ops The key operations to match, {@code null} if 1193 * not specified. 1194 * @param algs The JOSE algorithms to match, {@code null} if 1195 * not specified. 1196 * @param ids The key IDs to match, {@code null} if not 1197 * specified. 1198 * @param withUseOnly {@code true} to match a key with a set use. 1199 * @param withIDOnly {@code true} to match a key with a set ID. 1200 * @param privateOnly {@code true} to match a private key only. 1201 * @param publicOnly {@code true} to match a public key only. 1202 * @param nonRevokedOnly {@code true} to match a non-revoked key only. 1203 * @param revokedOnly {@code true} to match a revoked key only. 1204 * @param minSizeBits The minimum key size in bits, zero implies no 1205 * minimum size. 1206 * @param maxSizeBits The maximum key size in bits, zero implies no 1207 * maximum size. 1208 * @param sizesBits The key sizes in bits, {@code null} if not 1209 * specified. 1210 * @param curves The curves to match (for EC and OKP keys), 1211 * {@code null} if not specified. 1212 * @param x5tS256s The X.509 certificate thumbprints to match, 1213 * {@code null} if not specified. 1214 * @param withX5COnly {@code true} to match a key with a set X.509 1215 * certificate chain. 1216 */ 1217 public JWKMatcher(final Set<KeyType> types, 1218 final Set<KeyUse> uses, 1219 final Set<KeyOperation> ops, 1220 final Set<Algorithm> algs, 1221 final Set<String> ids, 1222 final boolean withUseOnly, 1223 final boolean withIDOnly, 1224 final boolean privateOnly, 1225 final boolean publicOnly, 1226 final boolean nonRevokedOnly, 1227 final boolean revokedOnly, 1228 final int minSizeBits, 1229 final int maxSizeBits, 1230 final Set<Integer> sizesBits, 1231 final Set<Curve> curves, 1232 final Set<Base64URL> x5tS256s, 1233 final boolean withX5COnly) { 1234 1235 this.types = types; 1236 this.uses = uses; 1237 this.ops = ops; 1238 this.algs = algs; 1239 this.ids = ids; 1240 this.withUseOnly = withUseOnly; 1241 this.withIDOnly = withIDOnly; 1242 this.privateOnly = privateOnly; 1243 this.publicOnly = publicOnly; 1244 this.nonRevokedOnly = nonRevokedOnly; 1245 this.revokedOnly = revokedOnly; 1246 this.minSizeBits = minSizeBits; 1247 this.maxSizeBits = maxSizeBits; 1248 this.sizesBits = sizesBits; 1249 this.curves = curves; 1250 this.x5tS256s = x5tS256s; 1251 this.withX5COnly = withX5COnly; 1252 } 1253 1254 1255 /** 1256 * Returns a {@link JWKMatcher} based on the given {@link JWEHeader}. 1257 * 1258 * <p>The {@link JWKMatcher} is configured as follows: 1259 * 1260 * <ul> 1261 * <li>The key type to match is determined by the JWE algorithm 1262 * (alg). 1263 * <li>The key ID to match is set by the JWE header key ID (kid) 1264 * parameter (if set). 1265 * <li>The key uses to match are set to encryption or not 1266 * specified. 1267 * <li>The key algorithm to match is set to the JWE algorithm (alg) 1268 * or not specified. 1269 * </ul> 1270 * 1271 * <p>Other JWE header parameters are not taken into account. 1272 * 1273 * @param jweHeader The header to use. 1274 * 1275 * @return A {@code JWKMatcher} based on the given header. 1276 */ 1277 public static JWKMatcher forJWEHeader(final JWEHeader jweHeader) { 1278 1279 return new JWKMatcher.Builder() 1280 .keyType(KeyType.forAlgorithm(jweHeader.getAlgorithm())) 1281 .keyID(jweHeader.getKeyID()) 1282 .keyUses(KeyUse.ENCRYPTION, null) 1283 .algorithms(jweHeader.getAlgorithm(), null) 1284 .build(); 1285 } 1286 1287 1288 /** 1289 * Returns a {@link JWKMatcher} based on the given {@link JWSHeader}. 1290 * 1291 * <p>The {@link JWKMatcher} is configured as follows: 1292 * 1293 * <ul> 1294 * <li>The key type to match is determined by the JWS algorithm 1295 * (alg). 1296 * <li>The key ID to match is set by the JWS header key ID (kid) 1297 * parameter (if set). 1298 * <li>The key uses to match are set to signature or not specified. 1299 * <li>The key algorithm to match is set to the JWS algorithm (alg) 1300 * or not specified. 1301 * <li>The X.509 certificate SHA-256 thumbprint to match is set to 1302 * the x5t#S256 parameter (if set). 1303 * </ul> 1304 * 1305 * <p>Other JWS header parameters are not taken into account. 1306 * 1307 * @param jwsHeader The header to use. 1308 * 1309 * @return A {@code JWKMatcher} based on the given header, {@code null} 1310 * if the JWS algorithm is not supported. 1311 */ 1312 public static JWKMatcher forJWSHeader(final JWSHeader jwsHeader) { 1313 1314 JWSAlgorithm algorithm = jwsHeader.getAlgorithm(); 1315 if (JWSAlgorithm.Family.RSA.contains(algorithm) || JWSAlgorithm.Family.EC.contains(algorithm)) { 1316 // RSA or EC key matcher 1317 return new JWKMatcher.Builder() 1318 .keyType(KeyType.forAlgorithm(algorithm)) 1319 .keyID(jwsHeader.getKeyID()) 1320 .keyUses(KeyUse.SIGNATURE, null) 1321 .algorithms(algorithm, null) 1322 .x509CertSHA256Thumbprint(jwsHeader.getX509CertSHA256Thumbprint()) 1323 .build(); 1324 } else if (JWSAlgorithm.Family.HMAC_SHA.contains(algorithm)) { 1325 // HMAC secret matcher 1326 return new JWKMatcher.Builder() 1327 .keyType(KeyType.forAlgorithm(algorithm)) 1328 .keyID(jwsHeader.getKeyID()) 1329 .privateOnly(true) 1330 .algorithms(algorithm, null) 1331 .build(); 1332 } else if (JWSAlgorithm.Family.ED.contains(algorithm)) { 1333 return new JWKMatcher.Builder() 1334 .keyType(KeyType.forAlgorithm(algorithm)) 1335 .keyID(jwsHeader.getKeyID()) 1336 .keyUses(KeyUse.SIGNATURE, null) 1337 .algorithms(algorithm, null) 1338 .curves(Curve.forJWSAlgorithm(algorithm)) 1339 .build(); 1340 } else { 1341 return null; // Unsupported algorithm 1342 } 1343 } 1344 1345 1346 /** 1347 * Returns the key types to match. 1348 * 1349 * @return The key types, {@code null} if not specified. 1350 */ 1351 public Set<KeyType> getKeyTypes() { 1352 1353 return types; 1354 } 1355 1356 1357 /** 1358 * Returns the public key uses to match. 1359 * 1360 * @return The public key uses, {@code null} if not specified. 1361 */ 1362 public Set<KeyUse> getKeyUses() { 1363 1364 return uses; 1365 } 1366 1367 1368 /** 1369 * Returns the key operations to match. 1370 * 1371 * @return The key operations, {@code null} if not specified. 1372 */ 1373 public Set<KeyOperation> getKeyOperations() { 1374 1375 return ops; 1376 } 1377 1378 1379 /** 1380 * Returns the JOSE algorithms to match. 1381 * 1382 * @return The JOSE algorithms, {@code null} if not specified. 1383 */ 1384 public Set<Algorithm> getAlgorithms() { 1385 1386 return algs; 1387 } 1388 1389 1390 /** 1391 * Returns the key IDs to match. 1392 * 1393 * @return The key IDs, {@code null} if not specified. 1394 */ 1395 public Set<String> getKeyIDs() { 1396 1397 return ids; 1398 } 1399 1400 1401 /** 1402 * Returns {@code true} if keys with a specified use are matched. 1403 * 1404 * @return {@code true} if keys with a specified use are matched, else 1405 * {@code false}. 1406 */ 1407 @Deprecated 1408 public boolean hasKeyUse() { 1409 1410 return isWithKeyUseOnly(); 1411 } 1412 1413 1414 /** 1415 * Returns {@code true} if keys with a specified use are matched. 1416 * 1417 * @return {@code true} if keys with a specified use are matched, else 1418 * {@code false}. 1419 */ 1420 public boolean isWithKeyUseOnly() { 1421 1422 return withUseOnly; 1423 } 1424 1425 1426 /** 1427 * Returns {@code true} if keys with a specified ID are matched. 1428 * 1429 * @return {@code true} if keys with a specified ID are matched, else 1430 * {@code false}. 1431 */ 1432 @Deprecated 1433 public boolean hasKeyID() { 1434 1435 return isWithKeyIDOnly(); 1436 } 1437 1438 1439 /** 1440 * Returns {@code true} if keys with a specified ID are matched. 1441 * 1442 * @return {@code true} if keys with a specified ID are matched, else 1443 * {@code false}. 1444 */ 1445 public boolean isWithKeyIDOnly() { 1446 1447 return withIDOnly; 1448 } 1449 1450 1451 /** 1452 * Returns {@code true} if only private keys are matched. 1453 * 1454 * @return {@code true} if only private keys are matched, else 1455 * {@code false}. 1456 */ 1457 public boolean isPrivateOnly() { 1458 1459 return privateOnly; 1460 } 1461 1462 1463 /** 1464 * Returns {@code true} if only public keys are matched. 1465 * 1466 * @return {@code true} if only public keys are matched, else 1467 * {@code false}. 1468 */ 1469 public boolean isPublicOnly() { 1470 1471 return publicOnly; 1472 } 1473 1474 1475 /** 1476 * Returns {@code true} if only non-revoked keys are matched. 1477 * 1478 * @return {@code true} if only non-revoked keys are matched, else 1479 * {@code false}. 1480 */ 1481 public boolean isNonRevokedOnly() { 1482 1483 return nonRevokedOnly; 1484 } 1485 1486 1487 /** 1488 * Returns {@code true} if only revoked keys are matched. 1489 * 1490 * @return {@code true} if only revoked keys are matched, else 1491 * {@code false}. 1492 */ 1493 public boolean isRevokedOnly() { 1494 1495 return revokedOnly; 1496 } 1497 1498 1499 /** 1500 * Returns the minimum key size. Use {@link #getMinKeySize()} instead. 1501 * 1502 * @return The minimum key size in bits, zero implies no minimum size 1503 * limit. 1504 */ 1505 @Deprecated 1506 public int getMinSize() { 1507 1508 return getMinKeySize(); 1509 } 1510 1511 1512 /** 1513 * Returns the minimum key size. 1514 * 1515 * @return The minimum key size in bits, zero implies no minimum size 1516 * limit. 1517 */ 1518 public int getMinKeySize() { 1519 1520 return minSizeBits; 1521 } 1522 1523 1524 /** 1525 * Returns the maximum key size. Use {@link #getMaxKeySize()} instead. 1526 * 1527 * @return The maximum key size in bits, zero implies no maximum size 1528 * limit. 1529 */ 1530 @Deprecated 1531 public int getMaxSize() { 1532 1533 return getMaxKeySize(); 1534 } 1535 1536 1537 /** 1538 * Returns the maximum key size. 1539 * 1540 * @return The maximum key size in bits, zero implies no maximum size 1541 * limit. 1542 */ 1543 public int getMaxKeySize() { 1544 1545 return maxSizeBits; 1546 } 1547 1548 1549 /** 1550 * Returns the key sizes. 1551 * 1552 * @return The key sizes in bits, {@code null} if not specified. 1553 */ 1554 public Set<Integer> getKeySizes() { 1555 1556 return sizesBits; 1557 } 1558 1559 1560 /** 1561 * Returns the curves to match (for EC and OKP keys). 1562 * 1563 * @return The curves, {@code null} if not specified. 1564 */ 1565 public Set<Curve> getCurves() { 1566 1567 return curves; 1568 } 1569 1570 /** 1571 * Returns the X.509 certificate SHA-256 thumbprints to match. 1572 * 1573 * @return The thumbprints, {@code null} if not specified. 1574 */ 1575 public Set<Base64URL> getX509CertSHA256Thumbprints() { 1576 1577 return x5tS256s; 1578 } 1579 1580 1581 /** 1582 * Returns {@code true} if keys with a specified X.509 certificate 1583 * chain are matched. 1584 * 1585 * @return {@code true} if keys with a specified X.509 certificate are 1586 * matched, else {@code false}. 1587 */ 1588 @Deprecated 1589 public boolean hasX509CertChain() { 1590 1591 return isWithX509CertChainOnly(); 1592 } 1593 1594 1595 /** 1596 * Returns {@code true} if keys with a specified X.509 certificate 1597 * chain are matched. 1598 * 1599 * @return {@code true} if keys with a specified X.509 certificate 1600 * chain are matched, else {@code false}. 1601 */ 1602 public boolean isWithX509CertChainOnly() { 1603 1604 return withX5COnly; 1605 } 1606 1607 1608 /** 1609 * Returns {@code true} if the specified JWK matches. 1610 * 1611 * @param key The JSON Web Key (JWK). Must not be {@code null}. 1612 * 1613 * @return {@code true} if the JWK matches, else {@code false}. 1614 */ 1615 public boolean matches(final JWK key) { 1616 1617 if (withUseOnly && key.getKeyUse() == null) 1618 return false; 1619 1620 if (withIDOnly && (key.getKeyID() == null || key.getKeyID().trim().isEmpty())) 1621 return false; 1622 1623 if (privateOnly && ! key.isPrivate()) 1624 return false; 1625 1626 if (publicOnly && key.isPrivate()) 1627 return false; 1628 1629 if (nonRevokedOnly && key.getKeyRevocation() != null) 1630 return false; 1631 1632 if (revokedOnly && key.getKeyRevocation() == null) 1633 return false; 1634 1635 if (types != null && ! types.contains(key.getKeyType())) 1636 return false; 1637 1638 if (uses != null && ! uses.contains(key.getKeyUse())) 1639 return false; 1640 1641 if (ops != null) { 1642 1643 if (ops.contains(null) && key.getKeyOperations() == null) { 1644 // pass 1645 } else if (key.getKeyOperations() != null && ops.containsAll(key.getKeyOperations())) { 1646 // pass 1647 } else { 1648 return false; 1649 } 1650 } 1651 1652 if (algs != null && ! algs.contains(key.getAlgorithm())) 1653 return false; 1654 1655 if (ids != null && ! ids.contains(key.getKeyID())) 1656 return false; 1657 1658 if (minSizeBits > 0) { 1659 1660 if (key.size() < minSizeBits) 1661 return false; 1662 } 1663 1664 if (maxSizeBits > 0) { 1665 1666 if (key.size() > maxSizeBits) 1667 return false; 1668 } 1669 1670 if (sizesBits != null) { 1671 if (! sizesBits.contains(key.size())) 1672 return false; 1673 } 1674 1675 if (curves != null) { 1676 1677 if (! (key instanceof CurveBasedJWK)) 1678 return false; 1679 1680 CurveBasedJWK curveBasedJWK = (CurveBasedJWK) key; 1681 1682 if (! curves.contains(curveBasedJWK.getCurve())) 1683 return false; 1684 } 1685 1686 if (x5tS256s != null) { 1687 1688 boolean matchingCertFound = false; 1689 1690 if (key.getX509CertChain() != null && ! key.getX509CertChain().isEmpty()) { 1691 try { 1692 X509Certificate cert = X509CertUtils.parseWithException(key.getX509CertChain().get(0).decode()); 1693 matchingCertFound = x5tS256s.contains(X509CertUtils.computeSHA256Thumbprint(cert)); 1694 } catch (CertificateException e) { 1695 // Ignore 1696 } 1697 } 1698 1699 boolean matchingX5T256Found = x5tS256s.contains(key.getX509CertSHA256Thumbprint()); 1700 1701 if (! matchingCertFound && ! matchingX5T256Found) { 1702 return false; 1703 } 1704 } 1705 1706 if (withX5COnly) { 1707 return key.getX509CertChain() != null && !key.getX509CertChain().isEmpty(); 1708 } 1709 1710 return true; 1711 } 1712 1713 1714 @Override 1715 public String toString() { 1716 StringBuilder sb = new StringBuilder(); 1717 1718 append(sb, JWKParameterNames.KEY_TYPE, types); 1719 append(sb, JWKParameterNames.PUBLIC_KEY_USE, uses); 1720 append(sb, JWKParameterNames.KEY_OPS, ops); 1721 append(sb, JWKParameterNames.ALGORITHM, algs); 1722 append(sb, JWKParameterNames.KEY_ID, ids); 1723 1724 if (withUseOnly) { 1725 sb.append("with_use_only=true "); 1726 } 1727 1728 if (withIDOnly) { 1729 sb.append("with_id_only=true "); 1730 } 1731 1732 if (privateOnly) { 1733 sb.append("private_only=true "); 1734 } 1735 1736 if (publicOnly) { 1737 sb.append("public_only=true "); 1738 } 1739 1740 if (nonRevokedOnly) { 1741 sb.append("non_revoked_only=true "); 1742 } 1743 1744 if (revokedOnly) { 1745 sb.append("revoked_only=true "); 1746 } 1747 1748 if (minSizeBits > 0) { 1749 sb.append("min_size=" + minSizeBits + " "); 1750 } 1751 1752 if (maxSizeBits > 0) { 1753 sb.append("max_size=" + maxSizeBits + " "); 1754 } 1755 1756 append(sb, "size", sizesBits); 1757 append(sb, JWKParameterNames.ELLIPTIC_CURVE, curves); 1758 append(sb, JWKParameterNames.X_509_CERT_SHA_256_THUMBPRINT, x5tS256s); 1759 if (withX5COnly) { 1760 sb.append("with_x5c_only=true" ); 1761 } 1762 1763 return sb.toString().trim(); 1764 } 1765 1766 1767 /** 1768 * Appends the specified JWK matcher parameter to a string builder. 1769 * 1770 * @param sb The string builder. Must not be {@code null}. 1771 * @param key The parameter key. Must not be {@code null}. 1772 * @param values The parameter value, {@code null} if not specified. 1773 */ 1774 private static void append(final StringBuilder sb, final String key, final Set<?> values) { 1775 1776 if (values != null) { 1777 1778 sb.append(key); 1779 sb.append('='); 1780 if (values.size() == 1) { 1781 Object value = values.iterator().next(); 1782 if (value == null) { 1783 sb.append("ANY"); 1784 } else { 1785 sb.append(value.toString().trim()); 1786 } 1787 } else { 1788 sb.append(values.toString().trim()); 1789 } 1790 1791 sb.append(' '); 1792 } 1793 } 1794}