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