0

I am implementing an OSGI bundle (using kura) to do some AES encryption. I added the third library javax.crypto directly in my bundle, here is the manifest:

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: AES
Bundle-SymbolicName: org.eclipse.kura.AES
Bundle-Version: 1.0.0.qualifier
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Import-Package: org.osgi.service.component;version="1.2.0",
 org.slf4j;version="1.7.21"
Service-Component: component.xml
Export-Package: org.eclipse.kura.AES.services
Bundle-ClassPath: .,
 lib/javax-crypto.jar

I am getting this error when I try the decryption:

java.lang.ClassCastException: com.sun.crypto.provider.AESCipher$General cannot be cast to javax.crypto.CipherSpi
        at javax.crypto.Cipher.getInstance(Cipher.java:166)
        at org.eclipse.kura.AES.services.AesServices.decrypt(AesServices.java:33)
        at org.eclipse.kura.AES.AES_Activator.activate(AES_Activator.java:19)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at org.eclipse.equinox.internal.ds.model.ServiceComponent.activate(ServiceComponent.java:235)
        at org.eclipse.equinox.internal.ds.model.ServiceComponentProp.activate(ServiceComponentProp.java:146)
        at org.eclipse.equinox.internal.ds.model.ServiceComponentProp.build(ServiceComponentProp.java:347)
        at org.eclipse.equinox.internal.ds.InstanceProcess.buildComponent(InstanceProcess.java:620)
        at org.eclipse.equinox.internal.ds.InstanceProcess.buildComponents(InstanceProcess.java:197)
        at org.eclipse.equinox.internal.ds.Resolver.buildNewlySatisfied(Resolver.java:473)
        at org.eclipse.equinox.internal.ds.Resolver.enableComponents(Resolver.java:217)
        at org.eclipse.equinox.internal.ds.SCRManager.performWork(SCRManager.java:816)
        at org.eclipse.equinox.internal.ds.SCRManager$QueuedJob.dispatch(SCRManager.java:783)
        at org.eclipse.equinox.internal.ds.WorkThread.run(WorkThread.java:89)
        at org.eclipse.equinox.internal.util.impl.tpt.threadpool.Executor.run(Executor.java:70)

I am using openjdk on my raspberry pi. I tried with oracle java but still got the same issue. Either I did not completly remove the openjdk or there is another cause that I am not able to identify. Any ideas?

sabrina2020
  • 2,102
  • 3
  • 25
  • 54

3 Answers3

1

The error you get is typical if the same class is resolved using different bundles.

I suspect that you embed the package javax.crypto into your bundle. So your bundle sees the internal class CipherSpi while bundles outside see the version from the jdk or another bundle.

The solution is to make sure you resolve such api packages from only one source. In your case it probably is enough to import the package javax.crypto and not embed the javax-crypto.jar. Instead you will then have to export the package from the jdk or install a bundle that contains it.

The general rule is to never embed a package that might be visisible through the api you expose to the outside world.

Christian Schneider
  • 19,420
  • 2
  • 39
  • 64
1

As mentioned in other answers, you must be very careful to avoid exposing internal packages through your API. In this case the manifest and stack trace that you've provided point at a number of severe and fatal issues.

The supplied manifest defines the following Import-Package statement.

Import-Package: org.osgi.service.component;version="1.2.0",
    org.slf4j;version="1.7.21"

This is immediately suspicious for several reasons:

  1. The stack trace proves that you want to use AES through javax.crypto, but do not import the package. Instead you have repackaged the API in your bundle, but not an implementation. If you want to use the JDK implementation then you need to share a class space with it.

  2. You import the Declarative Services API (org.osgi.service.component) it is unusual to do this as DS components are usually POJOs.

  3. Your imports all use single versions, not version ranges. In OSGi parlance this means that your imports are from version X up to infinity. This is an anti-pattern.

I surmise from these issues that your manifest is hand-created. I strongly recommend that you use a tool ((such as bnd) to generate your manifest as it will stop you from making many of these mistakes.

Tim Ward
  • 1,169
  • 8
  • 9
1

For my case issue is resolved after adding,

@PowerMockIgnore({"javax.crypto.*"}) at class level

Here you can find git link for issue

Clemsang
  • 5,053
  • 3
  • 23
  • 41