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