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