Skip to content

GamCryptography EO migration to GamUtils EO on Github #885

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 26 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
2d150fc
GamUtils + tests
sgrampone Jul 26, 2024
083bef0
Fix test
sgrampone Jul 26, 2024
77fab66
Fix quality issues and Log
sgrampone Aug 2, 2024
9cb8c02
New features, tests and some needed refactoring
sgrampone Aug 6, 2024
a2c7ae2
Load encrypted private keys + tests
sgrampone Aug 7, 2024
055badf
GamUtilsEO simplification and module refactor + tests
sgrampone Aug 15, 2024
63abd1d
Fix cast type error for jwk keys on gamutils
sgrampone Aug 15, 2024
c1be143
Add DynamicCall EO to GamUtils
sgrampone Aug 19, 2024
761a632
Merge branch 'master' into gamutils_eo
sgrampone Aug 29, 2024
842a761
Add sha256 and encoding features for PKCE implementation
sgrampone Aug 29, 2024
5322c50
Fix hash class
sgrampone Aug 29, 2024
09ce4c3
Refactor Encoding class name
sgrampone Aug 30, 2024
be96dd3
Merge branch 'master' into gamutils_eo
sgrampone Oct 7, 2024
2bc6616
Adding missing functions
sgrampone Jan 14, 2025
84b897d
Delete usless function
sgrampone Jan 15, 2025
038b14c
Merge branch 'master' into gamutils_eo
sgrampone Jan 16, 2025
75fcc40
Adding Base64Url encoding functions and fixing symmetric and asymmetric
sgrampone Jan 21, 2025
c7e5e15
Adding Base64Url encoding functions and fixing symmetric and asymmetr…
sgrampone Jan 21, 2025
788dff3
Fix JWTAlgorithm bug with RSA header
sgrampone Jan 21, 2025
594c264
Add Base64ToHexa function
sgrampone Feb 27, 2025
a2e0259
GamUtilsEO add functions for PKCE
sgrampone Feb 28, 2025
096fcb6
Merge branch 'master' into gamutils_eo
sgrampone Mar 12, 2025
f077408
Fix pkce functions
sgrampone Mar 26, 2025
5c3eb3c
Change Base64Url functions
sgrampone Mar 27, 2025
30563cc
Merge branch 'master' into gamutils_eo
sgrampone Mar 27, 2025
c8ba835
Fix key extension detection for azure OIDC discovery
sgrampone Apr 29, 2025
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ These are the source of the GeneXus Standard Classes for Java, valid since GeneX
| gxexternalproviders | Implements service provider for IBM Cloud, Google, Azure, Amazon
| gxgeospatial | Geography data type implementation
| gxodata | OData access
| gamutils | GAM external object with utilities

The dependencies between the projects are specified in each pom.xml within their directory.

Expand Down
72 changes: 72 additions & 0 deletions gamutils/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>com.genexus</groupId>
<artifactId>parent</artifactId>
<version>${revision}${changelist}</version>
</parent>

<artifactId>gamutils</artifactId>
<name>GAM Utils EO</name>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.nimbusds</groupId>
<artifactId>nimbus-jose-jwt</artifactId>
<version>9.37.3</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk18on</artifactId>
<version>1.78.1</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk18on</artifactId>
<version>1.78.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>gxcommon</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.15</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<finalName>gamutils</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>

</project>
106 changes: 106 additions & 0 deletions gamutils/src/main/java/com/genexus/gam/GamUtilsEO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package com.genexus.gam;

import com.genexus.gam.utils.Encoding;
import com.genexus.gam.utils.Pkce;
import com.genexus.gam.utils.Random;
import com.genexus.gam.utils.cryptography.Encryption;
import com.genexus.gam.utils.cryptography.Hash;
import com.genexus.gam.utils.json.Jwk;
import com.genexus.gam.utils.json.Jwt;
import com.genexus.gam.utils.json.UnixTimestamp;

import java.util.Date;

