com.nimbusds.jose.jwk.OctetSequenceKey Maven / Gradle / Ivy
package com.nimbusds.jose.jwk;
import java.net.URI;
import java.util.LinkedHashMap;
import java.util.List;
import java.text.ParseException;
import java.util.Set;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import net.jcip.annotations.Immutable;
import net.minidev.json.JSONObject;
import com.nimbusds.jose.Algorithm;
import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.util.Base64;
import com.nimbusds.jose.util.Base64URL;
import com.nimbusds.jose.util.JSONObjectUtils;
/**
* {@link KeyType#OCT Octet sequence} JSON Web Key (JWK), used to represent
* symmetric keys. This class is immutable.
*
* Octet sequence JWKs should specify the algorithm intended to be used with
* the key, unless the application uses other means or convention to determine
* the algorithm used.
*
*
Example JSON object representation of an octet sequence JWK:
*
*
* {
* "kty" : "oct",
* "alg" : "A128KW",
* "k" : "GawgguFyGrWKav7AX4VKUg"
* }
*
*
* @author Justin Richer
* @author Vladimir Dzhuvinov
* @version 2015-12-08
*/
@Immutable
public final class OctetSequenceKey extends JWK implements SecretJWK {
private static final long serialVersionUID = 1L;
/**
* The key value.
*/
private final Base64URL k;
/**
* Builder for constructing octet sequence JWKs.
*
* Example usage:
*
*
* OctetSequenceKey key = new OctetSequenceKey.Builder(k).
* algorithm(JWSAlgorithm.HS512).
* keyID("123").
* build();
*
*/
public static class Builder {
/**
* The key value.
*/
private final Base64URL k;
/**
* The public key use, optional.
*/
private KeyUse use;
/**
* The key operations, optional.
*/
private Set ops;
/**
* The intended JOSE algorithm for the key, optional.
*/
private Algorithm alg;
/**
* The key ID, optional.
*/
private String kid;
/**
* X.509 certificate URL, optional.
*/
private URI x5u;
/**
* X.509 certificate thumbprint, optional.
*/
private Base64URL x5t;
/**
* The X.509 certificate chain, optional.
*/
private List x5c;
/**
* Creates a new octet sequence JWK builder.
*
* @param k The key value. It is represented as the Base64URL
* encoding of value's big endian representation. Must
* not be {@code null}.
*/
public Builder(final Base64URL k) {
if (k == null) {
throw new IllegalArgumentException("The key value must not be null");
}
this.k = k;
}
/**
* Creates a new octet sequence JWK builder.
*
* @param key The key value. Must not be empty byte array or
* {@code null}.
*/
public Builder(final byte[] key) {
this(Base64URL.encode(key));
if (key.length == 0) {
throw new IllegalArgumentException("The key must have a positive length");
}
}
/**
* Creates a new octet sequence JWK builder.
*
* @param secretKey The secret key to represent. Must not be
* {@code null}.
*/
public Builder(final SecretKey secretKey) {
this(secretKey.getEncoded());
}
/**
* Sets the use ({@code use}) of the JWK.
*
* @param use The key use, {@code null} if not specified or if
* the key is intended for signing as well as
* encryption.
*
* @return This builder.
*/
public Builder keyUse(final KeyUse use) {
this.use = use;
return this;
}
/**
* Sets the operations ({@code key_ops}) of the JWK (for a
* non-public key).
*
* @param ops The key operations, {@code null} if not
* specified.
*
* @return This builder.
*/
public Builder keyOperations(final Set ops) {
this.ops = ops;
return this;
}
/**
* Sets the intended JOSE algorithm ({@code alg}) for the JWK.
*
* @param alg The intended JOSE algorithm, {@code null} if not
* specified.
*
* @return This builder.
*/
public Builder algorithm(final Algorithm alg) {
this.alg = alg;
return this;
}
/**
* Sets the ID ({@code kid}) of the JWK. The key ID can be used
* to match a specific key. This can be used, for instance, to
* choose a key within a {@link JWKSet} during key rollover.
* The key ID may also correspond to a JWS/JWE {@code kid}
* header parameter value.
*
* @param kid The key ID, {@code null} if not specified.
*
* @return This builder.
*/
public Builder keyID(final String kid) {
this.kid = kid;
return this;
}
/**
* Sets the ID ({@code kid}) of the JWK to its SHA-256 JWK
* thumbprint (RFC 7638). The key ID can be used to match a
* specific key. This can be used, for instance, to choose a
* key within a {@link JWKSet} during key rollover. The key ID
* may also correspond to a JWS/JWE {@code kid} header
* parameter value.
*
* @return This builder.
*
* @throws JOSEException If the SHA-256 hash algorithm is not
* supported.
*/
public Builder keyIDFromThumbprint()
throws JOSEException {
return keyIDFromThumbprint("SHA-256");
}
/**
* Sets the ID ({@code kid}) of the JWK to its JWK thumbprint
* (RFC 7638). The key ID can be used to match a specific key.
* This can be used, for instance, to choose a key within a
* {@link JWKSet} during key rollover. The key ID may also
* correspond to a JWS/JWE {@code kid} header parameter value.
*
* @param hashAlg The hash algorithm for the JWK thumbprint
* computation. Must not be {@code null}.
*
* @return This builder.
*
* @throws JOSEException If the hash algorithm is not
* supported.
*/
public Builder keyIDFromThumbprint(final String hashAlg)
throws JOSEException {
// Put mandatory params in sorted order
LinkedHashMap requiredParams = new LinkedHashMap<>();
requiredParams.put("k", k.toString());
requiredParams.put("kty", KeyType.OCT.getValue());
this.kid = ThumbprintUtils.compute(hashAlg, requiredParams).toString();
return this;
}
/**
* Sets the X.509 certificate URL ({@code x5u}) of the JWK.
*
* @param x5u The X.509 certificate URL, {@code null} if not
* specified.
*
* @return This builder.
*/
public Builder x509CertURL(final URI x5u) {
this.x5u = x5u;
return this;
}
/**
* Sets the X.509 certificate thumbprint ({@code x5t}) of the
* JWK.
*
* @param x5t The X.509 certificate thumbprint, {@code null} if
* not specified.
*
* @return This builder.
*/
public Builder x509CertThumbprint(final Base64URL x5t) {
this.x5t = x5t;
return this;
}
/**
* Sets the X.509 certificate chain ({@code x5c}) of the JWK.
*
* @param x5c The X.509 certificate chain as a unmodifiable
* list, {@code null} if not specified.
*
* @return This builder.
*/
public Builder x509CertChain(final List x5c) {
this.x5c = x5c;
return this;
}
/**
* Builds a new octet sequence JWK.
*
* @return The octet sequence JWK.
*
* @throws IllegalStateException If the JWK parameters were
* inconsistently specified.
*/
public OctetSequenceKey build() {
try {
return new OctetSequenceKey(k, use, ops, alg, kid, x5u, x5t, x5c);
} catch (IllegalArgumentException e) {
throw new IllegalStateException(e.getMessage(), e);
}
}
}
/**
* Creates a new octet sequence JSON Web Key (JWK) with the specified
* parameters.
*
* @param k The key value. It is represented as the Base64URL
* encoding of the value's big endian representation. Must
* not be {@code null}.
* @param use The key use, {@code null} if not specified or if the key
* is intended for signing as well as encryption.
* @param ops The key operations, {@code null} if not specified.
* @param alg The intended JOSE algorithm for the key, {@code null} if
* not specified.
* @param kid The key ID. {@code null} if not specified.
* @param x5u The X.509 certificate URL, {@code null} if not specified.
* @param x5t The X.509 certificate thumbprint, {@code null} if not
* specified.
* @param x5c The X.509 certificate chain, {@code null} if not
* specified.
*/
public OctetSequenceKey(final Base64URL k,
final KeyUse use, final Set ops, final Algorithm alg, final String kid,
final URI x5u, final Base64URL x5t, final List x5c) {
super(KeyType.OCT, use, ops, alg, kid, x5u, x5t, x5c);
if (k == null) {
throw new IllegalArgumentException("The key value must not be null");
}
this.k = k;
}
/**
* Returns the value of this octet sequence key.
*
* @return The key value. It is represented as the Base64URL encoding
* of the value's big endian representation.
*/
public Base64URL getKeyValue() {
return k;
}
/**
* Returns a copy of this octet sequence key value as a byte array.
*
* @return The key value as a byte array.
*/
public byte[] toByteArray() {
return getKeyValue().decode();
}
/**
* Returns a secret key representation of this octet sequence key.
*
* @return The secret key representation, with an algorithm set to
* {@code NONE}.
*/
@Override
public SecretKey toSecretKey() {
return toSecretKey("NONE");
}
/**
* Returns a secret key representation of this octet sequence key with
* the specified Java Cryptography Architecture (JCA) algorithm.
*
* @param jcaAlg The JCA algorithm. Must not be {@code null}.
*
* @return The secret key representation.
*/
public SecretKey toSecretKey(final String jcaAlg) {
return new SecretKeySpec(toByteArray(), jcaAlg);
}
@Override
public LinkedHashMap getRequiredParams() {
// Put mandatory params in sorted order
LinkedHashMap requiredParams = new LinkedHashMap<>();
requiredParams.put("k", k.toString());
requiredParams.put("kty", getKeyType().toString());
return requiredParams;
}
/**
* Octet sequence (symmetric) keys are never considered public, this
* method always returns {@code true}.
*
* @return {@code true}
*/
@Override
public boolean isPrivate() {
return true;
}
/**
* Octet sequence (symmetric) keys are never considered public, this
* method always returns {@code null}.
*
* @return {@code null}
*/
@Override
public OctetSequenceKey toPublicJWK() {
return null;
}
@Override
public JSONObject toJSONObject() {
JSONObject o = super.toJSONObject();
// Append key value
o.put("k", k.toString());
return o;
}
/**
* Parses an octet sequence JWK from the specified JSON object string
* representation.
*
* @param s The JSON object string to parse. Must not be {@code null}.
*
* @return The octet sequence JWK.
*
* @throws ParseException If the string couldn't be parsed to an octet
* sequence JWK.
*/
public static OctetSequenceKey parse(final String s)
throws ParseException {
return parse(JSONObjectUtils.parse(s));
}
/**
* Parses an octet sequence JWK from the specified JSON object
* representation.
*
* @param jsonObject The JSON object to parse. Must not be
* {@code null}.
*
* @return The octet sequence JWK.
*
* @throws ParseException If the JSON object couldn't be parsed to an
* octet sequence JWK.
*/
public static OctetSequenceKey parse(final JSONObject jsonObject)
throws ParseException {
// Parse the mandatory parameters first
Base64URL k = new Base64URL(JSONObjectUtils.getString(jsonObject, "k"));
// Check key type
KeyType kty = JWKMetadata.parseKeyType(jsonObject);
if (kty != KeyType.OCT) {
throw new ParseException("The key type \"kty\" must be oct", 0);
}
return new OctetSequenceKey(k,
JWKMetadata.parseKeyUse(jsonObject),
JWKMetadata.parseKeyOperations(jsonObject),
JWKMetadata.parseAlgorithm(jsonObject),
JWKMetadata.parseKeyID(jsonObject),
JWKMetadata.parseX509CertURL(jsonObject),
JWKMetadata.parseX509CertThumbprint(jsonObject),
JWKMetadata.parseX509CertChain(jsonObject));
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy