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