private Map<String, Object> createRSAJWK(RSAPublicKey key, KeyUse use, String alg)
     throws ServerException {
   String alias = null;
   try {
     alias = getStringSetting(realm, OAuth2Constants.OAuth2ProviderService.KEYSTORE_ALIAS);
   } catch (SSOException | SMSException e) {
     logger.error(e.getMessage());
     throw new ServerException(e);
   }
   if (StringUtils.isBlank(alias)) {
     logger.error("Alias of ID Token Signing Key not set.");
     throw new ServerException("Alias of ID Token Signing Key not set.");
   } else if ("test".equals(alias)) {
     logger.warning("Alias of ID Token Signing Key should be changed from default, 'test'.");
   }
   String kid =
       Hash.hash(alias + key.getModulus().toString() + key.getPublicExponent().toString());
   return json(object(
           field("kty", "RSA"),
           field(OAuth2Constants.JWTTokenParams.KEY_ID, kid),
           field("use", use.toString()),
           field("alg", alg),
           field("n", Base64url.encode(key.getModulus().toByteArray())),
           field("e", Base64url.encode(key.getPublicExponent().toByteArray()))))
       .asMap();
 }
  /**
   * Generates hash values, by hashing the valueToEncode using the requests's "alg" parameter, then
   * returning the base64url encoding of the leftmost half of the returned bytes. Used for both
   * at_hash and c_hash claims.
   */
  private String generateHash(
      String algorithm, String valueToEncode, OAuth2ProviderSettings providerSettings)
      throws ServerException {

    if (!providerSettings.getSupportedIDTokenSigningAlgorithms().contains(algorithm)) {
      logger.message("Unsupported signing algorithm requested for hash value.");
      return null;
    }

    final JwsAlgorithm alg = JwsAlgorithm.valueOf(algorithm);

    MessageDigest digest;
    try {
      digest = MessageDigest.getInstance(alg.getMdAlgorithm());
    } catch (NoSuchAlgorithmException e) {
      logger.message("Unsupported signing algorithm chosen for hashing.");
      throw new ServerException("Algorithm not supported.");
    }

    final byte[] result = digest.digest(valueToEncode.getBytes(Utils.CHARSET));
    final byte[] toEncode = Arrays.copyOfRange(result, 0, result.length / 2);

    return Base64url.encode(toEncode);
  }