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