001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions Copyrighted [year] [name of copyright owner]". 013 * 014 * Copyright 2013-2016 ForgeRock AS. 015 */ 016 017package org.forgerock.json.jose.jwk; 018 019import java.io.IOException; 020import java.util.List; 021import java.util.Map; 022 023import org.forgerock.json.JsonException; 024import org.forgerock.json.JsonValue; 025import org.forgerock.json.jose.jwt.JWObject; 026 027import com.fasterxml.jackson.databind.ObjectMapper; 028 029/** 030 * The abstract base class for the 3 implementations of JWK. 031 */ 032public abstract class JWK extends JWObject { 033 /** 034 * The KeyType key. 035 */ 036 protected static final String KTY = "kty"; 037 038 /** 039 * The KeyUse key. 040 */ 041 protected static final String USE = "use"; 042 043 /** 044 * The Algorithm key. 045 */ 046 protected static final String ALG = "alg"; 047 048 /** 049 * The KeyID key. 050 */ 051 protected static final String KID = "kid"; 052 053 /** 054 * The X509 URL key. 055 */ 056 protected static final String X5U = "x5u"; 057 058 /** 059 * The X509 thumbnail key. 060 */ 061 protected static final String X5T = "x5t"; 062 063 /** 064 * The X509 chain key. 065 */ 066 protected static final String X5C = "x5c"; 067 068 /** 069 * Creates a JWK given the basic parameters. 070 * @param kty the JWK key type 071 * @param use the JWK use 072 * @param alg the JWK algorithm 073 * @param kid the JWK key id 074 */ 075 protected JWK(KeyType kty, KeyUse use, String alg, String kid) { 076 this(kty, use, alg, kid, null, null, null); 077 } 078 079 /** 080 * Creates a JWK given the basic parameters. 081 * @param kty the JWK key type 082 * @param use the JWK use 083 * @param alg the JWK algorithm 084 * @param kid the JWK key id 085 * @param x5u the x509 url for the key 086 * @param x5t the x509 thumbnail for the key 087 * @param x5c the x509 chain as a list of Base64 encoded strings 088 */ 089 protected JWK(KeyType kty, KeyUse use, String alg, String kid, String x5u, String x5t, List<String> x5c) { 090 super(); 091 if (kty == null) { 092 new JsonException("kty is a required field"); 093 } 094 put(KTY, kty.toString()); 095 if (kid == null || kid.isEmpty()) { 096 new JsonException("kid is a required field"); 097 } 098 put(KID, kid); 099 if (use != null) { 100 put(USE, use.toString()); 101 } 102 if (alg != null && !alg.isEmpty()) { 103 put(ALG, alg); 104 } 105 if (x5c != null && !x5c.isEmpty()) { 106 put(X5C, x5c); 107 } 108 if (x5t != null && !x5t.isEmpty()) { 109 put(X5T, x5t); 110 } 111 if (x5u != null && !x5u.isEmpty()) { 112 put(X5U, x5u); 113 } 114 } 115 116 /** 117 * Gets the kty parameter of the JWK. 118 * @return A KeyType for the JWK 119 */ 120 public KeyType getKeyType() { 121 return KeyType.getKeyType(get(KTY).asString()); 122 } 123 124 /** 125 * Gets the use parameter of the JWK. 126 * @return A String representing the use parameter 127 */ 128 public KeyUse getUse() { 129 return KeyUse.getKeyUse(get(USE).asString()); 130 } 131 132 /** 133 * Gets the alg parameter of the JWK. 134 * @return A String representing the alg parameter 135 */ 136 public String getAlgorithm() { 137 return get(ALG).asString(); 138 } 139 140 /** 141 * Gets the kid parameter of the JWK. 142 * @return A String representing the kid parameter 143 */ 144 public String getKeyId() { 145 return get(KID).asString(); 146 } 147 148 /** 149 * Prints the JWK Object as a json string. 150 * @return A String representing JWK 151 */ 152 public String toJsonString() { 153 return toString(); 154 } 155 156 /** 157 * Parses a String into the proper JWK type. 158 * 159 * @param json The json String. 160 * @return A JWK object 161 * @throws org.forgerock.json.JsonException If there is a problem parsing the json String. 162 */ 163 public static JWK parse(String json) { 164 JsonValue jwk = new JsonValue(toJsonValue(json)); 165 return parse(jwk); 166 } 167 168 /** 169 * Parses a JsonValue into the proper JWK type. 170 * 171 * @param jwk The JsonValue Object. 172 * @return A JWK object 173 * @throws org.forgerock.json.JsonException If there is a problem parsing the json String. 174 */ 175 public static JWK parse(JsonValue jwk) { 176 KeyType kty = KeyType.getKeyType(jwk.get(KTY).asString()); 177 178 if (kty.equals(KeyType.RSA)) { 179 return RsaJWK.parse(jwk); 180 } else if (kty.equals(KeyType.OCT)) { 181 return OctJWK.parse(jwk); 182 } else if (kty.equals(KeyType.EC)) { 183 return EcJWK.parse(jwk); 184 } else { 185 throw new JsonException("Failed to parse json invalid kty parameter"); 186 } 187 } 188 189 /** 190 * Converts a String into a JsonValue. 191 * 192 * @param json The json String. 193 * @return A JsonValue object. 194 * @throws org.forgerock.json.JsonException If there is a problem parsing the json String. 195 */ 196 protected static JsonValue toJsonValue(String json) { 197 ObjectMapper mapper = new ObjectMapper(); 198 try { 199 return new JsonValue(mapper.readValue(json, Map.class)); 200 } catch (IOException e) { 201 throw new JsonException("Failed to parse json", e); 202 } 203 } 204 205 /** 206 * Gets the X509 URL. 207 * @return the url of the 509 cert header or null 208 */ 209 public String getX509URL() { 210 return get(X5U).asString(); 211 } 212 213 /** 214 * Gets the X509 thumbnail. 215 * @return Base64url of the X509 thumbnail 216 */ 217 public String getX509Thumbnail() { 218 return get(X5T).asString(); 219 } 220 221 /** 222 * Gets a List of X509 chain certs. 223 * @return X509 Cert Chain as list of encoded strings or null if none are available. 224 */ 225 public List<String> getX509Chain() { 226 return get(X5C).asList(String.class); 227 } 228}