Faster RSA Ciphers on JRuby

When most people think about Lookout, they rarely consider more software than what is available in the Android or iOS App Stores. But truth be told, the vast majority of what powers Lookout, and in fact makes us Lookout, is a very large set of backend web and data services offloading a tremendous amount of work from mobile clients themselves. The platform powering a non-trivial amount of this backend infrastructure is JRuby.

The JRuby runtime is compelling for a number of reasons, one of the most often touted is performance. Like many users we’ve generally seen good performance from JRuby, so imagine our surprise when we found ponderously slow performance in some of our OpenSSL operations.

Despite generally positive Ruby performance in JRuby, overall performance is still tied to the capabilities of the JVM itself. In the case of OpenSSL operations, what’s really being compared is the performance of Java’s SSL library versus the openssl’s C library. Unfortunately, for RSA-specific operations, Java has some slower math operations under the covers. For example, here’s some benchmark code using RSA ciphers for signing/signature verification/encryption/decription on MRI versus JRuby 1.7.21:

$ ruby2.1 -v benchmark.rb
ruby 2.1.2p95 (2014-05-08) [x86_64-linux-gnu]
                        user     system      total        real
sign                9.710000   0.000000   9.710000 (  9.706266)
verify              0.150000   0.000000   0.150000 (  0.158150)
encrypt             0.170000   0.000000   0.170000 (  0.167504)
decrypt             9.720000   0.000000   9.720000 (  9.716763)

$ ruby -I benchmark.rb
jruby 1.7.21 (1.9.3p551) 2015-07-07 a741a82 on OpenJDK 64-Bit Server VM
1.7.0_79-b14 +jit [linux-amd64]

                        user     system      total        real
sign               45.600000   0.230000  45.830000 ( 45.451000)
verify              0.950000   0.000000   0.950000 (  0.810000)
encrypt             0.790000   0.060000   0.850000 (  0.815000)
decrypt            45.280000   0.080000  45.360000 ( 45.257000)

Signing and decryption operations in JRuby are 5x slower than their counter-parts in MRI!

Fortunately, this is a known problem and our colleagues at Square have published jnagmp and bouncycastle-rsa which provides some faster math calls to the JVM, significantly improving the performance of RSA operations on the JVM.

Today we’re releasing a small gem called fast-rsa-engine which we’ve written to incorporate Square’s “bouncycastle-rsa” into the jruby-openssl library.

Revisiting that same benchmark from above with fast-rsa-engine loaded into the JRuby runtime:

$ ruby -v benchmark.rb
jruby 1.7.21 (1.9.3p551) 2015-07-07 a741a82 on OpenJDK 64-Bit Server VM
1.7.0_79-b14 +jit [linux-amd64]
                        user     system      total        real
sign               11.160000   0.000000  11.160000 ( 11.055000)
verify              0.450000   0.010000   0.460000 (  0.324000)
encrypt             0.420000   0.050000   0.470000 (  0.343000)
decrypt            11.050000   0.080000  11.130000 ( 10.972000)

Instead of 5x slower, it’s now only 1.2x slower, which is a big speed up!

These improvements exist as a stand-alone gem currently, and may in the future be incorporated into jruby-openssl. For now however, you can install the gem from with gem install fast-rsa-engine

If you’re interested in talking about JRuby, OpenSSL or fun on the JVM, come talk to us at JRubyConf EU 2015!

posted in: · · · ·

We're back! Join Lookout at JRubyConf EU 2015!

Last year, around this time, we were thrilled to be presenting at JRubyConf EU 2014 and as luck would have it: JRubyConf EU is back, and so is Lookout! Lookout engineer R. Tyler Croy will be presenting a talk on JRuby/Gradle at this year’s conference.

Tyler’s talk “JRuby/Gradle: Bringing Java powertools to Ruby” will be the second session of the day, and according to the abstract:

This talk will introduce the JRuby/Gradle project, an effort to combine the very best in Java tooling with the Ruby world, providing top-notch integration for JRuby devs. During the talk we will cover the motivations of the jruby-gradle project and describe how it helps bridge the gap between Java and Ruby. By combining the flexibility of JRuby with the power of Gradle, we can breathe new life into JRuby, opening it up to an even broader audience than before.

Another special part of this year’s JRubyConf EU is that there will be a few of Lookout’s Europe-based hackers, including frequent JRuby contributor Christian Meier, in attendance. JRuby users may recognize his name, as he has built some of the most common tools of every JRuby toolchain, such as jbundler.

JRubyConf EU will be held as part of Eurucamp on July 31st in Potsdam, southwest of Berlin. Please join us to talk about Ruby, JRuby, Lookout, mobile security and scalable systems!

posted in: · · · ·

Cassandra Health Checks: can A see B and C?

We recently ran into a problem during a rolling restart where one node was up, but couldn’t see the other nodes. While a restart solved the problem pretty easily, it took us a lot of time to figure out what was going wrong, especially since all of our current monitoring focused primarily on the health of a single node.

What we were missing was that a node is only really “healthy” if it can answer some queries itself as well as talk to every other node in the cluster. This isn’t easy for Cassandra since nodes can come and go.

What we found was that creating a keyspace with a replication factor equal to the number of nodes in the cluster, then doing a SELECT on that with CL_ALL will guarantee that every node is reachable from the node performing the query. So, we wrote some code to do just that.

Our new open source Cassandra Health Check automatically creates and/or recreates a keyspace named ‘healthcheck’ that has a replication factor equal to the number of nodes in the cluster, then inserts a row and queries for that row. If the selected coordinator reports that all of the replicas are consistent, you get an exit code of 0 (success).

While that’s what happens most of the time, sometimes the coordinator can’t get consensus from all of the nodes in the cluster. In that case, the code downgrades the consistency to make sure the data is available somewhere. We treat that as a warning, and return an exit code of 1.

If something more catastrophic goes wrong, and you can’t get any data at all from this node, then you get an exit code of 2.

This exit code is used by our consul service so we can get better cluster-wide health information from the consul gui interface, as well as alerting.

Special care is taken to make sure that the coordination of the query happens only from localhost (or the node specified on the command line).

Just want a standalone binary? Grab the jar from bintray, then just run it with

java -jar cassandra-health-check-1.0.0-all.jar

posted in: · · ·