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