001    package com.nimbusds.jose.jwk;
002    
003    
004    import java.text.ParseException;
005    
006    import net.jcip.annotations.Immutable;
007    import net.minidev.json.JSONObject;
008    
009    import com.nimbusds.jose.Algorithm;
010    import com.nimbusds.jose.util.Base64URL;
011    import com.nimbusds.jose.util.JSONObjectUtils;
012    
013    
014    /**
015     * {@link KeyType#OCT Octet sequence} JSON Web Key (JWK), used to represent
016     * symmetric keys. This class is immutable.
017     *
018     * <p>Example JSON object representation of an octet sequence JWK:
019     *
020     * <pre>
021     * {
022     *   "kty" : "oct",
023     *   "alg" : "A128KW",
024     *   "k"   : "GawgguFyGrWKav7AX4VKUg"
025     * }
026     * </pre>
027     * 
028     * @author Justin Richer
029     * @author Vladimir Dzhuvinov
030     * @version $version$ (2013-03-26)
031     */
032    @Immutable
033    public class OctetSequenceKey extends JWK {
034    
035    
036            /**
037             * The symmetric key value.
038             */
039            private final Base64URL k;
040    
041            
042            /**
043             * Creates a new octet sequence JSON Web Key (JWK) with the specified
044             * parameters.
045             *
046             * @param k   The key value. It is represented as the Base64URL 
047             *            encoding of value's big endian representation. Must not 
048             *            be {@code null}.
049             * @param use The key use. {@code null} if not specified.
050             * @param alg The intended JOSE algorithm for the key, {@code null} if
051             *            not specified.
052             * @param kid The key ID. {@code null} if not specified.
053             */
054            public OctetSequenceKey(final Base64URL k, final Use use, final Algorithm alg, final String kid) {
055            
056                    super(KeyType.OCT, use, alg, kid);
057    
058                    if (k == null) {
059    
060                            throw new IllegalArgumentException("The key value must not be null");
061                    }
062    
063                    this.k = k;
064            }
065    
066    
067            /**
068             * Creates a new octet sequence JSON Web Key (JWK) with the specified
069             * parameters.
070             *
071             * @param k   The key value. It is represented as the value's big 
072             *            endian representation. Must not be {@code null}.
073             * @param use The key use. {@code null} if not specified.
074             * @param alg The intended JOSE algorithm for the key, {@code null} if
075             *            not specified.
076             * @param kid The key ID. {@code null} if not specified.
077             */
078            public OctetSequenceKey(final byte[] k, final Use use, final Algorithm alg, final String kid) {
079            
080                    super(KeyType.OCT, use, alg, kid);
081    
082                    if (k == null) {
083    
084                            throw new IllegalArgumentException("The key value must not be null");
085                    }
086    
087                    this.k = Base64URL.encode(k);
088            }
089        
090    
091            /**
092             * Returns the value of this octet sequence key. It is represented as 
093             * the Base64URL encoding of the coordinate's big endian 
094             * representation.
095             *
096             * @return The key value. 
097             */
098            public Base64URL getKeyValue() {
099    
100                    return k;
101            }
102            
103            
104            /**
105             * Returns a copy of this octet sequence key value as a byte array.
106             * 
107             * @return The key value as a byte array.
108             */
109            public byte[] toByteArray() {
110    
111                    return getKeyValue().decode();
112            }
113    
114    
115            /**
116             * Octet sequence (symmetric) keys are never considered public, this 
117             * method always returns {@code true}.
118             *
119             * @return {@code true}
120             */
121            @Override
122            public boolean isPrivate() {
123    
124                    return true;
125            }
126    
127    
128            /**
129             * Octet sequence (symmetric) keys are never considered public, this 
130             * method always returns {@code null}.
131             *
132             * @return {@code null}
133             */
134            @Override
135            public OctetSequenceKey toPublicJWK() {
136    
137                    return null;
138            }
139            
140    
141            @Override
142            public JSONObject toJSONObject() {
143    
144                    JSONObject o = super.toJSONObject();
145    
146                    // Append key value
147                    o.put("k", k.toString());
148                    
149                    return o;
150            }
151    
152    
153            /**
154             * Parses an octet sequence JWK from the specified JSON object string 
155             * representation.
156             *
157             * @param s The JSON object string to parse. Must not be {@code null}.
158             *
159             * @return The octet sequence JWK.
160             *
161             * @throws ParseException If the string couldn't be parsed to an octet
162             *                        sequence JWK.
163             */
164            public static OctetSequenceKey parse(final String s)
165                    throws ParseException {
166    
167                    return parse(JSONObjectUtils.parseJSONObject(s));
168            }
169    
170            
171            /**
172             * Parses an octet sequence JWK from the specified JSON object 
173             * representation.
174             *
175             * @param jsonObject The JSON object to parse. Must not be 
176             *                   @code null}.
177             *
178             * @return The octet sequence JWK.
179             *
180             * @throws ParseException If the JSON object couldn't be parsed to an
181             *                        octet sequence JWK.
182             */
183            public static OctetSequenceKey parse(final JSONObject jsonObject) 
184                    throws ParseException {
185    
186                    // Parse the mandatory parameters first
187                    Base64URL k = new Base64URL(JSONObjectUtils.getString(jsonObject, "k"));
188    
189                    // Check key type
190                    KeyType kty = KeyType.parse(JSONObjectUtils.getString(jsonObject, "kty"));
191    
192                    if (kty != KeyType.OCT) {
193    
194                            throw new ParseException("The key type \"kty\" must be oct", 0);
195                    }
196                    
197                    // Get optional key use
198                    Use use = JWK.parseKeyUse(jsonObject);
199    
200                    // Get optional intended algorithm
201                    Algorithm alg = JWK.parseAlgorithm(jsonObject);
202    
203                    // Get optional key ID
204                    String kid = JWK.parseKeyID(jsonObject);
205    
206                    return new OctetSequenceKey(k, use, alg, kid);
207            }
208    }