I generate UUIDs, and valid them against a Regex in my code; I just ran into problems that confused me
Here is the code that generates UUIDs (in a mongodb context)
import java.util.UUID;
... ...
Document setOnInsert = new Document(Params.sender, UUID.randomUUID())
.append(Params.userDevice, userDevice)
.append(Params.hostId,"");
This is the code of validating an UUID; I had copied the Regex from this post
static final Pattern UUID = Pattern.compile("([0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12})");
public static boolean isUUID(String uuid){
if(uuid == null){
return false;
}else{
return UUID.matcher(uuid).matches();
}
}
and below are the 2 UUIDs that I have problems with
aa4aaa2c-c6ca-d5f5-b8b2-0b5c78ee2cb7
b24dd64c-de6b-5bf6-6283-aa2167cc93a7
These two UUIDs had been generated by the code mentioned above; the validating method (isUUID()) judged them as invalid in my latest debug; yet I posted these UUIDs to an online validator , and it says ok
This is my system information
wjz#bj:~$ java -version
java version "1.8.0_121"
Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)
wjz#bj:~$
wjz#bj:~$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 16.04.1 LTS
Release: 16.04
Codename: xenial
wjz#bj:~$
Some background: I had been working on jdk 1.8.0_111; these UUIDs had been generated then, and had no problems. then I upgraded to 1.8.0_121 today, and run into this problem...
So my question is: Whether the above mentioned UUIDs are correct or wrong? who to believe, the generator or the validation
My suggestion is, do not reinvent the wheel.
Basically, if you generate the ids with UUID.randomUUID(), there is no need to validate them.
If you are anyway curious that they might get manipulated manually.
You can just use UUID.fromString(yourUUID) and catch the IllegalArgumentExcepetion and the NumberFormatException that might be thrown.
Throws IllegalArgumentExcepetion:
If name does not conform to the string representation as described in toString()
Furthermore, you can check behind, if the UUID got converted correctly with
UUID id = UUID.fromString(yourUUID);
if(id.toString().equals(yourUUID){
//success
}
You can use UUID.randomUUID() which will generate a valid UUID, you dont need the regx.
Had a look at some other SO answers, other languages ..., and here is a pure Java solution which handles v4 cases (as used by default in Java 8):
UUID myUuid = UUID.fromString(uuidStr); // Step 1, throws errors !
... myUuid.version() == 4 // Step 2, check for the version you desire
See: https://docs.oracle.com/javase/9/docs/api/java/util/UUID.html#version--
Here is an example of a perfectly valid UUID string but version 1:
public static void main(final String[] args) {
final UUID myUuid = UUID.fromString("61614667-d279-11e7-a5ac-f941ac8dfc39");
System.out.println(myUuid.version()); // Prints 1, not 4 !
}
To try out more v4 UUIDs use UUID.randomUUID() or online:
https://www.uuidgenerator.net/version4
Note: UUID.randomUUID() of Java will work well see How good is Java's UUID.randomUUID?
Security note:
Static factory to retrieve a type 4 (pseudo randomly generated) UUID.
The UUID is generated using a cryptographically strong pseudo random
number generator
There are several aspects:
Total UUID length
Characters used
Valid size of groups (between dashes)
Lower case or upper case
Valid version
Valid variant
Nil allowed
To have a code example, see the UUID validator implementation I recently added to Apache Commons Validator. It's not yet been merged, but you can vote for it here: https://github.com/apache/commons-validator/pull/68
Related
I am upgrading a legacy application from Java 8 to Java 11 (Oracle Version) and having issue while getting the corbaloc reference.
I have read below
articles here and here that specifies that CORBA support is removed form JAVA 11 and with the help of Glassfish Corba I can use the packages again.
The issue I am facing is with below function call
((com.sun.corba.se.spi.orb.ORB) orb.orb()).register_initial_reference(idStr, ref);
In Eclipse the Error is ORB cannot be resolved to a type.
As I know we should not use any package related to sun but this is old code and not sure about the replacement.
I have changed the package from com.sun.corba.se.spi.orb.ORB to org.omg.CORBA.ORB but the method register_initial_reference(idStr, ref) is not found.
I am not sure what needs to be changed or any example that will help to get the possible alternate change. Any guide or help is highly appreciated. Even I have almost NO idea about CORBA and very less examples are available.
Below is the function that starts the service
final byte[] id = "\u00ffPNS_Service\u0000PNS_Study".getBytes();
final String idStr = new String(id);
final Policy[] policies = new Policy[] {
root.create_lifespan_policy(LifespanPolicyValue.PERSISTENT) };
final POA poa = root.create_POA("PNS_Service",root.the_POAManager(),policies);
poa.the_POAManager().activate();
poa.activate_object(studyService);
final org.omg.CORBA.Object ref = poa.servant_to_reference(studyService);
((com.sun.corba.se.spi.orb.ORB) orb.orb()).register_initial_reference(idStr , ref);```
I am trying to create a deterministic UUID in java to generate same UUID as we have in our ruby codebase but unable to do so and need help.
#ruby code using uuidtools gem (version: 2.1.5)
# UUIDTools::UUID_OID_NAMESPACE is UUID created for string "6ba7b812-9dad-11d1-80b4-00c04fd430c8".
# github link for gem: https://github.com/sporkmonger/uuidtools
UUIDTools::UUID.md5_create(UUIDTools::UUID_OID_NAMESPACE, "tej").to_s
## OUTPUT: d7d1d470-3585-589e-cf25-d2bcb54c7ba2
// java code using NameBasedGenerator from java-uuid-generator-3.1.4.
MessageDigest md = MessageDigest.getInstance("MD5");
NameBasedGenerator nameBasedGenerator = new NameBasedGenerator(NameBasedGenerator.NAMESPACE_OID, md, UUIDType.NAME_BASED_MD5);
nameBasedGenerator.generate("tej").toString();
// OUTPUT: d7d1d470-3585-389e-8f25-d2bcb54c7ba2
// java code using uuid-creator-4.6.1
UUID uuid = UuidCreator.getNameBasedMd5(UuidNamespace.NAMESPACE_ISO_OID, "tej");
uuid.toString();
// OUTPUT: d7d1d470-3585-389e-8f25-d2bcb54c7ba2
I tried with couple of other strings as well and every time first character of either 3rd or 4th part (or both) of the output is different in java and ruby. Is there any issue in any of these libs (suspecting it to be in ruby) or am I doing something wrong, I mean should I change version of java lib I am using (can't make any change in ruby and also with java it will be difficult to downgrade as this lib would already be imported as part of jackson but i guess upgrade should not be an issue, hopefully).
Have referred above suggestions from:
What namespace does the JDK use to generate a UUID with nameUUIDFromBytes?
What I saw as difference in the UUIDs generated using ruby and java libs was that the variant output was different for the two. But that looks to be more of the implementation of variant method in the two libs/languages (in ruby we are returning 4 when the variant is 2, I assume this wouldn't have impact on the UUID generation part). Please find the implementation of variant method below:
###RUBY
##
# Returns the UUID variant.
# Possible values:
# 0b000 - Reserved, NCS backward compatibility.
# 0b100 - The variant specified in this document.
# 0b110 - Reserved, Microsoft Corporation backward compatibility.
# 0b111 - Reserved for future definition.
def variant
variant_raw = (clock_seq_hi_and_reserved >> 5)
result = nil
if (variant_raw >> 2) == 0
result = 0x000
elsif (variant_raw >> 1) == 2
result = 0x100
else
result = variant_raw
end
return (result >> 6)
end
//JAVA:
/**
* The variant number associated with this {#code UUID}. The variant
* number describes the layout of the {#code UUID}.
*
* The variant number has the following meaning:
* <ul>
* <li>0 Reserved for NCS backward compatibility
* <li>2 IETF RFC 4122
* (Leach-Salz), used by this class
* <li>6 Reserved, Microsoft Corporation backward compatibility
* <li>7 Reserved for future definition
* </ul>
*
* #return The variant number of this {#code UUID}
*/
public int variant() {
// This field is composed of a varying number of bits.
// 0 - - Reserved for NCS backward compatibility
// 1 0 - The IETF aka Leach-Salz variant (used by this class)
// 1 1 0 Reserved, Microsoft backward compatibility
// 1 1 1 Reserved for future definition.
return (int) ((leastSigBits >>> (64 - (leastSigBits >>> 62)))
& (leastSigBits >> 63));
}
On Linux, uuidgen generates the same UUID as the Java libraries generate:
$ uuidgen --namespace #oid --md5 --name "tej"
d7d1d470-3585-389e-8f25-d2bcb54c7ba2
Python also generates the same UUID:
>>> import uuid
>>> uuid.uuid3(uuid.NAMESPACE_OID, 'tej')
UUID('d7d1d470-3585-389e-8f25-d2bcb54c7ba2')
The same for Javascript:
> require('uuid').v3('tej', '6ba7b812-9dad-11d1-80b4-00c04fd430c8')
'd7d1d470-3585-389e-8f25-d2bcb54c7ba2'
You are not doing anything wrong. The ruby library used is returning wrong values. I think you should find another lib for ruby.
I am trying to read a PKCS#8 private key which looks like following:
key.k8 --> (Sample key. Passphrase - 123456):
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIFLTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQILbKY9hPxYSoCAggA
MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBCvaGt2Hmm2NpHpxbLvHKyOBIIE
0IQ7dVrAGXLZl0exYIvyxLAu6zO00jL6b3sb/agTcCFOz8JU6fBanxY0d5aYO4Dn
mynQG7BoljU470s0zIwW/wk0MmdUFl4nXWBX/4qnG0sZqZ9KZ7I8R/WrBkmpX8C/
4pjdVhu8Ht8dfOYbkbjMBTohDJz8vJ0QwDIXi9yFjjef+QjwrFOl6kAeDJFVMGqc
s7K/wOnhsL1XxfW9uTulPiZh5YTZKcatMkeGDR7c+cg5I+Mutim92diWuCekhNoa
uvhUy1M3cbs7Azp1Mhz+V0CDKklI95EvN4u23WhiJPCjAofC/e45/heOP3Dwm7WZ
zHEY1C/X8PsTl6MEEIF3ZJP+4Vr0corAs1L2FqE6oOng8dFFYmF5eRyBx6bxFd05
iYbfOH24/b3qtFKPC689kGEd0gWp1dwES35SNNK+cJqVRTjgI0oKhOai3rhbGnmp
tx4+JqploQgTorj4w9asbtZ/qZA2mYSSR/Q64SHv7LfoUCI9bgx73MqRQBgvI5yS
b4BoFBnuEgOduZLaGKGjKVW3m5/q8oiDAaspcSLCJMIrdOTYWJB+7mfxX4Xy0vEe
5m2jXpSLQmrfjgpSTpHDKi/3b6OzKOcHjSFBf8IoiHuLc5DVvLECzDUxxaMrTZ71
0YXvEPwl2R9BzEANwwR9ghJvFg1Be/d5W/WA1Efe6cNQNBlmErxD6l+4KDUgGjTr
Aaksp9SZAv8uQAsg7C57NFHpTA5Hznr5JctL+WlO+Gk0cAV6i4Py3kA6EcfatsnS
PqP2KbxT+rb2ATMUZqgWc20QvDt6j0CTA1BuVD1PNhnAUFvb2ocyEEXOra22DPPS
UPu6jirSIyFcjqFjJ9A1FD9L4/UuX2UkDSLqblFlYB1+G55KZp+EKz8SZoN5qXy1
LyMtnacEP5OtRDrOjopzVNiuV1Uv63M9QVi1hZlVLJEomgjWuvuyEuIwDaY2uryW
vx+jJEZyySFkb1JwAbrm+p6sCTFnbQ/URKC2cit/FJyKqNim6VQvGL8Sez34qV3z
D13QJgTZfsy+BaZoaQ6cJTXtJ8cN0IcQciOiDNBKMW66zO6ujS8G+KNviNQypDm6
h4sOgjMqLaZ4ezPEdNj/gaxV7Y15nVRu0re8dVkaa5t9ft/sh6A+yeTD5tS5hHkf
NI7uJPTaTXVoz7xq2PAJUTWujMLMZKtmNOzNqYvxWRy3tCOFobBQkMxqEBEwHd+x
SA+gFcJKJ+aNfCGZJ5fFr8rNlhtOF6uMwOAlfiUlP/pCUDUCKPjZVj4K95yNc8Io
jSZSPb5tGPe0HqXgc6IAfQarlUZt90oVtzL0OfOfTxe1bEzS2ccNadbx/6vjLBc4
q5UuUBppl3rXpbuZ7J1Rp3n2byF4APxFdT2LHKq+MYMfWUToau/TCMT4lFIM9tM8
7TuuyUT2PKzf/xlsl4iScw96z9xxGPQrXn7IA2W5iL+0eCLztJdjNRX1FisdfIBL
PraOVlmF8jHKbFdRZ8Yi8pApbQjvHi24g7dX7u/cq1FH/VE+nJ0O8YVCYVDw13CW
h0p7yD7BuB0R+0WnR0yvkp30vK4/rtCB+Ob8bH/+HvAZrAU5X8jq/wsQbLkrLHZV
6A6GGfX8+hy5AoaXsH1BHnMyXkaF6Mv29z8JcslDJxX/
-----END ENCRYPTED PRIVATE KEY-----
Following code is being used to parse the private key:
InputStream privateKeyInputStream = getPrivateKeyInputStream(); // reads the key file from classpath and share as DataStream
logger.info("InputStreamExists --> {} ", privateKeyInputStream.available());
PEMParser pemParser = new PEMParser(new InputStreamReader(privateKeyInputStream));
Object pemObject = pemParser.readObject();
if (pemObject instanceof PKCS8EncryptedPrivateKeyInfo) {
// Handle the case where the private key is encrypted.
PKCS8EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = (PKCS8EncryptedPrivateKeyInfo) pemObject;
InputDecryptorProvider pkcs8Prov =
new JceOpenSSLPKCS8DecryptorProviderBuilder().build(passphrase.toCharArray());
privateKeyInfo = encryptedPrivateKeyInfo.decryptPrivateKeyInfo(pkcs8Prov); // fails here
}
InputStream resourceAsStream = null;
if ("local".equals(privateKeyMode)) {
resourceAsStream = this.getClass().getResourceAsStream(privateKeyPath);
} else {
File keyFile = new File(privateKeyPath);
logger.info(
"Key file found in {} mode. FileName : {}, Exists : {}",
privateKeyMode,
keyFile.getName(),
keyFile.exists());
try {
resourceAsStream = new DataInputStream(new FileInputStream(keyFile));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
When I am running this code through intelliJ on windows, the code works fine but when I run it through docker container I am getting following exception:
org.bouncycastle.pkcs.PKCSException: unable to read encrypted data: failed to construct sequence from byte[]: Extra data detected in stream
snowflake-report-sync | at org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo.decryptPrivateKeyInfo(Unknown Source) ~[bcpkix-jdk15on-1.64.jar!/:1.64.00.0]
snowflake-report-sync | at com.optum.snowflakereportsync.configuration.SnowFlakeConfig.getPrivateKey(SnowFlakeConfig.java:103) ~[classes!/:na]
snowflake-report-sync | at com.optum.snowflakereportsync.configuration.SnowFlakeConfig.getConnectionProperties(SnowFlakeConfig.java:67) ~[classes!/:na]
Following is Dockerfile used:
FROM adoptopenjdk/openjdk11-openj9:latest
COPY build/libs/snowflake-report-sync-*.jar snowflake-report-sync.jar
RUN mkdir /encryption-keys
COPY encryption-keys/ /encryption-keys/ #keys are picked from docker filesystem when running in container
EXPOSE 8080
CMD java -Dcom.sun.management.jmxremote -noverify ${JAVA_OPTS} -jar snowflake-report-sync.jar
Options tried:
Ensured that key file is being read while running in container. Logger "InputStreamExists --> {}" gives number of bytes
Ran dos2unix on key.k8 just to make sure there are no Window's "^M" characters which be could be causing issue as container is linux one : FROM adoptopenjdk/openjdk11-openj9:latest
Not sure what I am doing wrong but any help or pointers would be appreciated.
Like #Bragolgirith suspected, BouncyCastle seems to have problems with OpenJ9. I guess it is not a Docker issue, because I can reproduce it on GitHub Actions, too. It is also not limited to BouncyCastle 1.64 or 1.70, it happens in both versions. It also happens on OpenJ9 JDK 11, 14, 17 on Windows, MacOS and Linux, but for the same matrix of Java and OS versions it works on Adopt-Hotspot and Zulu.
Here is an example Maven project and a failed matrix build. So if you select another JVM type, you should be fine. I know that #Bragolgirith already suggested that, but I wanted to make the problem reproducible for everyone and also provide an MCVE, in case someone wants to open a BC or OpenJ9 issue.
P.S.: It is also not a character set issue with the InputStreamReader. This build fails exactly the same as before after I changed the constructor call.
Update: I have created BC-Java issue #1099. Let's see what the maintainers can say about this.
Update 2: The solution to your problem is to explicitly set the security provider to BC for your input decryptor provider. Thanks to David Hook for his helpful comment in #1099.
BouncyCastleProvider securityProvider = new BouncyCastleProvider();
Security.addProvider(securityProvider);
// (...)
InputDecryptorProvider pkcs8Prov = new JceOpenSSLPKCS8DecryptorProviderBuilder()
// Explicitly setting security provider helps to avoid ambiguities
// which otherwise can cause problems, e.g. on OpenJ9 JVMs
.setProvider(securityProvider)
.build(passphrase.toCharArray());
See this commit and the corresponding build, now passing on all platforms, Java versions and JVM types (including OpenJ9).
Because #Bragolgirith mentioned it in his answer: If you want to avoid the explicit new JceOpenSSLPKCS8DecryptorProviderBuilder().setProvider(securityProvider), the call Security.insertProviderAt(securityProvider, 1) instead of simply Security.addProvider(securityProvider) would in this case also solve the problem. But this holds true only as long as no other part of your code or any third-party library sets another provider to position 1 afterwards, as explained in the Javadoc. So maybe it is not a good idea to rely on that.
Edit:
On second thought, when creating the JceOpenSSLPKCS8DecryptorProviderBuilder, you're not explicitly specifying the provider:
new JceOpenSSLPKCS8DecryptorProviderBuilder()
.setProvider(BouncyCastleProvider.PROVIDER_NAME) // add this line
.build(passphrase.toCharArray());
It seems OpenJ9 uses a different provider/algo selection mechanism and selects the SunJCE's AESCipher class as CipherSpi by default, while Hotspot selects BouncyCastleProvider's AES class.
Explicitly specifying the provider should work in all cases.
Alternatively, when adding the BouncyCastleProvider you could insert it at the first preferred position (i.e. Security.insertProviderAt(new BouncyCastleProvider(), 1) instead of Security.addProvider(new BouncyCastleProvider())) so that it gets selected.
(It's still unclear to me why the provider selection mechanism differs between the different JVMs.)
Original post:
I've managed to reproduce the issue and at this point I'd say it's an incompatibility issue with the OpenJ9 JVM.
Starting from a Hotspot base image instead, e.g.
FROM adoptopenjdk:11-jre-hotspot
makes the code work.
(Not yet entirely sure whether the fault lies with the Docker image itself, the OpenJ9 JVM or BouncyCastle)
What am I doing?
I am writing a data analysis program in Java which relies on R´s arulesViz library to mine association rules.
What do I want?
My purpose is to store the rules in a String variable in Java so that I can process them later.
How does it work?
The code works using a combination of String.format and eval Java and RJava instructions respectively, being its behavior summarized as:
Given properly formatted Java data structures, creates a data frame in R.
Formats the recently created data frame into a transaction list using the arules library.
Runs the apriori algorithm with the transaction list and some necessary values passed as parameter.
Reorders the generated association rules.
Given that the association rules cannot be printed, they are written to the standard output with R´s write method, capture the output and store it in a variable. We have converted the association rules into a string variable.
We return the string.
The code is the following:
// Step 1
Rutils.rengine.eval("dataFrame <- data.frame(as.factor(c(\"Red\", \"Blue\", \"Yellow\", \"Blue\", \"Yellow\")), as.factor(c(\"Big\", \"Small\", \"Small\", \"Big\", \"Tiny\")), as.factor(c(\"Heavy\", \"Light\", \"Light\", \"Heavy\", \"Heavy\")))");
//Step 2
Rutils.rengine.eval("transList <- as(dataFrame, 'transactions')");
//Step 3
Rutils.rengine.eval(String.format("info <- apriori(transList, parameter = list(supp = %f, conf = %f, maxlen = 2))", supportThreshold, confidenceThreshold));
// Step 4
Rutils.rengine.eval("orderedRules <- sort(info, by = c('count', 'lift'), order = FALSE)");
// Step 5
REXP res = Rutils.rengine.eval("rulesAsString <- paste(capture.output(write(orderedRules, file = stdout(), sep = ',', quote = TRUE, row.names = FALSE, col.names = FALSE)), collapse='\n')");
// Step 6
return res.asString().replaceAll("'", "");
What´s wrong?
Running the code in Linux Will work perfectly, but when I try to run it in Windows, I get the following error referring to the return line:
Exception in thread "main" java.lang.NullPointerException
This is a common error I have whenever the R code generates a null result and passes it to Java. There´s no way to syntax check the R code inside Java, so whenever it´s wrong, this error message appears.
However, when I run the R code in brackets in the R command line in Windows, it works flawlessly, so both the syntax and the data flow are OK.
Technical information
In Linux, I am using R with OpenJDK 10.
In Windows, I am currently using Oracle´s latest JDK release, but trying to run the program with OpenJDK 12 for Windows does not solve anything.
Everything is 64 bits.
The IDE used in both operating systems is IntelliJ IDEA 2019.
Screenshots
Linux run configuration:
Windows run configuration:
I have a java application that uses jna to call a 64 bit third party DLL to communicate with scanners (with native 64 bit drivers). I am receiving an invalid memory access error with the combination of windows 10 / java11 / jna that I do not receive with any other combination.
This code works fine on all the following without errors:
Windows 7 / 64 bit java 8 runtime
Windows 7 / 64 bit java 11 runtime
Windows 10 / 64 bit java 8 runtime
I am using latest and greatest jna (5.3.1) and have tried older versions as well, with the same result.
/* Open Scanner */
EZT.TWAIN_SetHideUI(true);
if (EZT.TWAIN_GetSourceList()) {
if (!EZT.TWAIN_OpenDefaultSource()) {
throw new RuntimeException("Cannot open scanner");
}
}
/* Retrieve scanner capabilities for resolution */
int hcon = EZT.TWAIN_Get(EZLibrary.ICAP_XRESOLUTION);
if (hcon != 0) {
int resolutions[] = new int[EZT.CONTAINER_ItemCount(hcon)];
...
}
.....
private interface EZLibrary extends Library {
int ICAP_XRESOLUTION = 4376;
void TWAIN_SetHideUI(boolean bHide);
boolean TWAIN_GetSourceList();
boolean TWAIN_OpenDefaultSource();
int TWAIN_Get(int uCap);
int CONTAINER_ItemCount(int hcon);
}
The call to "EZT.CONTAINER_ItemCount(hcon)" in this example returns an Invalid Memory Access Error. However, when this code is a part of my larger application and not this sample application, the same code sequence throws the Invalid Memory access error up higher on "EZT.TWAIN_OpenDefaultSource()".
So, in summary:
windows 7 / java 8 : as expected results
windows 7 / java 11: as expected results
windows 10 / java 8: as expected results
windows 10 / java 11:
java.lang.Error: Invalid memory access
at com.sun.jna.Native.invokeInt(Native Method)
at com.sun.jna.Function.invoke(Function.java:426)
at com.sun.jna.Function.invoke(Function.java:361)
at com.sun.jna.Library$Handler.invoke(Library.java:265)
at com.sun.jna.Native$3.invoke(Native.java:1202)
at $Proxy0.CONTAINER_ItemCount(Unknown Source)
My question becomes is there an issue with JNA with win 10 / java 11 or is it something in the third party code, or something I'm doing wrong?
I did end up finding a solution for this.
I am not entirely sure why, but for 64 bit my JNA implementation needed:
Long TWAIN_Get(int uCap);
Long TWAIN_Acquire(int hwndApp);
With 32 bit it needed to be:
Integer TWAIN_Get(int uCap);
Integer TWAIN_Acquire(int hwndApp);
So to handle both I just use:
Number hcon = EZT.TWAIN_Get(EZTwainPro.ICAP_XRESOLUTION);
Doing this resolved the invalid memory access. I know it is because of the int returned was an unsigned int, but I am not entirely sure why the "long" implementation only works on 64 bit and not 32 bit runtimes. It has to be different in order to have both work. Also, the "long" implementation was only needed for win10, not win7, but it works for win7 too.