001    package com.nimbusds.jose;
002    
003    
004    import java.net.URL;
005    import java.text.ParseException;
006    import java.util.Arrays;
007    
008    import net.minidev.json.JSONArray;
009    import net.minidev.json.JSONObject;
010    
011    import com.nimbusds.jose.jwk.JWK;
012    import com.nimbusds.jose.util.Base64;
013    import 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     */
037    public 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    }