001/* 002 * nimbus-jose-jwt 003 * 004 * Copyright 2012-2016, Connect2id Ltd. 005 * 006 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 007 * this file except in compliance with the License. You may obtain a copy of the 008 * License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software distributed 013 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 014 * CONDITIONS OF ANY KIND, either express or implied. See the License for the 015 * specific language governing permissions and limitations under the License. 016 */ 017 018package com.nimbusds.jose; 019 020 021import com.nimbusds.jose.jwk.JWK; 022import com.nimbusds.jose.util.Base64; 023import com.nimbusds.jose.util.Base64URL; 024import com.nimbusds.jose.util.JSONObjectUtils; 025import com.nimbusds.jose.util.X509CertChainUtils; 026import net.jcip.annotations.Immutable; 027 028import java.net.URI; 029import java.text.ParseException; 030import java.util.*; 031 032 033/** 034 * JSON Web Encryption (JWE) header. This class is immutable. 035 * 036 * <p>Supports the following {@link #getRegisteredParameterNames registered 037 * header parameters}: 038 * 039 * <ul> 040 * <li>alg 041 * <li>enc 042 * <li>epk 043 * <li>zip 044 * <li>jku 045 * <li>jwk 046 * <li>x5u 047 * <li>x5t 048 * <li>x5t#S256 049 * <li>x5c 050 * <li>kid 051 * <li>typ 052 * <li>cty 053 * <li>crit 054 * <li>apu 055 * <li>apv 056 * <li>p2s 057 * <li>p2c 058 * <li>iv 059 * <li>skid 060 * <li>authTag 061 * </ul> 062 * 063 * <p>The header may also include {@link #getCustomParams custom 064 * parameters}; these will be serialised and parsed along the registered ones. 065 * 066 * <p>Example header: 067 * 068 * <pre> 069 * { 070 * "alg" : "RSA1_5", 071 * "enc" : "A128CBC-HS256" 072 * } 073 * </pre> 074 * 075 * @author Vladimir Dzhuvinov 076 * @version 2024-04-20 077 */ 078@Immutable 079public final class JWEHeader extends CommonSEHeader { 080 081 082 private static final long serialVersionUID = 1L; 083 084 085 /** 086 * The registered parameter names. 087 */ 088 private static final Set<String> REGISTERED_PARAMETER_NAMES; 089 090 091 static { 092 Set<String> p = new HashSet<>(); 093 094 p.add(HeaderParameterNames.ALGORITHM); 095 p.add(HeaderParameterNames.ENCRYPTION_ALGORITHM); 096 p.add(HeaderParameterNames.EPHEMERAL_PUBLIC_KEY); 097 p.add(HeaderParameterNames.COMPRESSION_ALGORITHM); 098 p.add(HeaderParameterNames.JWK_SET_URL); 099 p.add(HeaderParameterNames.JWK); 100 p.add(HeaderParameterNames.X_509_CERT_URL); 101 p.add(HeaderParameterNames.X_509_CERT_SHA_1_THUMBPRINT); 102 p.add(HeaderParameterNames.X_509_CERT_SHA_256_THUMBPRINT); 103 p.add(HeaderParameterNames.X_509_CERT_CHAIN); 104 p.add(HeaderParameterNames.KEY_ID); 105 p.add(HeaderParameterNames.TYPE); 106 p.add(HeaderParameterNames.CONTENT_TYPE); 107 p.add(HeaderParameterNames.CRITICAL); 108 p.add(HeaderParameterNames.AGREEMENT_PARTY_U_INFO); 109 p.add(HeaderParameterNames.AGREEMENT_PARTY_V_INFO); 110 p.add(HeaderParameterNames.PBES2_SALT_INPUT); 111 p.add(HeaderParameterNames.PBES2_COUNT); 112 p.add(HeaderParameterNames.INITIALIZATION_VECTOR); 113 p.add(HeaderParameterNames.AUTHENTICATION_TAG); 114 p.add(HeaderParameterNames.SENDER_KEY_ID); 115 p.add("authTag"); // this is a non-standard header, but we should leave it for backwards compatibility 116 117 REGISTERED_PARAMETER_NAMES = Collections.unmodifiableSet(p); 118 } 119 120 121 /** 122 * Builder for constructing JSON Web Encryption (JWE) headers. 123 * 124 * <p>Example usage: 125 * 126 * <pre> 127 * JWEHeader header = new JWEHeader.Builder(JWEAlgorithm.RSA1_5, EncryptionMethod.A128GCM) 128 * .contentType("text/plain") 129 * .customParam("exp", new Date().getTime()) 130 * .build(); 131 * </pre> 132 */ 133 public static class Builder { 134 135 136 /** 137 * The encryption method. 138 */ 139 private final EncryptionMethod enc; 140 141 142 /** 143 * The JWE algorithm. 144 */ 145 private JWEAlgorithm alg; 146 147 148 /** 149 * The JOSE object type. 150 */ 151 private JOSEObjectType typ; 152 153 154 /** 155 * The content type. 156 */ 157 private String cty; 158 159 160 /** 161 * The critical headers. 162 */ 163 private Set<String> crit; 164 165 166 /** 167 * Public JWK Set URL. 168 */ 169 private URI jku; 170 171 172 /** 173 * Public JWK. 174 */ 175 private JWK jwk; 176 177 178 /** 179 * X.509 certificate URL. 180 */ 181 private URI x5u; 182 183 184 /** 185 * X.509 certificate SHA-1 thumbprint. 186 */ 187 @Deprecated 188 private Base64URL x5t; 189 190 191 /** 192 * X.509 certificate SHA-256 thumbprint. 193 */ 194 private Base64URL x5t256; 195 196 197 /** 198 * The X.509 certificate chain corresponding to the key used to 199 * sign the JWS object. 200 */ 201 private List<Base64> x5c; 202 203 204 /** 205 * Key ID. 206 */ 207 private String kid; 208 209 210 /** 211 * The ephemeral public key. 212 */ 213 private JWK epk; 214 215 216 /** 217 * The compression algorithm. 218 */ 219 private CompressionAlgorithm zip; 220 221 222 /** 223 * The agreement PartyUInfo. 224 */ 225 private Base64URL apu; 226 227 228 /** 229 * The agreement PartyVInfo. 230 */ 231 private Base64URL apv; 232 233 234 /** 235 * The PBES2 salt. 236 */ 237 private Base64URL p2s; 238 239 240 /** 241 * The PBES2 count. 242 */ 243 private int p2c; 244 245 246 /** 247 * The initialisation vector. 248 */ 249 private Base64URL iv; 250 251 252 /** 253 * The authentication authTag. 254 */ 255 private Base64URL tag; 256 257 258 /** 259 * Sender key ID. 260 */ 261 private String skid; 262 263 264 /** 265 * Custom header parameters. 266 */ 267 private Map<String,Object> customParams; 268 269 270 /** 271 * The parsed Base64URL. 272 */ 273 private Base64URL parsedBase64URL; 274 275 276 /** 277 * Creates a new JWE header builder. 278 * 279 * @param alg The JWE algorithm ({@code alg}) parameter. Must 280 * not be "none" or {@code null}. 281 * @param enc The encryption method. Must not be {@code null}. 282 */ 283 public Builder(final JWEAlgorithm alg, final EncryptionMethod enc) { 284 285 if (alg.getName().equals(Algorithm.NONE.getName())) { 286 throw new IllegalArgumentException("The JWE algorithm \"alg\" cannot be \"none\""); 287 } 288 this.alg = alg; 289 290 this.enc = Objects.requireNonNull(enc); 291 } 292 293 294 /** 295 * Creates a new JWE header builder. This builder is intended 296 * for {@link JWEObjectJSON multi-recipient JWE}. 297 * 298 * @param enc The encryption method. Must not be {@code null}. 299 */ 300 public Builder(final EncryptionMethod enc) { 301 302 this.enc = Objects.requireNonNull(enc); 303 } 304 305 306 /** 307 * Creates a new JWE header builder with the parameters from 308 * the specified header. 309 * 310 * @param jweHeader The JWE header to use. Must not be 311 * {@code null}. 312 */ 313 public Builder(final JWEHeader jweHeader) { 314 315 this(jweHeader.getEncryptionMethod()); 316 317 alg = jweHeader.getAlgorithm(); 318 typ = jweHeader.getType(); 319 cty = jweHeader.getContentType(); 320 crit = jweHeader.getCriticalParams(); 321 customParams = jweHeader.getCustomParams(); 322 323 jku = jweHeader.getJWKURL(); 324 jwk = jweHeader.getJWK(); 325 x5u = jweHeader.getX509CertURL(); 326 x5t = jweHeader.getX509CertThumbprint(); 327 x5t256 = jweHeader.getX509CertSHA256Thumbprint(); 328 x5c = jweHeader.getX509CertChain(); 329 kid = jweHeader.getKeyID(); 330 331 epk = jweHeader.getEphemeralPublicKey(); 332 zip = jweHeader.getCompressionAlgorithm(); 333 apu = jweHeader.getAgreementPartyUInfo(); 334 apv = jweHeader.getAgreementPartyVInfo(); 335 p2s = jweHeader.getPBES2Salt(); 336 p2c = jweHeader.getPBES2Count(); 337 iv = jweHeader.getIV(); 338 tag = jweHeader.getAuthTag(); 339 340 skid = jweHeader.getSenderKeyID(); 341 342 customParams = jweHeader.getCustomParams(); 343 } 344 345 346 347 /** 348 * Sets the algorithm ({@code alg}) parameter. 349 * 350 * @param alg The alg parameter, {@code null} if not 351 * specified. 352 * 353 * @return This builder. 354 */ 355 public Builder alg(final JWEAlgorithm alg) { 356 357 this.alg = alg; 358 return this; 359 } 360 361 362 /** 363 * Sets the type ({@code typ}) parameter. 364 * 365 * @param typ The type parameter, {@code null} if not 366 * specified. 367 * 368 * @return This builder. 369 */ 370 public Builder type(final JOSEObjectType typ) { 371 372 this.typ = typ; 373 return this; 374 } 375 376 377 /** 378 * Sets the content type ({@code cty}) parameter. 379 * 380 * @param cty The content type parameter, {@code null} if not 381 * specified. 382 * 383 * @return This builder. 384 */ 385 public Builder contentType(final String cty) { 386 387 this.cty = cty; 388 return this; 389 } 390 391 392 /** 393 * Sets the critical header parameters ({@code crit}) 394 * parameter. 395 * 396 * @param crit The names of the critical header parameters, 397 * empty set or {@code null} if none. 398 * 399 * @return This builder. 400 */ 401 public Builder criticalParams(final Set<String> crit) { 402 403 this.crit = crit; 404 return this; 405 } 406 407 408 /** 409 * Sets the public JSON Web Key (JWK) Set URL ({@code jku}) 410 * parameter. 411 * 412 * @param jku The public JSON Web Key (JWK) Set URL parameter, 413 * {@code null} if not specified. 414 * 415 * @return This builder. 416 */ 417 public Builder jwkURL(final URI jku) { 418 419 this.jku = jku; 420 return this; 421 } 422 423 424 /** 425 * Sets the public JSON Web Key (JWK) ({@code jwk}) parameter. 426 * 427 * @param jwk The public JSON Web Key (JWK) ({@code jwk}) 428 * parameter, {@code null} if not specified. 429 * 430 * @return This builder. 431 */ 432 public Builder jwk(final JWK jwk) { 433 434 if (jwk != null && jwk.isPrivate()) { 435 throw new IllegalArgumentException("The JWK must be public"); 436 } 437 438 this.jwk = jwk; 439 return this; 440 } 441 442 443 /** 444 * Sets the X.509 certificate URL ({@code x5u}) parameter. 445 * 446 * @param x5u The X.509 certificate URL parameter, {@code null} 447 * if not specified. 448 * 449 * @return This builder. 450 */ 451 public Builder x509CertURL(final URI x5u) { 452 453 this.x5u = x5u; 454 return this; 455 } 456 457 458 /** 459 * Sets the X.509 certificate SHA-1 thumbprint ({@code x5t}) 460 * parameter. 461 * 462 * @param x5t The X.509 certificate SHA-1 thumbprint parameter, 463 * {@code null} if not specified. 464 * 465 * @return This builder. 466 */ 467 @Deprecated 468 public Builder x509CertThumbprint(final Base64URL x5t) { 469 470 this.x5t = x5t; 471 return this; 472 } 473 474 475 /** 476 * Sets the X.509 certificate SHA-256 thumbprint 477 * ({@code x5t#s256}) parameter. 478 * 479 * @param x5t256 The X.509 certificate SHA-256 thumbprint 480 * parameter, {@code null} if not specified. 481 * 482 * @return This builder. 483 */ 484 public Builder x509CertSHA256Thumbprint(final Base64URL x5t256) { 485 486 this.x5t256 = x5t256; 487 return this; 488 } 489 490 491 /** 492 * Sets the X.509 certificate chain parameter ({@code x5c}) 493 * corresponding to the key used to sign the JWS object. 494 * 495 * @param x5c The X.509 certificate chain parameter, 496 * {@code null} if not specified. 497 * 498 * @return This builder. 499 */ 500 public Builder x509CertChain(final List<Base64> x5c) { 501 502 this.x5c = x5c; 503 return this; 504 } 505 506 507 /** 508 * Sets the key ID ({@code kid}) parameter. 509 * 510 * @param kid The key ID parameter, {@code null} if not 511 * specified. 512 * 513 * @return This builder. 514 */ 515 public Builder keyID(final String kid) { 516 517 this.kid = kid; 518 return this; 519 } 520 521 522 /** 523 * Sets the Ephemeral Public Key ({@code epk}) parameter. 524 * 525 * @param epk The Ephemeral Public Key parameter, {@code null} 526 * if not specified. 527 * 528 * @return This builder. 529 */ 530 public Builder ephemeralPublicKey(final JWK epk) { 531 532 this.epk = epk; 533 return this; 534 } 535 536 537 /** 538 * Sets the compression algorithm ({@code zip}) parameter. 539 * 540 * @param zip The compression algorithm parameter, {@code null} 541 * if not specified. 542 * 543 * @return This builder. 544 */ 545 public Builder compressionAlgorithm(final CompressionAlgorithm zip) { 546 547 this.zip = zip; 548 return this; 549 } 550 551 552 /** 553 * Sets the agreement PartyUInfo ({@code apu}) parameter. 554 * 555 * @param apu The agreement PartyUInfo parameter, {@code null} 556 * if not specified. 557 * 558 * @return This builder. 559 */ 560 public Builder agreementPartyUInfo(final Base64URL apu) { 561 562 this.apu = apu; 563 return this; 564 } 565 566 567 /** 568 * Sets the agreement PartyVInfo ({@code apv}) parameter. 569 * 570 * @param apv The agreement PartyVInfo parameter, {@code null} 571 * if not specified. 572 * 573 * @return This builder. 574 */ 575 public Builder agreementPartyVInfo(final Base64URL apv) { 576 577 this.apv = apv; 578 return this; 579 } 580 581 582 /** 583 * Sets the PBES2 salt ({@code p2s}) parameter. 584 * 585 * @param p2s The PBES2 salt parameter, {@code null} if not 586 * specified. 587 * 588 * @return This builder. 589 */ 590 public Builder pbes2Salt(final Base64URL p2s) { 591 592 this.p2s = p2s; 593 return this; 594 } 595 596 597 /** 598 * Sets the PBES2 count ({@code p2c}) parameter. 599 * 600 * @param p2c The PBES2 count parameter, zero if not specified. 601 * Must not be negative. 602 * 603 * @return This builder. 604 */ 605 public Builder pbes2Count(final int p2c) { 606 607 if (p2c < 0) 608 throw new IllegalArgumentException("The PBES2 count parameter must not be negative"); 609 610 this.p2c = p2c; 611 return this; 612 } 613 614 615 /** 616 * Sets the initialisation vector ({@code iv}) parameter. 617 * 618 * @param iv The initialisation vector, {@code null} if not 619 * specified. 620 * 621 * @return This builder. 622 */ 623 public Builder iv(final Base64URL iv) { 624 625 this.iv = iv; 626 return this; 627 } 628 629 630 /** 631 * Sets the authentication tag ({@code tag}) parameter. 632 * 633 * @param tag The authentication tag, {@code null} if not 634 * specified. 635 * 636 * @return This builder. 637 */ 638 public Builder authTag(final Base64URL tag) { 639 640 this.tag = tag; 641 return this; 642 } 643 644 645 /** 646 * Sets the sender key ID ({@code skid}) parameter. 647 * 648 * @param skid The sender Key ID parameter, {@code null} if not 649 * specified. 650 * 651 * @return This builder. 652 */ 653 public Builder senderKeyID(final String skid) { 654 655 this.skid = skid; 656 return this; 657 } 658 659 660 /** 661 * Sets a custom (non-registered) parameter. 662 * 663 * @param name The name of the custom parameter. Must not 664 * match a registered parameter name and must not 665 * be {@code null}. 666 * @param value The value of the custom parameter, should map 667 * to a valid JSON entity, {@code null} if not 668 * specified. 669 * 670 * @return This builder. 671 * 672 * @throws IllegalArgumentException If the specified parameter 673 * name matches a registered 674 * parameter name. 675 */ 676 public Builder customParam(final String name, final Object value) { 677 678 if (getRegisteredParameterNames().contains(name)) { 679 throw new IllegalArgumentException("The parameter name \"" + name + "\" matches a registered name"); 680 } 681 682 if (customParams == null) { 683 customParams = new HashMap<>(); 684 } 685 686 customParams.put(name, value); 687 688 return this; 689 } 690 691 692 /** 693 * Sets the custom (non-registered) parameters. The values must 694 * be serialisable to a JSON entity, otherwise will be ignored. 695 * 696 * @param customParameters The custom parameters, empty map or 697 * {@code null} if none. 698 * 699 * @return This builder. 700 */ 701 public Builder customParams(final Map<String, Object> customParameters) { 702 703 this.customParams = customParameters; 704 return this; 705 } 706 707 708 /** 709 * Sets the parsed Base64URL. 710 * 711 * @param base64URL The parsed Base64URL, {@code null} if the 712 * header is created from scratch. 713 * 714 * @return This builder. 715 */ 716 public Builder parsedBase64URL(final Base64URL base64URL) { 717 718 this.parsedBase64URL = base64URL; 719 return this; 720 } 721 722 723 /** 724 * Builds a new JWE header. 725 * 726 * @return The JWE header. 727 */ 728 public JWEHeader build() { 729 730 return new JWEHeader( 731 alg, enc, typ, cty, crit, 732 jku, jwk, x5u, x5t, x5t256, x5c, kid, 733 epk, zip, apu, apv, p2s, p2c, 734 iv, tag, skid, 735 customParams, parsedBase64URL); 736 } 737 } 738 739 740 /** 741 * The encryption method ({@code enc}) parameter. 742 */ 743 private final EncryptionMethod enc; 744 745 746 /** 747 * The ephemeral public key ({@code epk}) parameter. 748 */ 749 private final JWK epk; 750 751 752 /** 753 * The compression algorithm ({@code zip}) parameter. 754 */ 755 private final CompressionAlgorithm zip; 756 757 758 /** 759 * The agreement PartyUInfo ({@code apu}) parameter. 760 */ 761 private final Base64URL apu; 762 763 764 /** 765 * The agreement PartyVInfo ({@code apv}) parameter. 766 */ 767 private final Base64URL apv; 768 769 770 /** 771 * The PBES2 salt ({@code p2s}) parameter. 772 */ 773 private final Base64URL p2s; 774 775 776 /** 777 * The PBES2 count ({@code p2c}) parameter. 778 */ 779 private final int p2c; 780 781 782 /** 783 * The initialisation vector ({@code iv}) parameter. 784 */ 785 private final Base64URL iv; 786 787 788 /** 789 * The authentication tag ({@code tag}) parameter. 790 */ 791 private final Base64URL tag; 792 793 794 /** 795 * The sender key ID ({@code skid}) parameter. 796 */ 797 private final String skid; 798 799 800 /** 801 * Creates a new minimal JSON Web Encryption (JWE) header. 802 * 803 * @param enc The encryption method parameter. Must not be 804 * {@code null}. 805 */ 806 public JWEHeader(final EncryptionMethod enc) { 807 808 this( 809 null, enc, 810 null, null, null, null, null, null, null, null, null, null, 811 null, null, null, null, null, 0, 812 null, null, 813 null, null, null); 814 } 815 816 817 /** 818 * Creates a new minimal JSON Web Encryption (JWE) header. 819 * 820 * <p>Note: Use {@link PlainHeader} to create a header with algorithm 821 * {@link Algorithm#NONE none}. 822 * 823 * @param alg The JWE algorithm parameter. Must not be "none" or 824 * {@code null}. 825 * @param enc The encryption method parameter. Must not be 826 * {@code null}. 827 */ 828 public JWEHeader(final JWEAlgorithm alg, final EncryptionMethod enc) { 829 830 this( 831 alg, enc, 832 null, null, null, null, null, null, null, null, null, null, 833 null, null, null, null, null, 0, 834 null, null, 835 null, null, null); 836 } 837 838 839 /** 840 * Creates a new JSON Web Encryption (JWE) header. 841 * 842 * <p>Note: Use {@link PlainHeader} to create a header with algorithm 843 * {@link Algorithm#NONE none}. 844 * 845 * @param alg The JWE algorithm ({@code alg}) parameter. 846 * {@code null} if not specified. 847 * @param enc The encryption method parameter. Must not be 848 * {@code null}. 849 * @param typ The type ({@code typ}) parameter, 850 * {@code null} if not specified. 851 * @param cty The content type ({@code cty}) parameter, 852 * {@code null} if not specified. 853 * @param crit The names of the critical header 854 * ({@code crit}) parameters, empty set or 855 * {@code null} if none. 856 * @param jku The JSON Web Key (JWK) Set URL ({@code jku}) 857 * parameter, {@code null} if not specified. 858 * @param jwk The X.509 certificate URL ({@code jwk}) 859 * parameter, {@code null} if not specified. 860 * @param x5u The X.509 certificate URL parameter 861 * ({@code x5u}), {@code null} if not specified. 862 * @param x5t The X.509 certificate SHA-1 thumbprint 863 * ({@code x5t}) parameter, {@code null} if not 864 * specified. 865 * @param x5t256 The X.509 certificate SHA-256 thumbprint 866 * ({@code x5t#S256}) parameter, {@code null} if 867 * not specified. 868 * @param x5c The X.509 certificate chain ({@code x5c}) 869 * parameter, {@code null} if not specified. 870 * @param kid The key ID ({@code kid}) parameter, 871 * {@code null} if not specified. 872 * @param epk The Ephemeral Public Key ({@code epk}) 873 * parameter, {@code null} if not specified. 874 * @param zip The compression algorithm ({@code zip}) 875 * parameter, {@code null} if not specified. 876 * @param apu The agreement PartyUInfo ({@code apu}) 877 * parameter, {@code null} if not specified. 878 * @param apv The agreement PartyVInfo ({@code apv}) 879 * parameter, {@code null} if not specified. 880 * @param p2s The PBES2 salt ({@code p2s}) parameter, 881 * {@code null} if not specified. 882 * @param p2c The PBES2 count ({@code p2c}) parameter, zero 883 * if not specified. Must not be negative. 884 * @param iv The initialisation vector ({@code iv}) 885 * parameter, {@code null} if not specified. 886 * @param tag The authentication tag ({@code tag}) 887 * parameter, {@code null} if not specified. 888 * @param skid The sender key ID ({@code skid}) parameter, 889 * {@code null} if not specified. 890 * @param customParams The custom parameters, empty map or 891 * {@code null} if none. 892 * @param parsedBase64URL The parsed Base64URL, {@code null} if the 893 * header is created from scratch. 894 */ 895 public JWEHeader(final Algorithm alg, 896 final EncryptionMethod enc, 897 final JOSEObjectType typ, 898 final String cty, 899 final Set<String> crit, 900 final URI jku, 901 final JWK jwk, 902 final URI x5u, 903 final Base64URL x5t, 904 final Base64URL x5t256, 905 final List<Base64> x5c, 906 final String kid, 907 final JWK epk, 908 final CompressionAlgorithm zip, 909 final Base64URL apu, 910 final Base64URL apv, 911 final Base64URL p2s, 912 final int p2c, 913 final Base64URL iv, 914 final Base64URL tag, 915 final String skid, 916 final Map<String,Object> customParams, 917 final Base64URL parsedBase64URL) { 918 919 super(alg, typ, cty, crit, jku, jwk, x5u, x5t, x5t256, x5c, kid, customParams, parsedBase64URL); 920 921 if (alg != null && alg.getName().equals(Algorithm.NONE.getName())) { 922 throw new IllegalArgumentException("The JWE algorithm cannot be \"none\""); 923 } 924 925 if (epk != null && epk.isPrivate()) { 926 throw new IllegalArgumentException("Ephemeral public key should not be a private key"); 927 } 928 929 this.enc = Objects.requireNonNull(enc); 930 931 this.epk = epk; 932 this.zip = zip; 933 this.apu = apu; 934 this.apv = apv; 935 this.p2s = p2s; 936 this.p2c = p2c; 937 this.iv = iv; 938 this.tag = tag; 939 this.skid = skid; 940 } 941 942 943 /** 944 * Deep copy constructor. 945 * 946 * @param jweHeader The JWE header to copy. Must not be {@code null}. 947 */ 948 public JWEHeader(final JWEHeader jweHeader) { 949 950 this( 951 jweHeader.getAlgorithm(), 952 jweHeader.getEncryptionMethod(), 953 jweHeader.getType(), 954 jweHeader.getContentType(), 955 jweHeader.getCriticalParams(), 956 jweHeader.getJWKURL(), 957 jweHeader.getJWK(), 958 jweHeader.getX509CertURL(), 959 jweHeader.getX509CertThumbprint(), 960 jweHeader.getX509CertSHA256Thumbprint(), 961 jweHeader.getX509CertChain(), 962 jweHeader.getKeyID(), 963 jweHeader.getEphemeralPublicKey(), 964 jweHeader.getCompressionAlgorithm(), 965 jweHeader.getAgreementPartyUInfo(), 966 jweHeader.getAgreementPartyVInfo(), 967 jweHeader.getPBES2Salt(), 968 jweHeader.getPBES2Count(), 969 jweHeader.getIV(), 970 jweHeader.getAuthTag(), 971 jweHeader.getSenderKeyID(), 972 jweHeader.getCustomParams(), 973 jweHeader.getParsedBase64URL() 974 ); 975 } 976 977 978 /** 979 * Gets the registered parameter names for JWE headers. 980 * 981 * @return The registered parameter names, as an unmodifiable set. 982 */ 983 public static Set<String> getRegisteredParameterNames() { 984 985 return REGISTERED_PARAMETER_NAMES; 986 } 987 988 989 /** 990 * Gets the algorithm ({@code alg}) parameter. 991 * 992 * @return The algorithm parameter. 993 */ 994 @Override 995 public JWEAlgorithm getAlgorithm() { 996 997 return (JWEAlgorithm)super.getAlgorithm(); 998 } 999 1000 1001 /** 1002 * Gets the encryption method ({@code enc}) parameter. 1003 * 1004 * @return The encryption method parameter. 1005 */ 1006 public EncryptionMethod getEncryptionMethod() { 1007 1008 return enc; 1009 } 1010 1011 1012 /** 1013 * Gets the Ephemeral Public Key ({@code epk}) parameter. 1014 * 1015 * @return The Ephemeral Public Key parameter, {@code null} if not 1016 * specified. 1017 */ 1018 public JWK getEphemeralPublicKey() { 1019 1020 return epk; 1021 } 1022 1023 1024 /** 1025 * Gets the compression algorithm ({@code zip}) parameter. 1026 * 1027 * @return The compression algorithm parameter, {@code null} if not 1028 * specified. 1029 */ 1030 public CompressionAlgorithm getCompressionAlgorithm() { 1031 1032 return zip; 1033 } 1034 1035 1036 /** 1037 * Gets the agreement PartyUInfo ({@code apu}) parameter. 1038 * 1039 * @return The agreement PartyUInfo parameter, {@code null} if not 1040 * specified. 1041 */ 1042 public Base64URL getAgreementPartyUInfo() { 1043 1044 return apu; 1045 } 1046 1047 1048 /** 1049 * Gets the agreement PartyVInfo ({@code apv}) parameter. 1050 * 1051 * @return The agreement PartyVInfo parameter, {@code null} if not 1052 * specified. 1053 */ 1054 public Base64URL getAgreementPartyVInfo() { 1055 1056 return apv; 1057 } 1058 1059 1060 /** 1061 * Gets the PBES2 salt ({@code p2s}) parameter. 1062 * 1063 * @return The PBES2 salt parameter, {@code null} if not specified. 1064 */ 1065 public Base64URL getPBES2Salt() { 1066 1067 return p2s; 1068 } 1069 1070 1071 /** 1072 * Gets the PBES2 count ({@code p2c}) parameter. 1073 * 1074 * @return The PBES2 count parameter, zero if not specified. 1075 */ 1076 public int getPBES2Count() { 1077 1078 return p2c; 1079 } 1080 1081 1082 /** 1083 * Gets the initialisation vector ({@code iv}) parameter. 1084 * 1085 * @return The initialisation vector, {@code null} if not specified. 1086 */ 1087 public Base64URL getIV() { 1088 1089 return iv; 1090 } 1091 1092 1093 /** 1094 * Gets the authentication tag ({@code tag}) parameter. 1095 * 1096 * @return The authentication tag, {@code null} if not specified. 1097 */ 1098 public Base64URL getAuthTag() { 1099 1100 return tag; 1101 } 1102 1103 1104 /** 1105 * Gets the sender key ID ({@code skid}) parameter. 1106 * 1107 * @return The sender key ID, {@code null} if not specified. 1108 */ 1109 public String getSenderKeyID() { 1110 1111 return skid; 1112 } 1113 1114 1115 @Override 1116 public Set<String> getIncludedParams() { 1117 1118 Set<String> includedParameters = super.getIncludedParams(); 1119 1120 if (enc != null) { 1121 includedParameters.add(HeaderParameterNames.ENCRYPTION_ALGORITHM); 1122 } 1123 1124 if (epk != null) { 1125 includedParameters.add(HeaderParameterNames.EPHEMERAL_PUBLIC_KEY); 1126 } 1127 1128 if (zip != null) { 1129 includedParameters.add(HeaderParameterNames.COMPRESSION_ALGORITHM); 1130 } 1131 1132 if (apu != null) { 1133 includedParameters.add(HeaderParameterNames.AGREEMENT_PARTY_U_INFO); 1134 } 1135 1136 if (apv != null) { 1137 includedParameters.add(HeaderParameterNames.AGREEMENT_PARTY_V_INFO); 1138 } 1139 1140 if (p2s != null) { 1141 includedParameters.add(HeaderParameterNames.PBES2_SALT_INPUT); 1142 } 1143 1144 if (p2c > 0) { 1145 includedParameters.add(HeaderParameterNames.PBES2_COUNT); 1146 } 1147 1148 if (iv != null) { 1149 includedParameters.add(HeaderParameterNames.INITIALIZATION_VECTOR); 1150 } 1151 1152 if (tag != null) { 1153 includedParameters.add(HeaderParameterNames.AUTHENTICATION_TAG); 1154 } 1155 1156 if (skid != null) { 1157 includedParameters.add(HeaderParameterNames.SENDER_KEY_ID); 1158 } 1159 1160 return includedParameters; 1161 } 1162 1163 1164 @Override 1165 public Map<String, Object> toJSONObject() { 1166 1167 Map<String, Object> o = super.toJSONObject(); 1168 1169 if (enc != null) { 1170 o.put(HeaderParameterNames.ENCRYPTION_ALGORITHM, enc.toString()); 1171 } 1172 1173 if (epk != null) { 1174 o.put(HeaderParameterNames.EPHEMERAL_PUBLIC_KEY, epk.toJSONObject()); 1175 } 1176 1177 if (zip != null) { 1178 o.put(HeaderParameterNames.COMPRESSION_ALGORITHM, zip.toString()); 1179 } 1180 1181 if (apu != null) { 1182 o.put(HeaderParameterNames.AGREEMENT_PARTY_U_INFO, apu.toString()); 1183 } 1184 1185 if (apv != null) { 1186 o.put(HeaderParameterNames.AGREEMENT_PARTY_V_INFO, apv.toString()); 1187 } 1188 1189 if (p2s != null) { 1190 o.put(HeaderParameterNames.PBES2_SALT_INPUT, p2s.toString()); 1191 } 1192 1193 if (p2c > 0) { 1194 o.put(HeaderParameterNames.PBES2_COUNT, p2c); 1195 } 1196 1197 if (iv != null) { 1198 o.put(HeaderParameterNames.INITIALIZATION_VECTOR, iv.toString()); 1199 } 1200 1201 if (tag != null) { 1202 o.put(HeaderParameterNames.AUTHENTICATION_TAG, tag.toString()); 1203 } 1204 1205 if (skid != null) { 1206 o.put(HeaderParameterNames.SENDER_KEY_ID, skid); 1207 } 1208 1209 return o; 1210 } 1211 1212 1213 /** 1214 * Parses an encryption method ({@code enc}) parameter from the 1215 * specified JWE header JSON object. 1216 * 1217 * @param json The JSON object to parse. Must not be {@code null}. 1218 * 1219 * @return The encryption method. 1220 * 1221 * @throws ParseException If the {@code enc} parameter couldn't be 1222 * parsed. 1223 */ 1224 private static EncryptionMethod parseEncryptionMethod(final Map<String, Object> json) 1225 throws ParseException { 1226 1227 return EncryptionMethod.parse(JSONObjectUtils.getString(json, HeaderParameterNames.ENCRYPTION_ALGORITHM)); 1228 } 1229 1230 1231 /** 1232 * Parses a JWE header from the specified JSON object. 1233 * 1234 * @param jsonObject The JSON object to parse. Must not be 1235 * {@code null}. 1236 * 1237 * @return The JWE header. 1238 * 1239 * @throws ParseException If the specified JSON object doesn't 1240 * represent a valid JWE header. 1241 */ 1242 public static JWEHeader parse(final Map<String, Object> jsonObject) 1243 throws ParseException { 1244 1245 return parse(jsonObject, null); 1246 } 1247 1248 1249 /** 1250 * Parses a JWE header from the specified JSON object. 1251 * 1252 * @param jsonObject The JSON object to parse. Must not be 1253 * {@code null}. 1254 * @param parsedBase64URL The original parsed Base64URL, {@code null} 1255 * if not applicable. 1256 * 1257 * @return The JWE header. 1258 * 1259 * @throws ParseException If the specified JSON object doesn't 1260 * represent a valid JWE header. 1261 */ 1262 public static JWEHeader parse(final Map<String, Object> jsonObject, 1263 final Base64URL parsedBase64URL) 1264 throws ParseException { 1265 1266 // Get the "enc" parameter 1267 EncryptionMethod enc = parseEncryptionMethod(jsonObject); 1268 1269 JWEHeader.Builder header = new Builder(enc).parsedBase64URL(parsedBase64URL); 1270 1271 // Parse optional + custom parameters 1272 for(final String name: jsonObject.keySet()) { 1273 1274 if(HeaderParameterNames.ALGORITHM.equals(name)) { 1275 header = header.alg(JWEAlgorithm.parse(JSONObjectUtils.getString(jsonObject, name))); 1276 } else if(HeaderParameterNames.ENCRYPTION_ALGORITHM.equals(name)) { 1277 // skip 1278 } else if(HeaderParameterNames.TYPE.equals(name)) { 1279 String typValue = JSONObjectUtils.getString(jsonObject, name); 1280 if (typValue != null) { 1281 header = header.type(new JOSEObjectType(typValue)); 1282 } 1283 } else if(HeaderParameterNames.CONTENT_TYPE.equals(name)) { 1284 header = header.contentType(JSONObjectUtils.getString(jsonObject, name)); 1285 } else if(HeaderParameterNames.CRITICAL.equals(name)) { 1286 List<String> critValues = JSONObjectUtils.getStringList(jsonObject, name); 1287 if (critValues != null) { 1288 header = header.criticalParams(new HashSet<>(critValues)); 1289 } 1290 } else if(HeaderParameterNames.JWK_SET_URL.equals(name)) { 1291 header = header.jwkURL(JSONObjectUtils.getURI(jsonObject, name)); 1292 } else if(HeaderParameterNames.JWK.equals(name)) { 1293 header = header.jwk(CommonSEHeader.parsePublicJWK(JSONObjectUtils.getJSONObject(jsonObject, name))); 1294 } else if(HeaderParameterNames.X_509_CERT_URL.equals(name)) { 1295 header = header.x509CertURL(JSONObjectUtils.getURI(jsonObject, name)); 1296 } else if(HeaderParameterNames.X_509_CERT_SHA_1_THUMBPRINT.equals(name)) { 1297 header = header.x509CertThumbprint(Base64URL.from(JSONObjectUtils.getString(jsonObject, name))); 1298 } else if(HeaderParameterNames.X_509_CERT_SHA_256_THUMBPRINT.equals(name)) { 1299 header = header.x509CertSHA256Thumbprint(Base64URL.from(JSONObjectUtils.getString(jsonObject, name))); 1300 } else if(HeaderParameterNames.X_509_CERT_CHAIN.equals(name)) { 1301 header = header.x509CertChain(X509CertChainUtils.toBase64List(JSONObjectUtils.getJSONArray(jsonObject, name))); 1302 } else if(HeaderParameterNames.KEY_ID.equals(name)) { 1303 header = header.keyID(JSONObjectUtils.getString(jsonObject, name)); 1304 } else if(HeaderParameterNames.EPHEMERAL_PUBLIC_KEY.equals(name)) { 1305 header = header.ephemeralPublicKey(JWK.parse(JSONObjectUtils.getJSONObject(jsonObject, name))); 1306 } else if(HeaderParameterNames.COMPRESSION_ALGORITHM.equals(name)) { 1307 String zipValue = JSONObjectUtils.getString(jsonObject, name); 1308 if (zipValue != null) { 1309 header = header.compressionAlgorithm(new CompressionAlgorithm(zipValue)); 1310 } 1311 } else if(HeaderParameterNames.AGREEMENT_PARTY_U_INFO.equals(name)) { 1312 header = header.agreementPartyUInfo(Base64URL.from(JSONObjectUtils.getString(jsonObject, name))); 1313 } else if(HeaderParameterNames.AGREEMENT_PARTY_V_INFO.equals(name)) { 1314 header = header.agreementPartyVInfo(Base64URL.from(JSONObjectUtils.getString(jsonObject, name))); 1315 } else if(HeaderParameterNames.PBES2_SALT_INPUT.equals(name)) { 1316 header = header.pbes2Salt(Base64URL.from(JSONObjectUtils.getString(jsonObject, name))); 1317 } else if(HeaderParameterNames.PBES2_COUNT.equals(name)) { 1318 header = header.pbes2Count(JSONObjectUtils.getInt(jsonObject, name)); 1319 } else if(HeaderParameterNames.INITIALIZATION_VECTOR.equals(name)) { 1320 header = header.iv(Base64URL.from(JSONObjectUtils.getString(jsonObject, name))); 1321 } else if(HeaderParameterNames.AUTHENTICATION_TAG.equals(name)) { 1322 header = header.authTag(Base64URL.from(JSONObjectUtils.getString(jsonObject, name))); 1323 } else if(HeaderParameterNames.SENDER_KEY_ID.equals(name)) { 1324 header = header.senderKeyID(JSONObjectUtils.getString(jsonObject, name)); 1325 } else { 1326 header = header.customParam(name, jsonObject.get(name)); 1327 } 1328 } 1329 1330 return header.build(); 1331 } 1332 1333 1334 /** 1335 * Parses a JWE header from the specified JSON object string. 1336 * 1337 * @param jsonString The JSON object string to parse. Must not be {@code null}. 1338 * 1339 * @return The JWE header. 1340 * 1341 * @throws ParseException If the specified JSON object string doesn't 1342 * represent a valid JWE header. 1343 */ 1344 public static JWEHeader parse(final String jsonString) 1345 throws ParseException { 1346 1347 return parse(JSONObjectUtils.parse(jsonString), null); 1348 } 1349 1350 1351 /** 1352 * Parses a JWE header from the specified JSON object string. 1353 * 1354 * @param jsonString The JSON string to parse. Must not be 1355 * {@code null}. 1356 * @param parsedBase64URL The original parsed Base64URL, {@code null} 1357 * if not applicable. 1358 * 1359 * @return The JWE header. 1360 * 1361 * @throws ParseException If the specified JSON object string doesn't 1362 * represent a valid JWE header. 1363 */ 1364 public static JWEHeader parse(final String jsonString, 1365 final Base64URL parsedBase64URL) 1366 throws ParseException { 1367 1368 return parse(JSONObjectUtils.parse(jsonString, MAX_HEADER_STRING_LENGTH), parsedBase64URL); 1369 } 1370 1371 1372 /** 1373 * Parses a JWE header from the specified Base64URL. 1374 * 1375 * @param base64URL The Base64URL to parse. Must not be {@code null}. 1376 * 1377 * @return The JWE header. 1378 * 1379 * @throws ParseException If the specified Base64URL doesn't represent 1380 * a valid JWE header. 1381 */ 1382 public static JWEHeader parse(final Base64URL base64URL) 1383 throws ParseException { 1384 1385 return parse(base64URL.decodeToString(), base64URL); 1386 } 1387}