Skip to content

Commit 0ee467d

Browse files
committed
Use own implementation of hex encoding instead of Guava
This implementation is also consistently faster than Guava's, as measured by `BinaryUtilBenchmark`: ``` Benchmark Mode Cnt Score Error Units Impl BinaryUtilBenchmark.fromHexLong1024 thrpt 50 301818.344 ± 1823.327 ops/s BEFORE BinaryUtilBenchmark.fromHexLong1024 thrpt 50 436189.249 ± 7222.349 ops/s AFTER BinaryUtilBenchmark.fromHexLong128 thrpt 50 2547578.209 ± 36429.270 ops/s BEFORE BinaryUtilBenchmark.fromHexLong128 thrpt 50 3424637.978 ± 74009.099 ops/s AFTER BinaryUtilBenchmark.fromHexLong2048 thrpt 50 155698.523 ± 1851.933 ops/s BEFORE BinaryUtilBenchmark.fromHexLong2048 thrpt 50 213877.472 ± 6278.015 ops/s AFTER BinaryUtilBenchmark.fromHexLong256 thrpt 50 1263837.915 ± 15008.090 ops/s BEFORE BinaryUtilBenchmark.fromHexLong256 thrpt 50 1755787.013 ± 34779.702 ops/s AFTER BinaryUtilBenchmark.fromHexLong512 thrpt 50 612113.541 ± 9002.875 ops/s BEFORE BinaryUtilBenchmark.fromHexLong512 thrpt 50 865881.718 ± 20505.584 ops/s AFTER BinaryUtilBenchmark.fromHexShort thrpt 50 1684110.673 ± 13361.998 ops/s BEFORE BinaryUtilBenchmark.fromHexShort thrpt 50 3068635.083 ± 19792.031 ops/s AFTER BinaryUtilBenchmark.toHexLong1024 thrpt 50 123499.030 ± 1958.386 ops/s BEFORE BinaryUtilBenchmark.toHexLong1024 thrpt 50 489521.929 ± 8109.498 ops/s AFTER BinaryUtilBenchmark.toHexLong128 thrpt 50 1262978.123 ± 78118.670 ops/s BEFORE BinaryUtilBenchmark.toHexLong128 thrpt 50 4992184.518 ± 54967.597 ops/s AFTER BinaryUtilBenchmark.toHexLong2048 thrpt 50 60673.623 ± 954.492 ops/s BEFORE BinaryUtilBenchmark.toHexLong2048 thrpt 50 261067.839 ± 5633.761 ops/s AFTER BinaryUtilBenchmark.toHexLong256 thrpt 50 508383.710 ± 5657.270 ops/s BEFORE BinaryUtilBenchmark.toHexLong256 thrpt 50 2190927.893 ± 16407.648 ops/s AFTER BinaryUtilBenchmark.toHexLong512 thrpt 50 252395.165 ± 2757.667 ops/s BEFORE BinaryUtilBenchmark.toHexLong512 thrpt 50 1008894.819 ± 7572.435 ops/s AFTER BinaryUtilBenchmark.toHexShort thrpt 50 1205170.498 ± 11219.835 ops/s BEFORE BinaryUtilBenchmark.toHexShort thrpt 50 2579415.167 ± 13612.182 ops/s AFTER ```
1 parent 61d26f8 commit 0ee467d

File tree

3 files changed

+23
-9
lines changed

3 files changed

+23
-9
lines changed

webauthn-server-demo/src/main/java/com/yubico/webauthn/attestation/matcher/ExtensionMatcher.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,7 @@ public boolean matches(X509Certificate attestationCertificate, JsonNode paramete
6969
}
7070
} catch (IOException e) {
7171
log.error(
72-
"Failed to parse extension value as ASN1: {}",
73-
new ByteArray(extensionValue),
74-
e);
72+
"Failed to parse extension value as ASN1: {}", new ByteArray(extensionValue), e);
7573
}
7674
}
7775
}

yubico-util/build.gradle.kts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ dependencies {
2525
implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-cbor")
2626
implementation("com.fasterxml.jackson.datatype:jackson-datatype-jdk8")
2727
implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310")
28-
implementation("com.google.guava:guava")
2928
implementation("com.upokecenter:cbor")
3029
implementation("org.slf4j:slf4j-api")
3130

yubico-util/src/main/java/com/yubico/internal/util/BinaryUtil.java

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424

2525
package com.yubico.internal.util;
2626

27-
import com.google.common.io.BaseEncoding;
2827
import java.io.IOException;
2928
import java.io.InputStream;
3029
import java.nio.ByteBuffer;
@@ -40,15 +39,33 @@ public static byte[] copy(byte[] bytes) {
4039
/**
4140
* @param bytes Bytes to encode
4241
*/
43-
public static String toHex(byte[] bytes) {
44-
return BaseEncoding.base16().encode(bytes).toLowerCase();
42+
public static String toHex(final byte[] bytes) {
43+
final char[] digits = new char[bytes.length * 2];
44+
for (int i = 0; i < bytes.length; ++i) {
45+
final int i2 = i * 2;
46+
digits[i2] = Character.forDigit((bytes[i] >> 4) & 0x0f, 16);
47+
digits[i2 + 1] = Character.forDigit(bytes[i] & 0x0f, 16);
48+
}
49+
return new String(digits);
4550
}
4651

4752
/**
4853
* @param hex String of hexadecimal digits to decode as bytes.
4954
*/
50-
public static byte[] fromHex(String hex) {
51-
return BaseEncoding.base16().decode(hex.toUpperCase());
55+
public static byte[] fromHex(final String hex) {
56+
if (hex.length() % 2 != 0) {
57+
throw new IllegalArgumentException("Length of hex string is not even: " + hex);
58+
}
59+
60+
final byte[] result = new byte[hex.length() / 2];
61+
for (int i = 0; i < hex.length(); ++i) {
62+
final int d = Character.digit(hex.charAt(i), 16);
63+
if (d < 0) {
64+
throw new IllegalArgumentException("Invalid hex digit at index " + i + " in: " + hex);
65+
}
66+
result[i / 2] |= d << (((i + 1) % 2) * 4);
67+
}
68+
return result;
5269
}
5370

5471
/**

0 commit comments

Comments
 (0)