Good solid cryptography is an essential foundation for sound business usage of the Internet, and essential to provide a sane privacy level. But the tools for Java programmers are in horrible shape.
OpenPGP · The crypto landscape is wide and disorderly, but in the area I most care about, private messaging, OpenPGP is central. RFC 4880 gives pretty crisp and clean coverage of how it works. So what we need are nice clean OpenPGP tools for Java-heads.
OpenPGP describes public/private key formats and what signed/encrypted messages look like. So there are four or less inputs to any PGP process: The key, the payload (to be encrypted and/or signed), the encrypted data (to be decrypted), and the signature (to be checked). I could write down a Java interface that would give developers what they need in a few minutes. It’s a little harder than you’d think because you need to handle streaming data, but this does not need to be a complicated interface.
I’m pretty sure this is possible because there’s an
excellent open-source
OpenPGP implementation that has a command line tool, so you can say
things like gpg decrypt
and gpg check
; so give me a
Java API to do that.
Case study · The problem I’m facing is that I want to check a Keybase.io proof (for geeks, here’s a compact JSON version). So, I have a payload, the JSON starting with:
{\"body\":{\"key\":{\"fingerprint\":
I have a signature, the start of which looks like this:
-----BEGIN PGP MESSAGE-----
Version: Keybase OpenPGP JS 0.0.1
Comment: https://keybase.io/crypto
yMLDAnicdZF/TBNXAMfb0jKs61bi+CFlw95cSKR0116vd+2mA7fEIiLoyMaWbvWO
And I have a key, whose ASCII form may be fetched from keybase.io/timbray/key.asc.
Thus, I need a Java method something like
boolean checkSig(byte[] payload, String sig, String asciiKey);
Wish me luck; I’ll need it.
The library landscape · Of course, Java comes a set of Security packages that can among other things can check signatures, but all over the Internet it says “Of course, to do X (for almost any value of X) you’re going to need an external package like Bouncy Castle” (which exists in Java and C#). Unless you’re on Android, where the Bouncy Castle version is hard to use, thus someone has obligingly provided Spongy Castle as a drop-in replacement. [Update: Explanation in the comments.]
Hokay then, let’s go spelunk through the Bouncy Castle documentation and tutorials to figure out how to check that signature. Well I tried, but man, it’s far from obvious. Part of the problem (and this seems to be true a lot in crypto software) is that the libraries provide soup-to-nuts implementations of a huge swathe of crypto stuff, of which OpenPGP is just a corner case. And since this is all written by deep-crypto nerds (whom I admire immensely) you get an effect where you sort of have to understand everything to understand anything.
I’m never going to be a deep-crypto nerd, but I understand things at a conceptual level and, with the help of RFC4880, I think I understand key structures well enough to write code to build them and pick them apart.
There’s a Java OpenPGP library over at Apache Commons, but its functionality is limited and it seems very lightly maintained.
So, how hard is it to use Bouncy Castle to do basic OpenPGP messaging stuff? Let’s look at the excellent OpenKeychain Android app, which does just that. The openpgp subtree has 23 classes containing 15K lines of code.
It shouldn’t be this hard · At this point, since I’m interested in Android clients, I’m in Java-land. I don’t know if the picture in other languages is as grim as it is here. But if someone wanted to give what’s maybe still the world’s most popular programming platform a major shot in the arm, a tractable OpenPGP API for mere mortals would be huge.
But maybe I’m wrong · You know what would be great? If someone stuck up their hand and said “you noob moron, just grab this here library and use these five lines of Java and you’re done.” Not holding my breath.
What’s more likely is that someone says “A simple generic API will leave it open for developers to use it wrong and they think they’re getting good encryption when they’re not.” But I’m deeply unconvinced, I think it’s just a hole in the software inventory.
Comment feed for ongoing:
From: Aaron (Jun 30 2014, at 15:09)
This might be close...
import java.security.*;
import java.security.spec.*;
boolean checkSig(String plainText, String sig, String asciiKey)
{
Signature dsa = Signature.getInstance("SHA1withDSA");
dsa.initVerify(KeyFactory.getInstance("DSA").generatePublic(
new X509EncodedKeySpec(Base64.decode(asciiKey))));
dsa.update(plainText.getBytes());
return dsa.verify(Base64.decode(sig));
}
[link]
From: Jon Eaves (Jun 30 2014, at 15:41)
As one of the BC library developers, I just wanted to provide some background on SpongyCastle.
It's built and maintained by a wonderful person, who I'm pretty sure doesn't hold us in any disdain, to support the Android community.
When Android was built, Google took and used the BC class libraries for the security framework. The modified some of them slightly and then unfortunately left them stale for many releases, and also leaked the classes outside the "system use" into the "user domain" where program developers can get access to them and use them as system provided libraries.
Over time, the BC libraries fixed bugs, added enhancements and changed subtly the API interfaces which made them incompatible with the system libraries.
Now when people packaged Android applications, the system classpath and the library classpath had classes with the same package names - and BOOM.
So, SpongyCastle is basically a repackaging of the BC libraries under different package names to make it easy to use on Android.
We used to do exactly the same thing many years ago with obfuscation because of some of our compatibility classes in the library and the way we managed the JavaME -> JavaEE libraries.
Now, I can also add some degree of sympathy about the landscape of writing "simple" crypto apps. It's entirely possible, and it's not even that hard - it's probably just harder than you expected, which is why we end up with so much shitty crypto using software out there. (And dare I say, programs in general)
[link]
From: Jeroen (Jul 01 2014, at 02:14)
This is exactly why Dan Bernstein and others have developed the NaCL library.
It provides an implementation of the most important cryptographic functions, with a sensible interface, so that developers are a whole lot less likely to shoot themselves in the foot.
The only problem is that it is currently only available for C and C++, with some support for Python. I hope that someone stands up and ports this to Java.
[link]
From: Larry Reid (Jul 01 2014, at 08:19)
"A simple, generic API..." should always lead to the most secure code. We're not doing our job as security library developers unless it does. If it's easier to do it wrong than to do it right, then programmers using a library will do it wrong. (And that's not meant to be a comment on programmers' work ethic. It's just a statement about human nature.)
[link]