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-2015 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; 026import org.forgerock.util.encode.Base64; 027 028import com.fasterxml.jackson.databind.ObjectMapper; 029 030/** 031 * The abstract base class for the 3 implementations of JWK. 032 */ 033public abstract class JWK extends JWObject { 034 /** 035 * The KeyType key. 036 */ 037 protected static final String KTY = "kty"; 038 039 /** 040 * The KeyUse key. 041 */ 042 protected static final String USE = "use"; 043 044 /** 045 * The Algorithm key. 046 */ 047 protected static final String ALG = "alg"; 048 049 /** 050 * The KeyID key. 051 */ 052 protected static final String KID = "kid"; 053 054 /** 055 * The X509 URL key. 056 */ 057 protected static final String X5U = "x5u"; 058 059 /** 060 * The X509 thumbnail key. 061 */ 062 protected static final String X5T = "x5t"; 063 064 /** 065 * The X509 chain key. 066 */ 067 protected static final String X5C = "x5c"; 068 069 /** 070 * Creates a JWK given the basic parameters. 071 * @param kty the JWK key type 072 * @param use the JWK use 073 * @param alg the JWK algorithm 074 * @param kid the JWK key id 075 */ 076 protected JWK(KeyType kty, KeyUse use, String alg, String kid) { 077 this(kty, use, alg, kid, null, null, null); 078 } 079 080 /** 081 * Creates a JWK given the basic parameters. 082 * @param kty the JWK key type 083 * @param use the JWK use 084 * @param alg the JWK algorithm 085 * @param kid the JWK key id 086 * @param x5u the x509 url for the key 087 * @param x5t the x509 thumbnail for the key 088 * @param x5c the x509 chain 089 */ 090 protected JWK(KeyType kty, KeyUse use, String alg, String kid, String x5u, String x5t, List<Base64> x5c) { 091 super(); 092 if (kty == null) { 093 new JsonException("kty is a required field"); 094 } 095 put(KTY, kty.toString()); 096 if (kid == null || kid.isEmpty()) { 097 new JsonException("kid is a required field"); 098 } 099 put(KID, kid); 100 if (use != null) { 101 put(USE, use.toString()); 102 } 103 if (alg != null && !alg.isEmpty()) { 104 put(ALG, alg); 105 } 106 if (x5c != null && !x5c.isEmpty()) { 107 put(X5C, x5c); 108 } 109 if (x5t != null && !x5t.isEmpty()) { 110 put(X5T, x5t); 111 } 112 if (x5u != null && !x5u.isEmpty()) { 113 put(X5U, x5u); 114 } 115 } 116 117 /** 118 * Gets the kty parameter of the JWK. 119 * @return A KeyType for the JWK 120 */ 121 public KeyType getKeyType() { 122 return KeyType.getKeyType(get(KTY).asString()); 123 } 124 125 /** 126 * Gets the use parameter of the JWK. 127 * @return A String representing the use parameter 128 */ 129 public KeyUse getUse() { 130 return KeyUse.getKeyUse(get(USE).asString()); 131 } 132 133 /** 134 * Gets the alg parameter of the JWK. 135 * @return A String representing the alg parameter 136 */ 137 public String getAlgorithm() { 138 return get(ALG).asString(); 139 } 140 141 /** 142 * Gets the kid parameter of the JWK. 143 * @return A String representing the kid parameter 144 */ 145 public String getKeyId() { 146 return get(KID).asString(); 147 } 148 149 /** 150 * Prints the JWK Object as a json string. 151 * @return A String representing JWK 152 */ 153 public String toJsonString() { 154 return toString(); 155 } 156 157 /** 158 * Parses a String into the proper JWK type. 159 * 160 * @param json The json String. 161 * @return A JWK object 162 * @throws org.forgerock.json.JsonException If there is a problem parsing the json String. 163 */ 164 public static JWK parse(String json) { 165 JsonValue jwk = new JsonValue(toJsonValue(json)); 166 return parse(jwk); 167 } 168 169 /** 170 * Parses a JsonValue into the proper JWK type. 171 * 172 * @param jwk The JsonValue Object. 173 * @return A JWK object 174 * @throws org.forgerock.json.JsonException If there is a problem parsing the json String. 175 */ 176 public static JWK parse(JsonValue jwk) { 177 KeyType kty = KeyType.getKeyType(jwk.get(KTY).asString()); 178 179 if (kty.equals(KeyType.RSA)) { 180 return RsaJWK.parse(jwk); 181 } else if (kty.equals(KeyType.OCT)) { 182 return OctJWK.parse(jwk); 183 } else if (kty.equals(KeyType.EC)) { 184 return EcJWK.parse(jwk); 185 } else { 186 throw new JsonException("Failed to parse json invalid kty parameter"); 187 } 188 } 189 190 /** 191 * Converts a String into a JsonValue. 192 * 193 * @param json The json String. 194 * @return A JsonValue object. 195 * @throws org.forgerock.json.JsonException If there is a problem parsing the json String. 196 */ 197 protected static JsonValue toJsonValue(String json) { 198 ObjectMapper mapper = new ObjectMapper(); 199 try { 200 return new JsonValue(mapper.readValue(json, Map.class)); 201 } catch (IOException e) { 202 throw new JsonException("Failed to parse json", e); 203 } 204 } 205 206 /** 207 * Gets the X509 URL. 208 * @return the url of the 509 cert header or null 209 */ 210 public String getX509URL() { 211 return get(X5U).asString(); 212 } 213 214 /** 215 * Gets the X509 thumbnail. 216 * @return Base64url of the X509 thumbnail 217 */ 218 public String getX509Thumbnail() { 219 return get(X5T).asString(); 220 } 221 222 /** 223 * Gets a List of base64 encoded chain certs. 224 * @return X509 Cert Chain 225 */ 226 public List<Base64> getX509Chain() { 227 return get(X5C).asList(Base64.class); 228 } 229}