001    package com.nimbusds.jose;
002    
003    
004    import java.net.URL;
005    import java.util.Arrays;
006    
007    import java.text.ParseException;
008    
009    import net.minidev.json.JSONArray;
010    import net.minidev.json.JSONObject;
011    
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                    if (jwk != null)
212                            o.put("jwk", jwk.toJSONObject());
213                    
214                    if (x5u != null)
215                            o.put("x5u", x5u.toString());
216                    
217                    if (x5t != null)
218                            o.put("x5t", x5t.toString());
219            
220                    if (x5c != null)
221                            o.put("x5c", Arrays.asList(x5c));
222                    
223                    if (kid != null)
224                            o.put("kid", kid);
225                    
226                    return o;
227            }
228            
229            
230            /**
231             * Parses an X.509 certificate chain from the specified JSON array.
232             *
233             * @param jsonArray The JSON array to parse. Must not be {@code null}.
234             *
235             * @return The X.509 certificate chain.
236             *
237             * @throws ParseException If the X.509 certificate chain couldn't be
238             *                        parsed.
239             */
240            protected static Base64[] parseX509CertChain(final JSONArray jsonArray)
241                    throws ParseException {
242                    
243                    Base64[] chain = new Base64[jsonArray.size()];
244                    
245                    for (int i=0; i < jsonArray.size(); i++) {
246                    
247                            Object item = jsonArray.get(i);
248                            
249                            if (item == null)
250                                    throw new ParseException("The X.509 certificate at position " + i + " must not be null", 0);
251                    
252                            if  (! (item instanceof String))
253                                    throw new ParseException("The X.509 certificate must be encoded as a Base64 string", 0);
254                            
255                            chain[i] = new Base64((String)item);
256                    }
257                    
258                    return chain;
259            }
260    }