public class GamUtilsEO {

/********EXTERNAL OBJECT PUBLIC METHODS - BEGIN ********/

//**HASH**//
public static String sha512(String plainText) {
return Hash.hash(plainText, Hash.SHA512);
}

public static String sha256(String plainText) {
return Hash.hash(plainText, Hash.SHA256);
}

//**ENCRYPTION**//

public static String AesGcm(String input, String key, String nonce, int macSize, boolean toEncrypt) {
return Encryption.AesGcm(input, key, nonce, macSize, toEncrypt);
}

//**RANDOM**//
public static String randomAlphanumeric(int length) {
return Random.alphanumeric(length);
}

public static String randomNumeric(int length) {
return Random.numeric(length);
}

public static String randomHexaBits(int bits) {
return Random.hexaBits(bits);
}

//**JWK**//

public static String generateKeyPair() {
return Jwk.generateKeyPair();
}

public static String getPublicJwk(String jwkString) {
return Jwk.getPublic(jwkString);
}

public static String getJwkAlgorithm(String jwkString) {
return Jwk.getAlgorithm(jwkString);
}

//**JWT**//
public static boolean verifyJwt(String path, String alias, String password, String token) {
return Jwt.verify(path, alias, password, token);
}

public static String createJwt(String path, String alias, String password, String payload, String header) {
return Jwt.create(path, alias, password, payload, header);
}

public static boolean verifyAlgorithm(String expectedAlgorithm, String token)
{
return Jwt.verifyAlgorithm(expectedAlgorithm, token);
}

public static long createUnixTimestamp(Date date) {
return UnixTimestamp.create(date);
}

public static String getJwtHeader(String token) {
return Jwt.getHeader(token);
}

public static String getJwtPayload(String token) {
return Jwt.getPayload(token);
}

//**ENCODING**//
public static String base64ToBase64Url(String base64) {
return Encoding.b64ToB64Url(base64);
}

public static String hexaToBase64(String hexa) { return Encoding.hexaToBase64(hexa); }

public static String toBase64Url(String input) { return Encoding.toBase64Url(input); }

public static String fromBase64Url(String base64) { return Encoding.fromBase64Url(base64); }

public static String base64ToHexa(String base64) { return Encoding.base64ToHexa(base64); }

//**PKCE**//

public static String pkce_create(int len, String option) { return Pkce.create(len, option); }

public static boolean pkce_verify(String code_verifier, String code_challenge, String option) { return Pkce.verify(code_verifier, code_challenge, option); }

/********EXTERNAL OBJECT PUBLIC METHODS - END ********/
}
100 changes: 100 additions & 0 deletions gamutils/src/main/java/com/genexus/gam/utils/DynamicCall.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package com.genexus.gam.utils;

import com.genexus.ModelContext;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

