[java-shib-shared] branch main updated: Add a HexSupport wrapper around commons-codec routines.
Codeberg
noreply at shibboleth.net
Thu Oct 22 16:16:07 UTC 2026
This is an automated email from the git hooks/post-receive script.
codeberg pushed a commit to branch main
in repository java-shib-shared.
View the commit online:
https://codeberg.org/Shibboleth/java-shib-shared/commit/4e81a2bdfeb6f50cf5741f414cff70133daf9e89
The following commit(s) were added to refs/heads/main by this push:
new 4e81a2bd Add a HexSupport wrapper around commons-codec routines.
4e81a2bd is described below
commit 4e81a2bdfeb6f50cf5741f414cff70133daf9e89
Author: Scott Cantor <scott at restingparrotsoftware.com>
AuthorDate: Thu Oct 22 12:15:56 2026 -0400
Add a HexSupport wrapper around commons-codec routines.
---
.../shibboleth/shared/net/CookieManagerTest.java | 13 ++--
.../security/RandomIdentifierParameterSpec.java | 3 +-
.../impl/RandomIdentifierGenerationStrategy.java | 47 +++++++-----
.../SecureRandomIdentifierGenerationStrategy.java | 4 +-
...cureRandomIdentifierGenerationStrategyTest.java | 3 +-
.../net/shibboleth/shared/codec/HexSupport.java | 84 ++++++++++++++++++++++
.../shibboleth/shared/codec/StringDigester.java | 9 ++-
.../shared/codec/StringDigesterTest.java | 1 +
8 files changed, 125 insertions(+), 39 deletions(-)
diff --git a/shib-networking/src/test/java/net/shibboleth/shared/net/CookieManagerTest.java b/shib-networking/src/test/java/net/shibboleth/shared/net/CookieManagerTest.java
index 78b09b35..dc618247 100644
--- a/shib-networking/src/test/java/net/shibboleth/shared/net/CookieManagerTest.java
+++ b/shib-networking/src/test/java/net/shibboleth/shared/net/CookieManagerTest.java
@@ -22,10 +22,6 @@ import java.util.random.RandomGenerator;
import javax.annotation.Nonnull;
-import org.apache.commons.codec.BinaryEncoder;
-import org.apache.commons.codec.EncoderException;
-import org.apache.commons.codec.binary.Hex;
-import org.apache.commons.codec.binary.StringUtils;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.testng.Assert;
@@ -35,6 +31,7 @@ import org.testng.annotations.Test;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
+import net.shibboleth.shared.codec.HexSupport;
import net.shibboleth.shared.collection.CollectionSupport;
import net.shibboleth.shared.component.ComponentInitializationException;
import net.shibboleth.shared.net.CookieManager.SameSiteValue;
@@ -45,12 +42,10 @@ import net.shibboleth.shared.primitive.NonnullSupplier;
public class CookieManagerTest {
private RandomGenerator random;
- private BinaryEncoder encoder;
@BeforeClass
public void setUp() {
random = new SecureRandom();
- encoder = new Hex();
}
@Test public void testInitFailure() {
@@ -143,7 +138,7 @@ public class CookieManagerTest {
Assert.assertEquals(cookie.getAttribute("SameSite"), SameSiteValue.Lax.getValue());
}
- @Test public void testPurge() throws ComponentInitializationException, InterruptedException, EncoderException {
+ @Test public void testPurge() throws ComponentInitializationException, InterruptedException {
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletResponse response = new MockHttpServletResponse();
@@ -170,13 +165,13 @@ public class CookieManagerTest {
Assert.assertTrue(respCookies[0].getName().compareTo(respCookies[1].getName()) > 0);
}
- @Nonnull private String getCookieName() throws EncoderException {
+ @Nonnull private String getCookieName() {
final byte[] buf = new byte[16];
random.nextBytes(buf);
final Instant now = Instant.now();
- return "_test_" + now.toEpochMilli() + '_' + StringUtils.newStringUsAscii(encoder.encode(buf));
+ return "_test_" + now.toEpochMilli() + '_' + HexSupport.encodeLowerCase(buf);
}
}
\ No newline at end of file
diff --git a/shib-security/src/main/java/net/shibboleth/shared/security/RandomIdentifierParameterSpec.java b/shib-security/src/main/java/net/shibboleth/shared/security/RandomIdentifierParameterSpec.java
index 5c3d7163..1a3c0dc4 100644
--- a/shib-security/src/main/java/net/shibboleth/shared/security/RandomIdentifierParameterSpec.java
+++ b/shib-security/src/main/java/net/shibboleth/shared/security/RandomIdentifierParameterSpec.java
@@ -20,7 +20,6 @@ import java.util.random.RandomGenerator;
import javax.annotation.Nullable;
import org.apache.commons.codec.BinaryEncoder;
-import org.apache.commons.codec.binary.Hex;
import net.shibboleth.shared.annotation.ParameterName;
import net.shibboleth.shared.annotation.constraint.NonNegative;
@@ -32,7 +31,7 @@ import net.shibboleth.shared.security.IdentifierGenerationStrategy.ParameterSpec
*
* @param source random generator (this MUST be thread-safe), defaults to standard Java {@link SecureRandom}
* @param identifierSize size of identifiers to generate, defaults to 16
- * @param identifierEncoder an encoder to apply to the random data, defaults to {@link Hex}
+ * @param identifierEncoder an encoder to apply to the random data, defaults to hex encoding
*/
public record RandomIdentifierParameterSpec(@Nullable @ParameterName(name="source") RandomGenerator source,
@Nullable @NonNegative @ParameterName(name="identifierSize") Integer identifierSize,
diff --git a/shib-security/src/main/java/net/shibboleth/shared/security/impl/RandomIdentifierGenerationStrategy.java b/shib-security/src/main/java/net/shibboleth/shared/security/impl/RandomIdentifierGenerationStrategy.java
index 6e272a87..2f1682a1 100644
--- a/shib-security/src/main/java/net/shibboleth/shared/security/impl/RandomIdentifierGenerationStrategy.java
+++ b/shib-security/src/main/java/net/shibboleth/shared/security/impl/RandomIdentifierGenerationStrategy.java
@@ -14,26 +14,27 @@
package net.shibboleth.shared.security.impl;
+import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.SecureRandom;
import java.util.Random;
import java.util.random.RandomGenerator;
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe;
import net.shibboleth.shared.annotation.constraint.NotEmpty;
+import net.shibboleth.shared.codec.HexSupport;
import net.shibboleth.shared.security.IdentifierGenerationStrategy;
import net.shibboleth.shared.security.RandomIdentifierParameterSpec;
import org.apache.commons.codec.BinaryEncoder;
import org.apache.commons.codec.EncoderException;
-import org.apache.commons.codec.binary.Hex;
-import org.apache.commons.codec.binary.StringUtils;
/**
* Generates a random number of bytes via a {@link Random} source and encodes them into a string using a
- * {@link BinaryEncoder} ({@link Hex} by default).
+ * {@link BinaryEncoder}, or hex-encoding by default.
*/
@ThreadSafe
public class RandomIdentifierGenerationStrategy implements IdentifierGenerationStrategy {
@@ -45,18 +46,18 @@ public class RandomIdentifierGenerationStrategy implements IdentifierGenerationS
private final int sizeOfIdentifier;
/** Encoder used to convert the random bytes in to a string. */
- @Nonnull private final BinaryEncoder encoder;
+ @Nullable private final BinaryEncoder encoder;
/**
* Default constructor.
*
* <p>Initializes the random number source to a new {@link SecureRandom}, size of identifier is set to 16
- * bytes, and the encoder is set to a {@link Hex}.</p>
+ * bytes, and the encoder is unset to default to hex-encoding.</p>
*/
public RandomIdentifierGenerationStrategy() {
random = new SecureRandom();
sizeOfIdentifier = 16;
- encoder = new Hex();
+ encoder = null;
}
/**
@@ -86,12 +87,7 @@ public class RandomIdentifierGenerationStrategy implements IdentifierGenerationS
sizeOfIdentifier = 16;
}
- final BinaryEncoder enc = spec.identifierEncoder();
- if (enc != null) {
- encoder = enc;
- } else {
- encoder = new Hex();
- }
+ encoder = spec.identifierEncoder();
} else {
throw new InvalidAlgorithmParameterException("Invalid or unrecognized RandomParameterSpec");
}
@@ -106,13 +102,28 @@ public class RandomIdentifierGenerationStrategy implements IdentifierGenerationS
@Nonnull @NotEmpty public String generateIdentifier(final boolean xmlSafe) {
final byte[] buf = new byte[sizeOfIdentifier];
random.nextBytes(buf);
- try {
- if (xmlSafe) {
- return "_" + StringUtils.newStringUsAscii(encoder.encode(buf));
+ if (xmlSafe) {
+ return "_" + encode(buf);
+ }
+ return encode(buf);
+ }
+
+ /**
+ * Perform the specified encoding, or default to hex.
+ *
+ * @param data data to encode
+ *
+ * @return the encoded string
+ */
+ @Nonnull private String encode(@Nonnull final byte[] data) {
+ if (encoder != null) {
+ try {
+ return new String(encoder.encode(data), StandardCharsets.US_ASCII);
+ } catch (final EncoderException e) {
+ throw new RuntimeException(e);
}
- return StringUtils.newStringUsAscii(encoder.encode(buf));
- } catch (final EncoderException e) {
- throw new RuntimeException(e);
+ } else {
+ return HexSupport.encodeLowerCase(data);
}
}
diff --git a/shib-security/src/main/java/net/shibboleth/shared/security/impl/SecureRandomIdentifierGenerationStrategy.java b/shib-security/src/main/java/net/shibboleth/shared/security/impl/SecureRandomIdentifierGenerationStrategy.java
index 9c84d5de..4bef925b 100644
--- a/shib-security/src/main/java/net/shibboleth/shared/security/impl/SecureRandomIdentifierGenerationStrategy.java
+++ b/shib-security/src/main/java/net/shibboleth/shared/security/impl/SecureRandomIdentifierGenerationStrategy.java
@@ -20,8 +20,6 @@ import java.security.SecureRandom;
import javax.annotation.Nonnull;
import javax.annotation.concurrent.ThreadSafe;
-import org.apache.commons.codec.binary.Hex;
-
import net.shibboleth.shared.security.RandomIdentifierParameterSpec;
/**
@@ -35,7 +33,7 @@ public class SecureRandomIdentifierGenerationStrategy extends RandomIdentifierGe
* Default constructor.
*
* <p>Initializes the random number source to a new {@link SecureRandom}, size of identifier is set to 16
- * bytes, and the encoder is set to a {@link Hex}.</p>
+ * bytes, and the encoder is unset to default to hex-encoding.</p>
*/
public SecureRandomIdentifierGenerationStrategy() {
diff --git a/shib-security/src/test/java/net/shibboleth/shared/security/impl/SecureRandomIdentifierGenerationStrategyTest.java b/shib-security/src/test/java/net/shibboleth/shared/security/impl/SecureRandomIdentifierGenerationStrategyTest.java
index 25fce4b6..7247a61d 100644
--- a/shib-security/src/test/java/net/shibboleth/shared/security/impl/SecureRandomIdentifierGenerationStrategyTest.java
+++ b/shib-security/src/test/java/net/shibboleth/shared/security/impl/SecureRandomIdentifierGenerationStrategyTest.java
@@ -23,7 +23,6 @@ import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import org.apache.commons.codec.binary.Hex;
import org.testng.Assert;
import org.testng.annotations.Test;
@@ -71,7 +70,7 @@ public class SecureRandomIdentifierGenerationStrategyTest {
final Pattern ncNamePattern = Pattern.compile("^[a-zA-Z_][a-zA-Z0-9_\\-\\.]+$");
final IdentifierGenerationStrategy strat =
IdentifierGenerationStrategy.getInstance(ProviderType.RANDOM,
- new RandomIdentifierParameterSpec(SecureRandom.getInstance("SHA1PRNG"), 16, new Hex()));
+ new RandomIdentifierParameterSpec(SecureRandom.getInstance("SHA1PRNG"), 16, null));
final int howMany = 1000;
final Set<String> values = new HashSet<>(1000);
for (int iteration = 1; iteration <= howMany; iteration++) {
diff --git a/shib-support/src/main/java/net/shibboleth/shared/codec/HexSupport.java b/shib-support/src/main/java/net/shibboleth/shared/codec/HexSupport.java
new file mode 100644
index 00000000..1207425a
--- /dev/null
+++ b/shib-support/src/main/java/net/shibboleth/shared/codec/HexSupport.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.shared.codec;
+
+import javax.annotation.Nonnull;
+
+import net.shibboleth.shared.logic.Constraint;
+
+import org.apache.commons.codec.DecoderException;
+import org.apache.commons.codec.binary.Hex;
+
+/**
+ * Helper class for working with hex encoding/decoding of binary data.
+ *
+ * <p>This wraps the current commons-codec implementation to insulate
+ * calling code from the specific implementation for future revision.</p>
+ *
+ * @since 9.3.0
+ */
+public final class HexSupport {
+
+ /** Constructor. */
+ private HexSupport() {
+
+ }
+
+ /**
+ * Hex-encodes the given binary data into lower case characters.
+ *
+ * @param data data to encode
+ *
+ * @return the hex-encoded data
+ */
+ @Nonnull public static String encodeLowerCase(@Nonnull final byte[] data) {
+ Constraint.isNotNull(data, "Binary data to be encoded cannot be null");
+
+ return Hex.encodeHexString(data, true);
+ }
+
+ /**
+ * Hex-encodes the given binary data into upper case characters.
+ *
+ * @param data data to encode
+ *
+ * @return the hex-encoded data
+ */
+ @Nonnull public static String encodeUpperCase(@Nonnull final byte[] data) {
+ Constraint.isNotNull(data, "Binary data to be encoded cannot be null");
+
+ return Hex.encodeHexString(data, false);
+ }
+
+ /**
+ * Decodes hex-encoded data back into binary.
+ *
+ * @param data hex-encoded string
+ *
+ * @return the decoded data
+ *
+ * @throws DecodingException if unable to decode
+ */
+ @Nonnull public static byte[] decode(@Nonnull final String data) throws DecodingException{
+ Constraint.isNotNull(data, "Base64 encoded data cannot be null");
+
+ try {
+ return Hex.decodeHex(data);
+ } catch (final DecoderException e) {
+ throw new DecodingException(e);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/shib-support/src/main/java/net/shibboleth/shared/codec/StringDigester.java b/shib-support/src/main/java/net/shibboleth/shared/codec/StringDigester.java
index 1c9a34da..23b39b01 100644
--- a/shib-support/src/main/java/net/shibboleth/shared/codec/StringDigester.java
+++ b/shib-support/src/main/java/net/shibboleth/shared/codec/StringDigester.java
@@ -15,6 +15,7 @@
package net.shibboleth.shared.codec;
import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.function.Function;
@@ -28,8 +29,6 @@ import net.shibboleth.shared.logic.Constraint;
import net.shibboleth.shared.primitive.LoggerFactory;
import net.shibboleth.shared.primitive.StringSupport;
-import org.apache.commons.codec.CharEncoding;
-import org.apache.commons.codec.binary.Hex;
import org.slf4j.Logger;
/**
@@ -53,7 +52,7 @@ public class StringDigester implements Function<String,String> {
/** The default input character set.*/
@SuppressWarnings("null")
- @Nonnull public static final Charset DEFAULT_INPUT_CHARSET = Charset.forName(CharEncoding.UTF_8);
+ @Nonnull public static final Charset DEFAULT_INPUT_CHARSET = StandardCharsets.UTF_8;
/** Logger. */
@Nonnull private final Logger log = LoggerFactory.getLogger(StringDigester.class);
@@ -206,9 +205,9 @@ public class StringDigester implements Function<String,String> {
return null;
}
case HEX_LOWER:
- return new String(Hex.encodeHex(digestedBytes, true));
+ return HexSupport.encodeLowerCase(digestedBytes);
case HEX_UPPER:
- return new String(Hex.encodeHex(digestedBytes, false));
+ return HexSupport.encodeUpperCase(digestedBytes);
default:
break;
}
diff --git a/shib-support/src/test/java/net/shibboleth/shared/codec/StringDigesterTest.java b/shib-support/src/test/java/net/shibboleth/shared/codec/StringDigesterTest.java
index fad8097c..aeed7d2c 100644
--- a/shib-support/src/test/java/net/shibboleth/shared/codec/StringDigesterTest.java
+++ b/shib-support/src/test/java/net/shibboleth/shared/codec/StringDigesterTest.java
@@ -25,6 +25,7 @@ import org.testng.annotations.Test;
/**
* Test {@link StringDigester} functionality.
*/
+ at SuppressWarnings("javadoc")
public class StringDigesterTest {
private StringDigester digester;
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list