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 2019-10-04
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        public JWEAlgorithm getAlgorithm() {
920
921                return (JWEAlgorithm)super.getAlgorithm();
922        }
923
924
925        /**
926         * Gets the encryption method ({@code enc}) parameter.
927         *
928         * @return The encryption method parameter.
929         */
930        public EncryptionMethod getEncryptionMethod() {
931
932                return enc;
933        }
934
935
936        /**
937         * Gets the Ephemeral Public Key ({@code epk}) parameter.
938         *
939         * @return The Ephemeral Public Key parameter, {@code null} if not
940         *         specified.
941         */
942        public JWK getEphemeralPublicKey() {
943
944                return epk;
945        }
946
947
948        /**
949         * Gets the compression algorithm ({@code zip}) parameter.
950         *
951         * @return The compression algorithm parameter, {@code null} if not
952         *         specified.
953         */
954        public CompressionAlgorithm getCompressionAlgorithm() {
955
956                return zip;
957        }
958
959
960        /**
961         * Gets the agreement PartyUInfo ({@code apu}) parameter.
962         *
963         * @return The agreement PartyUInfo parameter, {@code null} if not
964         *         specified.
965         */
966        public Base64URL getAgreementPartyUInfo() {
967
968                return apu;
969        }
970
971
972        /**
973         * Gets the agreement PartyVInfo ({@code apv}) parameter.
974         *
975         * @return The agreement PartyVInfo parameter, {@code null} if not
976         *         specified.
977         */
978        public Base64URL getAgreementPartyVInfo() {
979
980                return apv;
981        }
982
983
984        /**
985         * Gets the PBES2 salt ({@code p2s}) parameter.
986         *
987         * @return The PBES2 salt parameter, {@code null} if not specified.
988         */
989        public Base64URL getPBES2Salt() {
990
991                return p2s;
992        }
993
994
995        /**
996         * Gets the PBES2 count ({@code p2c}) parameter.
997         *
998         * @return The PBES2 count parameter, zero if not specified.
999         */
1000        public int getPBES2Count() {
1001
1002                return p2c;
1003        }
1004
1005
1006        /**
1007         * Gets the initialisation vector ({@code iv}) parameter.
1008         *
1009         * @return The initialisation vector, {@code null} if not specified.
1010         */
1011        public Base64URL getIV() {
1012
1013                return iv;
1014        }
1015
1016
1017        /**
1018         * Gets the authentication tag ({@code tag}) parameter.
1019         *
1020         * @return The authentication tag, {@code null} if not specified.
1021         */
1022        public Base64URL getAuthTag() {
1023
1024                return tag;
1025        }
1026
1027
1028        @Override
1029        public Set<String> getIncludedParams() {
1030
1031                Set<String> includedParameters = super.getIncludedParams();
1032
1033                if (enc != null) {
1034                        includedParameters.add("enc");
1035                }
1036
1037                if (epk != null) {
1038                        includedParameters.add("epk");
1039                }
1040
1041                if (zip != null) {
1042                        includedParameters.add("zip");
1043                }
1044
1045                if (apu != null) {
1046                        includedParameters.add("apu");
1047                }
1048                
1049                if (apv != null) {
1050                        includedParameters.add("apv");
1051                }
1052
1053                if (p2s != null) {
1054                        includedParameters.add("p2s");
1055                }
1056
1057                if (p2c > 0) {
1058                        includedParameters.add("p2c");
1059                }
1060
1061                if (iv != null) {
1062                        includedParameters.add("iv");
1063                }
1064
1065                if (tag != null) {
1066                        includedParameters.add("tag");
1067                }
1068
1069                return includedParameters;
1070        }
1071
1072
1073        @Override
1074        public Map<String, Object> toJSONObject() {
1075
1076                Map<String, Object> o = super.toJSONObject();
1077
1078                if (enc != null) {
1079                        o.put("enc", enc.toString());
1080                }
1081
1082                if (epk != null) {
1083                        o.put("epk", epk.toJSONObject());
1084                }
1085
1086                if (zip != null) {
1087                        o.put("zip", zip.toString());
1088                }
1089
1090                if (apu != null) {
1091                        o.put("apu", apu.toString());
1092                }
1093                
1094                if (apv != null) {
1095                        o.put("apv", apv.toString());
1096                }
1097
1098                if (p2s != null) {
1099                        o.put("p2s", p2s.toString());
1100                }
1101
1102                if (p2c > 0) {
1103                        o.put("p2c", p2c);
1104                }
1105
1106                if (iv != null) {
1107                        o.put("iv", iv.toString());
1108                }
1109
1110                if (tag != null) {
1111                        o.put("tag", tag.toString());
1112                }
1113
1114                return o;
1115        }
1116
1117
1118        /**
1119         * Parses an encryption method ({@code enc}) parameter from the 
1120         * specified JWE header JSON object.
1121         *
1122         * @param json The JSON object to parse. Must not be {@code null}.
1123         *
1124         * @return The encryption method.
1125         *
1126         * @throws ParseException If the {@code enc} parameter couldn't be 
1127         *                        parsed.
1128         */
1129        private static EncryptionMethod parseEncryptionMethod(final Map<String, Object> json)
1130                throws ParseException {
1131
1132                return EncryptionMethod.parse(JSONObjectUtils.getString(json, "enc"));
1133        }
1134
1135
1136        /**
1137         * Parses a JWE header from the specified JSON object.
1138         *
1139         * @param jsonObject The JSON object to parse. Must not be
1140         *                   {@code null}.
1141         *
1142         * @return The JWE header.
1143         *
1144         * @throws ParseException If the specified JSON object doesn't
1145         *                        represent a valid JWE header.
1146         */
1147        public static JWEHeader parse(final Map<String, Object> jsonObject)
1148                throws ParseException {
1149
1150                return parse(jsonObject, null);
1151        }
1152
1153
1154        /**
1155         * Parses a JWE header from the specified JSON object.
1156         *
1157         * @param jsonObject      The JSON object to parse. Must not be
1158         *                        {@code null}.
1159         * @param parsedBase64URL The original parsed Base64URL, {@code null}
1160         *                        if not applicable.
1161         *
1162         * @return The JWE header.
1163         *
1164         * @throws ParseException If the specified JSON object doesn't 
1165         *                        represent a valid JWE header.
1166         */
1167        public static JWEHeader parse(final Map<String, Object> jsonObject,
1168                                      final Base64URL parsedBase64URL)
1169                throws ParseException {
1170
1171                // Get the "alg" parameter
1172                Algorithm alg = Header.parseAlgorithm(jsonObject);
1173
1174                if (! (alg instanceof JWEAlgorithm)) {
1175                        throw new ParseException("The algorithm \"alg\" header parameter must be for encryption", 0);
1176                }
1177
1178                // Get the "enc" parameter
1179                EncryptionMethod enc = parseEncryptionMethod(jsonObject);
1180
1181                JWEHeader.Builder header = new Builder((JWEAlgorithm)alg, enc).parsedBase64URL(parsedBase64URL);
1182
1183                // Parse optional + custom parameters
1184                for(final String name: jsonObject.keySet()) {
1185
1186                        if("alg".equals(name)) {
1187                                // skip
1188                        } else if("enc".equals(name)) {
1189                                // skip
1190                        } else if("typ".equals(name)) {
1191                                String typValue = JSONObjectUtils.getString(jsonObject, name);
1192                                if (typValue != null) {
1193                                        header = header.type(new JOSEObjectType(typValue));
1194                                }
1195                        } else if("cty".equals(name)) {
1196                                header = header.contentType(JSONObjectUtils.getString(jsonObject, name));
1197                        } else if("crit".equals(name)) {
1198                                List<String> critValues = JSONObjectUtils.getStringList(jsonObject, name);
1199                                if (critValues != null) {
1200                                        header = header.criticalParams(new HashSet<>(critValues));
1201                                }
1202                        } else if("jku".equals(name)) {
1203                                header = header.jwkURL(JSONObjectUtils.getURI(jsonObject, name));
1204                        } else if("jwk".equals(name)) {
1205                                Map<String, Object> jwkObject = JSONObjectUtils.getJSONObject(jsonObject, name);
1206                                if (jwkObject != null) {
1207                                        header = header.jwk(JWK.parse(jwkObject));
1208                                }
1209                        } else if("x5u".equals(name)) {
1210                                header = header.x509CertURL(JSONObjectUtils.getURI(jsonObject, name));
1211                        } else if("x5t".equals(name)) {
1212                                header = header.x509CertThumbprint(Base64URL.from(JSONObjectUtils.getString(jsonObject, name)));
1213                        } else if("x5t#S256".equals(name)) {
1214                                header = header.x509CertSHA256Thumbprint(Base64URL.from(JSONObjectUtils.getString(jsonObject, name)));
1215                        } else if("x5c".equals(name)) {
1216                                header = header.x509CertChain(X509CertChainUtils.toBase64List(JSONObjectUtils.getJSONArray(jsonObject, name)));
1217                        } else if("kid".equals(name)) {
1218                                header = header.keyID(JSONObjectUtils.getString(jsonObject, name));
1219                        } else if("epk".equals(name)) {
1220                                header = header.ephemeralPublicKey(JWK.parse(JSONObjectUtils.getJSONObject(jsonObject, name)));
1221                        } else if("zip".equals(name)) {
1222                                String zipValue = JSONObjectUtils.getString(jsonObject, name);
1223                                if (zipValue != null) {
1224                                        header = header.compressionAlgorithm(new CompressionAlgorithm(zipValue));
1225                                }
1226                        } else if("apu".equals(name)) {
1227                                header = header.agreementPartyUInfo(Base64URL.from(JSONObjectUtils.getString(jsonObject, name)));
1228                        } else if("apv".equals(name)) {
1229                                header = header.agreementPartyVInfo(Base64URL.from(JSONObjectUtils.getString(jsonObject, name)));
1230                        } else if("p2s".equals(name)) {
1231                                header = header.pbes2Salt(Base64URL.from(JSONObjectUtils.getString(jsonObject, name)));
1232                        } else if("p2c".equals(name)) {
1233                                header = header.pbes2Count(JSONObjectUtils.getInt(jsonObject, name));
1234                        } else if("iv".equals(name)) {
1235                                header = header.iv(Base64URL.from(JSONObjectUtils.getString(jsonObject, name)));
1236                        } else if("tag".equals(name)) {
1237                                header = header.authTag(Base64URL.from(JSONObjectUtils.getString(jsonObject, name)));
1238                        } else {
1239                                header = header.customParam(name, jsonObject.get(name));
1240                        }
1241                }
1242
1243                return header.build();
1244        }
1245
1246
1247        /**
1248         * Parses a JWE header from the specified JSON object string.
1249         *
1250         * @param jsonString The JSON object string to parse. Must not be {@code null}.
1251         *
1252         * @return The JWE header.
1253         *
1254         * @throws ParseException If the specified JSON object string doesn't 
1255         *                        represent a valid JWE header.
1256         */
1257        public static JWEHeader parse(final String jsonString)
1258                throws ParseException {
1259
1260                return parse(JSONObjectUtils.parse(jsonString), null);
1261        }
1262
1263
1264        /**
1265         * Parses a JWE header from the specified JSON object string.
1266         *
1267         * @param jsonString      The JSON string to parse. Must not be
1268         *                        {@code null}.
1269         * @param parsedBase64URL The original parsed Base64URL, {@code null}
1270         *                        if not applicable.
1271         *
1272         * @return The JWE header.
1273         *
1274         * @throws ParseException If the specified JSON object string doesn't
1275         *                        represent a valid JWE header.
1276         */
1277        public static JWEHeader parse(final String jsonString,
1278                                      final Base64URL parsedBase64URL)
1279                throws ParseException {
1280
1281                return parse(JSONObjectUtils.parse(jsonString), parsedBase64URL);
1282        }
1283
1284
1285        /**
1286         * Parses a JWE header from the specified Base64URL.
1287         *
1288         * @param base64URL The Base64URL to parse. Must not be {@code null}.
1289         *
1290         * @return The JWE header.
1291         *
1292         * @throws ParseException If the specified Base64URL doesn't represent
1293         *                        a valid JWE header.
1294         */
1295        public static JWEHeader parse(final Base64URL base64URL)
1296                throws ParseException {
1297
1298                return parse(base64URL.decodeToString(), base64URL);
1299        }
1300}