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