Debug Android key Hash null while doing Facebook Integration

I am working on Facebook integration in my application so just to get started i created an empty unity project and imported the facebook sdk(package) in the project. In the Facebook -> Edit Settings ,instead of showing me Debug Android Key Hash it gives me warning stating that Keytool not Found. Make sure that Java is installed , and that java tools are in your path. But it is installed and I can run my java commands in Command Prompt.Earlier on it was not taking the debug.keystore at all. Someone Pointed to change the DebugKeyStorePath in FacebookAndroidUtil and it worked. Then it was regarding Openssl path at that time i provided the jdk path to it with \ after bin.And it is taking the openssl command. Now both Openssl and keytool command are in same location so if it is taking Openssl then it should also take Keytool.
I made few changes in the FacebookAndroidUtil and now it is not giving any error . But it is not not returning any value. Here is the updated script::
using Facebook;
using UnityEngine;
using System.Diagnostics;
using System.Text;
using System.Collections;

namespace UnityEditor.FacebookEditor
{
    public class FacebookAndroidUtil
    {
        public const string ERROR_NO_SDK = "no_android_sdk";
        public const string ERROR_NO_KEYSTORE = "no_android_keystore";
        public const string ERROR_NO_KEYTOOL = "no_java_keytool";
        public const string ERROR_NO_OPENSSL = "no_openssl";
        public const string ERROR_KEYTOOL_ERROR = "java_keytool_error";

        private static string debugKeyHash;
        private static string setupError;

        public static bool IsSetupProperly()
        {
            return DebugKeyHash != null;
        }

        public static string DebugKeyHash
        {
            get
            {
                if (debugKeyHash == null)
                {
                    if (!HasAndroidSDK())
                    {
                        setupError = ERROR_NO_SDK;
                        return null;
                    }
                    if (!HasAndroidKeystoreFile())
                    {
                        setupError = ERROR_NO_KEYSTORE;
                        return null;
                    }
                    if (!DoesCommandExist("echo \"xxx\" | openssl base64"))
                    {
                        setupError = ERROR_NO_OPENSSL;
                        return null;
                    }
                    if (!DoesCommandExist("keytool"))
                    {
                        setupError = ERROR_NO_KEYTOOL;
                        return null;
                    }
                    debugKeyHash = GetKeyHash("androiddebugkey", DebugKeyStorePath, "android");
					UnityEngine.Debug.Log("Debug Key Hash:: "+debugKeyHash);
                }
                return debugKeyHash;
            }
        }

        private static string DebugKeyStorePath
        {
            get
            {
				//Added C: to the string so that it can take C drive 
                return (Application.platform == RuntimePlatform.WindowsEditor) ? "C:" + 
                    System.Environment.GetEnvironmentVariable("HOMEPATH") + @"\.android\debug.keystore" : 
					"C:" + System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal) + @"/.android/debug.keystore";
            }
        }

