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}