How to use WSSE in Android app

Share Button

Lire la version française
After publishing an article about WSSE configuration in Symfony2, we received a lot of questions about using WSSE in Android application. We hope this article will answer some of these questions!
Note that we will only speak about WSSE and not about designing a rest client in Android application.

Ingredients you need

WSSE authentication is based on 4 importants things :

  • an username
  • a nonce (a generated cryptographic number to prevent replay attacks)
  • the current timestamp in a given format
  • the password digest

3 of these are easily constructed :

  • The username is given by the user himself through a text input in the login activity (basically a form). Not a problem for an android developper
  • The nonce is generated, you just have to find the correct piece of code (we will paste it below, you’re a lucky guy!).
  • The current timestamp : no comment :)

How to generate the password digest

To generate the password digest, there is a little more work to do.

The user will type a clear password in an input text. Your Android app has to hash it and store it, for example in a sqlite database. The most important thing to keep in mind is that a part of wsse authentication mechanism is based on the comparison of two hashed passwords (one given by the client, the other one already stored by the server)

So, the hashed password in your Android app HAS TO be exactly the same as the one created and stored by Symfony (or something else) on the server side.

By default, Symfony uses the SHA-512 hash algorithm with a salted password (salt is a random string) and do it 5000 times.
You have to do the same process in your Android App but, to do that, you have to know the specific salt of this user.
The only solution we found is to publicly expose user’s salt in the REST Api (after some researches, we think that will not cause any security issues : Stackoverflow about salt (Private or public data?)).

For example, you can have a public ressource like which returns some public user’s information in json format (including the salt of course) like this :

{"username":"jb","salt":"e2l8uk8xhm0oo0c4ss4goooo0kc400w","usedName":"Jb IDZIK","firstname":"Jb","latitude":50.543009,"longitude":2.9833120000001,"gender":"M","avatar":"jb.png"}

When you have the salt, you can start hashing password. Stop talking, start coding. Here is a method to do it :

public String hashPassword(String salt, String clearPassword) {
	String hash = "";
	try {
		//Log.d("AuthProvider", "start hashing password...");
		String salted = null;
		if(salt == null || "".equals(salt)) {
			salted = clearPassword;
		} else {
			salted = clearPassword + "{" + salt + "}";
		MessageDigest md = MessageDigest.getInstance("SHA-512");
		byte sha[] = md.digest(salted.getBytes());
		for(int i = 1; i < 5000; i++) {
			byte c[] = new byte[sha.length + salted.getBytes().length];
			System.arraycopy(sha, 0, c, 0, sha.length);
			System.arraycopy(salted.getBytes(), 0, c, sha.length, salted.getBytes().length);
			sha = md.digest(c);
		hash = new String(Base64.encode(sha,Base64.NO_WRAP));
	} catch (NoSuchAlgorithmException e) {
		//do something with this exception
	//Log.d("AuthProvider", "hashing password is done!");
	return hash;

This is a big part of work.
(if you think iterate 5000 times is dirty, you may put hands on Symfony side to change this)

Generate proper WSSE headers

At this point, we have everything to create Http request with WSSE authentication.
We just need some methods which generate WSSE headers properly for us. Here is a full class to do that :

public class WsseToken {	
	public static final String HEADER_AUTHORIZATION = "Authorization";
	public static final String HEADER_WSSE = "X-WSSE";
	private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
	//in our case, User is an entity (just a POJO) persisted into sqlite database
	private User user;
	private String nonce;
	private String createdAt;
	private String digest;

	public WsseToken(User user) {
		//we need the user object because we need his username
		this.user = user;
		this.createdAt = generateTimestamp();
		this.nonce = generateNonce();
		this.digest = generateDigest();

	private String generateNonce() {
		SecureRandom random = new SecureRandom();
		byte seed[] = random.generateSeed(10);
		return bytesToHex(seed);
	public static String bytesToHex(byte[] bytes) {
	 final char[] hexArray = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
	 char[] hexChars = new char[bytes.length * 2];
	 int v;
	 for ( int j = 0; j < bytes.length; j++ ) {
	 v = bytes[j] & 0xFF;
	 hexChars[j * 2] = hexArray[v >>> 4];
	 hexChars[j * 2 + 1] = hexArray[v & 0x0F];
	 return new String(hexChars);

	private String generateTimestamp() {
		return sdf.format(new Date());

	private String generateDigest() {
		String digest = null;
		try {
			MessageDigest md = MessageDigest.getInstance("SHA-1");
			StringBuilder sb = new StringBuilder();
			byte sha[] = md.digest(sb.toString().getBytes());
			digest = Base64.encodeToString(sha,Base64.NO_WRAP);
		} catch (NoSuchAlgorithmException e) {
		return digest;

	public String getWsseHeader() {
		StringBuilder header = new StringBuilder();
		header.append("UsernameToken Username=\"");
		header.append("\", PasswordDigest=\"");
		header.append("\", Nonce=\"");
		header.append(Base64.encodeToString(this.nonce.getBytes(), Base64.NO_WRAP));
		header.append("\", Created=\"");
		return header.toString();
	public String getAuthorizationHeader() {
		return "WSSE profile=\"UsernameToken\"";

Create HTTP request with WSSE headers

Finally, you just have to call getWsseHeader() and getAuthorizationHeader() to get Wsse headers.
Here is an (very simplified) example to construct a get http method in Android App and use the previous method to add Wsse headers.

URL url = new URL(yourStringurl);
HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
httpCon.setRequestProperty("Content-Type", "application/json");
//here you use the WsseToken class to get wsse headers
WsseToken token = new WsseToken(user);
this.httpConnection.setRequestProperty(WsseToken.HEADER_AUTHORIZATION, token.getAuthorizationHeader());
this.httpConnection.setRequestProperty(WsseToken.HEADER_WSSE, token.getWsseHeader());

We hope this will help you! Now, have fun.

Share Button

Comments are closed.