Category Archives: Java

Counting results with Hibernate Criteria with multiple joins/associations

We struggled to find the answer to a Hibernate question recently. We are using Hibernate Criteria on an entity with multiple associations and showing these results in a table. The query to return the results of a specific page in the table is simple and works great.

Criteria crit = createCriteria(getResourceClass());
crit.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
crit.setFirstResult(start);
crit.setMaxResults(length);
crit = crit.createCriteria("roles");
crit = crit.createCriteria("principals");
crit.add(Restrictions.in("id", ids));
return (List) crit.list();

Because multiple roles can be added to the entity with the same principals this would normally cause duplicate results but thankfully the result transformer does its job. The problem came when we tried to get the total number of results as this was displayed also in the table.

The initial attempts to use the rowCount projection failed, we assumed this would work in conjunction with the distinct root entity transformer to return the exact number of rows.

crit.setProjection(Projections.rowCount());
...
return (Long) crit.uniqueResult();

After some experimentation we discovered the answer. Replace the CriteriaSpecification.DISTINCT_ROOT_ENTITY result transformer with CriteriaSpecification.PROJECTION and use the Projections.countDistinct projection against an entity field, in our case the name field.

crit.setProjection(Projections.countDistinct("name"));
crit.setResultTransformer(CriteriaSpecification.PROJECTION);

This was not straight forward and we failed to find any references to this method online. We hope that this helps others solve the same problem and avoid some head scratching.

Debugging OpenSAML request and responses.

SAML is a great protocol but can be confusing for any newbie having to develop with it for the first time.

Our team has been building an Identity Provider for the Hypersocket SSO project and one thing we struggled with was debugging SAML request and responses. It turns out a simple logging fix would provide the exact XML in our logs. This will be invaluable when developing and comparing responses with those expected by other systems.

log4j.category.PROTOCOL_MESSAGE=DEBUG

Quick and easy hibernate logging

Wow has it been that long. I’ve been busy building the Hypersocket Framework and the many projects based on it now. We’ll get more chatty about those soon but in the meantime I’d like to record my quick and easy way to enable hibernate logging just by using log4j.

# logs the SQL statements
log4j.logger.org.hibernate.SQL=debug
# Some more useful loggings
# Logs SQL statements for id generation
log4j.logger.org.hibernate.id=info
# Logs the JDBC-Parameter which are passed to a query (very verboose)
log4j.logger.org.hibernate.type=debug
# Logs cache related activities
log4j.logger.org.hibernate.cache=debug

PEMParser update

In my last post I talked about using PEMParser to load private keys from OpenSSL PEM files. After further testing I discovered I needed to refine the code a little.

There appears to be a couple of different ways the private key can be encoded in the file. I discovered this after generating some new test keys only to find they didn’t work with my existing code.

Object privatekey = parser.readObject();

if (privatekey instanceof PEMEncryptedKeyPair) {
     try {
	privatekey = ((PEMEncryptedKeyPair)privatekey).decryptKeyPair(new JcePEMDecryptorProviderBuilder().build(passphrase));
     } catch (Exception e) {
	throw new InvalidPassphraseException(e);
     }
} else if(privatekey instanceof PKCS8EncryptedPrivateKeyInfo) {
     try {
	privatekey = converter.getPrivateKey(((PKCS8EncryptedPrivateKeyInfo)privatekey).decryptPrivateKeyInfo(new JceOpenSSLPKCS8DecryptorProviderBuilder().build(passphrase)));
     } catch (Exception e) {
	throw new InvalidPassphraseException(e);
     }
}

if (privatekey instanceof PEMKeyPair) {
	return loadKeyPair((PEMKeyPair)privatekey);
} else if(privatekey instanceof RSAPrivateCrtKey){
	return loadKeyPair((RSAPrivateCrtKey)privatekey);
} else {
	throw new FileFormatException("The file doesn't seem to have any supported key types obj=" + privatekey);
}

Loading PEM keys & certificates from Java

I’ve worked for years with Java and SSL sockets and I’ve always struggled with support issues when it comes to SSL certificates. The problem is that most non-developer folks use Apache style PEM certificates and have come pretty use to them. When you present them with a different format and require they configure your application with a Java KeyStore your bound to get problems. The only solution is to allow your end users to configure your solution with the formats they know and love.

Thats why I decided to go with a more flexible approach for configuring Hypersocket with SSL certificates. I want end users to be able to upload their existing PEM keys and certificates and have this work out-of-the-box with no conversion, no formatting changes. Just use the files as they come. Luckily there are tools available at the Bouncycastle project that now make this possible.

First of all I’ve installed the Bouncycastle JCE provider 1.48 in the security providers list.

Security.addProvider(new BouncyCastleProvider());

I’m now going to load the private key from a PEM file, if the file is encrypted we will decrypt the key. I’m using PEMParser from the Bouncycastle PKIX/CMS/EAC/PKCS/TSP/OPENSSL package. Some checks and balances have been removed from the following code:

PEMParser parser = new PEMParser(new InputStreamReader(keyfile));

// Load the key object
Object privatekey = parser.readObject();

// Check to see if the object returned is an encrypted key pair
if (privatekey instanceof PEMEncryptedKeyPair) {
    privatekey = ((PEMEncryptedKeyPair)privatekey).decryptKeyPair(new JcePEMDecryptorProviderBuilder().build("xxxxxxxx".toCharArray()));
} 

// Cast to a PEMKeyPair
PEMKeyPair pair = (PEMKeyPair) privatekey;

// Get the encoded objects ready for conversion to Java objects
byte[] encodedPublicKey = pair.getPublicKeyInfo().getEncoded();
byte[] encodedPrivateKey = pair.getPrivateKeyInfo().getEncoded();

// Now convert to Java objects
KeyFactory keyFactory = KeyFactory.getInstance( "RSA");
			
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(encodedPublicKey);
PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);

PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(encodedPrivateKey);
PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);

KeyPair pair = new KeyPair(publicKey, privateKey);

We now have a KeyPair loaded into memory, but before we can initialize an SSL context we need to get the certificate from the .crt file. We can use the same APi to load the certificate:

PEMParser parser = new PEMParser(new InputStreamReader(certfile));

X509CertificateHolder obj = (X509CertificateHolder) parser.readObject();
Certificate cert = JcaX509CertificateConverter().setProvider("BC").getCertificate(obj);

Now the only thing left to do is to place these into a KeyStore object so we can initialize SSL context.

KeyStore store = KeyStore.getInstance("JKS");
store.load(null);

store.setKeyEntry(alias, pair.getPrivate(), passphrase,	new java.security.cert.Certificate[] { cert });