001package com.nimbusds.jose;
002
003
004import java.net.URL;
005import java.text.ParseException;
006import java.util.Arrays;
007
008import net.minidev.json.JSONArray;
009import net.minidev.json.JSONObject;
010
011import com.nimbusds.jose.jwk.JWK;
012import com.nimbusds.jose.util.Base64;
013import com.nimbusds.jose.util.Base64URL;
014
015
016/**
017 * Common class for JWS and JWE headers.
018 *
019 * <p>Supports all reserved header parameters shared by the JWS and JWE
020 * specifications:
021 *
022 * <ul>
023 *     <li>alg
024 *     <li>jku
025 *     <li>jwk
026 *     <li>x5u
027 *     <li>x5t
028 *     <li>x5c
029 *     <li>kid
030 *     <li>typ
031 *     <li>cty
032 * </ul>
033 *
034 * @author Vladimir Dzhuvinov
035 * @version $version$ (2012-09-22)
036 */
037public abstract class CommonSEHeader extends Header implements ReadOnlyCommonSEHeader {
038
039
040        /**
041         * JWK Set URL, {@code null} if not specified.
042         */
043        private URL jku;
044
045
046        /**
047         * JWK, {@code null} if not specified.
048         */
049        private JWK jwk;
050
051
052        /**
053         * X.509 certificate URL, {@code null} if not specified.
054         */
055        private URL x5u;
056
057
058        /**
059         * X.509 certificate thumbprint, {@code null} if not specified.
060         */
061        private Base64URL x5t;
062
063
064        /**
065         * The X.509 certificate chain corresponding to the key used to sign or 
066         * encrypt the JWS/JWE object, {@code null} if not specified.
067         */
068        private Base64[] x5c;
069
070
071        /**
072         * Key ID, {@code null} if not specified.
073         */
074        private String kid;
075
076
077        /**
078         * Creates a new common JWS and JWE header with the specified algorithm 
079         * ({@code alg}) parameter.
080         *
081         * @param alg The algorithm parameter. Must not be {@code null}.
082         */
083        protected CommonSEHeader(final Algorithm alg) {
084
085                super(alg);
086        }
087
088
089        @Override
090        public URL getJWKURL() {
091
092                return jku;
093        }
094
095
096        /**
097         * Sets the JSON Web Key (JWK) Set URL ({@code jku}) parameter.
098         *
099         * @param jku The JSON Web Key (JWK) Set URL parameter, {@code null} if 
100         *            not specified.
101         */
102        public void setJWKURL(final URL jku) {
103
104                this.jku = jku;
105        }
106
107
108        @Override
109        public JWK getJWK() {
110
111                return jwk;
112        }
113
114
115        /**
116         * Sets the JSON Web Key (JWK) ({@code jwk}) parameter.
117         *
118         * @param jwk The JSON Web Key (JWK) ({@code jwk}) parameter, 
119         *            {@code null} if not specified.
120         */
121        public void setJWK(final JWK jwk) {
122
123                this.jwk = jwk;
124        }
125
126
127        @Override
128        public URL getX509CertURL() {
129
130                return x5u;
131        }
132
133
134        /**
135         * Sets the X.509 certificate URL ({@code x5u}) parameter.
136         *
137         * @param x5u The X.509 certificate URL parameter, {@code null} if not 
138         *            specified.
139         */
140        public void setX509CertURL(final URL x5u) {
141
142                this.x5u = x5u;
143        }
144
145
146        @Override
147        public Base64URL getX509CertThumbprint() {
148
149                return x5t;
150        }
151
152
153        /**
154         * Sets the X.509 certificate thumbprint ({@code x5t}) parameter.
155         *
156         * @param x5t The X.509 certificate thumbprint parameter, {@code null}  
157         *            if not specified.
158         */
159        public void setX509CertThumbprint(final Base64URL x5t) {
160
161                this.x5t = x5t;
162        }
163
164
165        @Override
166        public Base64[] getX509CertChain() {
167
168                return x5c;
169        }
170
171
172        /**
173         * Sets the X.509 certificate chain parameter ({@code x5c}) 
174         * corresponding to the key used to sign or encrypt the JWS/JWE object.
175         *
176         * @param x5c The X.509 certificate chain parameter, {@code null} if not
177         *            specified.
178         */
179        public void setX509CertChain(final Base64[] x5c) {
180
181                this.x5c = x5c;
182        }
183
184
185        @Override
186        public String getKeyID() {
187
188                return kid;
189        }
190
191
192        /**
193         * Sets the key ID ({@code kid}) parameter.
194         *
195         * @param kid The key ID parameter, {@code null} if not specified.
196         */
197        public void setKeyID(final String kid) {
198
199                this.kid = kid;
200        }
201
202
203        @Override
204        public JSONObject toJSONObject() {
205
206                JSONObject o = super.toJSONObject();
207
208                if (jku != null) {
209                        o.put("jku", jku.toString());
210                }
211
212                if (jwk != null) {
213                        o.put("jwk", jwk.toJSONObject());
214                }
215
216                if (x5u != null) {
217                        o.put("x5u", x5u.toString());
218                }
219
220                if (x5t != null) {
221                        o.put("x5t", x5t.toString());
222                }
223
224                if (x5c != null) {
225                        o.put("x5c", Arrays.asList(x5c));
226                }
227
228                if (kid != null) {
229                        o.put("kid", kid);
230                }
231
232                return o;
233        }
234
235
236        /**
237         * Parses an X.509 certificate chain from the specified JSON array.
238         *
239         * @param jsonArray The JSON array to parse. Must not be {@code null}.
240         *
241         * @return The X.509 certificate chain.
242         *
243         * @throws ParseException If the X.509 certificate chain couldn't be
244         *                        parsed.
245         */
246        protected static Base64[] parseX509CertChain(final JSONArray jsonArray)
247                        throws ParseException {
248
249                Base64[] chain = new Base64[jsonArray.size()];
250
251                for (int i=0; i < jsonArray.size(); i++) {
252
253                        Object item = jsonArray.get(i);
254
255                        if (item == null) {
256                                throw new ParseException("The X.509 certificate at position " + i + " must not be null", 0);
257                        }
258
259                        if  (! (item instanceof String)) {
260                                throw new ParseException("The X.509 certificate must be encoded as a Base64 string", 0);
261                        }
262
263                        chain[i] = new Base64((String)item);
264                }
265
266                return chain;
267        }
268}