From 4f8f3c9508a168283b944d727f2edeb54583ad0d Mon Sep 17 00:00:00 2001 From: matoro Date: Tue, 16 Dec 2025 15:49:14 -0500 Subject: [PATCH] Fall back to SHA-1 for base64/binary hashCode MD5 digest algorithm is unavailable on a FIPS JVM, so fall back to SHA-1 for generating object hashCodes in this case. Only the first 32 bits are used, so the length difference will not matter. --- .../impl/values/JavaBase64Holder.java | 34 +---------- .../impl/values/JavaDigestableHolder.java | 60 +++++++++++++++++++ .../impl/values/JavaHexBinaryHolder.java | 35 +---------- 3 files changed, 62 insertions(+), 67 deletions(-) create mode 100644 src/main/java/org/apache/xmlbeans/impl/values/JavaDigestableHolder.java diff --git a/src/main/java/org/apache/xmlbeans/impl/values/JavaBase64Holder.java b/src/main/java/org/apache/xmlbeans/impl/values/JavaBase64Holder.java index 522af9aba..9858bc709 100644 --- a/src/main/java/org/apache/xmlbeans/impl/values/JavaBase64Holder.java +++ b/src/main/java/org/apache/xmlbeans/impl/values/JavaBase64Holder.java @@ -23,18 +23,14 @@ import org.apache.xmlbeans.impl.common.ValidationContext; import org.apache.xmlbeans.impl.schema.BuiltinSchemaTypeSystem; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; import java.util.Arrays; import java.util.Base64; -public abstract class JavaBase64Holder extends XmlObjectBase { +public abstract class JavaBase64Holder extends JavaDigestableHolder { public SchemaType schemaType() { return BuiltinSchemaTypeSystem.ST_BASE_64_BINARY; } - protected byte[] _value; - // SIMPLE VALUE ACCESSORS BELOW ------------------------------------------- // gets raw text value @@ -104,32 +100,4 @@ protected boolean equal_to(XmlObject i) { byte[] ival = ((XmlBase64Binary) i).getByteArrayValue(); return Arrays.equals(_value, ival); } - - //because computing hashcode is expensive we'll cache it - protected boolean _hashcached = false; - protected int hashcode = 0; - protected static final MessageDigest md5; - - static { - try { - md5 = MessageDigest.getInstance("MD5"); - } catch (NoSuchAlgorithmException e) { - throw new IllegalStateException("Cannot find MD5 hash Algorithm"); - } - } - - protected int value_hash_code() { - if (_hashcached) { - return hashcode; - } - - _hashcached = true; - - if (_value == null) { - return hashcode = 0; - } - - byte[] res = md5.digest(_value); - return hashcode = (res[0] << 24) | (res[1] << 16) | (res[2] << 8) | res[3]; - } } diff --git a/src/main/java/org/apache/xmlbeans/impl/values/JavaDigestableHolder.java b/src/main/java/org/apache/xmlbeans/impl/values/JavaDigestableHolder.java new file mode 100644 index 000000000..9690842bf --- /dev/null +++ b/src/main/java/org/apache/xmlbeans/impl/values/JavaDigestableHolder.java @@ -0,0 +1,60 @@ +/* Copyright 2004 The Apache Software Foundation + * + * 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 org.apache.xmlbeans.impl.values; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Objects; +import java.util.stream.Stream; + +public abstract class JavaDigestableHolder extends XmlObjectBase { + protected byte[] _value; + + //because computing hashcode is expensive we'll cache it + protected boolean _hashcached = false; + protected int hashcode = 0; + protected static final MessageDigest digest; + + static { + digest = Stream.of("MD5", "SHA-1") + .map(algorithm -> { + try { + return MessageDigest.getInstance(algorithm); + } + catch (NoSuchAlgorithmException ex) { + return null; + } + }) + .filter(Objects::nonNull) + .findFirst() + .orElseThrow(() -> new IllegalStateException("Cannot find any suitable hash algorithm")); + } + + protected int value_hash_code() { + if (_hashcached) { + return hashcode; + } + + _hashcached = true; + + if (_value == null) { + return hashcode = 0; + } + + byte[] res = digest.digest(_value); + return hashcode = (res[0] << 24) | (res[1] << 16) | (res[2] << 8) | res[3]; + } +} diff --git a/src/main/java/org/apache/xmlbeans/impl/values/JavaHexBinaryHolder.java b/src/main/java/org/apache/xmlbeans/impl/values/JavaHexBinaryHolder.java index 51e0fe0e2..2720cf395 100644 --- a/src/main/java/org/apache/xmlbeans/impl/values/JavaHexBinaryHolder.java +++ b/src/main/java/org/apache/xmlbeans/impl/values/JavaHexBinaryHolder.java @@ -25,17 +25,13 @@ import org.apache.xmlbeans.impl.util.HexBin; import java.nio.charset.StandardCharsets; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; import java.util.Arrays; -public abstract class JavaHexBinaryHolder extends XmlObjectBase { +public abstract class JavaHexBinaryHolder extends JavaDigestableHolder { public SchemaType schemaType() { return BuiltinSchemaTypeSystem.ST_HEX_BINARY; } - protected byte[] _value; - // SIMPLE VALUE ACCESSORS BELOW ------------------------------------------- // gets raw text value @@ -107,33 +103,4 @@ protected boolean equal_to(XmlObject i) { byte[] ival = ((XmlHexBinary) i).getByteArrayValue(); return Arrays.equals(_value, ival); } - - //because computing hashcode is expensive we'll cache it - protected boolean _hashcached = false; - protected int hashcode = 0; - protected static final MessageDigest md5; - - static { - try { - md5 = MessageDigest.getInstance("MD5"); - } catch (NoSuchAlgorithmException e) { - throw new IllegalStateException("Cannot find MD5 hash Algorithm"); - } - } - - protected int value_hash_code() { - if (_hashcached) { - return hashcode; - } - - _hashcached = true; - - if (_value == null) { - return hashcode = 0; - } - - byte[] res = md5.digest(_value); - return hashcode = (res[0] << 24) | (res[1] << 16) | (res[2] << 8) | res[3]; - } - }