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>tag
060 *     <li>skid
061 *     <li>iss
062 *     <li>sub
063 *     <li>aud
064 * </ul>
065 *
066 * <p>The header may also include {@link #getCustomParams custom
067 * parameters}; these will be serialised and parsed along the registered ones.
068 *
069 * <p>Example header:
070 *
071 * <pre>
072 * { 
073 *   "alg" : "RSA1_5",
074 *   "enc" : "A128CBC-HS256"
075 * }
076 * </pre>
077 *
078 * @author Vladimir Dzhuvinov
079 * @version 2024-10-01
080 */
081@Immutable
082public final class JWEHeader extends CommonSEHeader {
083
084
085        private static final long serialVersionUID = 1L;
086
087
088        /**
089         * The registered parameter names.
090         */
091        private static final Set<String> REGISTERED_PARAMETER_NAMES;
092
093
094        static {
095                Set<String> p = new HashSet<>();
096
097                p.add(HeaderParameterNames.ALGORITHM);
098                p.add(HeaderParameterNames.ENCRYPTION_ALGORITHM);
099                p.add(HeaderParameterNames.EPHEMERAL_PUBLIC_KEY);
100                p.add(HeaderParameterNames.COMPRESSION_ALGORITHM);
101                p.add(HeaderParameterNames.JWK_SET_URL);
102                p.add(HeaderParameterNames.JWK);
103                p.add(HeaderParameterNames.X_509_CERT_URL);
104                p.add(HeaderParameterNames.X_509_CERT_SHA_1_THUMBPRINT);
105                p.add(HeaderParameterNames.X_509_CERT_SHA_256_THUMBPRINT);
106                p.add(HeaderParameterNames.X_509_CERT_CHAIN);
107                p.add(HeaderParameterNames.KEY_ID);
108                p.add(HeaderParameterNames.TYPE);
109                p.add(HeaderParameterNames.CONTENT_TYPE);
110                p.add(HeaderParameterNames.CRITICAL);
111                p.add(HeaderParameterNames.AGREEMENT_PARTY_U_INFO);
112                p.add(HeaderParameterNames.AGREEMENT_PARTY_V_INFO);
113                p.add(HeaderParameterNames.PBES2_SALT_INPUT);
114                p.add(HeaderParameterNames.PBES2_COUNT);
115                p.add(HeaderParameterNames.INITIALIZATION_VECTOR);
116                p.add(HeaderParameterNames.AUTHENTICATION_TAG);
117                p.add(HeaderParameterNames.SENDER_KEY_ID);
118                p.add(HeaderParameterNames.ISSUER);
119                p.add(HeaderParameterNames.SUBJECT);
120                p.add(HeaderParameterNames.AUDIENCE);
121                p.add("authTag"); // non-standard (draft / pre-RFC) header, left for backwards compatibility
122
123                REGISTERED_PARAMETER_NAMES = Collections.unmodifiableSet(p);
124        }
125
126
127        /**
128         * Builder for constructing JSON Web Encryption (JWE) headers.
129         *
130         * <p>Example usage:
131         *
132         * <pre>
133         * JWEHeader header = new JWEHeader.Builder(JWEAlgorithm.RSA1_5, EncryptionMethod.A128GCM)
134         *                    .contentType("text/plain")
135         *                    .customParam("exp", new Date().getTime())
136         *                    .build();
137         * </pre>
138         */
139        public static class Builder {
140
141
142                /**
143                 * The encryption method.
144                 */
145                private final EncryptionMethod enc;
146
147
148                /**
149                 * The JWE algorithm.
150                 */
151                private JWEAlgorithm alg;
152
153
154                /**
155                 * The JOSE object type.
156                 */
157                private JOSEObjectType typ;
158
159
160                /**
161                 * The content type.
162                 */
163                private String cty;
164
165
166                /**
167                 * The critical headers.
168                 */
169                private Set<String> crit;
170
171
172                /**
173                 * Public JWK Set URL.
174                 */
175                private URI jku;
176
177
178                /**
179                 * Public JWK.
180                 */
181                private JWK jwk;
182
183
184                /**
185                 * X.509 certificate URL.
186                 */
187                private URI x5u;
188
189
190                /**
191                 * X.509 certificate SHA-1 thumbprint.
192                 */
193                @Deprecated
194                private Base64URL x5t;
195
196
197                /**
198                 * X.509 certificate SHA-256 thumbprint.
199                 */
200                private Base64URL x5t256;
201
202
203                /**
204                 * The X.509 certificate chain corresponding to the key used to
205                 * sign the JWS object.
206                 */
207                private List<Base64> x5c;
208
209
210                /**
211                 * Key ID.
212                 */
213                private String kid;
214
215                
216                /**
217                 * The ephemeral public key.
218                 */
219                private JWK epk;
220                
221                
222                /**
223                 * The compression algorithm.
224                 */
225                private CompressionAlgorithm zip;
226                
227                
228                /**
229                 * The agreement PartyUInfo.
230                 */
231                private Base64URL apu;
232                
233                
234                /**
235                 * The agreement PartyVInfo.
236                 */
237                private Base64URL apv;
238                
239                
240                /**
241                 * The PBES2 salt.
242                 */
243                private Base64URL p2s;
244                
245                
246                /**
247                 * The PBES2 count.
248                 */
249                private int p2c;
250                
251                
252                /**
253                 * The initialisation vector.
254                 */
255                private Base64URL iv;
256                
257                
258                /**
259                 * The authentication authTag.
260                 */
261                private Base64URL tag;
262                
263                
264                /**
265                 * Sender key ID.
266                 */
267                private String skid;
268
269
270                /**
271                 * Issuer as replicated claim.
272                 */
273                private String iss;
274
275
276                /**
277                 * Subject as replicated claim.
278                 */
279                private String sub;
280
281
282                /**
283                 * Audience as replicated claim.
284                 */
285                private List<String> aud;
286
287
288                /**
289                 * Custom header parameters.
290                 */
291                private Map<String,Object> customParams;
292
293
294                /**
295                 * The parsed Base64URL.
296                 */
297                private Base64URL parsedBase64URL;
298
299
300                /**
301                 * Creates a new JWE header builder.
302                 *
303                 * @param alg The JWE algorithm ({@code alg}) parameter. Must
304                 *            not be "none" or {@code null}.
305                 * @param enc The encryption method. Must not be {@code null}.
306                 */
307                public Builder(final JWEAlgorithm alg, final EncryptionMethod enc) {
308
309                        if (alg.getName().equals(Algorithm.NONE.getName())) {
310                                throw new IllegalArgumentException("The JWE algorithm \"alg\" cannot be \"none\"");
311                        }
312                        this.alg = alg;
313
314                        this.enc = Objects.requireNonNull(enc);
315                }
316
317
318                /**
319                 * Creates a new JWE header builder. This builder is intended
320                 * for {@link JWEObjectJSON multi-recipient JWE}.
321                 *
322                 * @param enc The encryption method. Must not be {@code null}.
323                 */
324                public Builder(final EncryptionMethod enc) {
325
326                        this.enc = Objects.requireNonNull(enc);
327                }
328
329
330                /**
331                 * Creates a new JWE header builder with the parameters from
332                 * the specified header.
333                 *
334                 * @param jweHeader The JWE header to use. Must not be
335                 *                  {@code null}.
336                 */
337                public Builder(final JWEHeader jweHeader) {
338
339                        this(jweHeader.getEncryptionMethod());
340
341                        alg = jweHeader.getAlgorithm();
342                        typ = jweHeader.getType();
343                        cty = jweHeader.getContentType();
344                        crit = jweHeader.getCriticalParams();
345                        customParams = jweHeader.getCustomParams();
346
347                        jku = jweHeader.getJWKURL();
348                        jwk = jweHeader.getJWK();
349                        x5u = jweHeader.getX509CertURL();
350                        x5t = jweHeader.getX509CertThumbprint();
351                        x5t256 = jweHeader.getX509CertSHA256Thumbprint();
352                        x5c = jweHeader.getX509CertChain();
353                        kid = jweHeader.getKeyID();
354
355                        epk = jweHeader.getEphemeralPublicKey();
356                        zip = jweHeader.getCompressionAlgorithm();
357                        apu = jweHeader.getAgreementPartyUInfo();
358                        apv = jweHeader.getAgreementPartyVInfo();
359                        p2s = jweHeader.getPBES2Salt();
360                        p2c = jweHeader.getPBES2Count();
361                        iv = jweHeader.getIV();
362                        tag = jweHeader.getAuthTag();
363
364                        skid = jweHeader.getSenderKeyID();
365
366                        iss = jweHeader.getIssuer();
367                        sub = jweHeader.getSubject();
368                        aud = jweHeader.getAudience();
369
370                        customParams = jweHeader.getCustomParams();
371                }
372
373
374                /**
375                 * Sets the algorithm ({@code alg}) parameter.
376                 *
377                 * @param alg The alg parameter, {@code null} if not
378                 *            specified.
379                 *
380                 * @return This builder.
381                 */
382                public Builder alg(final JWEAlgorithm alg) {
383
384                        this.alg = alg;
385                        return this;
386                }
387
388
389                /**
390                 * Sets the type ({@code typ}) parameter.
391                 *
392                 * @param typ The type parameter, {@code null} if not
393                 *            specified.
394                 *
395                 * @return This builder.
396                 */
397                public Builder type(final JOSEObjectType typ) {
398
399                        this.typ = typ;
400                        return this;
401                }
402
403
404                /**
405                 * Sets the content type ({@code cty}) parameter.
406                 *
407                 * @param cty The content type parameter, {@code null} if not
408                 *            specified.
409                 *
410                 * @return This builder.
411                 */
412                public Builder contentType(final String cty) {
413
414                        this.cty = cty;
415                        return this;
416                }
417
418
419                /**
420                 * Sets the critical header parameters ({@code crit})
421                 * parameter.
422                 *
423                 * @param crit The names of the critical header parameters,
424                 *             empty set or {@code null} if none.
425                 *
426                 * @return This builder.
427                 */
428                public Builder criticalParams(final Set<String> crit) {
429
430                        this.crit = crit;
431                        return this;
432                }
433
434
435                /**
436                 * Sets the public JSON Web Key (JWK) Set URL ({@code jku})
437                 * parameter.
438                 *
439                 * @param jku The public JSON Web Key (JWK) Set URL parameter,
440                 *            {@code null} if not specified.
441                 *
442                 * @return This builder.
443                 */
444                public Builder jwkURL(final URI jku) {
445
446                        this.jku = jku;
447                        return this;
448                }
449
450
451                /**
452                 * Sets the public JSON Web Key (JWK) ({@code jwk}) parameter.
453                 *
454                 * @param jwk The public JSON Web Key (JWK) ({@code jwk})
455                 *            parameter, {@code null} if not specified.
456                 *
457                 * @return This builder.
458                 */
459                public Builder jwk(final JWK jwk) {
460                        
461                        if (jwk != null && jwk.isPrivate()) {
462                                throw new IllegalArgumentException("The JWK must be public");
463                        }
464
465                        this.jwk = jwk;
466                        return this;
467                }
468
469
470                /**
471                 * Sets the X.509 certificate URL ({@code x5u}) parameter.
472                 *
473                 * @param x5u The X.509 certificate URL parameter, {@code null}
474                 *            if not specified.
475                 *
476                 * @return This builder.
477                 */
478                public Builder x509CertURL(final URI x5u) {
479
480                        this.x5u = x5u;
481                        return this;
482                }
483
484
485                /**
486                 * Sets the X.509 certificate SHA-1 thumbprint ({@code x5t})
487                 * parameter.
488                 *
489                 * @param x5t The X.509 certificate SHA-1 thumbprint parameter,
490                 *            {@code null} if not specified.
491                 *
492                 * @return This builder.
493                 */
494                @Deprecated
495                public Builder x509CertThumbprint(final Base64URL x5t) {
496
497                        this.x5t = x5t;
498                        return this;
499                }
500
501
502                /**
503                 * Sets the X.509 certificate SHA-256 thumbprint
504                 * ({@code x5t#s256}) parameter.
505                 *
506                 * @param x5t256 The X.509 certificate SHA-256 thumbprint
507                 *               parameter, {@code null} if not specified.
508                 *
509                 * @return This builder.
510                 */
511                public Builder x509CertSHA256Thumbprint(final Base64URL x5t256) {
512
513                        this.x5t256 = x5t256;
514                        return this;
515                }
516
517
518                /**
519                 * Sets the X.509 certificate chain parameter ({@code x5c})
520                 * corresponding to the key used to sign the JWS object.
521                 *
522                 * @param x5c The X.509 certificate chain parameter,
523                 *            {@code null} if not specified.
524                 *
525                 * @return This builder.
526                 */
527                public Builder x509CertChain(final List<Base64> x5c) {
528
529                        this.x5c = x5c;
530                        return this;
531                }
532
533
534                /**
535                 * Sets the key ID ({@code kid}) parameter.
536                 *
537                 * @param kid The key ID parameter, {@code null} if not
538                 *            specified.
539                 *
540                 * @return This builder.
541                 */
542                public Builder keyID(final String kid) {
543
544                        this.kid = kid;
545                        return this;
546                }
547
548
549                /**
550                 * Sets the Ephemeral Public Key ({@code epk}) parameter.
551                 *
552                 * @param epk The Ephemeral Public Key parameter, {@code null}
553                 *            if not specified.
554                 *
555                 * @return This builder.
556                 */
557                public Builder ephemeralPublicKey(final JWK epk) {
558
559                        this.epk = epk;
560                        return this;
561                }
562
563
564                /**
565                 * Sets the compression algorithm ({@code zip}) parameter.
566                 *
567                 * @param zip The compression algorithm parameter, {@code null}
568                 *            if not specified.
569                 *
570                 * @return This builder.
571                 */
572                public Builder compressionAlgorithm(final CompressionAlgorithm zip) {
573
574                        this.zip = zip;
575                        return this;
576                }
577
578
579                /**
580                 * Sets the agreement PartyUInfo ({@code apu}) parameter.
581                 *
582                 * @param apu The agreement PartyUInfo parameter, {@code null}
583                 *            if not specified.
584                 *
585                 * @return This builder.
586                 */
587                public Builder agreementPartyUInfo(final Base64URL apu) {
588
589                        this.apu = apu;
590                        return this;
591                }
592
593
594                /**
595                 * Sets the agreement PartyVInfo ({@code apv}) parameter.
596                 *
597                 * @param apv The agreement PartyVInfo parameter, {@code null}
598                 *            if not specified.
599                 *
600                 * @return This builder.
601                 */
602                public Builder agreementPartyVInfo(final Base64URL apv) {
603
604                        this.apv = apv;
605                        return this;
606                }
607
608
609                /**
610                 * Sets the PBES2 salt ({@code p2s}) parameter.
611                 *
612                 * @param p2s The PBES2 salt parameter, {@code null} if not
613                 *            specified.
614                 *
615                 * @return This builder.
616                 */
617                public Builder pbes2Salt(final Base64URL p2s) {
618
619                        this.p2s = p2s;
620                        return this;
621                }
622
623
624                /**
625                 * Sets the PBES2 count ({@code p2c}) parameter.
626                 *
627                 * @param p2c The PBES2 count parameter, zero if not specified.
628                 *            Must not be negative.
629                 *
630                 * @return This builder.
631                 */
632                public Builder pbes2Count(final int p2c) {
633
634                        if (p2c < 0)
635                                throw new IllegalArgumentException("The PBES2 count parameter must not be negative");
636
637                        this.p2c = p2c;
638                        return this;
639                }
640
641
642                /**
643                 * Sets the initialisation vector ({@code iv}) parameter.
644                 *
645                 * @param iv The initialisation vector, {@code null} if not
646                 *           specified.
647                 *
648                 * @return This builder.
649                 */
650                public Builder iv(final Base64URL iv) {
651
652                        this.iv = iv;
653                        return this;
654                }
655
656                
657                /**
658                 * Sets the sender key ID ({@code skid}) parameter.
659                 *
660                 * @param skid The sender Key ID parameter, {@code null} if not
661                 *             specified.
662                 *
663                 * @return This builder.
664                 */
665                public Builder senderKeyID(final String skid) {
666
667                        this.skid = skid;
668                        return this;
669                }
670
671
672                /**
673                 * Sets the issuer ({@code iss}) parameter as a replicated
674                 * claim.
675                 *
676                 * @param iss The issuer, {@code null} if not specified.
677                 *
678                 * @return This builder.
679                 */
680                public Builder issuer(final String iss) {
681
682                        this.iss = iss;
683                        return this;
684                }
685
686
687                /**
688                 * Sets the subject ({@code sub}) parameter as a replicated
689                 * claim.
690                 *
691                 * @param sub The subject, {@code null} if not specified.
692                 *
693                 * @return This builder.
694                 */
695                public Builder subject(final String sub) {
696
697                        this.sub = sub;
698                        return this;
699                }
700
701
702                /**
703                 * Sets the audience ({@code aud}) parameter as a replicated
704                 * claim.
705                 *
706                 * @param aud The audience, {@code null} if not specified.
707                 *
708                 * @return This builder.
709                 */
710                public Builder audience(final List<String> aud) {
711
712                        this.aud = aud;
713                        return this;
714                }
715
716
717                /**
718                 * Sets the authentication tag ({@code tag}) parameter.
719                 *
720                 * @param tag The authentication tag, {@code null} if not
721                 *            specified.
722                 *
723                 * @return This builder.
724                 */
725                public Builder authTag(final Base64URL tag) {
726
727                        this.tag = tag;
728                        return this;
729                }
730
731                
732                /**
733                 * Sets a custom (non-registered) parameter.
734                 *
735                 * @param name  The name of the custom parameter. Must not
736                 *              match a registered parameter name and must not
737                 *              be {@code null}.
738                 * @param value The value of the custom parameter, should map
739                 *              to a valid JSON entity, {@code null} if not
740                 *              specified.
741                 *
742                 * @return This builder.
743                 *
744                 * @throws IllegalArgumentException If the specified parameter
745                 *                                  name matches a registered
746                 *                                  parameter name.
747                 */
748                public Builder customParam(final String name, final Object value) {
749
750                        if (getRegisteredParameterNames().contains(name)) {
751                                throw new IllegalArgumentException("The parameter name \"" + name + "\" matches a registered name");
752                        }
753
754                        if (customParams == null) {
755                                customParams = new HashMap<>();
756                        }
757
758                        customParams.put(name, value);
759
760                        return this;
761                }
762
763
764                /**
765                 * Sets the custom (non-registered) parameters. The values must
766                 * be serialisable to a JSON entity, otherwise will be ignored.
767                 *
768                 * @param customParameters The custom parameters, empty map or
769                 *                         {@code null} if none.
770                 *
771                 * @return This builder.
772                 */
773                public Builder customParams(final Map<String, Object> customParameters) {
774
775                        this.customParams = customParameters;
776                        return this;
777                }
778
779
780                /**
781                 * Sets the parsed Base64URL.
782                 *
783                 * @param base64URL The parsed Base64URL, {@code null} if the
784                 *                  header is created from scratch.
785                 *
786                 * @return This builder.
787                 */
788                public Builder parsedBase64URL(final Base64URL base64URL) {
789
790                        this.parsedBase64URL = base64URL;
791                        return this;
792                }
793
794
795                /**
796                 * Builds a new JWE header.
797                 *
798                 * @return The JWE header.
799                 */
800                public JWEHeader build() {
801
802                        return new JWEHeader(
803                                alg, enc, typ, cty, crit,
804                                jku, jwk, x5u, x5t, x5t256, x5c, kid,
805                                epk, zip, apu, apv, p2s, p2c,
806                                iv, tag, skid,
807                                iss, sub, aud,
808                                customParams, parsedBase64URL);
809                }
810        }
811
812
813        /**
814         * The encryption method ({@code enc}) parameter.
815         */
816        private final EncryptionMethod enc;
817
818
819        /**
820         * The ephemeral public key ({@code epk}) parameter.
821         */
822        private final JWK epk;
823
824
825        /**
826         * The compression algorithm ({@code zip}) parameter.
827         */
828        private final CompressionAlgorithm zip;
829
830
831        /**
832         * The agreement PartyUInfo ({@code apu}) parameter.
833         */
834        private final Base64URL apu;
835        
836        
837        /**
838         * The agreement PartyVInfo ({@code apv}) parameter.
839         */
840        private final Base64URL apv;
841
842
843        /**
844         * The PBES2 salt ({@code p2s}) parameter.
845         */
846        private final Base64URL p2s;
847
848
849        /**
850         * The PBES2 count ({@code p2c}) parameter.
851         */
852        private final int p2c;
853
854
855        /**
856         * The initialisation vector ({@code iv}) parameter.
857         */
858        private final Base64URL iv;
859
860
861        /**
862         * The authentication tag ({@code tag}) parameter.
863         */
864        private final Base64URL tag;
865
866        
867        /**
868         * The sender key ID ({@code skid}) parameter.
869         */
870        private final String skid;
871
872
873        /**
874         * The issuer ({@code iss}) claim parameter.
875         */
876        private final String iss;
877
878
879        /**
880         * The subject ({@code sub}) claim parameter.
881         */
882        private final String sub;
883
884
885        /**
886         * The audience ({@code aud}) claim parameter.
887         */
888        private final List<String> aud;
889
890        
891        /**
892         * Creates a new minimal JSON Web Encryption (JWE) header.
893         *
894         * @param enc The encryption method parameter. Must not be
895         *            {@code null}.
896         */
897        public JWEHeader(final EncryptionMethod enc) {
898
899                this(
900                        null, enc,
901                        null, null, null, null, null, null, null, null, null, null,
902                        null, null, null, null, null, 0,
903                        null, null,
904                        null, null, null,
905                        null, null, null);
906        }
907
908
909        /**
910         * Creates a new minimal JSON Web Encryption (JWE) header.
911         *
912         * <p>Note: Use {@link PlainHeader} to create a header with algorithm
913         * {@link Algorithm#NONE none}.
914         *
915         * @param alg The JWE algorithm parameter. Must not be "none" or
916         *            {@code null}.
917         * @param enc The encryption method parameter. Must not be
918         *            {@code null}.
919         */
920        public JWEHeader(final JWEAlgorithm alg, final EncryptionMethod enc) {
921
922                this(
923                        alg, enc,
924                        null, null, null, null, null, null, null, null, null, null,
925                        null, null, null, null, null, 0,
926                        null, null,
927                        null, null, null,
928                        null, null, null);
929        }
930
931
932        /**
933         * Creates a new JSON Web Encryption (JWE) header.
934         *
935         * <p>Note: Use {@link PlainHeader} to create a header with algorithm
936         * {@link Algorithm#NONE none}.
937         *
938         * @param alg             The JWE algorithm ({@code alg}) parameter.
939         *                        {@code null} if not specified.
940         * @param enc             The encryption method parameter. Must not be
941         *                        {@code null}.
942         * @param typ             The type ({@code typ}) parameter,
943         *                        {@code null} if not specified.
944         * @param cty             The content type ({@code cty}) parameter,
945         *                        {@code null} if not specified.
946         * @param crit            The names of the critical header
947         *                        ({@code crit}) parameters, empty set or
948         *                        {@code null} if none.
949         * @param jku             The JSON Web Key (JWK) Set URL ({@code jku})
950         *                        parameter, {@code null} if not specified.
951         * @param jwk             The X.509 certificate URL ({@code jwk})
952         *                        parameter, {@code null} if not specified.
953         * @param x5u             The X.509 certificate URL parameter
954         *                        ({@code x5u}), {@code null} if not specified.
955         * @param x5t             The X.509 certificate SHA-1 thumbprint
956         *                        ({@code x5t}) parameter, {@code null} if not
957         *                        specified.
958         * @param x5t256          The X.509 certificate SHA-256 thumbprint
959         *                        ({@code x5t#S256}) parameter, {@code null} if
960         *                        not specified.
961         * @param x5c             The X.509 certificate chain ({@code x5c})
962         *                        parameter, {@code null} if not specified.
963         * @param kid             The key ID ({@code kid}) parameter,
964         *                        {@code null} if not specified.
965         * @param epk             The Ephemeral Public Key ({@code epk})
966         *                        parameter, {@code null} if not specified.
967         * @param zip             The compression algorithm ({@code zip})
968         *                        parameter, {@code null} if not specified.
969         * @param apu             The agreement PartyUInfo ({@code apu})
970         *                        parameter, {@code null} if not specified.
971         * @param apv             The agreement PartyVInfo ({@code apv})
972         *                        parameter, {@code null} if not specified.
973         * @param p2s             The PBES2 salt ({@code p2s}) parameter,
974         *                        {@code null} if not specified.
975         * @param p2c             The PBES2 count ({@code p2c}) parameter, zero
976         *                        if not specified. Must not be negative.
977         * @param iv              The initialisation vector ({@code iv})
978         *                        parameter, {@code null} if not specified.
979         * @param tag             The authentication tag ({@code tag})
980         *                        parameter, {@code null} if not specified.
981         * @param skid            The sender key ID ({@code skid}) parameter,
982         *                        {@code null} if not specified.
983         * @param customParams    The custom parameters, empty map or
984         *                        {@code null} if none.
985         * @param parsedBase64URL The parsed Base64URL, {@code null} if the
986         *                        header is created from scratch.
987         */
988        @Deprecated
989        public JWEHeader(final Algorithm alg,
990                         final EncryptionMethod enc,
991                         final JOSEObjectType typ,
992                         final String cty,
993                         final Set<String> crit,
994                         final URI jku,
995                         final JWK jwk,
996                         final URI x5u,
997                         final Base64URL x5t,
998                         final Base64URL x5t256,
999                         final List<Base64> x5c,
1000                         final String kid,
1001                         final JWK epk,
1002                         final CompressionAlgorithm zip,
1003                         final Base64URL apu,
1004                         final Base64URL apv,
1005                         final Base64URL p2s,
1006                         final int p2c,
1007                         final Base64URL iv,
1008                         final Base64URL tag,
1009                         final String skid,
1010                         final Map<String,Object> customParams,
1011                         final Base64URL parsedBase64URL) {
1012
1013                this(alg, enc, typ, cty, crit, jku, jwk, x5u, x5t, x5t256, x5c, kid, epk, zip,
1014                        apu, apv, p2s, p2c, iv, tag, skid,
1015                        null, null, null,
1016                        customParams, parsedBase64URL);
1017        }
1018
1019
1020        /**
1021         * Creates a new JSON Web Encryption (JWE) header.
1022         *
1023         * <p>Note: Use {@link PlainHeader} to create a header with algorithm
1024         * {@link Algorithm#NONE none}.
1025         *
1026         * @param alg             The JWE algorithm ({@code alg}) parameter.
1027         *                        {@code null} if not specified.
1028         * @param enc             The encryption method parameter. Must not be
1029         *                        {@code null}.
1030         * @param typ             The type ({@code typ}) parameter,
1031         *                        {@code null} if not specified.
1032         * @param cty             The content type ({@code cty}) parameter,
1033         *                        {@code null} if not specified.
1034         * @param crit            The names of the critical header
1035         *                        ({@code crit}) parameters, empty set or
1036         *                        {@code null} if none.
1037         * @param jku             The JSON Web Key (JWK) Set URL ({@code jku})
1038         *                        parameter, {@code null} if not specified.
1039         * @param jwk             The X.509 certificate URL ({@code jwk})
1040         *                        parameter, {@code null} if not specified.
1041         * @param x5u             The X.509 certificate URL parameter
1042         *                        ({@code x5u}), {@code null} if not specified.
1043         * @param x5t             The X.509 certificate SHA-1 thumbprint
1044         *                        ({@code x5t}) parameter, {@code null} if not
1045         *                        specified.
1046         * @param x5t256          The X.509 certificate SHA-256 thumbprint
1047         *                        ({@code x5t#S256}) parameter, {@code null} if
1048         *                        not specified.
1049         * @param x5c             The X.509 certificate chain ({@code x5c})
1050         *                        parameter, {@code null} if not specified.
1051         * @param kid             The key ID ({@code kid}) parameter,
1052         *                        {@code null} if not specified.
1053         * @param epk             The Ephemeral Public Key ({@code epk})
1054         *                        parameter, {@code null} if not specified.
1055         * @param zip             The compression algorithm ({@code zip})
1056         *                        parameter, {@code null} if not specified.
1057         * @param apu             The agreement PartyUInfo ({@code apu})
1058         *                        parameter, {@code null} if not specified.
1059         * @param apv             The agreement PartyVInfo ({@code apv})
1060         *                        parameter, {@code null} if not specified.
1061         * @param p2s             The PBES2 salt ({@code p2s}) parameter,
1062         *                        {@code null} if not specified.
1063         * @param p2c             The PBES2 count ({@code p2c}) parameter, zero
1064         *                        if not specified. Must not be negative.
1065         * @param iv              The initialisation vector ({@code iv})
1066         *                        parameter, {@code null} if not specified.
1067         * @param tag             The authentication tag ({@code tag})
1068         *                        parameter, {@code null} if not specified.
1069         * @param skid            The sender key ID ({@code skid}) parameter,
1070         *                        {@code null} if not specified.
1071         * @param iss             The issuer ({@code iss}) parameter as a
1072         *                        replicated claim, {@code null} if not
1073         *                        specified.
1074         * @param sub             The subject ({@code sub}) parameter as a
1075         *                        replicated claim, {@code null} if not
1076         *                        specified.
1077         * @param aud             The audience ({@code aud}) parameter as a
1078         *                        replicated claim, {@code null} if not
1079         *                        specified.
1080         * @param customParams    The custom parameters, empty map or
1081         *                        {@code null} if none.
1082         * @param parsedBase64URL The parsed Base64URL, {@code null} if the
1083         *                        header is created from scratch.
1084         */
1085        public JWEHeader(final Algorithm alg,
1086                         final EncryptionMethod enc,
1087                         final JOSEObjectType typ,
1088                         final String cty,
1089                         final Set<String> crit,
1090                         final URI jku,
1091                         final JWK jwk,
1092                         final URI x5u,
1093                         final Base64URL x5t,
1094                         final Base64URL x5t256,
1095                         final List<Base64> x5c,
1096                         final String kid,
1097                         final JWK epk,
1098                         final CompressionAlgorithm zip,
1099                         final Base64URL apu,
1100                         final Base64URL apv,
1101                         final Base64URL p2s,
1102                         final int p2c,
1103                         final Base64URL iv,
1104                         final Base64URL tag,
1105                         final String skid,
1106                         final String iss,
1107                         final String sub,
1108                         final List<String> aud,
1109                         final Map<String,Object> customParams,
1110                         final Base64URL parsedBase64URL) {
1111
1112                super(alg, typ, cty, crit, jku, jwk, x5u, x5t, x5t256, x5c, kid, customParams, parsedBase64URL);
1113
1114                if (alg != null && alg.getName().equals(Algorithm.NONE.getName())) {
1115                        throw new IllegalArgumentException("The JWE algorithm cannot be \"none\"");
1116                }
1117
1118                if (epk != null && epk.isPrivate()) {
1119                        throw new IllegalArgumentException("Ephemeral public key should not be a private key");
1120                }
1121
1122                this.enc = Objects.requireNonNull(enc);
1123
1124                this.epk = epk;
1125                this.zip = zip;
1126                this.apu = apu;
1127                this.apv = apv;
1128                this.p2s = p2s;
1129                this.p2c = p2c;
1130                this.iv = iv;
1131                this.tag = tag;
1132                this.skid = skid;
1133
1134                this.iss = iss;
1135                this.sub = sub;
1136                this.aud = aud;
1137        }
1138
1139
1140        /**
1141         * Deep copy constructor.
1142         *
1143         * @param jweHeader The JWE header to copy. Must not be {@code null}.
1144         */
1145        public JWEHeader(final JWEHeader jweHeader) {
1146
1147                this(
1148                        jweHeader.getAlgorithm(),
1149                        jweHeader.getEncryptionMethod(),
1150                        jweHeader.getType(),
1151                        jweHeader.getContentType(),
1152                        jweHeader.getCriticalParams(),
1153                        jweHeader.getJWKURL(),
1154                        jweHeader.getJWK(),
1155                        jweHeader.getX509CertURL(),
1156                        jweHeader.getX509CertThumbprint(),
1157                        jweHeader.getX509CertSHA256Thumbprint(),
1158                        jweHeader.getX509CertChain(),
1159                        jweHeader.getKeyID(),
1160                        jweHeader.getEphemeralPublicKey(),
1161                        jweHeader.getCompressionAlgorithm(),
1162                        jweHeader.getAgreementPartyUInfo(),
1163                        jweHeader.getAgreementPartyVInfo(),
1164                        jweHeader.getPBES2Salt(),
1165                        jweHeader.getPBES2Count(),
1166                        jweHeader.getIV(),
1167                        jweHeader.getAuthTag(),
1168                        jweHeader.getSenderKeyID(),
1169                        jweHeader.getIssuer(),
1170                        jweHeader.getSubject(),
1171                        jweHeader.getAudience(),
1172                        jweHeader.getCustomParams(),
1173                        jweHeader.getParsedBase64URL()
1174                );
1175        }
1176
1177
1178        /**
1179         * Gets the registered parameter names for JWE headers.
1180         *
1181         * @return The registered parameter names, as an unmodifiable set.
1182         */
1183        public static Set<String> getRegisteredParameterNames() {
1184
1185                return REGISTERED_PARAMETER_NAMES;
1186        }
1187
1188
1189        /**
1190         * Gets the algorithm ({@code alg}) parameter.
1191         *
1192         * @return The algorithm parameter.
1193         */
1194        @Override
1195        public JWEAlgorithm getAlgorithm() {
1196
1197                return (JWEAlgorithm)super.getAlgorithm();
1198        }
1199
1200
1201        /**
1202         * Gets the encryption method ({@code enc}) parameter.
1203         *
1204         * @return The encryption method parameter.
1205         */
1206        public EncryptionMethod getEncryptionMethod() {
1207
1208                return enc;
1209        }
1210
1211
1212        /**
1213         * Gets the Ephemeral Public Key ({@code epk}) parameter.
1214         *
1215         * @return The Ephemeral Public Key parameter, {@code null} if not
1216         *         specified.
1217         */
1218        public JWK getEphemeralPublicKey() {
1219
1220                return epk;
1221        }
1222
1223
1224        /**
1225         * Gets the compression algorithm ({@code zip}) parameter.
1226         *
1227         * @return The compression algorithm parameter, {@code null} if not
1228         *         specified.
1229         */
1230        public CompressionAlgorithm getCompressionAlgorithm() {
1231
1232                return zip;
1233        }
1234
1235
1236        /**
1237         * Gets the agreement PartyUInfo ({@code apu}) parameter.
1238         *
1239         * @return The agreement PartyUInfo parameter, {@code null} if not
1240         *         specified.
1241         */
1242        public Base64URL getAgreementPartyUInfo() {
1243
1244                return apu;
1245        }
1246
1247
1248        /**
1249         * Gets the agreement PartyVInfo ({@code apv}) parameter.
1250         *
1251         * @return The agreement PartyVInfo parameter, {@code null} if not
1252         *         specified.
1253         */
1254        public Base64URL getAgreementPartyVInfo() {
1255
1256                return apv;
1257        }
1258
1259
1260        /**
1261         * Gets the PBES2 salt ({@code p2s}) parameter.
1262         *
1263         * @return The PBES2 salt parameter, {@code null} if not specified.
1264         */
1265        public Base64URL getPBES2Salt() {
1266
1267                return p2s;
1268        }
1269
1270
1271        /**
1272         * Gets the PBES2 count ({@code p2c}) parameter.
1273         *
1274         * @return The PBES2 count parameter, zero if not specified.
1275         */
1276        public int getPBES2Count() {
1277
1278                return p2c;
1279        }
1280
1281
1282        /**
1283         * Gets the initialisation vector ({@code iv}) parameter.
1284         *
1285         * @return The initialisation vector, {@code null} if not specified.
1286         */
1287        public Base64URL getIV() {
1288
1289                return iv;
1290        }
1291
1292
1293        /**
1294         * Gets the authentication tag ({@code tag}) parameter.
1295         *
1296         * @return The authentication tag, {@code null} if not specified.
1297         */
1298        public Base64URL getAuthTag() {
1299
1300                return tag;
1301        }
1302        
1303        
1304        /**
1305         * Gets the sender key ID ({@code skid}) parameter.
1306         *
1307         * @return The sender key ID, {@code null} if not specified.
1308         */
1309        public String getSenderKeyID() {
1310
1311                return skid;
1312        }
1313
1314
1315        /**
1316         * Gets the issuer ({@code iss}) claim as a parameter.
1317         *
1318         * @return The issuer claim, {@code null} if not specified.
1319         */
1320        public String getIssuer() {
1321
1322                return iss;
1323        }
1324
1325
1326        /**
1327         * Gets the subject ({@code sub}) claim as a parameter.
1328         *
1329         * @return The subject claim, {@code null} if not specified.
1330         */
1331        public String getSubject() {
1332
1333                return sub;
1334        }
1335
1336
1337        /**
1338         * Gets the audience ({@code aud}) claim as a parameter.
1339         *
1340         * @return The audience claim, empty list if not specified.
1341         */
1342        public List<String> getAudience() {
1343
1344                if (aud == null) {
1345                        return Collections.emptyList();
1346                }
1347
1348                return aud;
1349        }
1350        
1351
1352        @Override
1353        public Set<String> getIncludedParams() {
1354
1355                Set<String> includedParameters = super.getIncludedParams();
1356
1357                if (enc != null) {
1358                        includedParameters.add(HeaderParameterNames.ENCRYPTION_ALGORITHM);
1359                }
1360
1361                if (epk != null) {
1362                        includedParameters.add(HeaderParameterNames.EPHEMERAL_PUBLIC_KEY);
1363                }
1364
1365                if (zip != null) {
1366                        includedParameters.add(HeaderParameterNames.COMPRESSION_ALGORITHM);
1367                }
1368
1369                if (apu != null) {
1370                        includedParameters.add(HeaderParameterNames.AGREEMENT_PARTY_U_INFO);
1371                }
1372                
1373                if (apv != null) {
1374                        includedParameters.add(HeaderParameterNames.AGREEMENT_PARTY_V_INFO);
1375                }
1376
1377                if (p2s != null) {
1378                        includedParameters.add(HeaderParameterNames.PBES2_SALT_INPUT);
1379                }
1380
1381                if (p2c > 0) {
1382                        includedParameters.add(HeaderParameterNames.PBES2_COUNT);
1383                }
1384
1385                if (iv != null) {
1386                        includedParameters.add(HeaderParameterNames.INITIALIZATION_VECTOR);
1387                }
1388
1389                if (tag != null) {
1390                        includedParameters.add(HeaderParameterNames.AUTHENTICATION_TAG);
1391                }
1392
1393                if (skid != null) {
1394                        includedParameters.add(HeaderParameterNames.SENDER_KEY_ID);
1395                }
1396
1397                if (iss != null) {
1398                        includedParameters.add(HeaderParameterNames.ISSUER);
1399                }
1400
1401                if (sub != null) {
1402                        includedParameters.add(HeaderParameterNames.SUBJECT);
1403                }
1404
1405                if (aud != null) {
1406                        includedParameters.add(HeaderParameterNames.AUDIENCE);
1407                }
1408
1409                return includedParameters;
1410        }
1411
1412
1413        @Override
1414        public Map<String, Object> toJSONObject() {
1415
1416                Map<String, Object> o = super.toJSONObject();
1417
1418                if (enc != null) {
1419                        o.put(HeaderParameterNames.ENCRYPTION_ALGORITHM, enc.toString());
1420                }
1421
1422                if (epk != null) {
1423                        o.put(HeaderParameterNames.EPHEMERAL_PUBLIC_KEY, epk.toJSONObject());
1424                }
1425
1426                if (zip != null) {
1427                        o.put(HeaderParameterNames.COMPRESSION_ALGORITHM, zip.toString());
1428                }
1429
1430                if (apu != null) {
1431                        o.put(HeaderParameterNames.AGREEMENT_PARTY_U_INFO, apu.toString());
1432                }
1433                
1434                if (apv != null) {
1435                        o.put(HeaderParameterNames.AGREEMENT_PARTY_V_INFO, apv.toString());
1436                }
1437
1438                if (p2s != null) {
1439                        o.put(HeaderParameterNames.PBES2_SALT_INPUT, p2s.toString());
1440                }
1441
1442                if (p2c > 0) {
1443                        o.put(HeaderParameterNames.PBES2_COUNT, p2c);
1444                }
1445
1446                if (iv != null) {
1447                        o.put(HeaderParameterNames.INITIALIZATION_VECTOR, iv.toString());
1448                }
1449
1450                if (tag != null) {
1451                        o.put(HeaderParameterNames.AUTHENTICATION_TAG, tag.toString());
1452                }
1453
1454                if (skid != null) {
1455                        o.put(HeaderParameterNames.SENDER_KEY_ID, skid);
1456                }
1457
1458                if (iss != null) {
1459                        o.put(HeaderParameterNames.ISSUER, iss);
1460                }
1461
1462                if (sub != null) {
1463                        o.put(HeaderParameterNames.SUBJECT, sub);
1464                }
1465
1466                if (aud != null) {
1467                        if (aud.size() == 1) {
1468                                o.put(HeaderParameterNames.AUDIENCE, aud.get(0));
1469                        } else if (!aud.isEmpty()) {
1470                                o.put(HeaderParameterNames.AUDIENCE, aud);
1471                        }
1472                }
1473
1474                return o;
1475        }
1476
1477
1478        /**
1479         * Parses an encryption method ({@code enc}) parameter from the 
1480         * specified JWE header JSON object.
1481         *
1482         * @param json The JSON object to parse. Must not be {@code null}.
1483         *
1484         * @return The encryption method.
1485         *
1486         * @throws ParseException If the {@code enc} parameter couldn't be 
1487         *                        parsed.
1488         */
1489        private static EncryptionMethod parseEncryptionMethod(final Map<String, Object> json)
1490                throws ParseException {
1491
1492                return EncryptionMethod.parse(JSONObjectUtils.getString(json, HeaderParameterNames.ENCRYPTION_ALGORITHM));
1493        }
1494
1495
1496        /**
1497         * Parses a JWE header from the specified JSON object.
1498         *
1499         * @param jsonObject The JSON object to parse. Must not be
1500         *                   {@code null}.
1501         *
1502         * @return The JWE header.
1503         *
1504         * @throws ParseException If the specified JSON object doesn't
1505         *                        represent a valid JWE header.
1506         */
1507        public static JWEHeader parse(final Map<String, Object> jsonObject)
1508                throws ParseException {
1509
1510                return parse(jsonObject, null);
1511        }
1512
1513
1514        /**
1515         * Parses a JWE header from the specified JSON object.
1516         *
1517         * @param jsonObject      The JSON object to parse. Must not be
1518         *                        {@code null}.
1519         * @param parsedBase64URL The original parsed Base64URL, {@code null}
1520         *                        if not applicable.
1521         *
1522         * @return The JWE header.
1523         *
1524         * @throws ParseException If the specified JSON object doesn't 
1525         *                        represent a valid JWE header.
1526         */
1527        public static JWEHeader parse(final Map<String, Object> jsonObject,
1528                                      final Base64URL parsedBase64URL)
1529                throws ParseException {
1530
1531                // Get the "enc" parameter
1532                EncryptionMethod enc = parseEncryptionMethod(jsonObject);
1533
1534                JWEHeader.Builder header = new Builder(enc).parsedBase64URL(parsedBase64URL);
1535
1536                // Parse optional + custom parameters
1537                for(final String name: jsonObject.keySet()) {
1538
1539                        if(HeaderParameterNames.ALGORITHM.equals(name)) {
1540                                header = header.alg(JWEAlgorithm.parse(JSONObjectUtils.getString(jsonObject, name)));
1541                        } else if(HeaderParameterNames.ENCRYPTION_ALGORITHM.equals(name)) {
1542                                // skip
1543                        } else if(HeaderParameterNames.TYPE.equals(name)) {
1544                                String typValue = JSONObjectUtils.getString(jsonObject, name);
1545                                if (typValue != null) {
1546                                        header = header.type(new JOSEObjectType(typValue));
1547                                }
1548                        } else if(HeaderParameterNames.CONTENT_TYPE.equals(name)) {
1549                                header = header.contentType(JSONObjectUtils.getString(jsonObject, name));
1550                        } else if(HeaderParameterNames.CRITICAL.equals(name)) {
1551                                List<String> critValues = JSONObjectUtils.getStringList(jsonObject, name);
1552                                if (critValues != null) {
1553                                        header = header.criticalParams(new HashSet<>(critValues));
1554                                }
1555                        } else if(HeaderParameterNames.JWK_SET_URL.equals(name)) {
1556                                header = header.jwkURL(JSONObjectUtils.getURI(jsonObject, name));
1557                        } else if(HeaderParameterNames.JWK.equals(name)) {
1558                                header = header.jwk(CommonSEHeader.parsePublicJWK(JSONObjectUtils.getJSONObject(jsonObject, name)));
1559                        } else if(HeaderParameterNames.X_509_CERT_URL.equals(name)) {
1560                                header = header.x509CertURL(JSONObjectUtils.getURI(jsonObject, name));
1561                        } else if(HeaderParameterNames.X_509_CERT_SHA_1_THUMBPRINT.equals(name)) {
1562                                header = header.x509CertThumbprint(Base64URL.from(JSONObjectUtils.getString(jsonObject, name)));
1563                        } else if(HeaderParameterNames.X_509_CERT_SHA_256_THUMBPRINT.equals(name)) {
1564                                header = header.x509CertSHA256Thumbprint(Base64URL.from(JSONObjectUtils.getString(jsonObject, name)));
1565                        } else if(HeaderParameterNames.X_509_CERT_CHAIN.equals(name)) {
1566                                header = header.x509CertChain(X509CertChainUtils.toBase64List(JSONObjectUtils.getJSONArray(jsonObject, name)));
1567                        } else if(HeaderParameterNames.KEY_ID.equals(name)) {
1568                                header = header.keyID(JSONObjectUtils.getString(jsonObject, name));
1569                        } else if(HeaderParameterNames.EPHEMERAL_PUBLIC_KEY.equals(name)) {
1570                                header = header.ephemeralPublicKey(JWK.parse(JSONObjectUtils.getJSONObject(jsonObject, name)));
1571                        } else if(HeaderParameterNames.COMPRESSION_ALGORITHM.equals(name)) {
1572                                String zipValue = JSONObjectUtils.getString(jsonObject, name);
1573                                if (zipValue != null) {
1574                                        header = header.compressionAlgorithm(new CompressionAlgorithm(zipValue));
1575                                }
1576                        } else if(HeaderParameterNames.AGREEMENT_PARTY_U_INFO.equals(name)) {
1577                                header = header.agreementPartyUInfo(Base64URL.from(JSONObjectUtils.getString(jsonObject, name)));
1578                        } else if(HeaderParameterNames.AGREEMENT_PARTY_V_INFO.equals(name)) {
1579                                header = header.agreementPartyVInfo(Base64URL.from(JSONObjectUtils.getString(jsonObject, name)));
1580                        } else if(HeaderParameterNames.PBES2_SALT_INPUT.equals(name)) {
1581                                header = header.pbes2Salt(Base64URL.from(JSONObjectUtils.getString(jsonObject, name)));
1582                        } else if(HeaderParameterNames.PBES2_COUNT.equals(name)) {
1583                                header = header.pbes2Count(JSONObjectUtils.getInt(jsonObject, name));
1584                        } else if(HeaderParameterNames.INITIALIZATION_VECTOR.equals(name)) {
1585                                header = header.iv(Base64URL.from(JSONObjectUtils.getString(jsonObject, name)));
1586                        } else if(HeaderParameterNames.AUTHENTICATION_TAG.equals(name)) {
1587                                header = header.authTag(Base64URL.from(JSONObjectUtils.getString(jsonObject, name)));
1588                        } else if(HeaderParameterNames.SENDER_KEY_ID.equals(name)) {
1589                                header = header.senderKeyID(JSONObjectUtils.getString(jsonObject, name));
1590                        } else if(HeaderParameterNames.ISSUER.equals(name)) {
1591                                header = header.issuer(JSONObjectUtils.getString(jsonObject, name));
1592                        } else if (HeaderParameterNames.SUBJECT.equals(name)) {
1593                                header = header.subject(JSONObjectUtils.getString(jsonObject, name));
1594                        } else if (HeaderParameterNames.AUDIENCE.equals(name)) {
1595                                if (jsonObject.get(name) instanceof String) {
1596                                        header = header.audience(Collections.singletonList(JSONObjectUtils.getString(jsonObject, name)));
1597                                } else {
1598                                        header = header.audience(JSONObjectUtils.getStringList(jsonObject, name));
1599                                }
1600                        } else {
1601                                header = header.customParam(name, jsonObject.get(name));
1602                        }
1603                }
1604
1605                return header.build();
1606        }
1607
1608
1609        /**
1610         * Parses a JWE header from the specified JSON object string.
1611         *
1612         * @param jsonString The JSON object string to parse. Must not be {@code null}.
1613         *
1614         * @return The JWE header.
1615         *
1616         * @throws ParseException If the specified JSON object string doesn't 
1617         *                        represent a valid JWE header.
1618         */
1619        public static JWEHeader parse(final String jsonString)
1620                throws ParseException {
1621
1622                return parse(JSONObjectUtils.parse(jsonString), null);
1623        }
1624
1625
1626        /**
1627         * Parses a JWE header from the specified JSON object string.
1628         *
1629         * @param jsonString      The JSON string to parse. Must not be
1630         *                        {@code null}.
1631         * @param parsedBase64URL The original parsed Base64URL, {@code null}
1632         *                        if not applicable.
1633         *
1634         * @return The JWE header.
1635         *
1636         * @throws ParseException If the specified JSON object string doesn't
1637         *                        represent a valid JWE header.
1638         */
1639        public static JWEHeader parse(final String jsonString,
1640                                      final Base64URL parsedBase64URL)
1641                throws ParseException {
1642
1643                return parse(JSONObjectUtils.parse(jsonString, MAX_HEADER_STRING_LENGTH), parsedBase64URL);
1644        }
1645
1646
1647        /**
1648         * Parses a JWE header from the specified Base64URL.
1649         *
1650         * @param base64URL The Base64URL to parse. Must not be {@code null}.
1651         *
1652         * @return The JWE header.
1653         *
1654         * @throws ParseException If the specified Base64URL doesn't represent
1655         *                        a valid JWE header.
1656         */
1657        public static JWEHeader parse(final Base64URL base64URL)
1658                throws ParseException {
1659
1660                return parse(base64URL.decodeToString(), base64URL);
1661        }
1662}