diff --git a/copyright.md b/copyright.md
index d764ff95bb..61357b1dcc 100644
--- a/copyright.md
+++ b/copyright.md
@@ -3,7 +3,7 @@ Copyright notice
Version 5.0, October 2024
-Copyright 2005-2024 Qlik
+Copyright 2005-2026 Qlik
The contents of this open source project are subject to the terms of the Apache 2.0 open
source license available at http://www.opensource.org/licenses/apache-2.0
diff --git a/mvnw b/mvnw
index aa09908bea..b8d231c9f6 100755
--- a/mvnw
+++ b/mvnw
@@ -28,7 +28,7 @@
# Optional ENV vars
# -----------------
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
-# e.g. to debug Maven itself, use
+# e.g., to debug Maven itself, use
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------
diff --git a/mvnw.cmd b/mvnw.cmd
index 1088545e13..fe66b73afa 100644
--- a/mvnw.cmd
+++ b/mvnw.cmd
@@ -27,7 +27,7 @@
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
-@REM e.g. to debug Maven itself, use
+@REM e.g., to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------
@@ -81,7 +81,7 @@ goto error
:init
-@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Find the project base dir, i.e., the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
diff --git a/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/AwsAuthenticator.java b/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/AwsAuthenticator.java
index 94215304db..d5b448f9e3 100644
--- a/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/AwsAuthenticator.java
+++ b/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/AwsAuthenticator.java
@@ -1,12 +1,11 @@
/**
- * Copyright 2005-2024 Qlik
- *
- * The contents of this file is subject to the terms of the Apache 2.0 open
- * source license available at http://www.opensource.org/licenses/apache-2.0
- *
+ * Copyright 2005-2026 Qlik
+ *
+ * The content of this file is subject to the terms of the Apache 2.0 open
+ * source license available at https://www.opensource.org/licenses/apache-2.0
+ *
* Restlet is a registered trademark of QlikTech International AB.
*/
-
package org.restlet.ext.crypto;
import org.restlet.Context;
@@ -18,19 +17,16 @@
/**
* Authenticator supporting the {@link ChallengeScheme#HTTP_AWS_S3} scheme.
- *
+ *
* @author Jean-Philippe Steinmetz
*/
public class AwsAuthenticator extends ChallengeAuthenticator {
/**
* Creates a new HttpAwsS3Authenticator instance.
- *
- * @param context
- * The context
- * @param optional
- * Indicates if the authentication success is optional
- * @param realm
- * The authentication realm
+ *
+ * @param context The context
+ * @param optional Indicates if the authentication success is optional
+ * @param realm The authentication realm
*/
public AwsAuthenticator(Context context, boolean optional, String realm) {
this(context, optional, realm, new AwsVerifier(null));
@@ -38,38 +34,30 @@ public AwsAuthenticator(Context context, boolean optional, String realm) {
/**
* Creates a new HttpAwsS3Authenticator instance.
- *
- * @param context
- * The context
- * @param optional
- * Indicates if the authentication success is optional
- * @param realm
- * The authentication realm
+ *
+ * @param context The context
+ * @param optional Indicates if the authentication success is optional
+ * @param realm The authentication realm
* @param verifier
*/
- public AwsAuthenticator(Context context, boolean optional, String realm,
- Verifier verifier) {
+ public AwsAuthenticator(Context context, boolean optional, String realm, Verifier verifier) {
super(context, optional, ChallengeScheme.HTTP_AWS_S3, realm, verifier);
}
/**
* Creates a new HttpAwsS3Authenticator instance.
- *
- * @param context
- * The context
- * @param realm
- * The authentication realm
+ *
+ * @param context The context
+ * @param realm The authentication realm
*/
public AwsAuthenticator(Context context, String realm) {
this(context, false, realm);
}
/**
- * Returns the maximum age of a request, in milliseconds, before it is
- * considered stale.
- *
- * A negative or zero value indicates no age restriction. The default value
- * is 15 minutes.
+ * Returns the maximum age of a request, in milliseconds, before it is considered stale.
+ *
+ *
A negative or zero value indicates no age restriction. The default value is 15 minutes.
*/
public long getMaxRequestAge() {
return getVerifier().getMaxRequestAge();
@@ -81,9 +69,9 @@ public AwsVerifier getVerifier() {
}
/**
- * Returns the secret verifier that will be wrapped by the real verifier
- * supporting all the HTTP AWS verifications.
- *
+ * Returns the secret verifier that will be wrapped by the real verifier supporting all the HTTP
+ * AWS verifications.
+ *
* @return the local wrapped verifier
*/
public LocalVerifier getWrappedVerifier() {
@@ -91,35 +79,30 @@ public LocalVerifier getWrappedVerifier() {
}
/**
- * Sets the maximum age of a request, in milliseconds, before it is
- * considered stale.
- *
- * A negative or zero value indicates no age restriction. The default value
- * is 15 minutes.
+ * Sets the maximum age of a request, in milliseconds, before it is considered stale.
+ *
+ *
A negative or zero value indicates no age restriction. The default value is 15 minutes.
*/
public void setMaxRequestAge(long value) {
getVerifier().setMaxRequestAge(value);
}
/**
- * Sets the internal verifier. In general you shouldn't replace it but
- * instead set the {@code wrappedVerifier} via the
- * {@link #setWrappedVerifier(LocalVerifier)} method.
+ * Sets the internal verifier. In general, you shouldn't replace it but instead set the {@code
+ * wrappedVerifier} via the {@link #setWrappedVerifier(LocalVerifier)} method.
*/
@Override
public void setVerifier(Verifier verifier) {
- if (!(verifier instanceof AwsVerifier))
- throw new IllegalArgumentException();
+ if (!(verifier instanceof AwsVerifier)) throw new IllegalArgumentException();
super.setVerifier(verifier);
}
/**
- * Sets the secret verifier that will be wrapped by the real verifier
- * supporting all the HTTP AWS verifications.
- *
- * @param verifier
- * The local verifier to wrap
+ * Sets the secret verifier that will be wrapped by the real verifier supporting all the HTTP
+ * AWS verifications.
+ *
+ * @param verifier The local verifier to wrap
*/
public void setWrappedVerifier(LocalVerifier verifier) {
getVerifier().setWrappedVerifier(verifier);
diff --git a/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/CookieAuthenticator.java b/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/CookieAuthenticator.java
index 3a2de458cc..cb38076388 100644
--- a/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/CookieAuthenticator.java
+++ b/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/CookieAuthenticator.java
@@ -1,18 +1,16 @@
/**
- * Copyright 2005-2024 Qlik
- *
- * The contents of this file is subject to the terms of the Apache 2.0 open
- * source license available at http://www.opensource.org/licenses/apache-2.0
- *
+ * Copyright 2005-2026 Qlik
+ *
+ * The content of this file is subject to the terms of the Apache 2.0 open
+ * source license available at https://www.opensource.org/licenses/apache-2.0
+ *
* Restlet is a registered trademark of QlikTech International AB.
*/
-
package org.restlet.ext.crypto;
import java.security.GeneralSecurityException;
import java.util.Base64;
import java.util.logging.Level;
-
import org.restlet.Context;
import org.restlet.Request;
import org.restlet.Response;
@@ -28,33 +26,29 @@
import org.restlet.security.ChallengeAuthenticator;
/**
- * Challenge authenticator based on browser cookies. This is useful when the web
- * application requires a finer grained control on the login and logout process
- * and can't rely solely on standard schemes such as
- * {@link ChallengeScheme#HTTP_BASIC}.
+ * Challenge authenticator based on browser cookies. This is useful when the web application
+ * requires a finer grained control on the login and logout process and can't rely solely on
+ * standard schemes such as {@link ChallengeScheme#HTTP_BASIC}.
*
- * Login can be automatically handled by intercepting HTTP POST calls to the
- * {@link #getLoginPath()} URI. The request entity should contain an HTML form
- * with two fields, the first one named {@link #getIdentifierFormName()} and the
- * second one named {@link #getSecretFormName()}.
+ * Login can be automatically handled by intercepting HTTP POST calls to the {@link #getLoginPath()}
+ * URI. The request entity should contain an HTML form with two fields, the first one named {@link
+ * #getIdentifierFormName()} and the second one named {@link #getSecretFormName()}.
*
- * Logout can be automatically handled as well by intercepting HTTP GET or POST
- * calls to the {@link #getLogoutPath()} URI.
+ * Logout can be automatically handled as well by intercepting HTTP GET or POST calls to the {@link
+ * #getLogoutPath()} URI.
*
- * After login or logout, the user's browser can be redirected to the URI
- * provided in a query parameter named by {@link #getRedirectQueryName()}.
+ * After login or logout, the user's browser can be redirected to the URI provided in a query
+ * parameter named by {@link #getRedirectQueryName()}.
*
- * When the credentials are missing or stale, the
- * {@link #challenge(Response, boolean)} method is invoked by the parent class,
- * and its default behavior is to redirect the user's browser to the
- * {@link #getLoginFormPath()} URI, adding the URI of the target resource as a
- * query parameter of name {@link #getRedirectQueryName()}.
+ * When the credentials are missing or stale, the {@link #challenge(Response, boolean)} method is
+ * invoked by the parent class, and its default behavior is to redirect the user's browser to the
+ * {@link #getLoginFormPath()} URI, adding the URI of the target resource as a query parameter of
+ * name {@link #getRedirectQueryName()}.
*
- * Note that credentials, both identifier and secret, are stored in a cookie in
- * an encrypted manner. The default encryption algorithm is AES but can be
- * changed with {@link #setEncryptAlgorithm(String)}. It is also strongly
- * recommended to
- *
+ * Note that credentials, both identifier and secret, are stored in a cookie in an encrypted manner.
+ * The default encryption algorithm is AES but can be changed with {@link
+ * #setEncryptAlgorithm(String)}. It is also strongly recommended to
+ *
* @author Remi Dewitte
* @author Jerome Louvel
*/
@@ -66,10 +60,7 @@ public class CookieAuthenticator extends ChallengeAuthenticator {
/** The name of the algorithm used to encrypt the log info cookie value. */
private volatile String encryptAlgorithm;
- /**
- * The secret key for the algorithm used to encrypt the log info cookie
- * value.
- */
+ /** The secret key for the algorithm used to encrypt the log info cookie value. */
private volatile byte[] encryptSecretKey;
/** The name of the HTML login form field containing the identifier. */
@@ -94,8 +85,8 @@ public class CookieAuthenticator extends ChallengeAuthenticator {
private volatile int maxCookieAge;
/**
- * The name of the query parameter containing the URI to redirect the
- * browser to after login or logout.
+ * The name of the query parameter containing the URI to redirect the browser to after login or
+ * logout.
*/
private volatile String redirectQueryName;
@@ -104,19 +95,15 @@ public class CookieAuthenticator extends ChallengeAuthenticator {
/**
* Constructor. Use the {@link ChallengeScheme#HTTP_COOKIE} pseudo-scheme.
- *
- * @param context
- * The parent context.
- * @param optional
- * Indicates if this authenticator is optional so alternative
- * authenticators down the chain can be attempted.
- * @param realm
- * The name of the security realm.
- * @param encryptSecretKey
- * The secret key used to encrypt the cookie value.
- */
- public CookieAuthenticator(Context context, boolean optional, String realm,
- byte[] encryptSecretKey) {
+ *
+ * @param context The parent context.
+ * @param optional Indicates if this authenticator is optional, so alternative authenticators
+ * down the chain can be attempted.
+ * @param realm The name of the security realm.
+ * @param encryptSecretKey The secret key used to encrypt the cookie value.
+ */
+ public CookieAuthenticator(
+ Context context, boolean optional, String realm, byte[] encryptSecretKey) {
super(context, optional, ChallengeScheme.HTTP_COOKIE, realm);
this.cookieName = "Credentials";
this.interceptingLogin = true;
@@ -133,31 +120,25 @@ public CookieAuthenticator(Context context, boolean optional, String realm,
/**
* Constructor for mandatory cookie authenticators.
- *
- * @param context
- * The parent context.
- * @param realm
- * The name of the security realm.
- * @param encryptSecretKey
- * The secret key used to encrypt the cookie value.
- */
- public CookieAuthenticator(Context context, String realm,
- byte[] encryptSecretKey) {
+ *
+ * @param context The parent context.
+ * @param realm The name of the security realm.
+ * @param encryptSecretKey The secret key used to encrypt the cookie value.
+ */
+ public CookieAuthenticator(Context context, String realm, byte[] encryptSecretKey) {
this(context, false, realm, encryptSecretKey);
}
/**
- * Attempts to redirect the user's browser to the URI provided in a query
- * parameter named by {@link #getRedirectQueryName()}.
- *
- * @param request
- * The current request.
- * @param response
- * The current response.
+ * Attempts to redirect the user's browser to the URI provided in a query parameter named by
+ * {@link #getRedirectQueryName()}.
+ *
+ * @param request The current request.
+ * @param response The current response.
*/
protected void attemptRedirect(Request request, Response response) {
- String targetUri = request.getResourceRef().getQueryAsForm()
- .getFirstValue(getRedirectQueryName());
+ String targetUri =
+ request.getResourceRef().getQueryAsForm().getFirstValue(getRedirectQueryName());
if (targetUri != null) {
response.redirectSeeOther(Reference.decode(targetUri));
@@ -165,45 +146,38 @@ protected void attemptRedirect(Request request, Response response) {
}
/**
- * Restores credentials from the cookie named {@link #getCookieName()} if
- * available. The usual processing is the followed.
+ * Restores credentials from the cookie named {@link #getCookieName()} if available. The usual
+ * processing is the followed.
*/
@Override
protected boolean authenticate(Request request, Response response) {
// Restore credentials from the cookie
- Cookie credentialsCookie = request.getCookies().getFirst(
- getCookieName());
+ Cookie credentialsCookie = request.getCookies().getFirst(getCookieName());
if (credentialsCookie != null) {
- request.setChallengeResponse(parseCredentials(credentialsCookie
- .getValue()));
+ request.setChallengeResponse(parseCredentials(credentialsCookie.getValue()));
}
return super.authenticate(request, response);
}
- /**
- * Sets or updates the credentials cookie.
- */
+ /** Sets or updates the credentials cookie. */
@Override
protected int authenticated(Request request, Response response) {
try {
- CookieSetting credentialsCookie = getCredentialsCookie(request,
- response);
- credentialsCookie.setValue(formatCredentials(request
- .getChallengeResponse()));
+ CookieSetting credentialsCookie = getCredentialsCookie(request, response);
+ credentialsCookie.setValue(formatCredentials(request.getChallengeResponse()));
credentialsCookie.setMaxAge(getMaxCookieAge());
} catch (GeneralSecurityException e) {
- getLogger().log(Level.SEVERE,
- "Could not format credentials cookie", e);
+ getLogger().log(Level.SEVERE, "Could not format credentials cookie", e);
}
return super.authenticated(request, response);
}
/**
- * Optionally handles the login and logout actions by intercepting the HTTP
- * calls to the {@link #getLoginPath()} and {@link #getLogoutPath()} URIs.
+ * Optionally handles the login and logout actions by intercepting the HTTP calls to the {@link
+ * #getLoginPath()} and {@link #getLogoutPath()} URIs.
*/
@Override
protected int beforeHandle(Request request, Response response) {
@@ -218,9 +192,9 @@ protected int beforeHandle(Request request, Response response) {
/**
* This method should be overridden to return a login form representation.
- * By default, it redirects the user's browser to the
- * {@link #getLoginFormPath()} URI, adding the URI of the target resource as
- * a query parameter of name {@link #getRedirectQueryName()}.
+ * By default, it redirects the user's browser to the {@link #getLoginFormPath()} URI, adding
+ * the URI of the target resource as a query parameter of name {@link #getRedirectQueryName()}.
+ *
* In case the getLoginFormPath() is not set, it calls the parent's method.
*/
@Override
@@ -230,13 +204,13 @@ public void challenge(Response response, boolean stale) {
} else {
Reference ref = response.getRequest().getResourceRef();
String redirectQueryName = getRedirectQueryName();
- String redirectQueryValue = ref.getQueryAsForm().getFirstValue(
- redirectQueryName, "");
+ String redirectQueryValue = ref.getQueryAsForm().getFirstValue(redirectQueryName, "");
if ("".equals(redirectQueryValue)) {
- redirectQueryValue = new Reference(getLoginFormPath())
- .addQueryParameter(redirectQueryName, ref.toString())
- .toString();
+ redirectQueryValue =
+ new Reference(getLoginFormPath())
+ .addQueryParameter(redirectQueryName, ref.toString())
+ .toString();
}
response.redirectSeeOther(redirectQueryValue);
@@ -245,19 +219,17 @@ public void challenge(Response response, boolean stale) {
/**
* Formats the raws credentials to store in the cookie.
- *
- * @param challenge
- * The challenge response to format.
+ *
+ * @param challenge The challenge response to format.
* @return The raw credentials.
* @throws GeneralSecurityException
*/
- public String formatCredentials(ChallengeResponse challenge)
- throws GeneralSecurityException {
+ public String formatCredentials(ChallengeResponse challenge) throws GeneralSecurityException {
// Data buffer
- StringBuffer sb = new StringBuffer();
+ StringBuilder sb = new StringBuilder();
// Indexes buffer
- StringBuffer isb = new StringBuffer();
+ StringBuilder isb = new StringBuilder();
String timeIssued = Long.toString(System.currentTimeMillis());
int i = timeIssued.length();
sb.append(timeIssued);
@@ -278,14 +250,16 @@ public String formatCredentials(ChallengeResponse challenge)
sb.append('/');
sb.append(isb);
- return Base64.getEncoder().encodeToString(CryptoUtils.encrypt(getEncryptAlgorithm(),
- getEncryptSecretKey(), sb.toString()));
+ return Base64.getEncoder()
+ .encodeToString(
+ CryptoUtils.encrypt(
+ getEncryptAlgorithm(), getEncryptSecretKey(), sb.toString()));
}
/**
- * Returns the cookie name to use for the authentication credentials. By
- * default, it is is "Credentials".
- *
+ * Returns the cookie name to use for the authentication credentials. By default, it is is
+ * "Credentials".
+ *
* @return The cookie name to use for the authentication credentials.
*/
public String getCookieName() {
@@ -293,19 +267,15 @@ public String getCookieName() {
}
/**
- * Returns the credentials cookie setting. It first try to find an existing
- * cookie. If necessary, it creates a new one.
- *
- * @param request
- * The current request.
- * @param response
- * The current response.
+ * Returns the credentials cookie setting. It first try to find an existing cookie. If
+ * necessary, it creates a new one.
+ *
+ * @param request The current request.
+ * @param response The current response.
* @return The credentials cookie setting.
*/
- protected CookieSetting getCredentialsCookie(Request request,
- Response response) {
- CookieSetting credentialsCookie = response.getCookieSettings()
- .getFirst(getCookieName());
+ protected CookieSetting getCredentialsCookie(Request request, Response response) {
+ CookieSetting credentialsCookie = response.getCookieSettings().getFirst(getCookieName());
if (credentialsCookie == null) {
credentialsCookie = new CookieSetting(getCookieName(), null);
@@ -326,31 +296,28 @@ protected CookieSetting getCredentialsCookie(Request request,
}
/**
- * Returns the name of the algorithm used to encrypt the log info cookie
- * value. By default, it returns "AES".
- *
- * @return The name of the algorithm used to encrypt the log info cookie
- * value.
+ * Returns the name of the algorithm used to encrypt the log info cookie value. By default, it
+ * returns "AES".
+ *
+ * @return The name of the algorithm used to encrypt the log info cookie value.
*/
public String getEncryptAlgorithm() {
return encryptAlgorithm;
}
/**
- * Returns the secret key for the algorithm used to encrypt the log info
- * cookie value.
- *
- * @return The secret key for the algorithm used to encrypt the log info
- * cookie value.
+ * Returns the secret key for the algorithm used to encrypt the log info cookie value.
+ *
+ * @return The secret key for the algorithm used to encrypt the log info cookie value.
*/
public byte[] getEncryptSecretKey() {
return encryptSecretKey;
}
/**
- * Returns the name of the HTML login form field containing the identifier.
- * Returns "login" by default.
- *
+ * Returns the name of the HTML login form field containing the identifier. Returns "login" by
+ * default.
+ *
* @return The name of the HTML login form field containing the identifier.
*/
public String getIdentifierFormName() {
@@ -359,7 +326,7 @@ public String getIdentifierFormName() {
/**
* Returns the URI path of the HTML login form to use to challenge the user.
- *
+ *
* @return The URI path of the HTML login form to use to challenge the user.
*/
public String getLoginFormPath() {
@@ -368,7 +335,7 @@ public String getLoginFormPath() {
/**
* Returns the login URI path to intercept.
- *
+ *
* @return The login URI path to intercept.
*/
public String getLoginPath() {
@@ -377,7 +344,7 @@ public String getLoginPath() {
/**
* Returns the logout URI path to intercept.
- *
+ *
* @return The logout URI path to intercept.
*/
public String getLogoutPath() {
@@ -385,9 +352,9 @@ public String getLogoutPath() {
}
/**
- * Returns the maximum age of the log info cookie. By default, it uses -1 to
- * make the cookie only last until the end of the current browser session.
- *
+ * Returns the maximum age of the log info cookie. By default, it uses -1 to make the cookie
+ * only last until the end of the current browser session.
+ *
* @return The maximum age of the log info cookie.
* @see CookieSetting#getMaxAge()
*/
@@ -396,20 +363,20 @@ public int getMaxCookieAge() {
}
/**
- * Returns the name of the query parameter containing the URI to redirect
- * the browser to after login or logout. By default, it uses "targetUri".
- *
- * @return The name of the query parameter containing the URI to redirect
- * the browser to after login or logout.
+ * Returns the name of the query parameter containing the URI to redirect the browser to after
+ * login or logout. By default, it uses "targetUri".
+ *
+ * @return The name of the query parameter containing the URI to redirect the browser to after
+ * login or logout.
*/
public String getRedirectQueryName() {
return redirectQueryName;
}
/**
- * Returns the name of the HTML login form field containing the secret.
- * Returns "password" by default.
- *
+ * Returns the name of the HTML login form field containing the secret. Returns "password" by
+ * default.
+ *
* @return The name of the HTML login form field containing the secret.
*/
public String getSecretFormName() {
@@ -418,7 +385,7 @@ public String getSecretFormName() {
/**
* Indicates if the login requests should be intercepted.
- *
+ *
* @return True if the login requests should be intercepted.
*/
public boolean isInterceptingLogin() {
@@ -427,7 +394,7 @@ public boolean isInterceptingLogin() {
/**
* Indicates if the logout requests should be intercepted.
- *
+ *
* @return True if the logout requests should be intercepted.
*/
public boolean isInterceptingLogout() {
@@ -435,51 +402,37 @@ public boolean isInterceptingLogout() {
}
/**
- * Indicates if the request is an attempt to log in and should be
- * intercepted.
- *
- * @param request
- * The current request.
- * @param response
- * The current response.
- * @return True if the request is an attempt to log in and should be
- * intercepted.
+ * Indicates if the request is an attempt to log in and should be intercepted.
+ *
+ * @param request The current request.
+ * @param response The current response.
+ * @return True if the request is an attempt to log in and should be intercepted.
*/
protected boolean isLoggingIn(Request request, Response response) {
return isInterceptingLogin()
- && getLoginPath()
- .equals(request.getResourceRef().getRemainingPart(
- false, false))
+ && getLoginPath().equals(request.getResourceRef().getRemainingPart(false, false))
&& Method.POST.equals(request.getMethod());
}
/**
- * Indicates if the request is an attempt to log out and should be
- * intercepted.
- *
- * @param request
- * The current request.
- * @param response
- * The current response.
- * @return True if the request is an attempt to log out and should be
- * intercepted.
+ * Indicates if the request is an attempt to log out and should be intercepted.
+ *
+ * @param request The current request.
+ * @param response The current response.
+ * @return True if the request is an attempt to log out and should be intercepted.
*/
protected boolean isLoggingOut(Request request, Response response) {
return isInterceptingLogout()
- && getLogoutPath()
- .equals(request.getResourceRef().getRemainingPart(
- false, false))
- && (Method.GET.equals(request.getMethod()) || Method.POST
- .equals(request.getMethod()));
+ && getLogoutPath().equals(request.getResourceRef().getRemainingPart(false, false))
+ && (Method.GET.equals(request.getMethod())
+ || Method.POST.equals(request.getMethod()));
}
/**
* Processes the login request.
- *
- * @param request
- * The current request.
- * @param response
- * The current response.
+ *
+ * @param request The current request.
+ * @param response The current response.
*/
protected void login(Request request, Response response) {
// Login detected
@@ -488,9 +441,11 @@ protected void login(Request request, Response response) {
Parameter secret = form.getFirst(getSecretFormName());
// Set credentials
- ChallengeResponse cr = new ChallengeResponse(getScheme(),
- identifier != null ? identifier.getValue() : null,
- secret != null ? secret.getValue() : null);
+ ChallengeResponse cr =
+ new ChallengeResponse(
+ getScheme(),
+ identifier != null ? identifier.getValue() : null,
+ secret != null ? secret.getValue() : null);
request.setChallengeResponse(cr);
// Attempt to redirect
@@ -499,17 +454,14 @@ protected void login(Request request, Response response) {
/**
* Processes the logout request.
- *
- * @param request
- * The current request.
- * @param response
- * The current response.
+ *
+ * @param request The current request.
+ * @param response The current response.
*/
protected int logout(Request request, Response response) {
// Clears the credentials
request.setChallengeResponse(null);
- CookieSetting credentialsCookie = getCredentialsCookie(request,
- response);
+ CookieSetting credentialsCookie = getCredentialsCookie(request, response);
credentialsCookie.setMaxAge(0);
// Attempt to redirect
@@ -519,26 +471,23 @@ protected int logout(Request request, Response response) {
}
/**
- * Decodes the credentials stored in a cookie into a proper
- * {@link ChallengeResponse} object.
- *
- * @param cookieValue
- * The credentials to decode from cookie value.
+ * Decodes the credentials stored in a cookie into a proper {@link ChallengeResponse} object.
+ *
+ * @param cookieValue The credentials to decode from cookie value.
* @return The credentials as a proper challenge response.
*/
protected ChallengeResponse parseCredentials(String cookieValue) {
+ if (cookieValue == null) {
+ return null;
+ }
+
try {
// 1) Decode Base64 string
byte[] encrypted = Base64.getDecoder().decode(cookieValue);
-
- if (encrypted == null) {
- getLogger().warning(
- "Cannot decode cookie credentials : " + cookieValue);
- }
-
+
// 2) Decrypt the credentials
- String decrypted = CryptoUtils.decrypt(getEncryptAlgorithm(),
- getEncryptSecretKey(), encrypted);
+ String decrypted =
+ CryptoUtils.decrypt(getEncryptAlgorithm(), getEncryptSecretKey(), encrypted);
// 3) Parse the decrypted cookie value
int lastSlash = decrypted.lastIndexOf('/');
@@ -549,24 +498,20 @@ protected ChallengeResponse parseCredentials(String cookieValue) {
// 4) Create the challenge response
ChallengeResponse cr = new ChallengeResponse(getScheme());
cr.setRawValue(cookieValue);
- cr.setTimeIssued(Long.parseLong(decrypted.substring(0,
- identifierIndex)));
- cr.setIdentifier(decrypted.substring(identifierIndex + 1,
- secretIndex));
+ cr.setTimeIssued(Long.parseLong(decrypted.substring(0, identifierIndex)));
+ cr.setIdentifier(decrypted.substring(identifierIndex + 1, secretIndex));
cr.setSecret(decrypted.substring(secretIndex + 1, lastSlash));
return cr;
} catch (Exception e) {
- getLogger().log(Level.INFO, "Unable to decrypt cookie credentials",
- e);
+ getLogger().log(Level.INFO, "Unable to decrypt cookie credentials", e);
return null;
}
}
/**
* Sets the cookie name to use for the authentication credentials.
- *
- * @param cookieName
- * The cookie name to use for the authentication credentials.
+ *
+ * @param cookieName The cookie name to use for the authentication credentials.
*/
public void setCookieName(String cookieName) {
this.cookieName = cookieName;
@@ -574,22 +519,17 @@ public void setCookieName(String cookieName) {
/**
* Sets the name of the algorithm used to encrypt the log info cookie value.
- *
- * @param secretAlgorithm
- * The name of the algorithm used to encrypt the log info cookie
- * value.
+ *
+ * @param secretAlgorithm The name of the algorithm used to encrypt the log info cookie value.
*/
public void setEncryptAlgorithm(String secretAlgorithm) {
this.encryptAlgorithm = secretAlgorithm;
}
/**
- * Sets the secret key for the algorithm used to encrypt the log info cookie
- * value.
- *
- * @param secretKey
- * The secret key for the algorithm used to encrypt the log info
- * cookie value.
+ * Sets the secret key for the algorithm used to encrypt the log info cookie value.
+ *
+ * @param secretKey The secret key for the algorithm used to encrypt the log info cookie value.
*/
public void setEncryptSecretKey(byte[] secretKey) {
this.encryptSecretKey = secretKey;
@@ -597,10 +537,8 @@ public void setEncryptSecretKey(byte[] secretKey) {
/**
* Sets the name of the HTML login form field containing the identifier.
- *
- * @param loginInputName
- * The name of the HTML login form field containing the
- * identifier.
+ *
+ * @param loginInputName The name of the HTML login form field containing the identifier.
*/
public void setIdentifierFormName(String loginInputName) {
this.identifierFormName = loginInputName;
@@ -608,9 +546,8 @@ public void setIdentifierFormName(String loginInputName) {
/**
* Indicates if the login requests should be intercepted.
- *
- * @param intercepting
- * True if the login requests should be intercepted.
+ *
+ * @param intercepting True if the login requests should be intercepted.
*/
public void setInterceptingLogin(boolean intercepting) {
this.interceptingLogin = intercepting;
@@ -618,9 +555,8 @@ public void setInterceptingLogin(boolean intercepting) {
/**
* Indicates if the logout requests should be intercepted.
- *
- * @param intercepting
- * True if the logout requests should be intercepted.
+ *
+ * @param intercepting True if the logout requests should be intercepted.
*/
public void setInterceptingLogout(boolean intercepting) {
this.interceptingLogout = intercepting;
@@ -628,10 +564,8 @@ public void setInterceptingLogout(boolean intercepting) {
/**
* Sets the URI path of the HTML login form to use to challenge the user.
- *
- * @param loginFormPath
- * The URI path of the HTML login form to use to challenge the
- * user.
+ *
+ * @param loginFormPath The URI path of the HTML login form to use to challenge the user.
*/
public void setLoginFormPath(String loginFormPath) {
this.loginFormPath = loginFormPath;
@@ -639,9 +573,8 @@ public void setLoginFormPath(String loginFormPath) {
/**
* Sets the login URI path to intercept.
- *
- * @param loginPath
- * The login URI path to intercept.
+ *
+ * @param loginPath The login URI path to intercept.
*/
public void setLoginPath(String loginPath) {
this.loginPath = loginPath;
@@ -649,9 +582,8 @@ public void setLoginPath(String loginPath) {
/**
* Sets the logout URI path to intercept.
- *
- * @param logoutPath
- * The logout URI path to intercept.
+ *
+ * @param logoutPath The logout URI path to intercept.
*/
public void setLogoutPath(String logoutPath) {
this.logoutPath = logoutPath;
@@ -659,9 +591,8 @@ public void setLogoutPath(String logoutPath) {
/**
* Sets the maximum age of the log info cookie.
- *
- * @param timeout
- * The maximum age of the log info cookie.
+ *
+ * @param timeout The maximum age of the log info cookie.
* @see CookieSetting#setMaxAge(int)
*/
public void setMaxCookieAge(int timeout) {
@@ -669,12 +600,11 @@ public void setMaxCookieAge(int timeout) {
}
/**
- * Sets the name of the query parameter containing the URI to redirect the
- * browser to after login or logout.
- *
- * @param redirectQueryName
- * The name of the query parameter containing the URI to redirect
- * the browser to after login or logout.
+ * Sets the name of the query parameter containing the URI to redirect the browser to after
+ * login or logout.
+ *
+ * @param redirectQueryName The name of the query parameter containing the URI to redirect the
+ * browser to after login or logout.
*/
public void setRedirectQueryName(String redirectQueryName) {
this.redirectQueryName = redirectQueryName;
@@ -682,12 +612,10 @@ public void setRedirectQueryName(String redirectQueryName) {
/**
* Sets the name of the HTML login form field containing the secret.
- *
- * @param passwordInputName
- * The name of the HTML login form field containing the secret.
+ *
+ * @param passwordInputName The name of the HTML login form field containing the secret.
*/
public void setSecretFormName(String passwordInputName) {
this.secretFormName = passwordInputName;
}
-
}
diff --git a/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/DigestAuthenticator.java b/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/DigestAuthenticator.java
index f8c1f410dc..7a6c959867 100644
--- a/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/DigestAuthenticator.java
+++ b/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/DigestAuthenticator.java
@@ -1,17 +1,15 @@
/**
- * Copyright 2005-2024 Qlik
- *
- * The contents of this file is subject to the terms of the Apache 2.0 open
- * source license available at http://www.opensource.org/licenses/apache-2.0
- *
+ * Copyright 2005-2026 Qlik
+ *
+ * The content of this file is subject to the terms of the Apache 2.0 open
+ * source license available at https://www.opensource.org/licenses/apache-2.0
+ *
* Restlet is a registered trademark of QlikTech International AB.
*/
-
package org.restlet.ext.crypto;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
-
import org.restlet.Context;
import org.restlet.data.ChallengeRequest;
import org.restlet.data.ChallengeScheme;
@@ -23,9 +21,9 @@
import org.restlet.security.Verifier;
/**
- * Authenticator supporting the digest challenge authentication schemes. By
- * default, it only knows about the {@link ChallengeScheme#HTTP_DIGEST} scheme.
- *
+ * Authenticator supporting the digest challenge authentication schemes. By default, it only knows
+ * about the {@link ChallengeScheme#HTTP_DIGEST} scheme.
+ *
* @see DigestVerifier
* @see DigestAuthenticator
* @author Jerome Louvel
@@ -45,41 +43,35 @@ public class DigestAuthenticator extends ChallengeAuthenticator {
private volatile String serverKey;
/**
- * Constructor. Sets the challenge scheme to
- * {@link ChallengeScheme#HTTP_DIGEST} and the nonce lifespan to 5 minutes
- * by default.
- *
- * @param context
- * The context.
- * @param optional
- * Indicates if the authentication success is optional.
- * @param realm
- * The authentication realm.
- * @param domainRefs
- * The URI references that define the protection domains.
- * @param serverKey
- * The secret key known only to server.
+ * Constructor. Sets the challenge scheme to {@link ChallengeScheme#HTTP_DIGEST} and the nonce
+ * lifespan to 5 minutes by default.
+ *
+ * @param context The context.
+ * @param optional Indicates if the authentication success is optional.
+ * @param realm The authentication realm.
+ * @param domainRefs The URI references that define the protection domains.
+ * @param serverKey The secret key known only to server.
*/
- public DigestAuthenticator(Context context, boolean optional, String realm,
- List domainRefs, String serverKey) {
+ public DigestAuthenticator(
+ Context context,
+ boolean optional,
+ String realm,
+ List domainRefs,
+ String serverKey) {
super(context, optional, ChallengeScheme.HTTP_DIGEST, realm);
this.domainRefs = domainRefs;
this.maxServerNonceAge = DEFAULT_MAX_SERVER_NONCE_AGE;
this.serverKey = serverKey;
- setVerifier(new org.restlet.ext.crypto.internal.HttpDigestVerifier(
- this, null, null));
+ setVerifier(new org.restlet.ext.crypto.internal.HttpDigestVerifier(this, null, null));
}
/**
- * Constructor. By default, it set the "optional" property to 'false' and
- * the "domainUris" property to a single '/' URI.
- *
- * @param context
- * The context.
- * @param realm
- * The authentication realm.
- * @param serverKey
- * secret key known only to server
+ * Constructor. By default, it sets the "optional" property to 'false' and the "domainUris"
+ * property to a single '/' URI.
+ *
+ * @param context The context.
+ * @param realm The authentication realm.
+ * @param serverKey secret key known only to server
*/
public DigestAuthenticator(Context context, String realm, String serverKey) {
this(context, false, realm, null, serverKey);
@@ -95,19 +87,18 @@ protected ChallengeRequest createChallengeRequest(boolean stale) {
}
/**
- * Generates a server nonce.
- *
- * @return A new server nonce.
+ * Generates server nonce.
+ *
+ * @return New server nonce.
*/
public String generateServerNonce() {
return CryptoUtils.makeNonce(getServerKey());
}
/**
- * Returns the base URI references that collectively define the protected
- * domains for the digest authentication. By default, it returns a list with a
- * single "/" URI reference.
- *
+ * Returns the base URI references that collectively define the protected domains for the digest
+ * authentication. By default, it returns a list with a single "/" URI reference.
+ *
* @return The base URI references.
*/
public List getDomainRefs() {
@@ -117,7 +108,7 @@ public List getDomainRefs() {
synchronized (this) {
r = this.domainRefs;
if (r == null) {
- this.domainRefs = r = new CopyOnWriteArrayList();
+ this.domainRefs = r = new CopyOnWriteArrayList<>();
this.domainRefs.add(new Reference("/"));
}
}
@@ -126,15 +117,12 @@ public List getDomainRefs() {
}
/**
- * Return the hashed secret. By default, it knows how to hash HTTP DIGEST
- * secrets, specified as A1 in section 3.2.2.2 of RFC2617, or null if the
- * identifier has no corresponding secret.
- *
- * @param identifier
- * The user identifier to hash.
- * @param secret
- * The user secret.
- * @return A hash of the user name, realm, and password.
+ * Return the hashed secret. By default, it knows how to hash HTTP DIGEST secrets, specified as
+ * A1 in section 3.2.2.2 of RFC2617, or null if the identifier has no corresponding secret.
+ *
+ * @param identifier The user identifier to hash.
+ * @param secret The user secret.
+ * @return A hash of the username, realm, and password.
*/
public String getHashedSecret(String identifier, char[] secret) {
if (ChallengeScheme.HTTP_DIGEST.equals(getScheme())) {
@@ -146,7 +134,7 @@ public String getHashedSecret(String identifier, char[] secret) {
/**
* Returns the number of milliseconds between each mandatory nonce refresh.
- *
+ *
* @return The server nonce lifespan.
*/
public long getMaxServerNonceAge() {
@@ -155,7 +143,7 @@ public long getMaxServerNonceAge() {
/**
* Returns the secret key known only by server.
- *
+ *
* @return The server secret key.
*/
public String getServerKey() {
@@ -169,11 +157,9 @@ public DigestVerifier getVerifier() {
}
/**
- * Sets the URI references that define the protection domains for the digest
- * authentication.
- *
- * @param domainRefs
- * The base URI references.
+ * Sets the URI references that define the protection domains for the digest authentication.
+ *
+ * @param domainRefs The base URI references.
*/
public void setDomainRefs(List domainRefs) {
this.domainRefs = domainRefs;
@@ -181,30 +167,27 @@ public void setDomainRefs(List domainRefs) {
/**
* Sets the number of milliseconds between each mandatory nonce refresh.
- *
- * @param maxServerNonceAge
- * The nonce lifespan in milliseconds.
+ *
+ * @param maxServerNonceAge The nonce lifespan in milliseconds.
*/
public void setMaxServerNonceAge(long maxServerNonceAge) {
this.maxServerNonceAge = maxServerNonceAge;
}
/**
- * Sets the secret key known only by server.
- *
- * @param serverKey
- * The server secret key.
+ * Sets the secret key known only by the server.
+ *
+ * @param serverKey The server secret key.
*/
public void setServerKey(String serverKey) {
this.serverKey = serverKey;
}
/**
- * Set the internal verifier. In general you shouldn't replace it and
- * instead use the {@link #setWrappedVerifier(LocalVerifier)} method.
- *
- * @param verifier
- * The internal verifier.
+ * Set the internal verifier. In general, you shouldn't replace it and instead use the {@link
+ * #setWrappedVerifier(LocalVerifier)} method.
+ *
+ * @param verifier The internal verifier.
*/
@Override
public void setVerifier(Verifier verifier) {
@@ -226,13 +209,11 @@ public void setVerifier(Verifier verifier) {
}
/**
- * Sets the digest algorithm of secrets returned by the wrapped verifier.
- * The secrets from the wrapped verifier are the ones used by the verifier
- * to compare those sent by clients when attempting to authenticate.
- *
- * @param wrappedAlgorithm
- * The digest algorithm of secrets returned by the wrapped
- * verifier.
+ * Sets the digest algorithm of secrets returned by the wrapped verifier. The secrets from the
+ * wrapped verifier are the ones used by the verifier to compare those sent by clients when
+ * attempting to authenticate.
+ *
+ * @param wrappedAlgorithm The digest algorithm of secrets returned by the wrapped verifier.
* @see Digest
*/
public void setWrappedAlgorithm(String wrappedAlgorithm) {
@@ -240,14 +221,12 @@ public void setWrappedAlgorithm(String wrappedAlgorithm) {
}
/**
- * Sets the secret verifier that will be wrapped by real verifier supporting
- * all the HTTP DIGEST verifications (nonce, domain URIs, etc.).
- *
- * @param localVerifier
- * The local verifier to wrap.
+ * Sets the secret verifier that will be wrapped by real verifier supporting all the HTTP DIGEST
+ * verifications (nonce, domain URIs, etc.).
+ *
+ * @param localVerifier The local verifier to wrap.
*/
public void setWrappedVerifier(LocalVerifier localVerifier) {
getVerifier().setWrappedVerifier(localVerifier);
}
-
}
diff --git a/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/DigestUtils.java b/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/DigestUtils.java
index 14faff4087..16cf37e8d1 100644
--- a/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/DigestUtils.java
+++ b/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/DigestUtils.java
@@ -1,49 +1,44 @@
/**
- * Copyright 2005-2024 Qlik
- *
- * The contents of this file is subject to the terms of the Apache 2.0 open
- * source license available at http://www.opensource.org/licenses/apache-2.0
- *
+ * Copyright 2005-2026 Qlik
+ *
+ * The content of this file is subject to the terms of the Apache 2.0 open
+ * source license available at https://www.opensource.org/licenses/apache-2.0
+ *
* Restlet is a registered trademark of QlikTech International AB.
*/
-
package org.restlet.ext.crypto;
import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
-
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
-
import org.restlet.data.Digest;
/**
* Security data manipulation utilities.
- *
+ *
* @author Jerome Louvel
*/
public class DigestUtils {
/**
- * General regex pattern to extract comma separated name-value components.
- * This pattern captures one name and value per match(), and is repeatedly
- * applied to the input string to extract all components. Must handle both
- * quoted and unquoted values as RFC2617 isn't consistent in this respect.
- * Pattern is immutable and thread-safe so reuse one static instance.
+ * General regex pattern to extract comma separated name-value components. This pattern captures
+ * one name and value per match() and is repeatedly applied to the input string to extract all
+ * components. Must handle both quoted and unquoted values as RFC2617 isn't consistent in this
+ * respect. Pattern is immutable and thread-safe, so reuse one static instance.
*/
- private static final char[] HEXDIGITS = "0123456789abcdef".toCharArray();
+ private static final char[] HEX_DIGITS = "0123456789abcdef".toCharArray();
/**
- * Returns the digest of the target string. Target is decoded to bytes using
- * the US-ASCII charset. Supports MD5 and SHA-1 algorithms.
- *
- * @param target
- * The string to encode.
- * @param algorithm
- * The digest algorithm to use.
+ * Returns the digest of the target string. Target is decoded to bytes using the US-ASCII
+ * charset. Supports MD5 and SHA-1 algorithms.
+ *
+ * @param target The string to encode.
+ * @param algorithm The digest algorithm to use.
* @return The digest of the target string.
*/
public static char[] digest(char[] target, String algorithm) {
@@ -51,13 +46,11 @@ public static char[] digest(char[] target, String algorithm) {
}
/**
- * Returns the digest of the target string. Target is decoded to bytes using
- * the US-ASCII charset. Supports MD5 and SHA-1 algorithms.
- *
- * @param target
- * The string to encode.
- * @param algorithm
- * The digest algorithm to use.
+ * Returns the digest of the target string. Target is decoded to bytes using the US-ASCII
+ * charset. Supports MD5 and SHA-1 algorithms.
+ *
+ * @param target The string to encode.
+ * @param algorithm The digest algorithm to use.
* @return The digest of the target string.
*/
public static String digest(String target, String algorithm) {
@@ -68,15 +61,13 @@ public static String digest(String target, String algorithm) {
}
throw new IllegalArgumentException("Unsupported algorithm.");
- };
+ }
/**
* Converts a source string to its HMAC/SHA-1 value.
- *
- * @param source
- * The source string to convert.
- * @param secretKey
- * The secret key to use for conversion.
+ *
+ * @param source The source string to convert.
+ * @param secretKey The secret key to use for conversion.
* @return The HMac value of the source string.
*/
public static byte[] toHMacSha1(String source, byte[] secretKey) {
@@ -94,12 +85,10 @@ public static byte[] toHMacSha1(String source, byte[] secretKey) {
result = mac.doFinal(source.getBytes());
} catch (NoSuchAlgorithmException nsae) {
throw new RuntimeException(
- "Could not find the SHA-1 algorithm. HMac conversion failed.",
- nsae);
+ "Could not find the SHA-1 algorithm. HMac conversion failed.", nsae);
} catch (InvalidKeyException ike) {
throw new RuntimeException(
- "Invalid key exception detected. HMac conversion failed.",
- ike);
+ "Invalid key exception detected. HMac conversion failed.", ike);
}
return result;
@@ -107,11 +96,9 @@ public static byte[] toHMacSha1(String source, byte[] secretKey) {
/**
* Converts a source string to its HMAC/SHA-1 value.
- *
- * @param source
- * The source string to convert.
- * @param secretKey
- * The secret key to use for conversion.
+ *
+ * @param source The source string to convert.
+ * @param secretKey The secret key to use for conversion.
* @return The HMac value of the source string.
*/
public static byte[] toHMacSha1(String source, String secretKey) {
@@ -120,11 +107,9 @@ public static byte[] toHMacSha1(String source, String secretKey) {
/**
* Converts a source string to its HMAC/SHA256 value.
- *
- * @param source
- * The source string to convert.
- * @param secretKey
- * The secret key to use for conversion.
+ *
+ * @param source The source string to convert.
+ * @param secretKey The secret key to use for conversion.
* @return The HMac value of the source string.
*/
public static byte[] toHMacSha256(String source, byte[] secretKey) {
@@ -132,30 +117,23 @@ public static byte[] toHMacSha256(String source, byte[] secretKey) {
try {
// Create the HMAC/SHA256 key
- SecretKeySpec signingKey = new SecretKeySpec(secretKey,
- "HmacSHA256");
+ SecretKeySpec signingKey = new SecretKeySpec(secretKey, "HmacSHA256");
// Create the message authentication code (MAC)
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(signingKey);
// Compute the HMAC value
- result = mac.doFinal(source.getBytes("UTF-8"));
+ result = mac.doFinal(source.getBytes(StandardCharsets.UTF_8));
} catch (NoSuchAlgorithmException nsae) {
throw new RuntimeException(
- "Could not find the SHA256 algorithm. HMac conversion failed.",
- nsae);
+ "Could not find the SHA256 algorithm. HMac conversion failed.", nsae);
} catch (InvalidKeyException ike) {
throw new RuntimeException(
- "Invalid key exception detected. HMac conversion failed.",
- ike);
+ "Invalid key exception detected. HMac conversion failed.", ike);
} catch (IllegalStateException ise) {
throw new RuntimeException(
- "IIllegal state exception detected. HMac conversion failed.",
- ise);
- } catch (UnsupportedEncodingException uee) {
- throw new RuntimeException(
- "Unsuported encoding UTF-8. HMac conversion failed.", uee);
+ "IIllegal state exception detected. HMac conversion failed.", ise);
}
return result;
@@ -163,11 +141,9 @@ public static byte[] toHMacSha256(String source, byte[] secretKey) {
/**
* Converts a source string to its HMAC/SHA256 value.
- *
- * @param source
- * The source string to convert.
- * @param secretKey
- * The secret key to use for conversion.
+ *
+ * @param source The source string to convert.
+ * @param secretKey The secret key to use for conversion.
* @return The HMac value of the source string.
*/
public static byte[] toHMacSha256(String source, String secretKey) {
@@ -175,21 +151,16 @@ public static byte[] toHMacSha256(String source, String secretKey) {
}
/**
- * Return the HTTP DIGEST hashed secret. It concatenates the identifier,
- * realm and secret, separated by a comma and digest them using MD5.
- *
- * @param identifier
- * The user identifier to hash.
- * @param secret
- * The user secret.
- * @param realm
- * The authentication realm.
- * @return A hash of the user name, realm, and password, specified as A1 in
- * section 3.2.2.2 of RFC2617, or null if the identifier has no
- * corresponding secret.
+ * Return the HTTP DIGEST hashed secret. It concatenates the identifier, realm and secret,
+ * separated by a comma and digests them using MD5.
+ *
+ * @param identifier The user identifier to hash.
+ * @param secret The user secret.
+ * @param realm The authentication realm.
+ * @return A hash of the username, realm, and password, specified as A1 in section 3.2.2.2 of
+ * RFC2617, or null if the identifier has no corresponding secret.
*/
- public static String toHttpDigest(String identifier, char[] secret,
- String realm) {
+ public static String toHttpDigest(String identifier, char[] secret, String realm) {
if (secret != null) {
return toMd5(identifier + ":" + realm + ":" + new String(secret));
}
@@ -198,13 +169,12 @@ public static String toHttpDigest(String identifier, char[] secret,
}
/**
- * Returns the MD5 digest of the target string. Target is decoded to bytes
- * using the US-ASCII charset. The returned hexadecimal String always
- * contains 32 lowercase alphanumeric characters. For example, if target is
- * "HelloWorld", this method returns "68e109f0f40ca72a15e05cc22786f8e6".
- *
- * @param target
- * The string to encode.
+ * Returns the MD5 digest of the target string. Target is decoded to bytes using the US-ASCII
+ * charset. The returned hexadecimal String always contains 32 lowercase alphanumeric
+ * characters. For example, if the target is "HelloWorld", this method returns
+ * "68e109f0f40ca72a15e05cc22786f8e6".
+ *
+ * @param target The string to encode.
* @return The MD5 digest of the target string.
*/
public static String toMd5(String target) {
@@ -218,43 +188,38 @@ public static String toMd5(String target) {
}
/**
- * Returns the MD5 digest of target string. Target is decoded to bytes using
- * the named charset. The returned hexadecimal String always contains 32
- * lowercase alphanumeric characters. For example, if target is
- * "HelloWorld", this method returns "68e109f0f40ca72a15e05cc22786f8e6".
- *
- * @param target
- * The string to encode.
- * @param charsetName
- * The character set.
+ * Returns the MD5 digest of the target string. Target is decoded to bytes using the named
+ * charset. The returned hexadecimal String always contains 32 lowercase alphanumeric
+ * characters. For example, if the target is "HelloWorld", this method returns
+ * "68e109f0f40ca72a15e05cc22786f8e6".
+ *
+ * @param target The string to encode.
+ * @param charsetName The character set.
* @return The MD5 digest of the target string.
- *
* @throws UnsupportedEncodingException
*/
public static String toMd5(String target, String charsetName)
throws UnsupportedEncodingException {
try {
- final byte[] md5 = MessageDigest.getInstance("MD5").digest(
- target.getBytes(charsetName));
+ final byte[] md5 =
+ MessageDigest.getInstance("MD5").digest(target.getBytes(charsetName));
final char[] md5Chars = new char[32];
int i = 0;
for (final byte b : md5) {
- md5Chars[i++] = HEXDIGITS[(b >> 4) & 0xF];
- md5Chars[i++] = HEXDIGITS[b & 0xF];
+ md5Chars[i++] = HEX_DIGITS[(b >> 4) & 0xF];
+ md5Chars[i++] = HEX_DIGITS[b & 0xF];
}
return new String(md5Chars);
} catch (NoSuchAlgorithmException nsae) {
- throw new RuntimeException(
- "No MD5 algorithm, unable to compute MD5");
+ throw new RuntimeException("No MD5 algorithm, unable to compute MD5");
}
}
/**
- * Returns the SHA1 digest of the target string. Target is decoded to bytes
- * using the US-ASCII charset.
- *
- * @param target
- * The string to encode.
+ * Returns the SHA1 digest of the target string. Target is decoded to bytes using the US-ASCII
+ * charset.
+ *
+ * @param target The string to encode.
* @return The MD5 digest of the target string.
*/
public static String toSha1(String target) {
@@ -268,34 +233,28 @@ public static String toSha1(String target) {
}
/**
- * Returns the SHA1 digest of target string. Target is decoded to bytes
- * using the named charset.
- *
- * @param target
- * The string to encode.
- * @param charsetName
- * The character set.
+ * Returns the SHA1 digest of the target string. Target is decoded to bytes using the named
+ * charset.
+ *
+ * @param target The string to encode.
+ * @param charsetName The character set.
* @return The SHA1 digest of the target string.
- *
* @throws UnsupportedEncodingException
*/
public static String toSha1(String target, String charsetName)
throws UnsupportedEncodingException {
try {
- return Base64.getEncoder().encodeToString(
- MessageDigest.getInstance("SHA1").digest(
- target.getBytes(charsetName)));
+ return Base64.getEncoder()
+ .encodeToString(
+ MessageDigest.getInstance("SHA1").digest(target.getBytes(charsetName)));
} catch (NoSuchAlgorithmException nsae) {
- throw new RuntimeException(
- "No SHA1 algorithm, unable to compute SHA1");
+ throw new RuntimeException("No SHA1 algorithm, unable to compute SHA1");
}
}
/**
- * Private constructor to ensure that the class acts as a true utility class
- * i.e. it isn't instantiable and extensible.
+ * Private constructor to ensure that the class acts as a true utility class i.e., it isn't
+ * instantiable and extensible.
*/
- private DigestUtils() {
- }
-
+ private DigestUtils() {}
}
diff --git a/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/DigestVerifier.java b/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/DigestVerifier.java
index 2fcac96935..f5f4cd92be 100644
--- a/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/DigestVerifier.java
+++ b/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/DigestVerifier.java
@@ -1,29 +1,26 @@
/**
- * Copyright 2005-2024 Qlik
- *
- * The contents of this file is subject to the terms of the Apache 2.0 open
- * source license available at http://www.opensource.org/licenses/apache-2.0
- *
+ * Copyright 2005-2026 Qlik
+ *
+ * The content of this file is subject to the terms of the Apache 2.0 open
+ * source license available at https://www.opensource.org/licenses/apache-2.0
+ *
* Restlet is a registered trademark of QlikTech International AB.
*/
-
package org.restlet.ext.crypto;
+import java.util.logging.Level;
import org.restlet.Context;
import org.restlet.data.Digest;
import org.restlet.security.LocalVerifier;
import org.restlet.security.SecretVerifier;
-import java.util.logging.Level;
-
/**
- * Wrapper verifier that can verify digested secrets. If the provided secret is
- * a digest, then the local secret must either be a digest of the same algorithm
- * or the wrapped verifier must be a {@link LocalVerifier} returning secrets in
- * clear.
+ * Wrapper verifier that can verify digested secrets. If the provided secret is a digest, then the
+ * local secret must either be a digest of the same algorithm or the wrapped verifier must be a
+ * {@link LocalVerifier} returning secrets in clear.
*
- * If the provided secret is a regular secret, then the local secret can be in
- * any digest algorithm or a regular secret.
+ * If the provided secret is a regular secret, then the local secret can be in any digest algorithm
+ * or a regular secret.
*
* @see Digest
* @see DigestAuthenticator
@@ -31,7 +28,7 @@
*/
public class DigestVerifier extends SecretVerifier {
- /** The digest algorithm of provided secrets. */
+ /** The digest algorithm. */
private String algorithm;
/** The digest algorithm of secrets returned by the wrapped verifier. */
@@ -43,34 +40,25 @@ public class DigestVerifier extends SecretVerifier {
/**
* Constructor.
*
- * @param algorithm
- * The digest algorithm of provided secrets.
- * @param wrappedVerifier
- * The wrapped secret verifier.
- * @param wrappedAlgorithm
- * The digest algorithm of secrets provided by the wrapped
- * verifier.
+ * @param algorithm The digest algorithm.
+ * @param wrappedVerifier The wrapped secret verifier.
+ * @param wrappedAlgorithm The digest algorithm of secrets provided by the wrapped verifier.
* @see Digest
*/
- public DigestVerifier(String algorithm, T wrappedVerifier,
- String wrappedAlgorithm) {
+ public DigestVerifier(String algorithm, T wrappedVerifier, String wrappedAlgorithm) {
this.algorithm = algorithm;
this.wrappedAlgorithm = wrappedAlgorithm;
this.wrappedVerifier = wrappedVerifier;
}
/**
- * Computes the digest of a secret according to a specified algorithm. By
- * default, MD5 hashes (represented as a sequence of 32 hexadecimal digits)
- * and SHA-1 hashes are supported. For additional algorithm, override this
- * method.
+ * Computes the digest of a secret according to a specified algorithm. By default, MD5 hashes
+ * (represented as a sequence of 32 hexadecimal digits) and SHA-1 hashes are supported. For an
+ * additional algorithm, override this method.
*
- * @param identifier
- * The user identifier.
- * @param secret
- * The regular secret to digest.
- * @param algorithm
- * The digest algorithm to use.
+ * @param identifier The user identifier.
+ * @param secret The regular secret to digest.
+ * @param algorithm The digest algorithm to use.
* @return The digested secret.
* @see Digest
*/
@@ -79,8 +67,8 @@ protected char[] digest(String identifier, char[] secret, String algorithm) {
}
/**
- * Returns the digest algorithm of provided secrets. Provided secrets are
- * the ones sent by clients when attempting to authenticate.
+ * Returns the digest algorithm of provided secrets. Provided secrets are the ones sent by
+ * clients when attempting to authenticate.
*
* @return The digest algorithm of input secrets.
*/
@@ -89,11 +77,10 @@ public String getAlgorithm() {
}
/**
- * Sets the digest algorithm of provided secrets. Provided secrets are the
- * ones sent by clients when attempting to authenticate.
+ * Sets the digest algorithm of provided secrets. Provided secrets are the ones sent by clients
+ * when attempting to authenticate.
*
- * @param algorithm
- * The digest algorithm of secrets provided by the user.
+ * @param algorithm The digest algorithm of secrets provided by the user.
* @see Digest
*/
public void setAlgorithm(String algorithm) {
@@ -101,9 +88,9 @@ public void setAlgorithm(String algorithm) {
}
/**
- * Returns the digest algorithm of secrets returned by the wrapped verifier.
- * The secrets from the wrapped verifier are the ones used by the verifier
- * to compare those sent by clients when attempting to authenticate.
+ * Returns the digest algorithm of secrets returned by the wrapped verifier. The secrets from
+ * the wrapped verifier are the ones used by the verifier to compare those sent by clients when
+ * attempting to authenticate.
*
* @return The digest algorithm of secrets returned by the wrapped verifier.
*/
@@ -112,13 +99,11 @@ public String getWrappedAlgorithm() {
}
/**
- * Sets the digest algorithm of secrets returned by the wrapped verifier.
- * The secrets from the wrapped verifier are the ones used by the verifier
- * to compare those sent by clients when attempting to authenticate.
+ * Sets the digest algorithm of secrets returned by the wrapped verifier. The secrets from the
+ * wrapped verifier are the ones used by the verifier to compare those sent by clients when
+ * attempting to authenticate.
*
- * @param wrappedAlgorithm
- * The digest algorithm of secrets returned by the wrapped
- * verifier.
+ * @param wrappedAlgorithm The digest algorithm of secrets returned by the wrapped verifier.
* @see Digest
*/
public void setWrappedAlgorithm(String wrappedAlgorithm) {
@@ -126,12 +111,11 @@ public void setWrappedAlgorithm(String wrappedAlgorithm) {
}
/**
- * Returns the wrapped secret associated to a given identifier. This method
- * can only be called if the wrapped verifier is a {@link LocalVerifier}.
+ * Returns the wrapped secret associated with a given identifier. This method can only be called
+ * if the wrapped verifier is a {@link LocalVerifier}.
*
- * @param identifier
- * The identifier to lookup.
- * @return The secret associated to the identifier or null.
+ * @param identifier The identifier to lookup.
+ * @return The secret associated with the identifier or null.
*/
public char[] getWrappedSecret(String identifier) {
char[] result = null;
@@ -140,7 +124,8 @@ public char[] getWrappedSecret(String identifier) {
result = localVerifier.getLocalSecret(identifier);
} else {
Context.getCurrentLogger()
- .log(Level.WARNING,
+ .log(
+ Level.WARNING,
"The wrapped verifier must be a LocalVerifier to allow digesting of wrapped secrets.");
}
@@ -148,26 +133,24 @@ public char[] getWrappedSecret(String identifier) {
}
/**
- * Returns the digest of the wrapped secret associated to a given
- * identifier. If the wrapped algorithm is null it returns the digest of the
- * wrapped secret, otherwise the algorithms must be identical. This method
- * can only be called if the wrapped verifier is a {@link LocalVerifier}.
+ * Returns the digest of the wrapped secret associated with a given identifier. If the wrapped
+ * algorithm is null, it returns the digest of the wrapped secret; otherwise the algorithms must
+ * be identical. This method can only be called if the wrapped verifier is a {@link
+ * LocalVerifier}.
*
- * @param identifier
- * The identifier to lookup.
- * @return The secret associated to the identifier or null.
+ * @param identifier The identifier to lookup.
+ * @return The secret associated with the identifier or null.
*/
public char[] getWrappedSecretDigest(String identifier) {
char[] result = null;
if (getWrappedAlgorithm() == null) {
- result = digest(identifier, getWrappedSecret(identifier),
- getAlgorithm());
+ result = digest(identifier, getWrappedSecret(identifier), getAlgorithm());
} else if (getAlgorithm().equals(getWrappedAlgorithm())) {
result = getWrappedSecret(identifier);
} else {
- Context.getCurrentLogger().log(Level.WARNING,
- "The digest algorithms can't be different.");
+ Context.getCurrentLogger()
+ .log(Level.WARNING, "The digest algorithms can't be different.");
}
return result;
@@ -185,8 +168,7 @@ public T getWrappedVerifier() {
/**
* Sets the wrapped secret verifier.
*
- * @param wrappedVerifier
- * The wrapped secret verifier.
+ * @param wrappedVerifier The wrapped secret verifier.
*/
public void setWrappedVerifier(T wrappedVerifier) {
this.wrappedVerifier = wrappedVerifier;
@@ -201,21 +183,22 @@ public int verify(String identifier, char[] secret) {
if (getWrappedAlgorithm() != null) {
secretDigest = digest(identifier, secret, getWrappedAlgorithm());
} else {
- // Both secrets should be in clear
+ // Both secrets should be clear
}
result = getWrappedVerifier().verify(identifier, secretDigest);
} else {
if (getWrappedAlgorithm() == null) {
- result = compare(secretDigest, getWrappedSecretDigest(identifier))
- ? RESULT_VALID
- : RESULT_INVALID;
+ result =
+ compare(secretDigest, getWrappedSecretDigest(identifier))
+ ? RESULT_VALID
+ : RESULT_INVALID;
} else if (getAlgorithm().equals(getWrappedAlgorithm())) {
result = getWrappedVerifier().verify(identifier, secretDigest);
} else {
result = RESULT_UNSUPPORTED;
- Context.getCurrentLogger().log(Level.WARNING,
- "The input and output algorithms can't be different.");
+ Context.getCurrentLogger()
+ .log(Level.WARNING, "The input and output algorithms can't be different.");
}
}
diff --git a/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/internal/AwsUtils.java b/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/internal/AwsUtils.java
index 120129c7ac..5d6770be96 100644
--- a/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/internal/AwsUtils.java
+++ b/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/internal/AwsUtils.java
@@ -1,12 +1,11 @@
/**
- * Copyright 2005-2024 Qlik
- *
- * The contents of this file is subject to the terms of the Apache 2.0 open
- * source license available at http://www.opensource.org/licenses/apache-2.0
- *
+ * Copyright 2005-2026 Qlik
+ *
+ * The content of this file is subject to the terms of the Apache 2.0 open
+ * source license available at https://www.opensource.org/licenses/apache-2.0
+ *
* Restlet is a registered trademark of QlikTech International AB.
*/
-
package org.restlet.ext.crypto.internal;
import java.util.Base64;
@@ -18,7 +17,6 @@
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-
import org.restlet.Request;
import org.restlet.data.Header;
import org.restlet.data.Method;
@@ -32,30 +30,26 @@
import org.restlet.util.Series;
/**
- * Provides utility functions for implementing the Amazon S3 Authentication
- * scheme.
- *
+ * Provides utility functions for implementing the Amazon S3 Authentication scheme.
+ *
* @author Jean-Philippe Steinmetz
- * @see
- * Authenticating REST Requests
+ * @see
+ * Authenticating REST Requests
*/
public class AwsUtils {
/**
* Returns the canonicalized AMZ headers.
- *
- * @param requestHeaders
- * The list of request headers.
+ *
+ * @param requestHeaders The list of request headers.
* @return The canonicalized AMZ headers.
*/
- public static String getCanonicalizedAmzHeaders(
- Series requestHeaders) {
+ public static String getCanonicalizedAmzHeaders(Series requestHeaders) {
StringBuilder sb = new StringBuilder();
Pattern spacePattern = Pattern.compile("\\s+");
- // Create a lexographically sorted list of headers that begin with x-amz
- SortedMap amzHeaders = new TreeMap();
+ // Create a lexicographically sorted list of headers that begin with x-amz
+ SortedMap amzHeaders = new TreeMap<>();
if (requestHeaders != null) {
for (Header header : requestHeaders) {
@@ -66,8 +60,7 @@ public static String getCanonicalizedAmzHeaders(
if (amzHeaders.containsKey(name))
value = amzHeaders.get(name) + "," + header.getValue();
- else
- value = header.getValue();
+ else value = header.getValue();
// All newlines and multiple spaces must be replaced with a
// single space character.
@@ -81,8 +74,7 @@ public static String getCanonicalizedAmzHeaders(
// Concatenate all AMZ headers
for (Entry entry : amzHeaders.entrySet()) {
- sb.append(entry.getKey()).append(':').append(entry.getValue())
- .append("\n");
+ sb.append(entry.getKey()).append(':').append(entry.getValue()).append("\n");
}
return sb.toString();
@@ -90,121 +82,97 @@ public static String getCanonicalizedAmzHeaders(
/**
* Returns the canonicalized resource name.
- *
- * @param reference
- * The resource reference
+ *
+ * @param reference The resource reference
* @return The canonicalized resource name.
*/
public static String getCanonicalizedResourceName(Reference reference) {
String hostName = reference.getHostDomain();
String path = reference.getPath();
- Pattern hostNamePattern = Pattern
- .compile("s3[a-z0-1\\-]*.amazonaws.com");
+ Pattern hostNamePattern = Pattern.compile("s3[a-z0-1\\-]*.amazonaws.com");
StringBuilder sb = new StringBuilder();
// Append the bucket
if (hostName != null) {
// If the host name contains a port number, remove it
- if (hostName.contains(":"))
- hostName = hostName.substring(0, hostName.indexOf(":"));
+ if (hostName.contains(":")) hostName = hostName.substring(0, hostName.indexOf(':'));
Matcher hostNameMatcher = hostNamePattern.matcher(hostName);
if (hostName.endsWith(".s3.amazonaws.com")) {
- String bucketName = hostName.substring(0,
- hostName.length() - 17);
+ String bucketName = hostName.substring(0, hostName.length() - 17);
sb.append("/").append(bucketName);
} else if (!hostNameMatcher.matches()) {
sb.append("/").append(hostName);
}
}
- int queryIdx = path.indexOf("?");
+ int queryIdx = path.indexOf('?');
// Append the resource path
- if (queryIdx >= 0)
- sb.append(path, 0, queryIdx);
- else
- sb.append(path);
+ if (queryIdx >= 0) sb.append(path, 0, queryIdx);
+ else sb.append(path);
// Append the AWS sub-resource
if (queryIdx >= 0) {
String query = path.substring(queryIdx - 1);
- if (query.contains("?acl"))
- sb.append("?acl");
- else if (query.contains("?location"))
- sb.append("?location");
- else if (query.contains("?logging"))
- sb.append("?logging");
- else if (query.contains("?torrent"))
- sb.append("?torrent");
+ if (query.contains("?acl")) sb.append("?acl");
+ else if (query.contains("?location")) sb.append("?location");
+ else if (query.contains("?logging")) sb.append("?logging");
+ else if (query.contains("?torrent")) sb.append("?torrent");
}
return sb.toString();
}
/**
- * Returns the AWS authentication compatible signature for the given string
- * to sign and secret.
- *
- * @param stringToSign
- * The string to sign.
- * @param secret
- * The user secret to sign with
+ * Returns the AWS authentication compatible signature for the given string to sign and secret.
+ *
+ * @param stringToSign The string to sign.
+ * @param secret The user secret to sign with
* @return The AWS compatible signature
*/
public static String getHmacSha1Signature(String stringToSign, char[] secret) {
- return Base64.getEncoder().encodeToString(
- DigestUtils.toHMacSha1(stringToSign,
- IoUtils.toByteArray(secret)));
+ return Base64.getEncoder()
+ .encodeToString(DigestUtils.toHMacSha1(stringToSign, IoUtils.toByteArray(secret)));
}
/**
- * Returns the AWS authentication compatible signature for the given string
- * to sign and secret.
- *
- * @param stringToSign
- * The string to sign.
- * @param secret
- * The user secret to sign with
+ * Returns the AWS authentication compatible signature for the given string to sign and secret.
+ *
+ * @param stringToSign The string to sign.
+ * @param secret The user secret to sign with
* @return The AWS compatible signature
*/
- public static String getHmacSha256Signature(String stringToSign,
- char[] secret) {
- return Base64.getEncoder().encodeToString(
- DigestUtils.toHMacSha256(stringToSign,
- IoUtils.toByteArray(secret)));
+ public static String getHmacSha256Signature(String stringToSign, char[] secret) {
+ return Base64.getEncoder()
+ .encodeToString(
+ DigestUtils.toHMacSha256(stringToSign, IoUtils.toByteArray(secret)));
}
/**
- * Returns the AWS SimpleDB authentication compatible signature for the
- * given request and secret.
- *
- * @param method
- * The request method.
- * @param resourceRef
- * The target resource reference.
- * @param params
- * The request parameters.
- * @param secret
- * The user secret to sign with
+ * Returns the AWS SimpleDB authentication compatible signature for the given request and
+ * secret.
+ *
+ * @param method The request method.
+ * @param resourceRef The target resource reference.
+ * @param params The request parameters.
+ * @param secret The user secret to sign with
* @return The AWS SimpleDB compatible signature
*/
- public static String getQuerySignature(Method method,
- Reference resourceRef, List params, char[] secret) {
- return getHmacSha256Signature(
- getQueryStringToSign(method, resourceRef, params), secret);
+ public static String getQuerySignature(
+ Method method, Reference resourceRef, List params, char[] secret) {
+ return getHmacSha256Signature(getQueryStringToSign(method, resourceRef, params), secret);
}
/**
* Returns the SimpleDB string to sign.
- *
- * @param resourceRef
- * The target resource reference.
+ *
+ * @param resourceRef The target resource reference.
* @return The string to sign.
*/
- public static String getQueryStringToSign(Method method,
- Reference resourceRef, List params) {
+ public static String getQueryStringToSign(
+ Method method, Reference resourceRef, List params) {
StringBuilder toSign = new StringBuilder();
// Append HTTP method
@@ -232,8 +200,7 @@ public static String getQueryStringToSign(Method method,
toSign.append(Reference.encode(param.getName()));
if (param.getValue() != null) {
- toSign.append('=').append(
- Reference.encode(param.getValue(), true));
+ toSign.append('=').append(Reference.encode(param.getValue(), true));
}
}
@@ -241,86 +208,76 @@ public static String getQueryStringToSign(Method method,
}
/**
- * Returns the AWS S3 authentication compatible signature for the given
- * request and secret.
- *
- * @param request
- * The request to create the signature for
- * @param secret
- * The user secret to sign with
+ * Returns the AWS S3 authentication compatible signature for the given request and secret.
+ *
+ * @param request The request to create the signature for
+ * @param secret The user secret to sign with
* @return The AWS S3 compatible signature
*/
public static String getS3Signature(Request request, char[] secret) {
@SuppressWarnings("unchecked")
- Series headers = (Series) request.getAttributes().get(
- HeaderConstants.ATTRIBUTE_HEADERS);
+ Series headers =
+ (Series) request.getAttributes().get(HeaderConstants.ATTRIBUTE_HEADERS);
return getS3Signature(request, headers, secret);
}
/**
- * Returns the AWS S3 authentication compatible signature for the given
- * request and secret.
- *
- * @param request
- * The request to create the signature for
- * @param headers
- * The HTTP headers associated with the request
- * @param secret
- * The user secret to sign with
+ * Returns the AWS S3 authentication compatible signature for the given request and secret.
+ *
+ * @param request The request to create the signature for
+ * @param headers The HTTP headers associated with the request
+ * @param secret The user secret to sign with
* @return The AWS S3 compatible signature
*/
- public static String getS3Signature(Request request,
- Series headers, char[] secret) {
+ public static String getS3Signature(Request request, Series headers, char[] secret) {
return getHmacSha1Signature(getS3StringToSign(request, headers), secret);
}
/**
* Returns the string to sign.
- *
- * @param request
- * The request to generate the signature string from
+ *
+ * @param request The request to generate the signature string from
* @return The string to sign
*/
public static String getS3StringToSign(Request request) {
@SuppressWarnings("unchecked")
- Series headers = (Series) request.getAttributes().get(
- HeaderConstants.ATTRIBUTE_HEADERS);
+ Series headers =
+ (Series) request.getAttributes().get(HeaderConstants.ATTRIBUTE_HEADERS);
return getS3StringToSign(request, headers);
}
/**
* Returns the S3 string to sign.
- *
- * @param request
- * The request to generate the signature string from
- * @param headers
- * The HTTP headers associated with the request
+ *
+ * @param request The request to generate the signature string from
+ * @param headers The HTTP headers associated with the request
* @return The string to sign
*/
- public static String getS3StringToSign(Request request,
- Series headers) {
+ public static String getS3StringToSign(Request request, Series headers) {
String canonicalizedAmzHeaders = getCanonicalizedAmzHeaders(headers);
- String canonicalizedResource = getCanonicalizedResourceName(request
- .getResourceRef());
- String contentMD5 = (headers == null) ? null : headers.getFirstValue(
- HeaderConstants.HEADER_CONTENT_MD5, true);
- String contentType = (headers == null) ? null : headers.getFirstValue(
- HeaderConstants.HEADER_CONTENT_TYPE, true);
- String date = (headers == null) ? null : headers.getFirstValue(
- "X-Amz-Date", true);
+ String canonicalizedResource = getCanonicalizedResourceName(request.getResourceRef());
+ String contentMD5 =
+ (headers == null)
+ ? null
+ : headers.getFirstValue(HeaderConstants.HEADER_CONTENT_MD5, true);
+ String contentType =
+ (headers == null)
+ ? null
+ : headers.getFirstValue(HeaderConstants.HEADER_CONTENT_TYPE, true);
+ String date = (headers == null) ? null : headers.getFirstValue("X-Amz-Date", true);
String method = request.getMethod().getName();
- // If amazon's date header wasn't found, try to grab the regular date
- // header
+ // If amazon's date header wasn't found, try to grab the regular date header
if (date == null || (date.isEmpty())) {
- date = (headers == null) ? null : headers.getFirstValue(
- HeaderConstants.HEADER_DATE, true);
+ date =
+ (headers == null)
+ ? null
+ : headers.getFirstValue(HeaderConstants.HEADER_DATE, true);
}
// If no date header exists, make one
if (date == null || (date.isEmpty())) {
- date = DateUtils.format(new Date(),
- DateUtils.FORMAT_RFC_1123.get(0));
+ date = DateUtils.format(new Date(), DateUtils.FORMAT_RFC_1123.getFirst());
if (headers != null) {
headers.add(HeaderConstants.HEADER_DATE, date);
}
@@ -331,12 +288,9 @@ public static String getS3StringToSign(Request request,
// This patch seems to apply to Sun JVM only.
final String jvmVendor = System.getProperty("java.vm.vendor");
- if ((jvmVendor != null)
- && (jvmVendor.toLowerCase()).startsWith("sun")) {
- final int majorVersionNumber = SystemUtils
- .getJavaMajorVersion();
- final int minorVersionNumber = SystemUtils
- .getJavaMinorVersion();
+ if ((jvmVendor != null) && (jvmVendor.toLowerCase()).startsWith("sun")) {
+ final int majorVersionNumber = SystemUtils.getJavaMajorVersion();
+ final int minorVersionNumber = SystemUtils.getJavaMinorVersion();
if (majorVersionNumber == 1) {
if (minorVersionNumber < 5) {
@@ -352,16 +306,15 @@ public static String getS3StringToSign(Request request,
contentType = "application/x-www-form-urlencoded";
}
- StringBuilder toSign = new StringBuilder();
- toSign.append(method != null ? method : "").append("\n");
- toSign.append(contentMD5 != null ? contentMD5 : "").append("\n");
- toSign.append(contentType != null ? contentType : "").append("\n");
- toSign.append(date != null ? date : "").append("\n");
- toSign.append(canonicalizedAmzHeaders != null ? canonicalizedAmzHeaders
- : "");
- toSign.append(canonicalizedResource != null ? canonicalizedResource
- : "");
-
- return toSign.toString();
+ return (method != null ? method : "")
+ + "\n"
+ + (contentMD5 != null ? contentMD5 : "")
+ + "\n"
+ + (contentType != null ? contentType : "")
+ + "\n"
+ + (date != null ? date : "")
+ + "\n"
+ + (canonicalizedAmzHeaders != null ? canonicalizedAmzHeaders : "")
+ + (canonicalizedResource != null ? canonicalizedResource : "");
}
}
diff --git a/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/internal/AwsVerifier.java b/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/internal/AwsVerifier.java
index 9a598d797e..ae5548d0f0 100644
--- a/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/internal/AwsVerifier.java
+++ b/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/internal/AwsVerifier.java
@@ -1,12 +1,11 @@
/**
- * Copyright 2005-2024 Qlik
- *
- * The contents of this file is subject to the terms of the Apache 2.0 open
- * source license available at http://www.opensource.org/licenses/apache-2.0
- *
+ * Copyright 2005-2026 Qlik
+ *
+ * The content of this file is subject to the terms of the Apache 2.0 open
+ * source license available at https://www.opensource.org/licenses/apache-2.0
+ *
* Restlet is a registered trademark of QlikTech International AB.
*/
-
package org.restlet.ext.crypto.internal;
import org.restlet.Request;
@@ -20,31 +19,23 @@
import org.restlet.util.Series;
/**
- * Wrapped verifier that can verify HTTP requests using the Amazon S3
- * authentication scheme. Verifies the user by computing the request signature
- * using the local secret and comparing it to the signature provided in the
- * request.
- *
- * Per the Amazon S3 specification the {@code Date} header is required. If the
- * {@code Date} header is missing or the request is older than the allowed time
- * limit, specified by the {@code maxRequestAge} property, the request fails
- * verification.
- *
+ * Wrapped verifier that can verify HTTP requests using the Amazon S3 authentication scheme.
+ * Verifies the user by computing the request signature using the local secret and comparing it to
+ * the signature provided in the request.
+ *
+ *
Per the Amazon S3 specification the {@code Date} header is required. If the {@code Date}
+ * header is missing or the request is older than the allowed time limit, specified by the {@code
+ * maxRequestAge} property, the request fails verification.
+ *
* @author Jean-Philippe Steinmetz
- * @see
- * Authenticating REST Requests
+ * @see
+ * Authenticating REST Requests
*/
public class AwsVerifier extends SecretVerifier {
- /**
- * Default maximum request age (15 minutes)
- */
+ /** Default maximum request age (15 minutes) */
private static final long DEFAULT_MAX_REQUEST_AGE = 15 * 60 * 1000L;
- /**
- * The maximum age of a request, in milliseconds, before it is considered
- * stale.
- */
+ /** The maximum age of a request, in milliseconds, before it is considered stale. */
private long maxRequestAge;
/** The local secret verifier. */
@@ -52,10 +43,8 @@ public class AwsVerifier extends SecretVerifier {
/**
* Creates a new HttpAwsS3Verifier instance.
- *
- * @param wrappedVerifier
- * The wrapped verifier containing local identifier/secret
- * couples
+ *
+ * @param wrappedVerifier The wrapped verifier containing local identifier/secret couples
*/
public AwsVerifier(LocalVerifier wrappedVerifier) {
this(wrappedVerifier, DEFAULT_MAX_REQUEST_AGE);
@@ -63,13 +52,10 @@ public AwsVerifier(LocalVerifier wrappedVerifier) {
/**
* Creates a new HttpAwsS3Verifier instance.
- *
- * @param wrappedVerifier
- * The wrapped verifier containing local identifier/secret
- * couples
- * @param maxRequestAge
- * The maximum age of a request, in milliseconds, before it is
- * considered stale
+ *
+ * @param wrappedVerifier The wrapped verifier containing local identifier/secret couples
+ * @param maxRequestAge The maximum age of a request, in milliseconds, before it is considered
+ * stale
*/
public AwsVerifier(LocalVerifier wrappedVerifier, long maxRequestAge) {
super();
@@ -78,34 +64,26 @@ public AwsVerifier(LocalVerifier wrappedVerifier, long maxRequestAge) {
}
/**
- * Returns the user identifier portion of an Amazon S3 compatible
- * {@code Authorization} header.
- *
- * An Amazon S3 compatible {@code Authorization} header has the following
- * pattern.
+ * Returns the user identifier portion of an Amazon S3 compatible {@code Authorization} header.
+ *
+ *
An Amazon S3 compatible {@code Authorization} header has the following pattern.
* {@code Authorization: AWS id:signature}
*/
@Override
protected String getIdentifier(Request request, Response response) {
if (request.getChallengeResponse() == null
- || request.getChallengeResponse().getRawValue() == null)
- return null;
+ || request.getChallengeResponse().getRawValue() == null) return null;
- String[] parts = request.getChallengeResponse().getRawValue()
- .split(":");
+ String[] parts = request.getChallengeResponse().getRawValue().split(":");
- if (parts != null && parts.length == 2)
- return parts[0];
- else
- return null;
+ return (parts.length == 2) ? parts[0] : null;
}
/**
- * Returns the local secret associated to a given identifier.
- *
- * @param identifier
- * The identifier to lookup.
- * @return The secret associated to the identifier or null.
+ * Returns the local secret associated with a given identifier.
+ *
+ * @param identifier The identifier to lookup.
+ * @return The secret associated with the identifier or null.
*/
public char[] getLocalSecret(String identifier) {
char[] result = null;
@@ -114,42 +92,33 @@ public char[] getLocalSecret(String identifier) {
}
/**
- * Returns the maximum age of a request, in milliseconds, before it is
- * considered stale.
- *
- * A negative or zero value indicates no age restriction. The default value
- * is 15 minutes.
+ * Returns the maximum age of a request, in milliseconds, before it is considered stale.
+ *
+ *
A negative or zero value indicates no age restriction. The default value is 15 minutes.
*/
public long getMaxRequestAge() {
return this.maxRequestAge;
}
/**
- * Returns the signature portion of an Amazon S3 compatible
- * {@code Authorization} header.
- *
- * An Amazon S3 compatible {@code Authorization} header has the following
- * pattern.
+ * Returns the signature portion of an Amazon S3 compatible {@code Authorization} header.
+ *
+ *
An Amazon S3 compatible {@code Authorization} header has the following pattern.
* {@code Authorization: AWS id:signature}
*/
@Override
protected char[] getSecret(Request request, Response response) {
if (request.getChallengeResponse() == null
- || request.getChallengeResponse().getRawValue() == null)
- return null;
+ || request.getChallengeResponse().getRawValue() == null) return null;
- String[] parts = request.getChallengeResponse().getRawValue()
- .split(":");
+ String[] parts = request.getChallengeResponse().getRawValue().split(":");
- if (parts != null && parts.length == 2)
- return parts[1].toCharArray();
- else
- return null;
+ return (parts.length == 2) ? parts[1].toCharArray() : null;
}
/**
* Returns the wrapped local secret verifier.
- *
+ *
* @return The local secret verifier.
*/
public LocalVerifier getWrappedVerifier() {
@@ -157,23 +126,19 @@ public LocalVerifier getWrappedVerifier() {
}
/**
- * Sets the maximum age of a request, in milliseconds, before it is
- * considered stale.
- *
- * A negative or zero value indicates no age restriction. The default value
- * is 15 minutes.
+ * Sets the maximum age of a request, in milliseconds, before it is considered stale.
+ *
+ *
A negative or zero value indicates no age restriction. The default value is 15 minutes.
*/
public void setMaxRequestAge(long value) {
- if (value < 0)
- value = 0;
+ if (value < 0) value = 0;
this.maxRequestAge = value;
}
/**
* Sets the wrapped local secret verifier.
- *
- * @param wrappedVerifier
- * The local secret verifier.
+ *
+ * @param wrappedVerifier The local secret verifier.
*/
public void setWrappedVerifier(LocalVerifier wrappedVerifier) {
this.wrappedVerifier = wrappedVerifier;
@@ -181,37 +146,32 @@ public void setWrappedVerifier(LocalVerifier wrappedVerifier) {
@Override
public int verify(Request request, Response response) {
- if (request.getChallengeResponse() == null)
- return RESULT_MISSING;
+ if (request.getChallengeResponse() == null) return RESULT_MISSING;
@SuppressWarnings("unchecked")
- Series headers = (Series) request.getAttributes().get(
- HeaderConstants.ATTRIBUTE_HEADERS);
+ Series headers =
+ (Series) request.getAttributes().get(HeaderConstants.ATTRIBUTE_HEADERS);
String userId = getIdentifier(request, response);
- if (userId == null || (userId.length() == 0))
- return RESULT_MISSING;
+ if (userId == null || (userId.isEmpty())) return RESULT_MISSING;
// A date header is always required
- if (headers.getFirstValue(HeaderConstants.HEADER_DATE, true) == null)
- return RESULT_INVALID;
+ if (headers.getFirstValue(HeaderConstants.HEADER_DATE, true) == null) return RESULT_INVALID;
// Make sure the date is not stale
if (getMaxRequestAge() > 0) {
- Long date = DateUtils.parse(
- headers.getFirstValue(HeaderConstants.HEADER_DATE, true))
- .getTime();
+ Long date =
+ DateUtils.parse(headers.getFirstValue(HeaderConstants.HEADER_DATE, true))
+ .getTime();
Long now = System.currentTimeMillis();
- if (now - date > getMaxRequestAge())
- return RESULT_STALE;
+ if (now - date > getMaxRequestAge()) return RESULT_STALE;
}
char[] userSecret = getLocalSecret(userId);
char[] signature = getSecret(request, response);
String sigToCompare = AwsUtils.getS3Signature(request, userSecret);
- if (!compare(signature, sigToCompare.toCharArray()))
- return RESULT_INVALID;
+ if (!compare(signature, sigToCompare.toCharArray())) return RESULT_INVALID;
request.getClientInfo().setUser(new User(userId));
@@ -219,13 +179,11 @@ public int verify(Request request, Response response) {
}
/**
- * This function is not implemented because the authorization scheme
- * requires direct access to the request. See
- * {@link #verify(Request, Response)}.
+ * This function is not implemented because the authorization scheme requires direct access to
+ * the request. See {@link #verify(Request, Response)}.
*/
@Override
- public int verify(String identifier, char[] secret)
- throws IllegalArgumentException {
+ public int verify(String identifier, char[] secret) throws IllegalArgumentException {
throw new RuntimeException("Method not implemented");
}
}
diff --git a/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/internal/CryptoUtils.java b/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/internal/CryptoUtils.java
index 5e548499f7..1534462157 100644
--- a/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/internal/CryptoUtils.java
+++ b/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/internal/CryptoUtils.java
@@ -1,26 +1,23 @@
/**
- * Copyright 2005-2024 Qlik
- *
- * The contents of this file is subject to the terms of the Apache 2.0 open
- * source license available at http://www.opensource.org/licenses/apache-2.0
- *
+ * Copyright 2005-2026 Qlik
+ *
+ * The content of this file is subject to the terms of the Apache 2.0 open
+ * source license available at https://www.opensource.org/licenses/apache-2.0
+ *
* Restlet is a registered trademark of QlikTech International AB.
*/
-
package org.restlet.ext.crypto.internal;
-import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.util.Base64;
-
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
-
import org.restlet.ext.crypto.DigestUtils;
/**
* Simple usage of standard cipher features from JRE.
- *
+ *
* @author Remi Dewitte
* @author Jerome Louvel
*/
@@ -28,19 +25,16 @@ public final class CryptoUtils {
/**
* Creates a cipher for a given algorithm and secret.
- *
- * @param algorithm
- * The cryptographic algorithm.
- * @param secretKey
- * The cryptographic secret.
- * @param mode
- * The cipher mode, either {@link Cipher#ENCRYPT_MODE} or
- * {@link Cipher#DECRYPT_MODE}.
+ *
+ * @param algorithm The cryptographic algorithm.
+ * @param secretKey The cryptographic secret.
+ * @param mode The cipher mode, either {@link Cipher#ENCRYPT_MODE} or {@link
+ * Cipher#DECRYPT_MODE}.
* @return The new cipher.
* @throws GeneralSecurityException
*/
- private static Cipher createCipher(String algorithm, byte[] secretKey,
- int mode) throws GeneralSecurityException {
+ private static Cipher createCipher(String algorithm, byte[] secretKey, int mode)
+ throws GeneralSecurityException {
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(mode, new SecretKeySpec(secretKey, algorithm));
return cipher;
@@ -48,117 +42,99 @@ private static Cipher createCipher(String algorithm, byte[] secretKey,
/**
* Decrypts a bytes array.
- *
- * @param algo
- * The cryptographic algorithm.
- * @param secretKey
- * The cryptographic secret key.
- * @param encrypted
- * The encrypted bytes.
+ *
+ * @param algo The cryptographic algorithm.
+ * @param secretKey The cryptographic secret key.
+ * @param encrypted The encrypted bytes.
* @return The decrypted content string.
* @throws GeneralSecurityException
*/
public static String decrypt(String algo, byte[] secretKey, byte[] encrypted)
throws GeneralSecurityException {
- byte[] original = doFinal(algo, secretKey, Cipher.DECRYPT_MODE,
- encrypted);
- return new String(original, Charset.forName("UTF-8"));
+ byte[] original = doFinal(algo, secretKey, Cipher.DECRYPT_MODE, encrypted);
+ return new String(original, StandardCharsets.UTF_8);
}
/**
* Decrypts a bytes array.
- *
- * @param algo
- * The cryptographic algorithm.
- * @param base64Secret
- * The cryptographic secret key, encoded as a Base64 string.
- * @param encrypted
- * The encrypted bytes.
+ *
+ * @param algo The cryptographic algorithm.
+ * @param base64Secret The cryptographic secret key, encoded as a Base64 string.
+ * @param encrypted The encrypted bytes.
* @return The decrypted content string.
* @throws GeneralSecurityException
*/
- public static String decrypt(String algo, String base64Secret,
- byte[] encrypted) throws GeneralSecurityException {
+ public static String decrypt(String algo, String base64Secret, byte[] encrypted)
+ throws GeneralSecurityException {
return decrypt(algo, Base64.getDecoder().decode(base64Secret), encrypted);
}
/**
* Does final processing.
- *
- * @param algo
- * The cryptographic algorithm.
- * @param secretKey
- * The cryptographic secret key.
- * @param mode
- * The processing mode, either {@link Cipher#DECRYPT_MODE} or
- * {@link Cipher#ENCRYPT_MODE}.
- * @param what
- * The byte array to process.
+ *
+ * @param algo The cryptographic algorithm.
+ * @param secretKey The cryptographic secret key.
+ * @param mode The processing mode, either {@link Cipher#DECRYPT_MODE} or {@link
+ * Cipher#ENCRYPT_MODE}.
+ * @param what The byte array to process.
* @return The processed byte array.
* @throws GeneralSecurityException
*/
- private static byte[] doFinal(String algo, byte[] secretKey, int mode,
- byte[] what) throws GeneralSecurityException {
+ private static byte[] doFinal(String algo, byte[] secretKey, int mode, byte[] what)
+ throws GeneralSecurityException {
return createCipher(algo, secretKey, mode).doFinal(what);
}
/**
* Encrypts a content string.
- *
- * @param algo
- * The cryptographic algorithm.
- * @param secretKey
- * The cryptographic secret key.
- * @param content
- * The content string to encrypt.
+ *
+ * @param algo The cryptographic algorithm.
+ * @param secretKey The cryptographic secret key.
+ * @param content The content string to encrypt.
* @return The encrypted bytes.
* @throws GeneralSecurityException
*/
public static byte[] encrypt(String algo, byte[] secretKey, String content)
throws GeneralSecurityException {
- return doFinal(algo, secretKey, Cipher.ENCRYPT_MODE, content.getBytes(Charset.forName("UTF-8")));
+ return doFinal(
+ algo, secretKey, Cipher.ENCRYPT_MODE, content.getBytes(StandardCharsets.UTF_8));
}
/**
* Encrypts a content string.
- *
- * @param algo
- * The cryptographic algorithm.
- * @param base64Secret
- * The cryptographic secret, encoded as a Base64 string.
- * @param content
- * The content string to encrypt.
+ *
+ * @param algo The cryptographic algorithm.
+ * @param base64Secret The cryptographic secret, encoded as a Base64 string.
+ * @param content The content string to encrypt.
* @return The encrypted bytes.
* @throws GeneralSecurityException
*/
- public static byte[] encrypt(String algo, String base64Secret,
- String content) throws GeneralSecurityException {
+ public static byte[] encrypt(String algo, String base64Secret, String content)
+ throws GeneralSecurityException {
return encrypt(algo, Base64.getDecoder().decode(base64Secret), content);
}
/**
- * Generates a nonce as recommended in section 3.2.1 of RFC-2617, but
- * without the ETag field. The format is:
+ * Generates nonce as recommended in section 3.2.1 of RFC-2617, but without the ETag field. The
+ * format is:
- *
- * @param secretKey
- * a secret value known only to the creator of the nonce. It's
- * inserted into the nonce, and can be used later to validate the
- * nonce.
+ *
+ * @param secretKey a secret value known only to the creator of the nonce. It's inserted into
+ * the nonce and can be used later to validate the nonce.
*/
public static String makeNonce(String secretKey) {
final long currentTimeMS = System.currentTimeMillis();
- return Base64.getEncoder().encodeToString(
- (currentTimeMS + ":" + DigestUtils.toMd5(currentTimeMS + ":"
- + secretKey)).getBytes());
+ return Base64.getEncoder()
+ .encodeToString(
+ (currentTimeMS + ":" + DigestUtils.toMd5(currentTimeMS + ":" + secretKey))
+ .getBytes());
}
/**
- * Private constructor to ensure that the class acts as a true utility class
- * i.e. it isn't instantiable and extensible.
+ * Private constructor to ensure that the class acts as a true utility class i.e., it isn't
+ * instantiable and extensible.
*/
- private CryptoUtils() {
- }
+ private CryptoUtils() {}
}
diff --git a/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/internal/HttpAwsQueryHelper.java b/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/internal/HttpAwsQueryHelper.java
index 3f5f5ccf4e..d2e5747c8e 100644
--- a/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/internal/HttpAwsQueryHelper.java
+++ b/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/internal/HttpAwsQueryHelper.java
@@ -1,16 +1,14 @@
/**
- * Copyright 2005-2024 Qlik
- *
- * The contents of this file is subject to the terms of the Apache 2.0 open
- * source license available at http://www.opensource.org/licenses/apache-2.0
- *
+ * Copyright 2005-2026 Qlik
+ *
+ * The content of this file is subject to the terms of the Apache 2.0 open
+ * source license available at https://www.opensource.org/licenses/apache-2.0
+ *
* Restlet is a registered trademark of QlikTech International AB.
*/
-
package org.restlet.ext.crypto.internal;
import java.util.Date;
-
import org.restlet.Request;
import org.restlet.data.ChallengeResponse;
import org.restlet.data.ChallengeScheme;
@@ -21,21 +19,19 @@
/**
* Implements the HTTP authentication for the Amazon Web Services.
- *
+ *
* @author Jerome Louvel
*/
public class HttpAwsQueryHelper extends AuthenticatorHelper {
- /**
- * Constructor.
- */
+ /** Constructor. */
public HttpAwsQueryHelper() {
super(ChallengeScheme.HTTP_AWS_QUERY, true, false);
}
@Override
- public Reference updateReference(Reference resourceRef,
- ChallengeResponse challengeResponse, Request request) {
+ public Reference updateReference(
+ Reference resourceRef, ChallengeResponse challengeResponse, Request request) {
Reference result = resourceRef;
Form query = result.getQueryAsForm();
@@ -44,13 +40,16 @@ public Reference updateReference(Reference resourceRef,
query.add("SignatureMethod", "HmacSHA256");
query.add("SignatureVersion", "2");
query.add("Version", "2009-04-15");
- String df = DateUtils.format(new Date(), DateUtils.FORMAT_ISO_8601.get(0));
+ String df = DateUtils.format(new Date(), DateUtils.FORMAT_ISO_8601.getFirst());
query.add("Timestamp", df);
// Compute then add the signature parameter
- String signature = AwsUtils.getQuerySignature(request.getMethod(),
- request.getResourceRef(), query, request
- .getChallengeResponse().getSecret());
+ String signature =
+ AwsUtils.getQuerySignature(
+ request.getMethod(),
+ request.getResourceRef(),
+ query,
+ request.getChallengeResponse().getSecret());
query.add("Signature", signature);
result = new Reference(resourceRef);
result.setQuery(query.getQueryString());
diff --git a/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/internal/HttpAwsS3Helper.java b/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/internal/HttpAwsS3Helper.java
index 23be92e432..7097b396cb 100644
--- a/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/internal/HttpAwsS3Helper.java
+++ b/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/internal/HttpAwsS3Helper.java
@@ -1,12 +1,11 @@
/**
- * Copyright 2005-2024 Qlik
- *
- * The contents of this file is subject to the terms of the Apache 2.0 open
- * source license available at http://www.opensource.org/licenses/apache-2.0
- *
+ * Copyright 2005-2026 Qlik
+ *
+ * The content of this file is subject to the terms of the Apache 2.0 open
+ * source license available at https://www.opensource.org/licenses/apache-2.0
+ *
* Restlet is a registered trademark of QlikTech International AB.
*/
-
package org.restlet.ext.crypto.internal;
import org.restlet.Request;
@@ -19,26 +18,25 @@
/**
* Implements the HTTP authentication for the Amazon S3 service.
- *
+ *
* @author Jerome Louvel
*/
public class HttpAwsS3Helper extends AuthenticatorHelper {
- /**
- * Constructor.
- */
+ /** Constructor. */
public HttpAwsS3Helper() {
super(ChallengeScheme.HTTP_AWS_S3, true, true);
}
@Override
- public void formatResponse(ChallengeWriter cw, ChallengeResponse challenge,
- Request request, Series httpHeaders) {
+ public void formatResponse(
+ ChallengeWriter cw,
+ ChallengeResponse challenge,
+ Request request,
+ Series httpHeaders) {
// Append the AWS credentials
cw.append(challenge.getIdentifier())
.append(':')
- .append(AwsUtils.getS3Signature(request, httpHeaders,
- challenge.getSecret()));
+ .append(AwsUtils.getS3Signature(request, httpHeaders, challenge.getSecret()));
}
-
}
diff --git a/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/internal/HttpAzureSharedKeyHelper.java b/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/internal/HttpAzureSharedKeyHelper.java
index 63635b8667..a6bf2d1316 100644
--- a/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/internal/HttpAzureSharedKeyHelper.java
+++ b/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/internal/HttpAzureSharedKeyHelper.java
@@ -1,20 +1,18 @@
/**
- * Copyright 2005-2024 Qlik
- *
- * The contents of this file is subject to the terms of the Apache 2.0 open
- * source license available at http://www.opensource.org/licenses/apache-2.0
- *
+ * Copyright 2005-2026 Qlik
+ *
+ * The content of this file is subject to the terms of the Apache 2.0 open
+ * source license available at https://www.opensource.org/licenses/apache-2.0
+ *
* Restlet is a registered trademark of QlikTech International AB.
*/
-
package org.restlet.ext.crypto.internal;
import java.util.Base64;
import java.util.Date;
-import java.util.Iterator;
+import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
-
import org.restlet.Request;
import org.restlet.data.ChallengeResponse;
import org.restlet.data.ChallengeScheme;
@@ -33,49 +31,41 @@
import org.restlet.util.Series;
/**
- * Implements the Shared Key authentication for Azure services. This concerns
- * Blob and Queues on Azure Storage.
+ * Implements the Shared Key authentication for Azure services. This concerns Blob and Queues on
+ * Azure Storage.
*
* More documentation is available here
- *
+ *
* @author Thierry Boileau
*/
public class HttpAzureSharedKeyHelper extends AuthenticatorHelper {
/**
* Returns the canonicalized Azure headers.
- *
- * @param requestHeaders
- * The list of request headers.
+ *
+ * @param requestHeaders The list of request headers.
* @return The canonicalized Azure headers.
*/
- private static String getCanonicalizedAzureHeaders(
- Series requestHeaders) {
+ private static String getCanonicalizedAzureHeaders(Series requestHeaders) {
// Filter out all the Azure headers required for SharedKey
// authentication
- SortedMap azureHeaders = new TreeMap();
+ SortedMap azureHeaders = new TreeMap<>();
String headerName;
for (Header header : requestHeaders) {
headerName = header.getName().toLowerCase();
if (headerName.startsWith("x-ms-")) {
- if (!azureHeaders.containsKey(headerName)) {
- azureHeaders.put(headerName,
- requestHeaders.getValues(headerName));
- }
+ azureHeaders.computeIfAbsent(headerName, requestHeaders::getValues);
}
}
// Concatenate all Azure headers
StringBuilder sb = new StringBuilder();
- for (Iterator iterator = azureHeaders.keySet().iterator(); iterator
- .hasNext();) {
- String key = iterator.next();
- sb.append(key).append(':').append(azureHeaders.get(key))
- .append("\n");
+ for (Map.Entry entry : azureHeaders.entrySet()) {
+ sb.append(entry.getKey()).append(':').append(entry.getValue()).append("\n");
}
return sb.toString();
@@ -83,9 +73,8 @@ private static String getCanonicalizedAzureHeaders(
/**
* Returns the canonicalized resource name.
- *
- * @param resourceRef
- * The resource reference.
+ *
+ * @param resourceRef The resource reference.
* @return The canonicalized resource name.
*/
private static String getCanonicalizedResourceName(Reference resourceRef) {
@@ -93,100 +82,108 @@ private static String getCanonicalizedResourceName(Reference resourceRef) {
Parameter param = form.getFirst("comp", true);
if (param != null) {
- StringBuilder sb = new StringBuilder(resourceRef.getPath());
- return sb.append("?").append("comp=").append(param.getValue())
- .toString();
+ return resourceRef.getPath() + "?" + "comp=" + param.getValue();
}
return resourceRef.getPath();
}
- /**
- * Constructor.
- */
+ /** Constructor. */
public HttpAzureSharedKeyHelper() {
super(ChallengeScheme.HTTP_AZURE_SHAREDKEY, true, false);
}
@Override
- public void formatResponse(ChallengeWriter cw, ChallengeResponse challenge,
- Request request, Series httpHeaders) {
-
- // Setup the method name
- final String methodName = request.getMethod().getName();
+ public void formatResponse(
+ ChallengeWriter cw,
+ ChallengeResponse challenge,
+ Request request,
+ Series httpHeaders) {
+
+ // Set up the message part
+ final String rest =
+ request.getMethod().getName()
+ + '\n'
+ + getContentMd5(httpHeaders)
+ + '\n'
+ + getContentTypeHeader(request, httpHeaders)
+ + '\n'
+ + getDateHeader(httpHeaders)
+ + '\n'
+ + getCanonicalizedAzureHeaders(httpHeaders)
+ + '/'
+ + challenge.getIdentifier()
+ + getCanonicalizedResourceName(request.getResourceRef());
- // Setup the Date header
- String date = "";
+ // Append the SharedKey credentials
+ cw.append(challenge.getIdentifier())
+ .append(':')
+ .append(
+ Base64.getEncoder()
+ .encodeToString(
+ DigestUtils.toHMacSha256(
+ rest,
+ Base64.getDecoder()
+ .decode(
+ IoUtils.toByteArray(
+ challenge.getSecret())))));
+ }
- if (httpHeaders.getFirstValue("x-ms-date", true) == null) {
- // X-ms-Date header didn't override the standard Date header
- date = httpHeaders.getFirstValue(HeaderConstants.HEADER_DATE, true);
- if (date == null) {
- // Add a fresh Date header
- date = DateUtils.format(new Date(),
- DateUtils.FORMAT_RFC_1123.get(0));
- httpHeaders.add(HeaderConstants.HEADER_DATE, date);
- }
- }
- // Setup the ContentType header
- String contentMd5 = httpHeaders.getFirstValue(
- HeaderConstants.HEADER_CONTENT_MD5, true);
+ private static String getContentMd5(final Series httpHeaders) {
+ String contentMd5 = httpHeaders.getFirstValue(HeaderConstants.HEADER_CONTENT_MD5, true);
if (contentMd5 == null) {
contentMd5 = "";
}
+ return contentMd5;
+ }
- // Setup the ContentType header
- String contentType = httpHeaders.getFirstValue(
- HeaderConstants.HEADER_CONTENT_TYPE, true);
- if (contentType == null) {
- boolean applyPatch = false;
-
- // This patch seems to apply to Sun JVM only.
- final String jvmVendor = System.getProperty("java.vm.vendor");
- if ((jvmVendor != null)
- && (jvmVendor.toLowerCase()).startsWith("sun")) {
- final int majorVersionNumber = SystemUtils
- .getJavaMajorVersion();
- final int minorVersionNumber = SystemUtils
- .getJavaMinorVersion();
-
- if (majorVersionNumber == 1) {
- if (minorVersionNumber < 5) {
- applyPatch = true;
- } else if (minorVersionNumber == 5) {
- // Sun fixed the bug in update 10
- applyPatch = (SystemUtils.getJavaUpdateVersion() < 10);
- }
- }
- }
+ private static String getContentTypeHeader(
+ final Request request, final Series httpHeaders) {
+ String contentType = httpHeaders.getFirstValue(HeaderConstants.HEADER_CONTENT_TYPE, true);
+
+ if (contentType != null) {
+ return contentType;
+ }
+
+ boolean applyPatch = false;
+
+ // This patch seems to apply to Sun JVM only.
+ final String jvmVendor = System.getProperty("java.vm.vendor");
+ if ((jvmVendor != null) && (jvmVendor.toLowerCase()).startsWith("sun")) {
+ final int majorVersionNumber = SystemUtils.getJavaMajorVersion();
+ final int minorVersionNumber = SystemUtils.getJavaMinorVersion();
- if (applyPatch && !request.getMethod().equals(Method.PUT)) {
- contentType = "application/x-www-form-urlencoded";
- } else {
- contentType = "";
+ if (majorVersionNumber == 1) {
+ if (minorVersionNumber < 5) {
+ applyPatch = true;
+ } else if (minorVersionNumber == 5) {
+ // Sun fixed the bug in update 10
+ applyPatch = (SystemUtils.getJavaUpdateVersion() < 10);
+ }
}
}
- // Setup the canonicalized AzureHeaders
- final String canonicalizedAzureHeaders = getCanonicalizedAzureHeaders(httpHeaders);
+ if (applyPatch && !request.getMethod().equals(Method.PUT)) {
+ contentType = "application/x-www-form-urlencoded";
+ } else {
+ contentType = "";
+ }
- // Setup the canonicalized path
- final String canonicalizedResource = getCanonicalizedResourceName(request
- .getResourceRef());
+ return contentType;
+ }
- // Setup the message part
- final StringBuilder rest = new StringBuilder();
- rest.append(methodName).append('\n').append(contentMd5).append('\n')
- .append(contentType).append('\n').append(date).append('\n')
- .append(canonicalizedAzureHeaders).append('/')
- .append(challenge.getIdentifier())
- .append(canonicalizedResource);
+ private static String getDateHeader(final Series httpHeaders) {
+ String date = "";
- // Append the SharedKey credentials
- cw.append(challenge.getIdentifier())
- .append(':')
- .append(Base64.getEncoder().encodeToString(
- DigestUtils.toHMacSha256(rest.toString(),
- Base64.getDecoder().decode(IoUtils.toByteArray(challenge.getSecret())))));
+ if (httpHeaders.getFirstValue("x-ms-date", true) == null) {
+ // X-ms-Date header didn't override the standard Date header
+ date = httpHeaders.getFirstValue(HeaderConstants.HEADER_DATE, true);
+ if (date == null) {
+ // Add a fresh Date header
+ date = DateUtils.format(new Date(), DateUtils.FORMAT_RFC_1123.getFirst());
+ httpHeaders.add(HeaderConstants.HEADER_DATE, date);
+ }
+ }
+ return date;
}
}
diff --git a/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/internal/HttpAzureSharedKeyLiteHelper.java b/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/internal/HttpAzureSharedKeyLiteHelper.java
index 12d87aadbf..c80866f9ae 100644
--- a/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/internal/HttpAzureSharedKeyLiteHelper.java
+++ b/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/internal/HttpAzureSharedKeyLiteHelper.java
@@ -1,17 +1,15 @@
/**
- * Copyright 2005-2024 Qlik
- *
- * The contents of this file is subject to the terms of the Apache 2.0 open
- * source license available at http://www.opensource.org/licenses/apache-2.0
- *
+ * Copyright 2005-2026 Qlik
+ *
+ * The content of this file is subject to the terms of the Apache 2.0 open
+ * source license available at https://www.opensource.org/licenses/apache-2.0
+ *
* Restlet is a registered trademark of QlikTech International AB.
*/
-
package org.restlet.ext.crypto.internal;
import java.util.Base64;
import java.util.Date;
-
import org.restlet.Request;
import org.restlet.data.ChallengeResponse;
import org.restlet.data.ChallengeScheme;
@@ -28,21 +26,20 @@
import org.restlet.util.Series;
/**
- * Implements the Shared Key Lite authentication for Azure services. This
- * concerns Table storage on Azure Storage.
+ * Implements the Shared Key Lite authentication for Azure services. This concerns Table storage on
+ * Azure Storage.
*
* More documentation is available here
- *
+ *
* @author Thierry Boileau
*/
public class HttpAzureSharedKeyLiteHelper extends AuthenticatorHelper {
/**
* Returns the canonicalized resource name.
- *
- * @param resourceRef
- * The resource reference.
+ *
+ * @param resourceRef The resource reference.
* @return The canonicalized resource name.
*/
private static String getCanonicalizedResourceName(Reference resourceRef) {
@@ -50,26 +47,25 @@ private static String getCanonicalizedResourceName(Reference resourceRef) {
Parameter param = form.getFirst("comp", true);
if (param != null) {
- StringBuilder sb = new StringBuilder(resourceRef.getPath());
- return sb.append("?").append("comp=").append(param.getValue())
- .toString();
+ return resourceRef.getPath() + "?" + "comp=" + param.getValue();
}
return resourceRef.getPath();
}
- /**
- * Constructor.
- */
+ /** Constructor. */
public HttpAzureSharedKeyLiteHelper() {
super(ChallengeScheme.HTTP_AZURE_SHAREDKEY_LITE, true, false);
}
@Override
- public void formatResponse(ChallengeWriter cw, ChallengeResponse challenge,
- Request request, Series httpHeaders) {
+ public void formatResponse(
+ ChallengeWriter cw,
+ ChallengeResponse challenge,
+ Request request,
+ Series httpHeaders) {
- // Setup the Date header
+ // Set up the Date header
String date = "";
if (httpHeaders.getFirstValue("x-ms-date", true) == null) {
@@ -78,29 +74,30 @@ public void formatResponse(ChallengeWriter cw, ChallengeResponse challenge,
if (date == null) {
// Add a fresh Date header
- date = DateUtils.format(new Date(),
- DateUtils.FORMAT_RFC_1123.get(0));
+ date = DateUtils.format(new Date(), DateUtils.FORMAT_RFC_1123.getFirst());
httpHeaders.add(HeaderConstants.HEADER_DATE, date);
}
} else {
date = httpHeaders.getFirstValue("x-ms-date", true);
}
- // Setup the canonicalized path
- String canonicalizedResource = getCanonicalizedResourceName(request
- .getResourceRef());
+ // Set up the canonicalized path
+ String canonicalizedResource = getCanonicalizedResourceName(request.getResourceRef());
- // Setup the message part
- StringBuilder rest = new StringBuilder();
- rest.append(date).append('\n').append('/')
- .append(challenge.getIdentifier())
- .append(canonicalizedResource);
+ // Set up the message part
+ final String rest = date + '\n' + '/' + challenge.getIdentifier() + canonicalizedResource;
// Append the SharedKey credentials
cw.append(challenge.getIdentifier())
.append(':')
- .append(Base64.getEncoder().encodeToString(
- DigestUtils.toHMacSha256(rest.toString(),
- Base64.getDecoder().decode(IoUtils.toByteArray(challenge.getSecret())))));
+ .append(
+ Base64.getEncoder()
+ .encodeToString(
+ DigestUtils.toHMacSha256(
+ rest,
+ Base64.getDecoder()
+ .decode(
+ IoUtils.toByteArray(
+ challenge.getSecret())))));
}
}
diff --git a/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/internal/HttpDigestHelper.java b/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/internal/HttpDigestHelper.java
index 4a79b533c5..090d3c7098 100644
--- a/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/internal/HttpDigestHelper.java
+++ b/org.restlet.ext.crypto/src/main/java/org/restlet/ext/crypto/internal/HttpDigestHelper.java
@@ -1,18 +1,15 @@
/**
- * Copyright 2005-2024 Qlik
- *
- * The contents of this file is subject to the terms of the Apache 2.0 open
- * source license available at http://www.opensource.org/licenses/apache-2.0
- *
+ * Copyright 2005-2026 Qlik
+ *
+ * The content of this file is subject to the terms of the Apache 2.0 open
+ * source license available at https://www.opensource.org/licenses/apache-2.0
+ *
* Restlet is a registered trademark of QlikTech International AB.
*/
-
package org.restlet.ext.crypto.internal;
-import java.io.IOException;
import java.util.Base64;
import java.util.logging.Level;
-
import org.restlet.Context;
import org.restlet.Request;
import org.restlet.Response;
@@ -33,38 +30,43 @@
/**
* Implements the HTTP DIGEST authentication.
- *
+ *
* @author Jerome Louvel
*/
public class HttpDigestHelper extends AuthenticatorHelper {
+ private static final String ALGORITHM = "algorithm";
+ private static final String CNONCE = "cnonce";
+ private static final String DOMAIN = "domain";
+ private static final String NC = "nc";
+ private static final String NONCE = "nonce";
+ private static final String OPAQUE = "opaque";
+ private static final String QUALITY_OPTION = "qop";
+ private static final String REALM = "realm";
+ private static final String RESPONSE = "response";
+ private static final String STALE = "stale";
+ private static final String URI = "uri";
+ private static final String USERNAME = "username";
+
/**
- * Checks whether the specified nonce is valid with respect to the specified
- * secretKey, and further confirms that the nonce was generated less than
- * lifespanMillis milliseconds ago
- *
- * @param nonce
- * The nonce value.
- * @param secretKey
- * The same secret value that was inserted into the nonce when it
- * was generated
- * @param lifespan
- * The nonce lifespan in milliseconds.
- * @return True if the nonce was generated less than lifespan milliseconds
- * ago, false otherwise.
- * @throws Exception
- * If the nonce does not match the specified secretKey, or if it
- * can't be parsed
+ * Checks whether the specified nonce is valid with respect to the specified secretKey and
+ * further confirms that the nonce was generated less than lifespanMillis milliseconds ago
+ *
+ * @param nonce The nonce value.
+ * @param secretKey The same secret value that was inserted into the nonce when it was generated
+ * @param lifespan The nonce lifespan in milliseconds.
+ * @return True if the nonce was generated less than lifespan milliseconds ago, false otherwise.
+ * @throws Exception If the nonce does not match the specified secretKey, or if it can't be
+ * parsed
*/
- public static boolean isNonceValid(String nonce, String secretKey,
- long lifespan) throws Exception {
+ public static boolean isNonceValid(String nonce, String secretKey, long lifespan)
+ throws Exception {
try {
String decodedNonce = new String(Base64.getDecoder().decode(nonce));
- long nonceTimeMS = Long.parseLong(decodedNonce.substring(0,
- decodedNonce.indexOf(':')));
+ long nonceTimeMS = Long.parseLong(decodedNonce.substring(0, decodedNonce.indexOf(':')));
- if (decodedNonce.equals(nonceTimeMS + ":"
- + DigestUtils.toMd5(nonceTimeMS + ":" + secretKey))) {
+ if (decodedNonce.equals(
+ nonceTimeMS + ":" + DigestUtils.toMd5(nonceTimeMS + ":" + secretKey))) {
// Valid with regard to the secretKey, now check lifespan
return lifespan > (System.currentTimeMillis() - nonceTimeMS);
}
@@ -75,19 +77,20 @@ public static boolean isNonceValid(String nonce, String secretKey,
throw new Exception("The nonce does not match secretKey");
}
- /**
- * Constructor.
- */
+ /** Constructor. */
public HttpDigestHelper() {
super(ChallengeScheme.HTTP_DIGEST, true, true);
}
@Override
- public void formatRequest(ChallengeWriter cw, ChallengeRequest challenge,
- Response response, Series httpHeaders) throws IOException {
+ public void formatRequest(
+ ChallengeWriter cw,
+ ChallengeRequest challenge,
+ Response response,
+ Series httpHeaders) {
if (challenge.getRealm() != null) {
- cw.appendQuotedChallengeParameter("realm", challenge.getRealm());
+ cw.appendQuotedChallengeParameter(REALM, challenge.getRealm());
} else {
getLogger()
.warning(
@@ -95,7 +98,7 @@ public void formatRequest(ChallengeWriter cw, ChallengeRequest challenge,
}
if (!challenge.getDomainRefs().isEmpty()) {
- cw.append(", domain=\"");
+ cw.append(", " + DOMAIN + "=\"");
for (int i = 0; i < challenge.getDomainRefs().size(); i++) {
if (i > 0) {
@@ -109,25 +112,23 @@ public void formatRequest(ChallengeWriter cw, ChallengeRequest challenge,
}
if (challenge.getServerNonce() != null) {
- cw.appendQuotedChallengeParameter("nonce",
- challenge.getServerNonce());
+ cw.appendQuotedChallengeParameter(NONCE, challenge.getServerNonce());
}
if (challenge.getOpaque() != null) {
- cw.appendQuotedChallengeParameter("opaque", challenge.getOpaque());
+ cw.appendQuotedChallengeParameter(OPAQUE, challenge.getOpaque());
}
if (challenge.isStale()) {
- cw.appendChallengeParameter("stale", "true");
+ cw.appendChallengeParameter(STALE, "true");
}
if (challenge.getDigestAlgorithm() != null) {
- cw.appendChallengeParameter("algorithm",
- challenge.getDigestAlgorithm());
+ cw.appendChallengeParameter(ALGORITHM, challenge.getDigestAlgorithm());
}
if (!challenge.getQualityOptions().isEmpty()) {
- cw.append(", qop=\"");
+ cw.append(", " + QUALITY_OPTION + "=\"");
for (int i = 0; i < challenge.getQualityOptions().size(); i++) {
if (i > 0) {
@@ -150,60 +151,54 @@ public void formatRequest(ChallengeWriter cw, ChallengeRequest challenge,
}
@Override
- public void formatResponse(ChallengeWriter cw, ChallengeResponse challenge,
- Request request, Series httpHeaders) {
+ public void formatResponse(
+ ChallengeWriter cw,
+ ChallengeResponse challenge,
+ Request request,
+ Series httpHeaders) {
if (challenge.getIdentifier() != null) {
- cw.appendQuotedChallengeParameter("username",
- challenge.getIdentifier());
+ cw.appendQuotedChallengeParameter(USERNAME, challenge.getIdentifier());
}
if (challenge.getRealm() != null) {
- cw.appendQuotedChallengeParameter("realm", challenge.getRealm());
+ cw.appendQuotedChallengeParameter(REALM, challenge.getRealm());
}
if (challenge.getServerNonce() != null) {
- cw.appendQuotedChallengeParameter("nonce",
- challenge.getServerNonce());
+ cw.appendQuotedChallengeParameter(NONCE, challenge.getServerNonce());
}
if (challenge.getDigestRef() != null) {
- challenge.setDigestRef(new Reference(request.getResourceRef()
- .getPath()));
- cw.appendQuotedChallengeParameter("uri", challenge.getDigestRef()
- .toString());
+ challenge.setDigestRef(new Reference(request.getResourceRef().getPath()));
+ cw.appendQuotedChallengeParameter(URI, challenge.getDigestRef().toString());
}
char[] responseDigest = formatResponseDigest(challenge, request);
if (responseDigest != null) {
- cw.appendQuotedChallengeParameter("response", new String(
- responseDigest));
+ cw.appendQuotedChallengeParameter(RESPONSE, new String(responseDigest));
}
if ((challenge.getDigestAlgorithm() != null)
&& !Digest.ALGORITHM_MD5.equals(challenge.getDigestAlgorithm())) {
- cw.appendChallengeParameter("algorithm",
- challenge.getDigestAlgorithm());
+ cw.appendChallengeParameter(ALGORITHM, challenge.getDigestAlgorithm());
}
if (challenge.getClientNonce() != null) {
- cw.appendQuotedChallengeParameter("cnonce",
- challenge.getClientNonce());
+ cw.appendQuotedChallengeParameter(CNONCE, challenge.getClientNonce());
}
if (challenge.getOpaque() != null) {
- cw.appendQuotedChallengeParameter("opaque", challenge.getOpaque());
+ cw.appendQuotedChallengeParameter(OPAQUE, challenge.getOpaque());
}
if (challenge.getQuality() != null) {
- cw.appendChallengeParameter("qop", challenge.getQuality());
+ cw.appendChallengeParameter(QUALITY_OPTION, challenge.getQuality());
}
- if ((challenge.getQuality() != null)
- && (challenge.getServerNonceCount() > 0)) {
- cw.appendChallengeParameter("nc",
- challenge.getServerNonceCountAsHex());
+ if ((challenge.getQuality() != null) && (challenge.getServerNonceCount() > 0)) {
+ cw.appendChallengeParameter(NC, challenge.getServerNonceCountAsHex());
}
for (Parameter param : challenge.getParameters()) {
@@ -217,48 +212,57 @@ public void formatResponse(ChallengeWriter cw, ChallengeResponse challenge,
/**
* Formats the response digest.
- *
- * @param challengeResponse
- * The challenge response.
- * @param request
- * The request if available.
+ *
+ * @param challengeResponse The challenge response.
+ * @param request The request if available.
* @return The formatted secret of a challenge response.
*/
- public char[] formatResponseDigest(ChallengeResponse challengeResponse,
- Request request) {
+ public char[] formatResponseDigest(ChallengeResponse challengeResponse, Request request) {
String a1 = null;
- if (!Digest.ALGORITHM_HTTP_DIGEST.equals(challengeResponse
- .getSecretAlgorithm())) {
- if (!AuthenticatorUtils
- .anyNull(challengeResponse.getIdentifier(),
- challengeResponse.getSecret(),
- challengeResponse.getRealm())) {
- a1 = DigestUtils.toHttpDigest(
- challengeResponse.getIdentifier(),
- challengeResponse.getSecret(),
- challengeResponse.getRealm());
+ if (!Digest.ALGORITHM_HTTP_DIGEST.equals(challengeResponse.getSecretAlgorithm())) {
+ if (!AuthenticatorUtils.anyNull(
+ challengeResponse.getIdentifier(),
+ challengeResponse.getSecret(),
+ challengeResponse.getRealm())) {
+ a1 =
+ DigestUtils.toHttpDigest(
+ challengeResponse.getIdentifier(),
+ challengeResponse.getSecret(),
+ challengeResponse.getRealm());
}
} else {
a1 = new String(challengeResponse.getSecret());
}
if (a1 != null
- && !AuthenticatorUtils.anyNull(request.getMethod(),
- challengeResponse.getDigestRef())) {
- StringBuilder sb = new StringBuilder().append(a1).append(':')
- .append(challengeResponse.getServerNonce());
-
- if (!AuthenticatorUtils.anyNull(challengeResponse.getQuality(),
+ && !AuthenticatorUtils.anyNull(
+ request.getMethod(), challengeResponse.getDigestRef())) {
+ StringBuilder sb =
+ new StringBuilder()
+ .append(a1)
+ .append(':')
+ .append(challengeResponse.getServerNonce());
+
+ if (!AuthenticatorUtils.anyNull(
+ challengeResponse.getQuality(),
challengeResponse.getClientNonce(),
challengeResponse.getServerNonceCount())) {
- sb.append(':').append(AuthenticatorUtils.formatNonceCount(challengeResponse.getServerNonceCount()))
- .append(':').append(challengeResponse.getClientNonce())
- .append(':').append(challengeResponse.getQuality());
+ sb.append(':')
+ .append(
+ AuthenticatorUtils.formatNonceCount(
+ challengeResponse.getServerNonceCount()))
+ .append(':')
+ .append(challengeResponse.getClientNonce())
+ .append(':')
+ .append(challengeResponse.getQuality());
}
- String a2 = DigestUtils.toMd5(request.getMethod().toString() + ":"
- + challengeResponse.getDigestRef().toString());
+ String a2 =
+ DigestUtils.toMd5(
+ request.getMethod().toString()
+ + ":"
+ + challengeResponse.getDigestRef().toString());
sb.append(':').append(a2);
return DigestUtils.toMd5(sb.toString()).toCharArray();
@@ -268,32 +272,29 @@ public char[] formatResponseDigest(ChallengeResponse challengeResponse,
}
@Override
- public void parseRequest(ChallengeRequest challenge, Response response,
- Series httpHeaders) {
+ public void parseRequest(
+ ChallengeRequest challenge, Response response, Series httpHeaders) {
if (challenge.getRawValue() != null) {
- HeaderReader