From 783f1e617dad3307807a86b0def2763ce68d54bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Ra=C4=8Dansk=C3=BD?= Date: Fri, 12 Jan 2024 06:51:20 +0100 Subject: [PATCH] Fix #554: Remove Guava dependency (#569) * Fix #554: Remove Guava dependency --- pom.xml | 7 --- powerauth-java-crypto/pom.xml | 4 -- .../lib/generator/IdentifierGenerator.java | 49 ++++++++++++------- .../powerauth/crypto/lib/totp/Totp.java | 3 +- .../crypto/lib/util/SignatureUtils.java | 3 +- ...Test.java => IdentifierGeneratorTest.java} | 20 ++++++-- .../powerauth/crypto/lib/totp/TotpTest.java | 1 - powerauth-java-http/pom.xml | 4 -- 8 files changed, 49 insertions(+), 42 deletions(-) rename powerauth-java-crypto/src/test/java/io/getlime/security/powerauth/crypto/activation/{PowerAuthRecoveryCodeTest.java => IdentifierGeneratorTest.java} (87%) diff --git a/pom.xml b/pom.xml index ea3e67f27..7c7183ce7 100644 --- a/pom.xml +++ b/pom.xml @@ -80,19 +80,12 @@ 3.6.3 3.3.0 3.2.3 - 32.1.3-jre 2.0.10 5.10.1 - - com.google.guava - guava - ${guava.version} - - org.slf4j slf4j-api diff --git a/powerauth-java-crypto/pom.xml b/powerauth-java-crypto/pom.xml index 0a7b80131..12a34d638 100644 --- a/powerauth-java-crypto/pom.xml +++ b/powerauth-java-crypto/pom.xml @@ -30,10 +30,6 @@ - - com.google.guava - guava - org.slf4j slf4j-api diff --git a/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/generator/IdentifierGenerator.java b/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/generator/IdentifierGenerator.java index 222352004..b38730602 100644 --- a/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/generator/IdentifierGenerator.java +++ b/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/generator/IdentifierGenerator.java @@ -16,7 +16,6 @@ */ package io.getlime.security.powerauth.crypto.lib.generator; -import com.google.common.io.BaseEncoding; import io.getlime.security.powerauth.crypto.lib.encryptor.ecies.kdf.KdfX9_63; import io.getlime.security.powerauth.crypto.lib.model.RecoveryInfo; import io.getlime.security.powerauth.crypto.lib.model.RecoverySeed; @@ -24,6 +23,7 @@ import io.getlime.security.powerauth.crypto.lib.model.exception.GenericCryptoException; import io.getlime.security.powerauth.crypto.lib.util.CRC16; import io.getlime.security.powerauth.crypto.lib.util.KeyConvertor; +import org.bouncycastle.util.encoders.Base32; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -79,17 +79,6 @@ public String generateActivationId() { return UUID.randomUUID().toString(); } - /** - * Generate a new string of a default length (5) with characters from Base32 encoding. - * - * @return New string with Base32 characters of a given length. - * @throws CryptoProviderException In case key cryptography provider is incorrectly initialized. - */ - private String generateBase32Token() throws CryptoProviderException { - byte[] randomBytes = keyGenerator.generateRandomBytes(BASE32_KEY_LENGTH); - return BaseEncoding.base32().omitPadding().encode(randomBytes).substring(0, BASE32_KEY_LENGTH); - } - /** * Generate version 3.0 or higher activation code. The format of activation code is "ABCDE-FGHIJ-KLMNO-PQRST". *

@@ -170,8 +159,8 @@ public boolean validateActivationCode(String activationCode) { return false; } - // Decode the Base32 value - byte[] activationCodeBytes = BaseEncoding.base32().decode(activationCode.replace("-", "")); + final String activationCodeBase32 = fetchActivationCodeBase32(activationCode); + final byte[] activationCodeBytes = Base32.decode(activationCodeBase32); // Verify byte array length if (activationCodeBytes.length != ACTIVATION_CODE_BYTES_LENGTH) { @@ -190,6 +179,32 @@ public boolean validateActivationCode(String activationCode) { return expectedChecksum == actualChecksum; } + /** + * Remove hyphens and calculate padding. + *

