I have made sso work in Java as:
import org.codehaus.jettison.json.JSONObject;
import sun.misc.BASE64Encoder;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.Random;
public class UserEchoSSOTokenGenerator {
public static final int BLOCK_SIZE = 16;
public static final int DEFAULT_EXPIRES = 1 * 24 * 60 * 60 * 1000; // 1 day
public static final String DEFAULT_USER_LANGUAGE = "en";
public static void main(String[] args) {
try {
if (args == null || args.length != 5) {
System.out.println("Usage: UserEchoSSOTokenGenerator <api-key> <project-key> <id> <name> <email>");
return;
}
String apiKey = args[0];
String applicationKey = args[1];
String id = args[2];
String name = args[3];
String email = args[4];
Date expiredDate = new Date(new Date().getTime() + DEFAULT_EXPIRES);
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
JSONObject attributes = new JSONObject();
attributes.put("guid", Long.parseLong(id));
attributes.put("expires_date", dateFormat.format(expiredDate));
attributes.put("display_name", name);
attributes.put("email", email);
attributes.put("locale", DEFAULT_USER_LANGUAGE);
attributes.put("avatar_url", "");
System.out.println(attributes);
byte[] iv = getRandomIV();
printByes("iv", iv);
byte[] keyBytes = getKeyBytes(apiKey, applicationKey);
printByes("keyBytes", keyBytes);
byte[] inputBytes = attributes.toString().getBytes("UTF-8");
printByes("inputBytes", inputBytes);
ivXORFirstBlock(inputBytes, iv);
printByes("XOR inputBytes", inputBytes);
// Please note: we don't need to do padding here since the following encryption will handle the padding
byte[] encryptedBytes = encrypt(inputBytes, iv, keyBytes);
printByes("encryptedBytes", encryptedBytes);
String base64Encoded = base64Encode(encryptedBytes);
System.out.println("\nbase64Encoded: \n");
System.out.println(base64Encoded);
String result = urlEncode(base64Encoded);
System.out.println("\nencoded: \n");
System.out.println("sso_token=" + result);
} catch (Exception e) {
e.printStackTrace();
}
}
// print out byte values to compare output from other language eg. php
protected static void printByes(String name, byte[] bytes) {
System.out.println();
System.out.print(name);
System.out.println(" length=" + bytes.length);
System.out.println();
for (int i = 0; i < bytes.length; i++) {
System.out.print(" ");
System.out.print(bytes[i] & 0xff);
}
System.out.println();
}
private static byte[] getRandomIV() throws UnsupportedEncodingException {
StringBuilder builder = new StringBuilder();
Random random = new Random();
for (int i = 0; i < BLOCK_SIZE; i++) {
builder.append((char) Math.floor(26 * random.nextDouble() + 65));
}
return builder.toString().getBytes("UTF-8");
}
private static byte[] getKeyBytes(String apiKey, String applicationKey) throws NoSuchAlgorithmException, UnsupportedEncodingException {
String message = apiKey + applicationKey;
MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
messageDigest.update(message.getBytes("UTF-8"));
return Arrays.copyOfRange(messageDigest.digest(), 0, BLOCK_SIZE);
}
private static void ivXORFirstBlock(byte[] inputBytes, byte[] iv) {
// double XOR first block message_json
for (int i = 0; i < BLOCK_SIZE; i++) {
inputBytes[i] ^= iv[i];
}
}
private static byte[] encrypt(byte[] json, byte[] iv, byte[] keyBytes) {
try {
SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec ips = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, key, ips);
return cipher.doFinal(json);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
private static String base64Encode(byte[] inputBytes) {
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(inputBytes);
}
private static String urlEncode(String input) throws UnsupportedEncodingException {
return URLEncoder.encode(input, "UTF-8");
}
}