When building your own web services, security has to be one of the concerns. Having worked with Amazon Web Services extensively over he past several years, I’ve become quite familiar with the Query API security features. I wrote a java client for many of their services, so the workings of the various signing methods needed to be understood.
On a recent project, I decided to implement the same version 2 signing that Amazon uses on most of their web services. I thought I’d be able to leverage my typica client code, and the signing code to help validate requests on the server side. Before any of this could happen, I needed to have a way to generate my own access id and secret key. Shown below is some code that I came up with (using some Eucalyptus code as a reference).
public class Credentials { static { Security.addProvider( new BouncyCastleProvider( ) ); } public static String genAccessId(String userName) { try { byte[] userBytes = userName.getBytes(); MessageDigest digest = MessageDigest.getInstance("SHA224", "BC"); digest.update(userBytes); byte [] digestBytes = digest.digest(); return new String(Base64.encodeBase64(digestBytes)).replaceAll( "\\p{Punct}", "" ).substring(0, 20); } catch (Exception ex) { // catch those security exceptions System.err.println("Error with provider : "+ex.getMessage()); System.exit(-2); } return null; } public static String genSecretKey(String userName) { try { byte[] userBytes = userName.getBytes(); MessageDigest digest = MessageDigest.getInstance("SHA256", "BC"); digest.update(userBytes); SecureRandom random = new SecureRandom(); random.setSeed(System.currentTimeMillis()); byte[] randomBytes = random.generateSeed(userBytes.length); digest.update(randomBytes); byte [] digestBytes = digest.digest(); return new String(Base64.encodeBase64(digestBytes)).substring(0, 40); } catch (Exception ex) { // catch those security exceptions System.err.println("Error with provider : "+ex.getMessage()); System.exit(-2); } return null; } }
When creating a user on the server, I generate an access id and secret key based on the username. A new secret key can be generated at any time, using that username. The access id shouldn’t be changed (as a rule).