Pass X509Certificate as String?

I

Ian Pilcher

This is a bit weird. I am writing an SSLSocketFactory for use with the
PostgreSQL JDBC driver. Unfortunately, the driver imposes some very
inconvenient criteria on the factory class.

http://jdbc.postgresql.org/documentation/91/ssl-factory.html

In particular, the class must have a zero-argument constructor or a
constructor that takes a single String argument. My challenge is to
somehow pass a java.security.cert.X509Certificate to this constructor.

The only idea I've been able to come up with thus far is to serialize
the certificate to a ByteArrayOutputStream, convert that to a String,
and reverse the process in the constructor.

Does anyone have a better idea?

If not, is there a character set that can handle all values 0-255?

Thanks!
 
A

Arne Vajhøj

This is a bit weird. I am writing an SSLSocketFactory for use with the
PostgreSQL JDBC driver. Unfortunately, the driver imposes some very
inconvenient criteria on the factory class.

http://jdbc.postgresql.org/documentation/91/ssl-factory.html

In particular, the class must have a zero-argument constructor or a
constructor that takes a single String argument. My challenge is to
somehow pass a java.security.cert.X509Certificate to this constructor.

The only idea I've been able to come up with thus far is to serialize
the certificate to a ByteArrayOutputStream, convert that to a String,
and reverse the process in the constructor.

Does anyone have a better idea?

I believe it is common to use Bas64 encoding of DER encoding
of the certificate.

Maybe you can use that!?

Arne
 
A

Arne Vajhøj

I believe it is common to use Bas64 encoding of DER encoding
of the certificate.

Maybe you can use that!?

The methods must be getInstance and getEncoded.

Arne
 
A

Arne Vajhøj

The methods must be getInstance and getEncoded.

Code snippet:

public static String b64encode(byte[] b) throws MessagingException,
IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStream b64os = MimeUtility.encode(baos, "base64");
b64os.write(b);
b64os.close();
return new String(baos.toByteArray());
}
public static byte[] b64decode(String s) throws
MessagingException, IOException {
ByteArrayInputStream bais = new ByteArrayInputStream(s.getBytes());
InputStream b64is = MimeUtility.decode(bais, "Base64");
byte[] tmp = new byte[s.length()];
int n = b64is.read(tmp);
byte[] res = new byte[n];
System.arraycopy(tmp, 0, res, 0, n);
return res;
}
public static String encode(X509Certificate cert) throws
CertificateEncodingException, MessagingException, IOException {
return b64encode(cert.getEncoded());
}
public static X509Certificate decode(String s) throws
CertificateException, MessagingException, IOException {
return X509Certificate.getInstance(b64decode(s));
}

Arne
 
I

Ian Pilcher

Code snippet:

You're as literal-minded as I am. :) (BTW, I also found base64
encode/decode methods in javax.xml.bind.DatatypeConverter.)

The cluebat fairy visited me, and I realized that it will be far more
efficient to simply "register" my CA certificate by name before
connecting to the database.

final class JdbcSSLSocketFactory extends SSLSocketFactory
{
private final static Map<String,X509Certificate> caCerts = new
HashMap<>();

public static void registerCA(String caName, X509Certificate caCert)
{
if (caName == null || caCert == null) {
throw new IllegalArgumentException(String.format(
"null value not allowed for %s",
caName == null ? "caName" : "caCert"));
caCerts.put(caName, caCert);
}

public JdbcSSLSocketFactory(String caName)
{
try {
X509Certificate caCert = caCerts.get(caName);
if (caCert == null) {
throw new IllegalStateException(String.format(
"No certificate authority named '%s' has been registered",
caName));
}

...

Thanks!
 
A

Arne Vajhøj

You're as literal-minded as I am. :) (BTW, I also found base64
encode/decode methods in javax.xml.bind.DatatypeConverter.)

Ah. That will get rid of the two b64 methods. Thanks.
The cluebat fairy visited me, and I realized that it will be far more
efficient to simply "register" my CA certificate by name before
connecting to the database.

:)

Arne
 
A

Arne Vajhøj

Ah. That will get rid of the two b64 methods. Thanks.

public static String encode(X509Certificate cert) throws
CertificateEncodingException, MessagingException, IOException {
return DatatypeConverter.printBase64Binary(cert.getEncoded());
}
public static X509Certificate decode(String s) throws
CertificateException, MessagingException, IOException {
return
X509Certificate.getInstance(DatatypeConverter.parseBase64Binary(s));
}

Arne
 
R

Roedy Green

In particular, the class must have a zero-argument constructor or a
constructor that takes a single String argument

Surely it has a very particular format for this string in mind. You
would have to convert the cert to this format, not just to some
arbitrary encoding.
--
Roedy Green Canadian Mind Products http://mindprod.com
The first 90% of the code accounts for the first 90% of the development time.
The remaining 10% of the code accounts for the other 90% of the development
time.
~ Tom Cargill Ninety-ninety Law
 
I

Ian Pilcher

Surely it has a very particular format for this string in mind. You
would have to convert the cert to this format, not just to some
arbitrary encoding.

Well, since I was thinking of writing the class, I would have been
writing both the serialization and deserialization code. Terribly
inefficient, though.
 
R

Roedy Green

Well, since I was thinking of writing the class, I would have been
writing both the serialization and deserialization code. Terribly
inefficient, though.

It you have something in binary and want to transport it as a string
that may meddle with chars such asLf Cr space, accented letters your
best bet is Base64 armouring. That is how certs are typically
armoured.

See http://mindprod/jgloss/base64.html
--
Roedy Green Canadian Mind Products http://mindprod.com
The first 90% of the code accounts for the first 90% of the development time.
The remaining 10% of the code accounts for the other 90% of the development
time.
~ Tom Cargill Ninety-ninety Law
 
A

Arne Vajhoej

It you have something in binary and want to transport it as a string
that may meddle with chars such asLf Cr space, accented letters your
best bet is Base64 armouring. That is how certs are typically
armoured.

Well base64 code was already posted a week ago.

Arne
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,012
Latest member
RoxanneDzm

Latest Threads

Top