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