001package com.nimbusds.jose.jwk; 002 003 004import java.util.*; 005 006import com.nimbusds.jose.Algorithm; 007 008 009/** 010 * Utility for selecting one or more JSON Web Keys (JWKs) from a JWK set. 011 * 012 * <p>Supports key selection by: 013 * 014 * <ul> 015 * <li>Any, unspecified, one or more key types (typ). 016 * <li>Any, unspecified, one or more key uses (use). 017 * <li>Any, unspecified, one or more key operations (key_ops). 018 * <li>Any, unspecified, one or more key algorithms (alg). 019 * <li>Any, unspecified, one or more key identifiers (kid). 020 * <li>Private only key. 021 * <li>Public only key. 022 * </ul> 023 * 024 * <p>Selection by X.509 certificate URL, thumbprint and chain is not 025 * supported. 026 * 027 * @author Vladimir Dzhuvinov 028 * @version $version$ (2014-04-03) 029 */ 030public class JWKSelector { 031 032 033 /** 034 * The selected key types. 035 */ 036 private Set<KeyType> types; 037 038 039 /** 040 * The selected public key uses. 041 */ 042 private Set<KeyUse> uses; 043 044 045 /** 046 * The selected key operations. 047 */ 048 private Set<KeyOperation> ops; 049 050 051 /** 052 * The selected algorithms. 053 */ 054 private Set<Algorithm> algs; 055 056 057 /** 058 * The selected key IDs. 059 */ 060 private Set<String> ids; 061 062 063 /** 064 * If {@code true} only private keys are matched. 065 */ 066 private boolean privateOnly = false; 067 068 069 /** 070 * If {@code true} only public keys are matched. 071 */ 072 private boolean publicOnly = false; 073 074 075 /** 076 * Gets the selected key types. 077 * 078 * @return The key types, {@code null} if not specified. 079 */ 080 public Set<KeyType> getKeyTypes() { 081 082 return types; 083 } 084 085 086 /** 087 * Sets a single selected key type. 088 * 089 * @param kty The key type, {@code null} if not specified. 090 */ 091 public void setKeyType(final KeyType kty) { 092 093 if (kty == null) { 094 types = null; 095 } else { 096 types = new HashSet<>(Arrays.asList(kty)); 097 } 098 } 099 100 101 /** 102 * Sets the selected key types. 103 * 104 * @param types The key types. 105 */ 106 public void setKeyTypes(final KeyType ... types) { 107 108 setKeyTypes(new HashSet<>(Arrays.asList(types))); 109 } 110 111 112 /** 113 * Sets the selected key types. 114 * 115 * @param types The key types, {@code null} if not specified. 116 */ 117 public void setKeyTypes(final Set<KeyType> types) { 118 119 this.types = types; 120 } 121 122 123 /** 124 * Gets the selected public key uses. 125 * 126 * @return The public key uses, {@code null} if not specified. 127 */ 128 public Set<KeyUse> getKeyUses() { 129 130 return uses; 131 } 132 133 134 /** 135 * Sets a single selected public key use. 136 * 137 * @param use The public key use, {@code null} if not specified. 138 */ 139 public void setKeyUse(final KeyUse use) { 140 141 if (use == null) { 142 uses = null; 143 } else { 144 uses = new HashSet<>(Arrays.asList(use)); 145 } 146 } 147 148 149 /** 150 * Sets the selected public key uses. 151 * 152 * @param uses The public key uses. 153 */ 154 public void setKeyUses(final KeyUse... uses) { 155 156 setKeyUses(new HashSet<>(Arrays.asList(uses))); 157 } 158 159 160 /** 161 * Sets the selected public key uses. 162 * 163 * @param uses The public key uses, {@code null} if not specified. 164 */ 165 public void setKeyUses(final Set<KeyUse> uses) { 166 167 this.uses = uses; 168 } 169 170 171 /** 172 * Gets the selected key operations. 173 * 174 * @return The key operations, {@code null} if not specified. 175 */ 176 public Set<KeyOperation> getKeyOperations() { 177 178 return ops; 179 } 180 181 182 /** 183 * Sets a single selected key operation. 184 * 185 * @param op The key operation, {@code null} if not specified. 186 */ 187 public void setKeyOperation(final KeyOperation op) { 188 189 if (op == null) { 190 ops = null; 191 } else { 192 ops = new HashSet<>(Arrays.asList(op)); 193 } 194 } 195 196 197 /** 198 * Sets the selected key operations. 199 * 200 * @param ops The key operations. 201 */ 202 public void setKeyOperations(final KeyOperation... ops) { 203 204 setKeyOperations(new HashSet<>(Arrays.asList(ops))); 205 } 206 207 208 /** 209 * Sets the selected key operations. 210 * 211 * @param ops The key operations, {@code null} if not specified. 212 */ 213 public void setKeyOperations(final Set<KeyOperation> ops) { 214 215 this.ops = ops; 216 } 217 218 219 /** 220 * Gets the selected JOSE algorithms. 221 * 222 * @return The JOSE algorithms, {@code null} if not specified. 223 */ 224 public Set<Algorithm> getAlgorithms() { 225 226 return algs; 227 } 228 229 230 /** 231 * Sets a singled selected JOSE algorithm. 232 * 233 * @param alg The JOSE algorithm, {@code null} if not specified. 234 */ 235 public void setAlgorithm(final Algorithm alg) { 236 237 if (alg == null) { 238 algs = null; 239 } else { 240 algs = new HashSet<>(Arrays.asList(alg)); 241 } 242 } 243 244 245 /** 246 * Sets the selected JOSE algorithms. 247 * 248 * @param algs The JOSE algorithms. 249 */ 250 public void setAlgorithms(final Algorithm ... algs) { 251 252 setAlgorithms(new HashSet<>(Arrays.asList(algs))); 253 } 254 255 256 /** 257 * Sets the selected JOSE algorithms. 258 * 259 * @param algs The JOSE algorithms, {@code null} if not specified. 260 */ 261 public void setAlgorithms(final Set<Algorithm> algs) { 262 263 this.algs = algs; 264 } 265 266 267 /** 268 * Gets the selected key IDs. 269 * 270 * @return The key IDs, {@code null} if not specified. 271 */ 272 public Set<String> getKeyIDs() { 273 274 return ids; 275 } 276 277 278 /** 279 * Sets the selected key IDs. 280 * 281 * @param ids The key IDs. 282 */ 283 public void setKeyIDs(final String ... ids) { 284 285 setKeyIDs(new HashSet<>(Arrays.asList(ids))); 286 } 287 288 289 /** 290 * Sets the selected key IDs. 291 * 292 * @param ids The key IDs, {@code null} if not specified. 293 */ 294 public void setKeyIDs(final Set<String> ids) { 295 296 this.ids = ids; 297 } 298 299 300 /** 301 * Sets a single selected key ID. 302 * 303 * @param id The key ID, {@code null} if not specified. 304 */ 305 public void setKeyID(final String id) { 306 307 if (id == null) { 308 ids = null; 309 } else { 310 ids = new HashSet<>(Arrays.asList(id)); 311 } 312 } 313 314 315 /** 316 * Gets the selection of private keys. 317 * 318 * @return If {@code true} only private keys are selected. 319 */ 320 public boolean isPrivateOnly() { 321 322 return privateOnly; 323 } 324 325 326 /** 327 * Sets the selection of private keys. 328 * 329 * @param privateOnly If {@code true} only private keys are selected. 330 */ 331 public void setPrivateOnly(final boolean privateOnly) { 332 333 this.privateOnly = privateOnly; 334 } 335 336 337 /** 338 * Gets the selection of public keys. 339 * 340 * @return If {@code true} only public keys are selected. 341 */ 342 public boolean isPublicOnly() { 343 344 return publicOnly; 345 } 346 347 348 /** 349 * Sets the selection of public keys. 350 * 351 * @param publicOnly If {@code true} only public keys are selected. 352 */ 353 public void setPublicOnly(final boolean publicOnly) { 354 355 this.publicOnly = publicOnly; 356 } 357 358 359 /** 360 * Selects the keys from the specified JWK set that match the 361 * configured criteria. 362 * 363 * @param jwkSet The JWK set. May be {@code null}. 364 * 365 * @return The selected keys, ordered by their position in the JWK set, 366 * empty list if none were matched or the JWK is {@code null}. 367 * 368 */ 369 public List<JWK> select(final JWKSet jwkSet) { 370 371 List<JWK> matches = new LinkedList<>(); 372 373 if (jwkSet == null) 374 return matches; 375 376 for (JWK key: jwkSet.getKeys()) { 377 378 if (privateOnly && ! key.isPrivate()) 379 continue; 380 381 if (publicOnly && key.isPrivate()) 382 continue; 383 384 if (types != null && ! types.contains(key.getKeyType())) 385 continue; 386 387 if (uses != null && ! uses.contains(key.getKeyUse())) 388 continue; 389 390 if (ops != null) { 391 392 if (ops.contains(null) && key.getKeyOperations() == null) { 393 // pass 394 } else if (key.getKeyOperations() != null && ops.containsAll(key.getKeyOperations())) { 395 // pass 396 } else { 397 continue; 398 } 399 } 400 401 if (algs != null && ! algs.contains(key.getAlgorithm())) 402 continue; 403 404 if (ids != null && ! ids.contains(key.getKeyID())) 405 continue; 406 407 matches.add(key); 408 } 409 410 return matches; 411 } 412}