Skip to content
Merged

Cleanup #1488

Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
cleanup
* use java.util.Base64 instead of third-party implementation;
* extract copy-pasted code into common method
  • Loading branch information
aleksandy committed Nov 13, 2025
commit 038bc94eddd21184d12b2a71d81d46b41d66e6d1
65 changes: 34 additions & 31 deletions framework/src/play/libs/Codec.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package play.libs;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;

import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;

import play.exceptions.UnexpectedException;
Expand Down Expand Up @@ -33,18 +33,18 @@ public static String UUID() {
* @return The base64 encoded String
*/
public static String encodeBASE64(String value) {
return new String(Base64.encodeBase64(value.getBytes(UTF_8)));
return java.util.Base64.getEncoder().encodeToString(value.getBytes(UTF_8));
}

/**
* Encode binary data to base64
*
*
* @param value
* The binary data
* @return The base64 encoded String
*/
public static String encodeBASE64(byte[] value) {
return new String(Base64.encodeBase64(value));
return java.util.Base64.getEncoder().encodeToString(value);
}

/**
Expand All @@ -55,50 +55,34 @@ public static String encodeBASE64(byte[] value) {
* @return decoded binary data
*/
public static byte[] decodeBASE64(String value) {
return Base64.decodeBase64(value.getBytes(UTF_8));
return java.util.Base64.getDecoder().decode(value);
}

/**
* Build an hexadecimal MD5 hash for a String
* Build a hexadecimal MD5 hash for a String
*
* @param value
* The String to hash
* @return An hexadecimal Hash
* @return A hexadecimal Hash
*/
public static String hexMD5(String value) {
try {
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
messageDigest.reset();
messageDigest.update(value.getBytes(UTF_8));
byte[] digest = messageDigest.digest();
return byteToHexString(digest);
} catch (Exception ex) {
throw new UnexpectedException(ex);
}
return hashToHexString("MD5", value);
}

/**
* Build an hexadecimal SHA1 hash for a String
*
* Build a hexadecimal SHA1 hash for a String
*
* @param value
* The String to hash
* @return An hexadecimal Hash
* @return A hexadecimal Hash
*/
public static String hexSHA1(String value) {
try {
MessageDigest md;
md = MessageDigest.getInstance("SHA-1");
md.update(value.getBytes(UTF_8));
byte[] digest = md.digest();
return byteToHexString(digest);
} catch (Exception ex) {
throw new UnexpectedException(ex);
}
return hashToHexString("SHA-1", value);
}

/**
* Write a byte array as hexadecimal String.
*
*
* @param bytes
* byte array
* @return The hexadecimal String
Expand All @@ -108,8 +92,8 @@ public static String byteToHexString(byte[] bytes) {
}

/**
* Transform an hexadecimal String to a byte array.
*
* Transform a hexadecimal String to a byte array.
*
* @param hexString
* Hexadecimal string to transform
* @return The byte array
Expand All @@ -122,4 +106,23 @@ public static byte[] hexStringToByte(String hexString) {
}
}

/**
* Build a hexadecimal hash specified by {@code algorithm} for a given {@code value}.
*
* @param algorithm The hash name
* @param value The String to hash
*
* @return A hexadecimal hash
*/
private static String hashToHexString(String algorithm, String value) {
try {
return byteToHexString(
MessageDigest.getInstance(algorithm)
.digest(value.getBytes(UTF_8))
);
} catch (NoSuchAlgorithmException ex) {
throw new UnexpectedException(ex);
}
}

}
58 changes: 58 additions & 0 deletions framework/test-src/play/libs/CodecTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package play.libs;

import org.junit.Test;

import static org.assertj.core.api.Assertions.assertThat;

public class CodecTest {

@Test
public void encodeBASE64() {
// input and expected data are taken from https://datatracker.ietf.org/doc/html/rfc4648#section-10
assertThat(Codec.encodeBASE64("")).isEmpty();
assertThat(Codec.encodeBASE64(new byte[0])).isEmpty();

assertThat(Codec.encodeBASE64("f")).isEqualTo("Zg==");
assertThat(Codec.encodeBASE64("fo")).isEqualTo("Zm8=");
assertThat(Codec.encodeBASE64("foo")).isEqualTo("Zm9v");
assertThat(Codec.encodeBASE64("foob")).isEqualTo("Zm9vYg==");
assertThat(Codec.encodeBASE64("fooba")).isEqualTo("Zm9vYmE=");
assertThat(Codec.encodeBASE64("foobar")).isEqualTo("Zm9vYmFy");

assertThat(Codec.encodeBASE64(new byte[] { 'f' })).isEqualTo("Zg==");
assertThat(Codec.encodeBASE64(new byte[] { 'f', 'o' })).isEqualTo("Zm8=");
assertThat(Codec.encodeBASE64(new byte[] { 'f', 'o', 'o' })).isEqualTo("Zm9v");
assertThat(Codec.encodeBASE64(new byte[] { 'f', 'o', 'o', 'b' })).isEqualTo("Zm9vYg==");
assertThat(Codec.encodeBASE64(new byte[] { 'f', 'o', 'o', 'b', 'a' })).isEqualTo("Zm9vYmE=");
assertThat(Codec.encodeBASE64(new byte[] { 'f', 'o', 'o', 'b', 'a', 'r' })).isEqualTo("Zm9vYmFy");
}

@Test
public void decodeBASE64() {
// input and expected data are taken from https://datatracker.ietf.org/doc/html/rfc4648#section-10
assertThat(Codec.decodeBASE64("")).isEmpty();
assertThat(Codec.decodeBASE64("Zg==")).isEqualTo(new byte[] { 'f' });
assertThat(Codec.decodeBASE64("Zm8=")).isEqualTo(new byte[] { 'f', 'o' });
assertThat(Codec.decodeBASE64("Zm9v")).isEqualTo(new byte[] { 'f', 'o', 'o' });
assertThat(Codec.decodeBASE64("Zm9vYg==")).isEqualTo(new byte[] { 'f', 'o', 'o', 'b' });
assertThat(Codec.decodeBASE64("Zm9vYmE=")).isEqualTo(new byte[] { 'f', 'o', 'o', 'b', 'a' });
assertThat(Codec.decodeBASE64("Zm9vYmFy")).isEqualTo(new byte[] { 'f', 'o', 'o', 'b', 'a', 'r' });
}

@Test
public void hexMD5() {
// https://www.febooti.com/products/filetweak/members/hash-and-crc/test-vectors/
assertThat(Codec.hexMD5("")).isEqualTo("d41d8cd98f00b204e9800998ecf8427e");
assertThat(Codec.hexMD5("The quick brown fox jumps over the lazy dog")).isEqualTo("9e107d9d372bb6826bd81d3542a419d6");
assertThat(Codec.hexMD5("Test vector from febooti.com")).isEqualTo("500ab6613c6db7fbd30c62f5ff573d0f");
}

@Test
public void hexSHA1() {
// https://www.febooti.com/products/filetweak/members/hash-and-crc/test-vectors/
assertThat(Codec.hexSHA1("")).isEqualTo("da39a3ee5e6b4b0d3255bfef95601890afd80709");
assertThat(Codec.hexSHA1("The quick brown fox jumps over the lazy dog")).isEqualTo("2fd4e1c67a2d28fced849ee1bb76e7391b93eb12");
assertThat(Codec.hexSHA1("Test vector from febooti.com")).isEqualTo("a7631795f6d59cd6d14ebd0058a6394a4b93d868");
}

}