Java + GnuPG
John Anderson
j_anderson@uop.edu
Tue Feb 26 06:03:02 2002
Hi there, I have been thinking of making up a small interface between
GnuPG and Java because I want to use something like that in a project
I've been toying with. I was unable to find anything like this, other
than Cryptix, which doesn't seem to be GPL. I found a thread on this
list about problems getting Java and GnuPG to play nice together with
IPC and file descriptors and such, so I decided to give it a whirl.
The discussion that sparked my coding can be found here:
http://lists.gnupg.org/pipermail/gnupg-devel/2002-January/006666.html
I came up with a 173 line Java class that can encrypt and decrypt text
strings, which can be used quite easily.
I will post the code below, so that if anyone is interested they'll be
able to play around with it. I look forward to any feedback and
suggestions.
The pertinent functions in GnuPG are:
encrypt(string_to_encrypt, recipient);
decrypt(string_to_decrypt, passphrase);
getResult();
getError();
The ProcessStreamReader class is there to work as a small thread to
gather the text that gpg spits out on its stdout and stderr file
descriptors. STDERR seems to be where it puts all status text, and
STDOUT is very clean, just giving the encrypted or decrypted text.
The decrypt function actually puts the string_to_decrypt into a file in
your system specific temporary directory, and then tells gpg to decrypt
that file, because I couldn't readily see how to make gpg read both the
passphrase and text to decrypt from stdin.
I am running JDK 1.4.0, gpg 1.0.6 all on Debian unstable.
Thanks,
John Anderson
PS - This stuff has worked flawlessly the few times I've tried it once
completed; I make no gaurantee that it's coded very well because I did
it up in a few hours.
PGPMSClient.java (A start of my toy project, a GPG-based message system)
----------------
public class PGPMSClient
{
public static void main(String[] args)
{
GnuPG gpg = new GnuPG();
gpg.encrypt("The quick brown fox jumped over the lazy dog.\n",
"j_anderson@uop.edu\n");
System.out.print(gpg.getResult());
// USE YOUR PASSWORD HERE...
gpg.decrypt(gpg.getResult(), "YOUR_PASSWORD_HERE\n");
System.out.print(gpg.getResult());
}
}
GnuPG.java
----------
/* License: GPL
* Author: John Anderson
* Description: A small class to encrypt and decrypt text using GnuPG.
*/
import java.io.*;
public class GnuPG
{
private Process p;
private String gpg_result;
private String gpg_err;
GnuPG()
{
}
public void encrypt(String str, String rcpt)
{
System.out.print("Encrypting... ");
try
{
p = Runtime.getRuntime().exec("gpg --armor --batch --encrypt -r " +
rcpt);
}
catch(IOException io)
{
System.out.println("Error creating process.");
}
ProcessStreamReader psr_stdout = new ProcessStreamReader("STDIN",
p.getInputStream());
ProcessStreamReader psr_stderr = new ProcessStreamReader("STDERR",
p.getErrorStream());
psr_stdout.start();
psr_stderr.start();
BufferedWriter out = new BufferedWriter(new
OutputStreamWriter(p.getOutputStream()));
try
{
out.write(str);
out.close();
}
catch(IOException io)
{
}
try
{
p.waitFor();
psr_stdout.join();
psr_stderr.join();
}
catch(InterruptedException i)
{
}
gpg_result = psr_stdout.getString();
gpg_err = psr_stdout.getString();
System.out.println("Done.");
}
public void decrypt(String str, String passphrase)
{
File f = null;
try
{
f = File.createTempFile("gpg-decrypt", null);
FileWriter fw = new FileWriter(f);
fw.write(str);
fw.flush();
}
catch(IOException io)
{
}
System.out.print("Decrypting from: " + f.getAbsolutePath());
try
{
p = Runtime.getRuntime().exec("gpg --passphrase-fd 0 --batch
--decrypt "
+ f.getAbsolutePath());
}
catch(IOException io)
{
System.out.println("Error creating process.");
}
ProcessStreamReader psr_stdout = new ProcessStreamReader("STDIN",
p.getInputStream());
ProcessStreamReader psr_stderr = new ProcessStreamReader("STDERR",
p.getErrorStream());
psr_stdout.start();
psr_stderr.start();
BufferedWriter out = new BufferedWriter(new
OutputStreamWriter(p.getOutputStream()));
try
{
out.write(passphrase);
out.close();
}
catch(IOException io)
{
}
try
{
p.waitFor();
psr_stdout.join();
psr_stderr.join();
}
catch(InterruptedException i)
{
}
gpg_result = psr_stdout.getString();
gpg_err = psr_stdout.getString();
System.out.println("Done.");
}
public String getResult()
{
return gpg_result;
}
public String getError()
{
return gpg_err;
}
}
class ProcessStreamReader
extends Thread
{
String name;
StringBuffer stream;
InputStreamReader in;
final static int BUFFER_SIZE = 256;
ProcessStreamReader(String name, InputStream in)
{
super();
this.name = name;
this.in = new InputStreamReader(in);
this.stream = new StringBuffer();
}
public void run()
{
try
{
int read;
char[] c = new char[BUFFER_SIZE];
while((read = in.read(c, 0, BUFFER_SIZE - 1)) > 0)
{
stream.append(c, 0, read);
if(read < BUFFER_SIZE - 1) break;
}
}
catch(IOException io) {}
}
String getString()
{
return stream.toString();
}
}