        private static string GetKeyHash(string alias, string keyStore, string password)
        {
            var proc = new Process();
            var arguments = @"""keytool -storepass {0} -keypass {1} -exportcert -alias {2} -keystore {3} | openssl sha1 -binary | openssl base64""";
            if (Application.platform == RuntimePlatform.WindowsEditor)
            {
                proc.StartInfo.FileName = "cmd";
				// Added the path of jdk bin helped me remove keytool error
                arguments = @"/C:\Program Files\Java\jdk1.6.0_39\bin\" + arguments;
				UnityEngine.Debug.Log("Arguments:: "+arguments);
			}
            else
            {
                proc.StartInfo.FileName = "bash";
                arguments = @"-c " + arguments;
            }
			// proc.StartInfo.FileName = "cmd"; this statement was not there originally added it to try 

			proc.StartInfo.FileName = "cmd";
            proc.StartInfo.Arguments = string.Format(arguments, password, password, alias, keyStore);
            proc.StartInfo.UseShellExecute = false;
            proc.StartInfo.CreateNoWindow = true;
            proc.StartInfo.RedirectStandardOutput = true;
            proc.Start();
            var keyHash = new StringBuilder();
            while (!proc.HasExited)
            {
                keyHash.Append(proc.StandardOutput.ReadToEnd());
				UnityEngine.Debug.Log("KEY HASH:: "+keyHash.ToString());
            }
			UnityEngine.Debug.Log("Exit Code:: "+proc.ExitCode);
            switch (proc.ExitCode)
            {
                case 255: setupError = ERROR_KEYTOOL_ERROR;
                    return null;
            }
            return keyHash.ToString().TrimEnd('

');
}

        public static string SetupError
        {
            get
            {
                return setupError;
            }
        }

        public static bool HasAndroidSDK()
        {
            return EditorPrefs.HasKey("AndroidSdkRoot") && System.IO.Directory.Exists(EditorPrefs.GetString("AndroidSdkRoot"));
        }

        public static bool HasAndroidKeystoreFile()
        {
		    return System.IO.File.Exists(DebugKeyStorePath);
        }


        private static bool DoesCommandExist(string command)
        {
            var proc = new Process();
            if (Application.platform == RuntimePlatform.WindowsEditor)
            {
				//Again added the path 
                proc.StartInfo.FileName = "cmd";
                proc.StartInfo.Arguments = @"/C:\Program Files\Java\jdk1.6.0_39\bin\" + command;
            }
            else
            {
                proc.StartInfo.FileName = "bash";
                proc.StartInfo.Arguments = @"-c " + command;
            }
            proc.StartInfo.UseShellExecute = false;
            proc.StartInfo.CreateNoWindow = true;
            proc.Start();
            proc.WaitForExit();
            if (Application.platform == RuntimePlatform.WindowsEditor)
            {
                return proc.ExitCode == 0;
            }
            else
            {
                return proc.ExitCode != 127;
            }
        }
    }
}

I debugged the FacebookAndroidUtil class a little and I think something is odd with the Keytool detection. It checks for proc.ExitCode == 0 which seems reasonable to me but for me the call returns 1 (on Win 8.1 Pro). If I enter the same command in the start8 menu it works so I figured: OK, the detection is simply wrong. For the sake of not knowing what the correct detection would be I replaced the line:

return proc.ExitCode == 0;

with

return true

in DoesCommandExist(), restarted Unity and tadaaa, it works and the key is generated.

OK, I got it to work right. It wasn’t working even if openSSL was in my path. What worked for me was downloading the setup of openSSL, not the archive. So the setup made it all good.

Hey Guys,

When using Process “cmd” we have to add “/A” to redirect the internal output of command line to a channel
“cmd /A /C keytool -storepass {0} -keypass {1} -exportcert -alias {2} -keystore {3} | openssl sha1 -binary | openssl base64”

    private static string GetKeyHash(string alias, string keyStore, string password)
    {
      var proc = new Process();
      var arguments = "keytool -storepass {0} -keypass {1} -exportcert -alias {2} -keystore {3} | openssl sha1 -binary | openssl base64";
      if (Application.platform == RuntimePlatform.WindowsEditor)
      {
        proc.StartInfo.FileName = "cmd.exe ";
        arguments = "/A /C " + arguments; // /A to stream output
      }
      else
      {
        proc.StartInfo.FileName = "bash";
        arguments = @"-c " + arguments;
      }
      proc.StartInfo.Arguments = string.Format(arguments, password, password, alias, keyStore);
      proc.StartInfo.UseShellExecute = false;
      proc.StartInfo.CreateNoWindow = true;
      proc.StartInfo.RedirectStandardOutput = true;
      proc.Start();
      var keyHash = new StringBuilder();
      while (!proc.HasExited)
      {
        keyHash.Append(proc.StandardOutput.ReadToEnd());
      }

      switch (proc.ExitCode)
      {
        case 255: setupError = ERROR_KEYTOOL_ERROR;
          return null;
      }
      return keyHash.ToString().TrimEnd('

');
}

i don’t know if people are still having trouble with this but, my fix was to make sure that “C:\Openssl\bin” was in my user path.

the Error seems to be thrown when unity cant talk to OpenSSL via a new command line process.
ensure that you can access OpenSLL in the command line and that you firewall isn’t blocking it.

hope this helps some out there :slight_smile:

Hi !

I was searching and testing a lot of solutions about this error and I solved it like Symyon :
I have installed OpenSSL on “C:/OpenSSL” after downloaded the setup file founded here : OpenSSL for Windows

And Finally it works !!! =D

See this topic

Hope it will help someone :slight_smile:

this video will help you to solve the hash key problem