How to use BouncyCastle in place of native crypto classes

505 views
Skip to first unread message

Shane

unread,
Apr 10, 2009, 11:43:38 AM4/10/09
to JetS3t Users
I'm developing an app which resides on the new Google App Engine for
Java environment. They enforce a class white list which prevents
access to native crypto classes. JetS3t tries to load these during an
S3 put operation so I'd like to use BouncyCastle (BC) for the
implementing classes. The only reference I've found is the
crypto.algorithm property.

Besides defining a BC algorithm and adding the BC library, what else
is needed?

Here's the latest exception:

org.jets3t.service.S3ServiceException: S3 PUT connection failed for '/
resized.jpg'
at
org.jets3t.service.impl.rest.httpclient.RestS3Service.performRequest
(RestS3Service.java:427)
at
org.jets3t.service.impl.rest.httpclient.RestS3Service.performRestPut
(RestS3Service.java:626)
at
org.jets3t.service.impl.rest.httpclient.RestS3Service.createObjectImpl
(RestS3Service.java:1100)
at org.jets3t.service.impl.rest.httpclient.RestS3Service.putObjectImpl
(RestS3Service.java:1050)
at org.jets3t.service.S3Service.putObject(S3Service.java:1232)
at org.jets3t.service.S3Service.putObject(S3Service.java:1257)
at com.digitalsanctum.angrygerbils.web.TransformServlet.saveToS3
(TransformServlet.java:91)
at com.digitalsanctum.angrygerbils.web.TransformServlet.service
(TransformServlet.java:66)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:806)
at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:
487)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter
(ServletHandler.java:1093)
at
com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter
(TransactionCleanupFilter.java:43)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter
(ServletHandler.java:1084)
at org.mortbay.jetty.servlet.ServletHandler.handle
(ServletHandler.java:360)
at org.mortbay.jetty.security.SecurityHandler.handle
(SecurityHandler.java:216)
at org.mortbay.jetty.servlet.SessionHandler.handle
(SessionHandler.java:181)
at org.mortbay.jetty.handler.ContextHandler.handle
(ContextHandler.java:712)
at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:
405)
at com.google.apphosting.utils.jetty.DevAppEngineWebAppContext.handle
(DevAppEngineWebAppContext.java:54)
at org.mortbay.jetty.handler.HandlerWrapper.handle
(HandlerWrapper.java:139)
at com.google.appengine.tools.development.JettyContainerService
$ApiProxyHandler.handle(JettyContainerService.java:306)
at org.mortbay.jetty.handler.HandlerWrapper.handle
(HandlerWrapper.java:139)
at org.mortbay.jetty.Server.handle(Server.java:313)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:
506)
at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete
(HttpConnection.java:830)
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:514)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:211)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:381)
at org.mortbay.io.nio.SelectChannelEndPoint.run
(SelectChannelEndPoint.java:396)
at org.mortbay.thread.BoundedThreadPool$PoolThread.run
(BoundedThreadPool.java:442)
Caused by: java.lang.ExceptionInInitializerError
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native
Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance
(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance
(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at java.lang.Class.newInstance0(Class.java:355)
at java.lang.Class.newInstance(Class.java:308)
at java.security.Provider$Service.newInstance(Provider.java:1221)
at javax.crypto.Mac.a(DashoA13*..)
at javax.crypto.Mac.init(DashoA13*..)
at org.jets3t.service.utils.ServiceUtils.signWithHmacSha1
(ServiceUtils.java:137)
at
org.jets3t.service.impl.rest.httpclient.RestS3Service.buildAuthorizationString
(RestS3Service.java:786)
at
org.jets3t.service.impl.rest.httpclient.RestS3Service.performRequest
(RestS3Service.java:278)
... 29 more
Caused by: java.security.AccessControlException: access denied
(java.lang.RuntimePermission loadLibrary.keychain)
at java.security.AccessControlContext.checkPermission
(AccessControlContext.java:323)
at java.security.AccessController.checkPermission
(AccessController.java:546)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:
532)
at com.google.appengine.tools.development.DevAppServerFactory
$CustomSecurityManager.checkPermission(DevAppServerFactory.java:76)
at java.lang.SecurityManager.checkLink(SecurityManager.java:818)
at java.lang.Runtime.loadLibrary0(Runtime.java:817)
at java.lang.System.loadLibrary(System.java:1030)
at com.apple.crypto.provider.HmacCore.<clinit>(HmacCore.java:26)
... 41 more

James Murty

unread,
Apr 10, 2009, 12:41:18 PM4/10/09
to jets3t...@googlegroups.com
I'm not familiar with Google's new Java App Engine support so my recommendations are just best-guesses.

If the issue is that Google App Engine (GAE) is preventing system-level security provider classes from loading, but will allow library-level security providers to work, you should be able to work around this issue by re-configuring your security providers.

Ideally you would configure your providers in some kind of GAE-specific "java.security" file, but you can also experiment by doing this directly in code. Either way, you should try removing the system-level security providers which cause exceptions, and add the Bouncy Castle provider in their place.

The following code will add the Bouncy Castle provider (BC) to your set of providers:

        Class bouncyCastleProviderClass =
            Class.forName("org.bouncycastle.jce.provider.BouncyCastleProvider");
        if (bouncyCastleProviderClass != null) {
            Provider bouncyCastleProvider = (Provider) bouncyCastleProviderClass
                .getConstructor(new Class[] {}).newInstance(new Object[] {});                       
            Security.addProvider(bouncyCastleProvider);
        }

You can list your providers like so:

        Provider[] providers = Security.getProviders();
        Provider p = null;
        for (int i = 0; i < providers.length; i++) {           
            p = providers[i];
            System.out.println("Provider: " + p.getName());
        }       

And remove any specific providers that cause exceptions by name like so:

        Security.removeProvider("Apple");


Presumably GAE has its own set of security providers to perform crypto functions? If so, removing the system-level providers that are explicitly disallowed may be enough to avoid these exceptions.

Hope this helps,
James

---
http://www.jamesmurty.com

Shane Witbeck

unread,
Apr 10, 2009, 1:05:25 PM4/10/09
to jets3t...@googlegroups.com
Thanks James. Your guidance is very helpful. Here's the latest:

java.security.AccessControlException: access denied (java.security.SecurityPermission removeProvider.Apple)

at java.security.AccessControlContext.checkPermission(AccessControlContext.java:323)

at java.security.AccessController.checkPermission(AccessController.java:546)

at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)

