Created
July 13, 2025 17:04
-
-
Save arleighdickerson/5d4549cd2a7647a91fbe30d0b151bf24 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import lombok.NonNull; | |
| import lombok.SneakyThrows; | |
| import org.apache.commons.codec.binary.Base32; | |
| import org.springframework.lang.Nullable; | |
| import java.nio.charset.StandardCharsets; | |
| import java.security.MessageDigest; | |
| import java.util.Arrays; | |
| import java.util.Locale; | |
| import java.util.regex.Pattern; | |
| public final class HashUtil { | |
| public static final String HASH_REGEX = "^[a-z0-9]{128}$"; | |
| private static final Pattern HASH_PATTERN = Pattern.compile(HASH_REGEX); | |
| public static boolean isValidHash(@Nullable String hash) { | |
| return hash == null || HASH_PATTERN.matcher(hash).matches(); | |
| } | |
| private HashUtil() { | |
| } | |
| public static String createHash(@NonNull String plainText) { | |
| return createHash(plainText, null); | |
| } | |
| /** | |
| * @param plainText the input text to hash | |
| * @param salt a salt for the hash | |
| * | |
| * @return the encoded value of the hash, containing only lowercase alphanumeric characters | |
| */ | |
| @SneakyThrows | |
| public static String createHash(@NonNull String plainText, @Nullable byte[] salt) { | |
| MessageDigest md = MessageDigest.getInstance("SHA-512"); | |
| if (salt != null && salt.length > 0) { | |
| // add salt if one is provided | |
| md.update(salt); | |
| } | |
| byte[] hash = md.digest(plainText.getBytes(StandardCharsets.UTF_8)); | |
| // encode with base32 for case-insensitivity | |
| return new Base32(false) | |
| // pad the hash before encoding to ensure url safety (no trailing '=' chars) | |
| .encodeToString(addPadding(hash)) | |
| // use [a-z] instead of [A-Z] | |
| .toLowerCase(Locale.ROOT); | |
| } | |
| public static byte[] addPadding(byte[] input) { | |
| int res = 16 - input.length % 16; | |
| byte[] result = new byte[res]; | |
| Arrays.fill(result, (byte) res); | |
| return merge(input, result); | |
| } | |
| private static byte[] merge(byte[] arr1, byte[] arr2) { | |
| byte[] results = new byte[arr1.length + arr2.length]; | |
| int i = 0; | |
| for (; i < arr1.length; i += 1) { | |
| results[i] = arr1[i]; | |
| } | |
| for (int j = i; j - i < arr2.length; j += 1) { | |
| results[j] = arr2[j - i]; | |
| } | |
| return results; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment