com.nimbusds.jose.jwk.JWKSet Maven / Gradle / Ivy
Show all versions of nimbus-jose-jwt Show documentation
/*
* nimbus-jose-jwt
*
* Copyright 2012-2018, Connect2id Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use
* this file except in compliance with the License. You may obtain a copy of the
* License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.nimbusds.jose.jwk;
import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.util.*;
import net.jcip.annotations.Immutable;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.net.Proxy;
import java.net.URL;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.cert.Certificate;
import java.security.interfaces.ECPublicKey;
import java.security.interfaces.RSAPublicKey;
import java.text.ParseException;
import java.util.*;
/**
* JSON Web Key (JWK) set. Represented by a JSON object that contains an array
* of {@link JWK JSON Web Keys} (JWKs) as the value of its "keys" member.
* Additional (custom) members of the JWK Set JSON object are also supported.
*
* Example JWK set:
*
*
* {
* "keys" : [ { "kty" : "EC",
* "crv" : "P-256",
* "x" : "MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4",
* "y" : "4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM",
* "use" : "enc",
* "kid" : "1" },
*
* { "kty" : "RSA",
* "n" : "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx
* 4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMs
* tn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2
* QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbI
* SD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqb
* w0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
* "e" : "AQAB",
* "alg" : "RS256",
* "kid" : "2011-04-29" } ]
* }
*
*
* @author Vladimir Dzhuvinov
* @author Vedran Pavic
* @version 2024-03-17
*/
@Immutable
public class JWKSet implements Serializable {
private static final long serialVersionUID = 1L;
/**
* The MIME type of JWK set objects:
* {@code application/jwk-set+json; charset=UTF-8}
*/
public static final String MIME_TYPE = "application/jwk-set+json; charset=UTF-8";
/**
* The JWK list.
*/
private final List keys;
/**
* Additional custom members.
*/
private final Map customMembers;
/**
* Creates a new empty JWK set.
*/
public JWKSet() {
this(Collections.emptyList());
}
/**
* Creates a new JWK set with a single key.
*
* @param key The JWK. Must not be {@code null}.
*/
public JWKSet(final JWK key) {
this(Collections.singletonList(Objects.requireNonNull(key, "The JWK must not be null")));
}
/**
* Creates a new JWK set with the specified keys.
*
* @param keys The JWK list. Must not be {@code null}.
*/
public JWKSet(final List keys) {
this(keys, Collections.emptyMap());
}
/**
* Creates a new JWK set with the specified keys and additional custom
* members.
*
* @param keys The JWK list. Must not be {@code null}.
* @param customMembers The additional custom members. Must not be
* {@code null}.
*/
public JWKSet(final List keys, final Map customMembers) {
this.keys = Collections.unmodifiableList(Objects.requireNonNull(keys, "The JWK list must not be null"));
this.customMembers = Collections.unmodifiableMap(customMembers);
}
/**
* Returns the keys (ordered) of this JWK set.
*
* @return The keys as an unmodifiable list, empty list if none.
*/
public List getKeys() {
return keys;
}
/**
* Returns {@code true} if this JWK set is empty.
*
* @return {@code true} if empty, else {@code false}.
*/
public boolean isEmpty() {
return keys.isEmpty();
}
/**
* Returns the number of keys in this JWK set.
*
* @return The number of keys, zero if none.
*/
public int size() {
return keys.size();
}
/**
* Returns the key from this JWK set as identified by its Key ID (kid)
* member.
*
* If more than one key exists in the JWK Set with the same
* identifier, this function returns only the first one in the set.
*
* @param kid They key identifier.
*
* @return The key identified by {@code kid} or {@code null} if no key
* exists.
*/
public JWK getKeyByKeyId(String kid) {
for (JWK key : getKeys()) {
if (key.getKeyID() != null && key.getKeyID().equals(kid)) {
return key;
}
}
// no key found
return null;
}
/**
* Returns {@code true} if this JWK set contains the specified JWK as
* public or private key, by comparing its thumbprint with those of the
* keys in the set.
*
* @param jwk The JWK to check. Must not be {@code null}.
*
* @return {@code true} if contained, {@code false} if not.
*
* @throws JOSEException If thumbprint computation failed.
*/
public boolean containsJWK(final JWK jwk) throws JOSEException {
Base64URL thumbprint = jwk.computeThumbprint();
for (JWK k: getKeys()) {
if (thumbprint.equals(k.computeThumbprint())) {
return true; // found
}
}
return false;
}
/**
* Returns the additional custom members of this (JWK) set.
*
* @return The additional custom members as an unmodifiable map, empty
* map if none.
*/
public Map getAdditionalMembers() {
return customMembers;
}
/**
* Returns a copy of this (JWK) set with all private keys and
* parameters removed.
*
* @return A copy of this JWK set with all private keys and parameters
* removed.
*/
public JWKSet toPublicJWKSet() {
List publicKeyList = new LinkedList<>();
for (JWK key: keys) {
JWK publicKey = key.toPublicJWK();
if (publicKey != null) {
publicKeyList.add(publicKey);
}
}
return new JWKSet(publicKeyList, customMembers);
}
/**
* Filters the keys in this JWK set.
*
* @param jwkMatcher The JWK matcher to filter the keys. Must not be
* {@code null}.
*
* @return The new filtered JWK set.
*/
public JWKSet filter(final JWKMatcher jwkMatcher) {
List matches = new LinkedList<>();
for (JWK key: keys) {
if (jwkMatcher.matches(key)) {
matches.add(key);
}
}
return new JWKSet(matches, customMembers);
}
/**
* Returns {@code true} if this JWK set contains non-public keys.
*
* @return {@code true} if non-public keys are found, {@code false} if
* there are only public keys in the JWK set.
*/
public boolean containsNonPublicKeys() {
for (JWK jwk: getKeys()) {
if (jwk.isPrivate()) {
return true;
}
}
return false;
}
/**
* Returns the JSON object representation of this JWK set. Only public
* keys will be included. Use the alternative
* {@link #toJSONObject(boolean)} method to include all key material.
*
* @return The JSON object representation.
*/
public Map toJSONObject() {
return toJSONObject(true);
}
/**
* Returns the JSON object representation of this JWK set.
*
* @param publicKeysOnly Controls the inclusion of private keys and
* parameters into the output JWK members. If
* {@code true} only public keys will be
* included. If {@code false} all available keys
* with their parameters will be included.
*
* @return The JSON object representation.
*/
public Map toJSONObject(final boolean publicKeysOnly) {
Map o = JSONObjectUtils.newJSONObject();
o.putAll(customMembers);
List