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