diff --git a/README.md b/README.md index db6344c1a..cadd9d371 100644 --- a/README.md +++ b/README.md @@ -9,17 +9,17 @@ These are the source of the GeneXus Standard Classes for Java, valid since GeneX ## Modules -| Name | Description -|---|--- -| common | Classes common to Android and Java -| gxcryptocommon | Classes common to Android and Java related to Cryptography -| gxmail | Classes related to mail handling -| java | Java standard classes, output is gxclassr.jar -| wrappercommon | Interfaces to encapsulate Java EE and Jakarta EE support, output is gxwrappercommon.jar -| wrapperjavax | Implement the interfaces defined in wrappercommon in Java EE, output is gxwrapperjavax.jar -| wrapperjakarta | Implement the interfaces defined in wrappercommon in Jakarta EE, output is gxwrapperjakarta.jar -| gxoffice | Formerly Java classes are now separated to be included only when using office. -| gxsearch | Formerly in Java classes are now separated to be included only when using search. +| Name | Description +|--------------------------------|--- +| common | Classes common to Android and Java +| gxcryptocommon | Classes common to Android and Java related to Cryptography +| gxmail | Classes related to mail handling +| java | Java standard classes, output is gxclassr.jar +| wrappercommon | Interfaces to encapsulate Java EE and Jakarta EE support, output is gxwrappercommon.jar +| wrapperjavax | Implement the interfaces defined in wrappercommon in Java EE, output is gxwrapperjavax.jar +| wrapperjakarta | Implement the interfaces defined in wrappercommon in Jakarta EE, output is gxwrapperjakarta.jar +| gxoffice | Formerly Java classes are now separated to be included only when using office. +| gxsearch | Formerly in Java classes are now separated to be included only when using search. | gxandroidpublisher and javapns | They are necessary for when you have Push Notifications in your old implementation. These are projects that should disappear in the short term. | android | The standard Android classes. **Note that this is not the full runtime for Android, the full runtime can be created by using the Android Flexible Client project**. | gxexternalproviders | Implements service provider for IBM Cloud, Google, Azure, Amazon @@ -32,6 +32,7 @@ These are the source of the GeneXus Standard Classes for Java, valid since GeneX | gxftps | SecurityAPI's GeneXusFTPS module | gxsftp | SecurityAPI's GeneXusSFTP module | gamutils | GAM external object with utilities +| gamtotp | GAM external object for RFC6238 implementation The dependencies between the projects are specified in each pom.xml within their directory. diff --git a/gamtotp/pom.xml b/gamtotp/pom.xml new file mode 100644 index 000000000..23a58cb0a --- /dev/null +++ b/gamtotp/pom.xml @@ -0,0 +1,51 @@ + + + 4.0.0 + + + com.genexus + parent + ${revision}${changelist} + + + gamtotp + GAM TOTP + + + UTF-8 + + + + + org.apache.logging.log4j + log4j-core + ${log4j.version} + + + dev.samstevens.totp + totp + 1.7.1 + + + com.beust + jcommander + 1.78 + + + + + + + gamtotp + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + + + + + \ No newline at end of file diff --git a/gamtotp/src/main/java/com/genexus/totp/TOTPAuthenticator.java b/gamtotp/src/main/java/com/genexus/totp/TOTPAuthenticator.java new file mode 100644 index 000000000..4ac184b29 --- /dev/null +++ b/gamtotp/src/main/java/com/genexus/totp/TOTPAuthenticator.java @@ -0,0 +1,94 @@ +package com.genexus.totp; + +import dev.samstevens.totp.code.CodeGenerator; +import dev.samstevens.totp.code.DefaultCodeGenerator; +import dev.samstevens.totp.code.DefaultCodeVerifier; +import dev.samstevens.totp.code.HashingAlgorithm; +import dev.samstevens.totp.qr.QrData; +import dev.samstevens.totp.qr.QrGenerator; +import dev.samstevens.totp.qr.ZxingPngQrGenerator; +import dev.samstevens.totp.secret.DefaultSecretGenerator; +import dev.samstevens.totp.secret.SecretGenerator; +import dev.samstevens.totp.time.SystemTimeProvider; +import dev.samstevens.totp.time.TimeProvider; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import static dev.samstevens.totp.util.Utils.getDataUriForImage; + +@SuppressWarnings("unused") +public class TOTPAuthenticator { + + private static final Logger logger = LogManager.getLogger(TOTPAuthenticator.class); + + public static String GenerateKey(int keyLength) { + logger.debug("GenerateKey"); + SecretGenerator secretGenerator = new DefaultSecretGenerator(keyLength * 8); + String str = secretGenerator.generate(); + try { + return str.substring(0, keyLength); + } catch (Exception e) { + logger.error("GenerateKey", e); + return str; + } + } + + public static String GenerateQRData(String accountName, String secretKey, String appName, String algorithm, int digits, int period) { + logger.debug("GenerateQRData"); + HashingAlgorithm hashAlg; + if (algorithm.equalsIgnoreCase("SHA512")) { + hashAlg = HashingAlgorithm.SHA512; + } else if (algorithm.equalsIgnoreCase("SHA256")) { + hashAlg = HashingAlgorithm.SHA256; + } else { + hashAlg = HashingAlgorithm.SHA1; + } + + QrData data = new QrData.Builder() + .label(accountName) + .secret(secretKey) + .issuer(appName) + .algorithm(hashAlg) + .digits(digits) + .period(period) + .build(); + + + QrGenerator generator = new ZxingPngQrGenerator(); + try { + return getDataUriForImage(generator.generate(data), generator.getImageMimeType()); + } catch (Exception e) { + logger.error("GenerateQRData", e); + return null; + } + } + + public static boolean VerifyTOTPCode(String secretKey, String code, String algorithm, int digits, int period) { + logger.debug("VerifyTOTPCode"); + HashingAlgorithm hashAlg; + if (algorithm.equalsIgnoreCase("SHA512")) { + hashAlg = HashingAlgorithm.SHA512; + } else if (algorithm.equalsIgnoreCase("SHA256")) { + hashAlg = HashingAlgorithm.SHA256; + } else { + hashAlg = HashingAlgorithm.SHA1; + } + + TimeProvider timeProvider = new SystemTimeProvider(); + + CodeGenerator codeGenerator = new DefaultCodeGenerator(hashAlg, digits); + DefaultCodeVerifier verifier = new DefaultCodeVerifier(codeGenerator, timeProvider); + + // sets the time period for codes to be valid for to X seconds + verifier.setTimePeriod(period); + + // allow codes valid for 1 time periods before/after to pass as valid + verifier.setAllowedTimePeriodDiscrepancy(0); + + // secret = the shared secret for the user + // code = the code submitted by the user + return verifier.isValidCode(secretKey, code); + } +} + + diff --git a/pom.xml b/pom.xml index 7a082f63a..400cf850e 100644 --- a/pom.xml +++ b/pom.xml @@ -120,6 +120,7 @@ gxsftp gxftps gamutils + gamtotp