/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the Common Development
* and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at
* src/com/vodafone360/people/VODAFONE.LICENSE.txt or
* http://github.com/360/360-Engine-for-Android
* See the License for the specific language governing permissions and
* limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each file and
* include the License file at src/com/vodafone360/people/VODAFONE.LICENSE.txt.
* If applicable, add the following below this CDDL HEADER, with the fields
* enclosed by brackets "[]" replaced with your own identifying information:
* Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
* Copyright 2010 Vodafone Sales & Services Ltd. All rights reserved.
* Use is subject to license terms.
*/
package com.vodafone360.people.service.utils;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Hashtable;
import java.util.List;
import java.util.Vector;
import com.vodafone360.people.Settings;
import com.vodafone360.people.SettingsManager;
import com.vodafone360.people.datatypes.AuthSessionHolder;
import com.vodafone360.people.utils.LogUtils;
/**
* Set of functions that are used for generating 'auth' parameter required for
* cresting requests and is usually based on a valid session created on
* sign-up/login.
*/
public class AuthUtils {
/**
* Generates a MD5 hash of the input.
*
* @param input - String from which MD5 will be created
* @return String containing MD5 hash created from input parameter
* @throws NullPointerException when input is NULL
* @throws NullPointerException MD5 algorithm could not be found
*/
public static String getMd5Hash(String input) {
if (input == null) {
throw new NullPointerException("AuthUtils.getMd5Hash() input cannot be NULL");
}
try {
String md5 = new BigInteger(1, MessageDigest.getInstance("MD5")
.digest(input.getBytes())).toString(16);
while (md5.length() < 32) {
md5 = "0" + md5;
}
return md5;
} catch (NoSuchAlgorithmException e) {
LogUtils
.logE("AuthUtils.getMd5Hash() NoSuchAlgorithmException, indicates that MD5 algorithm could not be found.");
throw new NullPointerException("AuthUtils.getMd5Hash() NoSuchAlgorithmException");
}
}
/**
* Calculates the AUTH parameter using a list of NameValues. TODO: Why is
* this called differently for every API?
*
* @param functionName - String representation of function, using the
* "class/funcName" convention e.g.
* "auth/getsessionbycredentials". Typically empty.
* @param parameters - List of name/value pairs
* @param timeStamp - String containing absolute time stamps, generated by
* calls to getCurrentTimeInSeconds()
* @param session - Valid session object or NULL
* @return AUTH parameter String
* @throws NullPointerException when functionName is NULL
* @throws NullPointerException when parameters is NULL
* @throws NullPointerException when timeStamp is NULL
*/
public static String calculateAuth(String functionName, Hashtable<String, Object> parameters,
String timeStamp, AuthSessionHolder session) {
LogUtils.logI("AuthUtils.calculateAuth() Call to function [" + functionName + "]");
if (functionName == null) {
throw new NullPointerException("AuthUtils.calculateAuth() functionName cannot be NULL");
}
if (parameters == null) {
throw new NullPointerException("AuthUtils.calculateAuth() parameters cannot be NULL");
}
if (timeStamp == null) {
throw new NullPointerException("AuthUtils.calculateAuth() timeStamp cannot be NULL");
}
StringBuffer toMd5 = new StringBuffer();
toMd5.append(SettingsManager.getProperty(Settings.APP_SECRET_KEY));
if (session != null) {
toMd5.append("&" + session.sessionSecret);
}
toMd5.append( "&" + functionName);
List<String> sortedList = AuthUtils.getSortedListOfKeys(parameters);
for (int i = 0; i < sortedList.size(); i++) {
String key = sortedList.get(i);
toMd5.append("&" + createSigningString(key, parameters.get(key)));
}
LogUtils.logI("AuthUtils.calculateAuth() Before auth[" + toMd5 + "]");
if (session == null) {
return SettingsManager.getProperty(Settings.APP_KEY_ID) + "::" + timeStamp + "::"
+ getMd5Hash(toMd5.toString());
} else {
return SettingsManager.getProperty(Settings.APP_KEY_ID) + "::" + session.sessionID
+ "::" + timeStamp + "::" + getMd5Hash(toMd5.toString());
}
}
/**
* Calculates a signing string from a name/value pair
*
* @param inputString - String name.
* @param inputObject - Object value can be Hashtable, Vector, byte[] or
* String.
* @return Signing String
* @throws NullPointerException when inputString is NULL
* @throws NullPointerException when inputObject is NULL
*/
@SuppressWarnings("unchecked")
private static String createSigningString(String inputString, Object inputObject) {
if (inputString == null) {
throw new NullPointerException("AuthUtils.createSigning() inputString cannot be NULL");
}
if (inputObject == null) {
throw new NullPointerException("AuthUtils.createSigning() inputObject cannot be NULL");
}
if (inputObject instanceof Hashtable<?, ?>) {
return inputString + "=" + createSignOfHastable((Hashtable<String, Object>)inputObject);
} else if (inputObject instanceof Vector<?>) {
return inputString + "=" + createSignOfVector((Vector<Object>)inputObject);
} else if (inputObject instanceof byte[]) {
return inputString + "=" + getMd5Hash(createSignOfByteAray((byte[])inputObject));
} else {
return inputString + "=" + inputObject.toString();
}
}
/**
* Calculates the sign value from a Hash table
*
* @param hashTable - Given Hash table
* @return Sign value String
* @throws NullPointerException when hashTable is NULL
*/
private static String createSignOfHastable(Hashtable<String, Object> hashTable) {
if (hashTable == null) {
throw new NullPointerException(
"AuthUtils.createSignOfHastable() hashTable cannot be NULL");
}
StringBuffer returnString = new StringBuffer();
List<String> list = AuthUtils.getSortedListOfKeys(hashTable);
for (int i = 0; i < list.size(); i++) {
String key = list.get(i);
Object obj = hashTable.get(key);
returnString.append(createSigningString(key, obj));
if (i < list.size() - 1) {
returnString.append("&");
}
}
return returnString.toString();
}
/**
* Calculates the sign value from a Vector
*
* @param hashTable - Given Vector
* @return Sign value String
* @throws NullPointerException when vector is NULL
*/
@SuppressWarnings("unchecked")
private static String createSignOfVector(Vector<Object> vector) {
if (vector == null) {
throw new NullPointerException("AuthUtils.createSignOfByteAray() vector cannot be NULL");
}
StringBuffer ret = new StringBuffer();
for (int i = 0; i < vector.size(); i++) {
Object tempObject = vector.get(i);
if (tempObject instanceof Hashtable<?, ?>) {
ret.append(createSignOfHastable((Hashtable<String, Object>) tempObject));
} else if (tempObject instanceof Vector<?>) {
ret.append(createSignOfVector((Vector<Object>) tempObject));
} else {
ret.append(tempObject.toString());
}
if (i < vector.size() - 1) {
ret.append("&");
}
}
return ret.toString();
}
/**
* Calculates the sign value from a byte array
*
* @param bytes - Given byte array
* @return Sign value String
* @throws NullPointerException when bytes is NULL
*/
private static String createSignOfByteAray(byte[] bytes) {
if (bytes == null) {
throw new NullPointerException("AuthUtils.createSignOfByteAray() bytes cannot be NULL");
}
return String.valueOf(bytes.length);
}
/**
* Returns a list of keys from the map in alphabetical order
*
* @param map The map to sort
* @return The ordered list of keys
*/
private static List<String> getSortedListOfKeys(Hashtable<String, Object> map) {
List<String> mList = new ArrayList<String>(map.keySet());
Collections.sort(mList);
return mList;
}
}