[SOLVED] ZWave - invoking bouncy castle crypto from junit/main fails with error

I’ve been working on S2 support. Most of the crypto is supported in the JDK, but occasionally I have to use the bouncy castle (BC) lib. No problem, I see it’s already used elsewhere within OH. All is well when running OH with app.bndrun from eclipse, BC gets invoked correctly, I can run pairing tests and make progress.

But, while working in the zwave project in eclipse or maven, if I try to invoke any BC code directly (as in junit or a main method), I get the following error:

java.lang.SecurityException: Security Invalid signature file digest for Manifest main attributes

I understand the error message. The bouncy castle jar is a signed jar. The error means the jar was modified (or exploded) so the signature validation fails. The question is… why does it fail only in this scenario?

The same error occurs if I run mvn test on the zwave project from the command line. My new test case CmacTest.test fails with the error above, all other test cases pass.

I’m confident the jar in my local maven cache is valid as I can create a new maven project in the OH eclipse, add BC to the pom.xml, and invoke BC code just fine. This is how I’ve been doing BC development for now. I copy the code to the alternate project, write/debug/test, copy it back to the zwave project.

Any ideas on how to resolve this? It would certainly speed things up and I’d need to add test cases.

The failing test case is in my zwave fork on the s2-testcase branch at dbadia/org.openhab.binding.zwave at s2-testcase (github.com)
to reproduce just checkout that branch, run mvn test and you should get

[ERROR] CmacTest.test:26 » Security Invalid signature file digest for Manifest main attributes
[ERROR] Tests run: 306, Failures: 0, Errors: 1, Skipped: 8

FWIW I’m using zulu17.32.13-ca-jdk17.0.2-win_x64 and apache-maven-3.9.5.

TIA!

I’m interested in your work, but can’t help. However, I think this post might be see more “action” under a pink Development category. I’m also going violate a guideline by pinging someone @splatch that I think might help :wink: As a regular, I have read a number of his helpful and insightful posts.

A lot depends if on basic fact of parallel build - if you use concurrent builds and several modules are built at the same time you might face situation where test classpath includes a JAR file which is not there yet or it is being rewritten at the time of the test. The reliability of parallel builds in Maven is fair, but a lot depends on actual build plugins. I am not certain if i.e. karaf-maven-plugin is thread safe. Probably due to heavy lifting it does (it actually embeds some portions of Karaf which serves openHAB core), it might not behave well with files being rolled during its execution.

I bring above because error message you see is related to JAR files. Knowing stack trace for this error might help us finding place which is guilty of rising it. I’d say that issue is not about BC itself, but other JARs which are written as a part of your IDE/build and which are pulled into junit test execution. I can’t comment on actual crypto part, but eventual inconsistencies in signature calculation would be raised within your code (having org.openhab at the top of the stack trace).

1 Like

Thanks. Perhaps I’ll violate a rule as well and cross-post if I can’t find a solution here :slight_smile: Off to OH forum jail we go!!!

Thanks for the insights. I’ll look into the concurrent builds a little more.
Here is the stack trace. Just points back to my test case which is triggering code, which in turn triggers the dynamic classloading of the BC jar

java.lang.SecurityException: Invalid signature file digest for Manifest main attributes
at java.base/sun.security.util.SignatureFileVerifier.processImpl(SignatureFileVerifier.java:340)
at java.base/sun.security.util.SignatureFileVerifier.process(SignatureFileVerifier.java:282)
at java.base/java.util.jar.JarVerifier.processEntry(JarVerifier.java:321)
at java.base/java.util.jar.JarVerifier.update(JarVerifier.java:234)
at java.base/java.util.jar.JarFile.initializeVerifier(JarFile.java:762)
at java.base/java.util.jar.JarFile.ensureInitialization(JarFile.java:1033)
at java.base/java.util.jar.JavaUtilJarAccessImpl.ensureInitialization(JavaUtilJarAccessImpl.java:72)
at java.base/jdk.internal.loader.URLClassPath$JarLoader$2.getManifest(URLClassPath.java:883)
at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:848)
at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:760)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:681)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:639)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
at org.openhab.binding.zwave.internal.protocol.security.crypto.ZWaveCryptoOperations.performAesCmac(ZWaveCryptoOperations.java:234)
at org.openhab.binding.zwave.internal.protocol.commandclass.security.CmacTest.test(CmacTest.java:26)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)

I tried enabling verbose classloading, but that gave no relevant output as the BC classes aren’t actually being loaded.

Problem comes from that line indeed and it is either javax.crypto.Mac class or org.bouncycastle.jce.provider.BouncyCastleProvider. I doubt it is first one, so as you said its likely related to BC… yet I can’t think of reason why BC would be causing this issue. Given that you have reproducible issue with different environments try removing bouncycastle dependencies from your local maven repository. This should force re-downloading of these and solve issues with eventual CRC inconsistencies of JAR file itself.

Ok, so I double checked the bouncy castle jar in my local maven repo with jarsigner, it passes just fine. This combined with the fact that I have a non-OH project in the same eclipse workspace invoking the BC code got me thinking… what if the signature failure isn’t on the BC jar at all?

Pointed my debugger to the JRE jar signing code and found out that it’s actually org.openhab.core.io.jetty.certificate-4.2.0-SNAPSHOT.jar that is failing the signature check. Apparently, the owner of that jar decided to bundle the BC classes inside of it :frowning: .

I’ll start another thread (or maybe a bug report?) about that.
Removing the fat jar logic from the io.jetty.certificate pom.xml and running a local install cleared up the problem.