+ * When {@code ACTIVATION_CODE_BYTES_LENGTH = 12}, the Base32 padding is always {@code ====}, but this method is safe to change the length in the future. + * + * @param activationCode activation code with hyphens + * @return base32 with padding + */ + private static String fetchActivationCodeBase32(final String activationCode) { + final String activationCodeWithoutHyphens = activationCode.replace("-", ""); + // The activation code does not contain the padding, but it must be present in the Base32 value to be valid. + final String activationCodePadding = switch (activationCodeWithoutHyphens.length() % 8) { + case 2: + yield "======"; + case 4: + yield "===="; + case 5: + yield "==="; + case 7: + yield "="; + default: + yield ""; + }; + return activationCodeWithoutHyphens + activationCodePadding; + } + /** * Generate recovery code and PUK. * @return Recovery code and PUK. @@ -367,9 +382,9 @@ private String generatePuk(SecretKey recoveryPukBaseKey, byte[] indexBytes) thro * @param activationCodeBytes Raw activation code bytes. * @return Base32 String representation of activation code. */ - private String encodeActivationCode(byte[] activationCodeBytes) { - // Generate Base32 representation from 12 activation code bytes, without padding characters. - String base32Encoded = BaseEncoding.base32().omitPadding().encode(activationCodeBytes); + private String encodeActivationCode(final byte[] activationCodeBytes) { + // Padding may be ignored; ACTIVATION_CODE_BYTES_LENGTH is set to 12 and the following substring takes only the first 20 characters. + final String base32Encoded = Base32.toBase32String(activationCodeBytes); // Split Base32 string into 4 groups, each one contains 5 characters. Use "-" as separator. return base32Encoded.substring(0, BASE32_KEY_LENGTH) diff --git a/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/totp/Totp.java b/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/totp/Totp.java index a0599c0c6..bcd0991ac 100644 --- a/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/totp/Totp.java +++ b/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/totp/Totp.java @@ -16,7 +16,6 @@ */ package io.getlime.security.powerauth.crypto.lib.totp; -import com.google.common.base.Strings; import io.getlime.security.powerauth.crypto.lib.model.exception.CryptoProviderException; import org.bouncycastle.util.Arrays; import org.slf4j.Logger; @@ -268,7 +267,7 @@ private static long countTimeSteps(final Instant instant, final Duration stepLen } private static String padWithZeros(final String source, final int length) { - return Strings.padStart(source, length, '0'); + return String.format("%1$" + length + "s", source).replace(' ', '0'); } /** diff --git a/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/util/SignatureUtils.java b/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/util/SignatureUtils.java index 316b2297e..f944470d5 100644 --- a/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/util/SignatureUtils.java +++ b/powerauth-java-crypto/src/main/java/io/getlime/security/powerauth/crypto/lib/util/SignatureUtils.java @@ -16,7 +16,6 @@ */ package io.getlime.security.powerauth.crypto.lib.util; -import com.google.common.base.Joiner; import io.getlime.security.powerauth.crypto.lib.config.DecimalSignatureConfiguration; import io.getlime.security.powerauth.crypto.lib.config.PowerAuthConfiguration; import io.getlime.security.powerauth.crypto.lib.config.SignatureConfiguration; @@ -164,7 +163,7 @@ private String computePowerAuthDecimalSignature(byte[] data, List sig signatureStringComponents[i] = String.format("%0" + signatureDecimalLength + "d", number); } // Join components with dash. - return Joiner.on("-").join(signatureStringComponents); + return String.join("-", signatureStringComponents); } /** diff --git a/powerauth-java-crypto/src/test/java/io/getlime/security/powerauth/crypto/activation/PowerAuthRecoveryCodeTest.java b/powerauth-java-crypto/src/test/java/io/getlime/security/powerauth/crypto/activation/IdentifierGeneratorTest.java similarity index 87% rename from powerauth-java-crypto/src/test/java/io/getlime/security/powerauth/crypto/activation/PowerAuthRecoveryCodeTest.java rename to powerauth-java-crypto/src/test/java/io/getlime/security/powerauth/crypto/activation/IdentifierGeneratorTest.java index 464b50979..360db676c 100644 --- a/powerauth-java-crypto/src/test/java/io/getlime/security/powerauth/crypto/activation/PowerAuthRecoveryCodeTest.java +++ b/powerauth-java-crypto/src/test/java/io/getlime/security/powerauth/crypto/activation/IdentifierGeneratorTest.java @@ -20,23 +20,25 @@ import io.getlime.security.powerauth.crypto.lib.generator.KeyGenerator; import io.getlime.security.powerauth.crypto.lib.model.RecoveryInfo; import io.getlime.security.powerauth.crypto.lib.model.RecoverySeed; -import io.getlime.security.powerauth.crypto.lib.model.exception.CryptoProviderException; -import io.getlime.security.powerauth.crypto.lib.model.exception.GenericCryptoException; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import javax.crypto.SecretKey; -import java.security.*; +import java.security.KeyPair; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.Security; import java.util.HashSet; import static org.junit.jupiter.api.Assertions.*; /** + * Test for {@link IdentifierGenerator}. * * @author Roman Strobl, roman.strobl@wultra.com */ -public class PowerAuthRecoveryCodeTest { +class IdentifierGeneratorTest { private final IdentifierGenerator identifierGenerator = new IdentifierGenerator(); @@ -50,7 +52,7 @@ public static void setUp() { } @Test - public void testRecoveryCodeDerivation() throws CryptoProviderException, InvalidKeyException, GenericCryptoException { + void testRecoveryCodeDerivation() throws Exception { // Number of PUKs to test int pukCount = 100; @@ -89,4 +91,12 @@ public void testRecoveryCodeDerivation() throws CryptoProviderException, Invalid } } + @Test + void testGenerateActivationCode() throws Exception { + final String result = identifierGenerator.generateActivationCode(new byte[10]); + + // Base32 is AAAAAAAAAAAAAAAAAAAA==== + assertEquals("AAAAA-AAAAA-AAAAA-AAAAA", result); + } + } diff --git a/powerauth-java-crypto/src/test/java/io/getlime/security/powerauth/crypto/lib/totp/TotpTest.java b/powerauth-java-crypto/src/test/java/io/getlime/security/powerauth/crypto/lib/totp/TotpTest.java index 9f2b7f80a..24e77f7d8 100644 --- a/powerauth-java-crypto/src/test/java/io/getlime/security/powerauth/crypto/lib/totp/TotpTest.java +++ b/powerauth-java-crypto/src/test/java/io/getlime/security/powerauth/crypto/lib/totp/TotpTest.java @@ -36,7 +36,6 @@ * Test for {@link Totp}. * * @author Lubos Racansky, lubos.racansky@wultra.com - * */ class TotpTest { diff --git a/powerauth-java-http/pom.xml b/powerauth-java-http/pom.xml index ea5cf1a60..2453a9eae 100644 --- a/powerauth-java-http/pom.xml +++ b/powerauth-java-http/pom.xml @@ -37,10 +37,6 @@ powerauth-java-crypto ${project.version} - - com.google.guava - guava - org.slf4j slf4j-api