@SuppressWarnings("unused")
public class DynamicCall {
private final ModelContext mContext;
private final Integer mRemoteHandle;
private static final Logger logger = LogManager.getLogger(DynamicCall.class);

/********EXTERNAL OBJECT PUBLIC METHODS - BEGIN ********/

@SuppressWarnings("unused")
public DynamicCall(ModelContext context, Integer remoteHandle) {
mContext = context;
mRemoteHandle = remoteHandle;
}

@SuppressWarnings("unused")
public boolean execute(String assembly, String typeName, boolean useContext, String method, String jsonParms, String[] jsonOutput) {
logger.debug("execute");
return doCall(assembly, typeName, useContext, method, false, "", jsonParms, jsonOutput);
}

@SuppressWarnings("unused")
public boolean executeEventHandler(String assembly, String typeName, boolean useContext, String method, String eventType, String jsonInput, String[] jsonOutput) {
logger.debug("executeEventHandler");
return doCall(assembly, typeName, useContext, method, true, eventType, jsonInput, jsonOutput);
}

/********EXTERNAL OBJECT PUBLIC METHODS - END ********/


private boolean doCall(String assembly, String typeName, boolean useContext, String method, boolean isEventHandler, String parm1, String parm2, String[] jsonOutput) {
logger.debug("doCall");
Object[] parms;
Class<?>[] parmTypes;
if (isEventHandler) {
parms = new Object[]{parm1, parm2, new String[]{jsonOutput[0]}};
parmTypes = new Class[]{String.class, String.class, String[].class};
} else {
parms = new Object[]{parm2, new String[]{jsonOutput[0]}};
parmTypes = new Class[]{String.class, String[].class};
}

try {
Class<?> myClass = Class.forName(typeName);
Class<?>[] constructorParms;
Constructor<?> constructor;
Object instance = null;

if (useContext && (mContext != null)) {
try {
constructorParms = new Class[]{int.class, ModelContext.class};
constructor = myClass.getConstructor(constructorParms);
instance = constructor.newInstance(new Object[]{mRemoteHandle, mContext});
} catch (NoSuchMethodException e) {
logger.error("doCall", e);
}
}

if (instance == null) {
constructorParms = new Class[]{int.class};
constructor = myClass.getConstructor(constructorParms);
instance = constructor.newInstance(new Object[]{-2});
}

myClass.getMethod(method, parmTypes).invoke(instance, parms);
} catch (ClassNotFoundException e) {
logger.error("doCall", e);
jsonOutput[0] = "{\"error\":\"" + " class " + typeName + " not found" + "\"}";
return false;
} catch (NoSuchMethodException e) {
logger.error("doCall", e);
jsonOutput[0] = "{\"error\":\"" + " method " + method + " not found" + "\"}";
return false;
} catch (InstantiationException e) {
logger.error("doCall", e);
jsonOutput[0] = "{\"error\":\"" + " cannot instantiate type " + typeName + "\"}";
return false;
} catch (IllegalAccessException e) {
logger.error("doCall", e);
jsonOutput[0] = "{\"error\":\"" + " cannot access method " + method + "\"}";
return false;
} catch (InvocationTargetException e) {
logger.error("doCall", e);
jsonOutput[0] = "{\"error\":\"" + " InvocationTargetException in class " + typeName + "\"}";
return false;
}
String[] result = (String[]) parms[parms.length - 1];
jsonOutput[0] = result[0];
logger.debug("doCall result {}", result[0]);
return true;
}
}
74 changes: 74 additions & 0 deletions gamutils/src/main/java/com/genexus/gam/utils/Encoding.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package com.genexus.gam.utils;


import com.nimbusds.jose.util.Base64URL;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.bouncycastle.util.encoders.Base64;
import org.bouncycastle.util.encoders.Hex;
import org.bouncycastle.util.encoders.UrlBase64;

import java.nio.charset.StandardCharsets;

public class Encoding {

private static final Logger logger = LogManager.getLogger(Encoding.class);

public static String b64ToB64Url(String input) {
logger.debug("b64ToB64Url");
try {
return java.util.Base64.getUrlEncoder().withoutPadding().encodeToString(Base64.decode(input));
} catch (Exception e) {
logger.error("b64ToB64Url", e);
return "";
}
}

public static String hexaToBase64(String hexa)
{
logger.debug("hexaToBase64");
try{
return Base64.toBase64String(Hex.decode(hexa));
}catch (Exception e)
{
logger.error("hexaToBase64", e);
return "";
}
}

public static String toBase64Url(String input)
{
logger.debug("UTF8toBase64Url");
try{
return java.util.Base64.getUrlEncoder().withoutPadding().encodeToString(input.getBytes(StandardCharsets.UTF_8));
}catch (Exception e)
{
logger.error("UTF8toBase64Url", e);
return "";
}
}

public static String fromBase64Url(String base64Url)
{
logger.debug("fromBase64Url");
try{
return new String(java.util.Base64.getUrlDecoder().decode(base64Url), StandardCharsets.ISO_8859_1);
}catch (Exception e)
{
logger.error("fromBase64Url", e);
return "";
}
}

public static String base64ToHexa(String base64)
{
logger.debug("base64ToHexa");
try{
return Hex.toHexString(Base64.decode(base64));
}catch (Exception e)
{
logger.error("base64ToHexa", e);
return "";
}
}
}
Loading