at com.google.appengine.tools.development.DevAppServerFactory$CustomSecurityManager.checkPermission(DevAppServerFactory.java:76)

at java.lang.SecurityManager.checkSecurityAccess(SecurityManager.java:1698)

at java.security.Security.check(Security.java:819)

at java.security.Security.removeProvider(Security.java:408)

at com.digitalsanctum.angrygerbils.web.TransformServlet.init(TransformServlet.java:49)

at javax.servlet.GenericServlet.init(GenericServlet.java:215)

at org.mortbay.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:433)

at org.mortbay.jetty.servlet.ServletHolder.getServlet(ServletHolder.java:342)

at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:463)

at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1093)

at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43)

at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1084)

at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:360)

at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)

at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)

at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:712)

at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:405)

at com.google.apphosting.utils.jetty.DevAppEngineWebAppContext.handle(DevAppEngineWebAppContext.java:54)

at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:139)

at com.google.appengine.tools.development.JettyContainerService$ApiProxyHandler.handle(JettyContainerService.java:306)

at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:139)

at org.mortbay.jetty.Server.handle(Server.java:313)

at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:506)

at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:830)

at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:514)

at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:211)

at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:381)

at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:396)

at org.mortbay.thread.BoundedThreadPool$PoolThread.run(BoundedThreadPool.java:442)



-Shane

James Murty

unread,
Apr 10, 2009, 1:17:37 PM4/10/09
to jets3t...@googlegroups.com
Hmm. The "Apple" provider is obviously specific to your system where you are running the GAE dev environment, and is not a part of GAE itself.

Given that you cannot remove providers in code, you will need to look for the "java.security" file where the providers are configured. Hopefully there is such a file for the GAE dev environment?

If there isn't a GAE-specific java.security file, you may need to edit your system-wide Java version. Be sure to make a backup before you do this, some changes could cause wide-ranging problems! The java.security file on my OSX machine is located at: /Library/Java/Home/lib/security/java.security

In the java.security file, look for the list of providers and try removing the Apple provider there. Here's what my default providers list looks like:

#
# List of providers and their preference orders (see above):
#
security.provider.1=sun.security.provider.Sun
security.provider.2=com.apple.crypto.provider.Apple
security.provider.3=sun.security.rsa.SunRsaSign
security.provider.4=com.sun.net.ssl.internal.ssl.Provider
security.provider.5=com.sun.crypto.provider.SunJCE
security.provider.6=sun.security.jgss.SunProvider
security.provider.7=com.sun.security.sasl.Provider

At this stage, it will probably be a matter of trial and error to work out which providers cause exceptions and which, if any, you can do without.

It is probably worth asking about configuring security providers on the GAE forums before you start messing with your whole Java setup, I am worried that following my naive advice may leave you with a broken system...

James
Reply all
Reply to author
Forward
0 new messages