All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.code.facebookapi.FacebookSignatureUtil Maven / Gradle / Ivy

The newest version!
package com.google.code.facebookapi;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Collection;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.Map.Entry;
import java.util.zip.CRC32;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Utility for managing Facebook-specific parameters, specifically those related to session/login aspects.
 */
public final class FacebookSignatureUtil {

	protected static Log log = LogFactory.getLog( FacebookSignatureUtil.class );

	public static SortedMap pulloutFbSigParams( Map reqParams ) {
		SortedMap out = new TreeMap();
		for ( Entry entry : reqParams.entrySet() ) {
			String key = entry.getKey();
			String[] values = entry.getValue();
			if ( values.length > 0 && key.startsWith( "fb_sig" ) ) {
				out.put( key, values[0] );
			}
		}
		return out;
	}

	/**
	 * Verifies that a signature received matches the expected value. Removes FacebookParam.SIGNATURE from params if present.
	 * 
	 * @param params
	 *            a map of parameters and their values, such as one obtained from extractFacebookNamespaceParams; expected to contain the signature as the
	 *            FacebookParam.SIGNATURE parameter
	 * @param secret
	 *            the developers 'secret' API key
	 * @return a boolean indicating whether the calculated signature matched the expected signature
	 */
	public static boolean verifySignature( SortedMap params, String secret ) {
		return ( getVerifiedParams( "fb_sig", params, secret ) != null );
	}

	public static SortedMap getVerifiedParams( String prefix, SortedMap map, String secret ) {
		SortedMap out = new TreeMap();
		String prefix2 = prefix + "_";
		String sig = null;
		for ( Entry entry : map.entrySet() ) {
			String key = entry.getKey();
			if ( key.equals( prefix ) ) {
				sig = entry.getValue();
			} else if ( key.startsWith( prefix2 ) ) {
				key = key.substring( prefix2.length() );
				out.put( key, entry.getValue() );
			}
		}
		String sigGen = generateSignature( out, secret );
		if ( StringUtils.equals( sig, sigGen ) ) {
			return out;
		}
		return null;
	}

	public static String generateSignature( SortedMap params, String secret ) {
		StringBuilder sb = generateBaseString( params );
		sb.append( secret );
		return generateMD5( sb.toString() );
	}

	public static StringBuilder generateBaseString( SortedMap params ) {
		StringBuilder sb = new StringBuilder();
		for ( Entry entry : params.entrySet() ) {
			String key = entry.getKey();
			sb.append( key );
			sb.append( "=" );
			String value = entry.getValue();
			sb.append( ( value == null ) ? "" : value );
		}
		return sb;
	}

	public static String generateMD5( String value ) {
		try {
			MessageDigest md = MessageDigest.getInstance( "MD5" );
			byte[] bytes;
			try {
				bytes = value.getBytes( "UTF-8" );
			}
			catch ( UnsupportedEncodingException e1 ) {
				bytes = value.getBytes();
			}
			StringBuilder result = new StringBuilder();
			for ( byte b : md.digest( bytes ) ) {
				result.append( Integer.toHexString( ( b & 0xf0 ) >>> 4 ) );
				result.append( Integer.toHexString( b & 0x0f ) );
			}
			return result.toString();
		}
		catch ( NoSuchAlgorithmException ex ) {
			throw new RuntimeException( ex );
		}
	}

	/**
	 * 
    *
  1. Normalize the email address. Trim leading and trailing whitespace, and convert all characters to lowercase.
  2. *
  3. Compute the CRC32 value for the normalized email address and use the unsigned integer representation of this value. (Note that some implementations return * signed integers, in which case you will need to convert that result to an unsigned integer.)
  4. *
  5. Compute the MD5 value for the normalized email address and use the hex representation of this value (using lowercase for A through F).
  6. *
  7. Combine these two value with an underscore.
  8. *
* For example, the address [email protected] converts to 4228600737_c96da02bba97aedfd26136e980ae3761. * * @param email * @return email_hash * @see IFacebookRestClient#connect_registerUsers(Collection) */ public static String generateEmailHash( String email ) { email = email.trim().toLowerCase(); CRC32 crc = new CRC32(); crc.update( email.getBytes() ); String md5 = generateMD5( email ); return crc.getValue() + "_" + md5; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy