Tutorial: Understanding Android App Signing

Tutorial: Understanding Android App Signing

I must admit that when I started developing mobile apps, I was confused by the various requirements for protecting apps and guaranteeing their authenticity. On the iOS side, you have terms like entitlement, provisioning profile, bundle ID, and a host of other things. Android has similar functionality and their phrasing is equally confusing, including terms such as keystore, key hash, alias and, in addition, there are commands which must be entered on the command line.

This week’s tutorial looks specifically at the Android signing process with the goal of bringing clarity and understanding to this potentially complex topic.

The Keystore

The basics behind protecting your Android app is to use a generated certificate and digital “key” which provides a unique, encrypted, and reasonably un-hackable signature. This proves that the app came from you, not some other suspicious source.

On Android, this is done via a keystore. The keystore is a simple file with a really large block of encrypted data. This file can be stored anywhere on your computer, and this is generally the first problem that developers encounter. Because there’s no standard location in which to store these, it’s easy to “lose” them — we will address this issue in a bit.

Next, there are two types of keystores that you should be aware of: debug and release. The debug keystore should be used while developing your app — for example, it can be used when manually installing (side-loading) apps to local Android devices. However, the debug keystore can not be used for an app destined for Google Play or Amazon — for this, you must use a release keystore.

For both types, a keystore is identified by two aspects: the filename that it’s stored in and an alias. Because a keystore file could potentially store multiple keystores, each one is identified by an alias. In most cases, you’ll only have one certificate/key pair in a file, but you still need to give it an alias.

Keystore files are also protected by a pair of passwords: one for the keystore file itself and another for each keystore/alias pair within the file. While these passwords should ideally be unique, most developers use the same password for both.

Debug

Debug keystores are somewhat standard. Google provides one with the Android Developer Tools but, for your convenience, Corona provides you with a debug keystore as well. This keystore is located in a standardized folder within your CoronaSDK application folder and you should use it while developing Corona apps.

Release

To create a release keystore for your app, you need to execute a command from your OS command line. For OS X, this is done via the Terminal app in which you’re presented with a $ prompt. For Windows, this is done via the Command Prompt which can be accessed by opening the Start menu and searching for cmd. In Windows, you’ll be presented with a prompt like: C:\>

As mentioned above, there’s no standard place to store keystore files, so it may be useful to create a folder specifically for this. By default, both the OS X Terminal and Windows Command Prompt will start within your “home” directory. On Mac, this translates to /Users/yourloginname and on Windows it translates to something like C:\Users\yourloginname. Within this home folder, you can create a folder to hold your keystores.

In Windows, type:

md Keystores

In OS X, type:

mkdir Keystores

Once this is done, you can access the folder by typing:

cd Keystores

Once inside the Keystores directory, you should issue a command that’s fairly complex. Before proceeding, it’s very important to understand that this is not a “copy-and-paste” procedure — you must substitute values that are specific to the keystore you wish to generate.

For the moment, let’s carefully inspect and dissect the following line:

keytool -genkey -v -keystore mykeystore.keystore -alias aliasname -keyalg RSA -validity 999999

Essentially, the first term means that this line will execute a program called keytool. For OS X, this should be installed already, but Windows users may need to install it (see below). Following this, all of the parts that begin with a hyphen (-) indicate parameters for the keytool command. Those options are as follows, and those in bold are the two which must be customized (the others can remain as shown):

  • -genkey — Tells keytool to generate a key.
  • -v — Tells keytool to be verbose (i.e. tell you what it’s doing).
  • -keystoreThe filename to save the keystore as.
  • -aliasThe alias name to identify the keystore.
  • -keyalg RSA — This says to use the RSA method to generate the keystore.
  • -validity 999999 — This says to make the keystore valid for 999,999 days.

For the keystore name, provide it with a name that makes sense. In theory, you should use a unique release keystore for each app, but it’s not required. For example, a puzzle game named “SwapIt” may have a keystore name such as swapit.keystore, but a more general release keystore could simply be release.keystore.

For alias, provide it with a similar sensible name, for example swapit.

With these changes, the line should look more like this:

keytool -genkey -v -keystore swapit.keystore -alias swapit -keyalg RSA -validity 999999

Now hit the return/enter key to execute the command. You’ll then be prompted for more information in a routine that will appear as follows in the command window:

The first password is the password for the overall keystore file. Next you’ll be asked for your first and last name (surname). The prompt for “organizational unit” is for companies with multiple departments like “Engineering” or “Development” and this value is not important for most Corona developers, but you need to still provide a value, such as “Development”. In addition, you’ll be prompted for your city, state/province, and country code.

At this point, you must type in yes to confirm the information. Finally, if desired, you can supply a different password to the individual alias entry, or simply press return/enter to use the same password associated with the keystore file.

When this is done, your keystore file will be in the folder where you ran the command.

Installing “keytool”

The keytool utility should be installed as part of JDK (Java Development Kit). This tutorial will not discuss actual installation of JDK, so if you’re new to this process, please read our corresponding guide.

On Mac, the keytool utility will be placed in a location such that you can just type keystore in the Terminal to run it. On Windows, this likely won’t be the case — when you installed the JDK, it was probably installed within a folder specific to the JDK version. For instance, on my Windows 7 computer, it’s located in:

Because the keytool utility is located here, it’s tempting to simply change to this directory and type keytool ... directly, but if you update/reinstall JDK and your keystores are stored here, you’ll lose all of those you already created. As such, a better solution is to prefix the location of your Java install before the keytool command. Before doing so, you must set an environment variable called JAVA_HOME which will provide a shortcut that you can use. If you’re not familiar with this task, see this tutorial. Once it’s set, you can prefix it to the keytool command as follows:

%JAVA_HOME\bin\keytool ...

For instance, using the example keystore details from above, the command becomes this:

%JAVA_HOME\bin\keytool -genkey -v -keystore swapit.keystore -alias swapit -keyalg RSA -validity 999999

Building the App

To build with your release keystore, launch Corona SDK, load your app, and then build for Android (File → Build → Android…). In the Keystore dialog box, click on the Browse… button beside the Keystore pulldown menu. Navigate to where you saved your keystore file and select it from the dialog box, upon which you’ll be prompted to enter the keystore password.

Once it’s loaded, you’ll see that the Key Alias field is empty. Select the proper alias in this pulldown list and click the Build button. Corona will then prompt you to enter the alias password. Once entered correctly, you’ll be taken back to the build screen where you can hit Build again to build the app. Fortunately, for as long as you use this same release keystore/alias, you won’t need to re-enter the passwords each time.

Keyhashes and SHA1 Signatures

When working with third parties like Facebook or Google Play Game Services (GPGS), sometimes you’ll be asked to generate a value from your keystore. For Google Play Game Services, you must use a release keystore for this task. For Facebook, you can develop/test with a debug keystore, but you’ll eventually need to provide them with information for an app signed with a release keystore.

Both a keyhash (used by Facebook) and a SHA1 signature (used by GPGS) are short strings consisting of values that are calculated from the much larger keystore file. While these two are different values, the concept is the same — some standard math is performed on the values in the keystore to generate a unique value that cannot be easily reversed, helping ensure that the keystore hasn’t been altered by a hacker.

Generating a Keyhash

To generate the keyhash, you once again need to use the command line and enter a line which appears complex but in truth consists of just three commands:

keytool -exportcert -alias yourkeyalias -keystore yourkeystore.keystore | openssl sha1 -binary | openssl base64

The three commands taken separately are as follows:

  • keytool -exportcert -alias yourkeyalias -keystore yourkeystore.keystore
  • openssl sha1 -binary — uses the SHA1 method of calculating a signature, output as binary.
  • openssl base64 — outputs the data in Base64.

As you can see, these three commands are separated by pipe (|) characters. The first command runs and outputs its results, which in turn becomes the input for the second command. Then the second command outputs its results which become the input for the third command. This can cause potential issues because, if there’s even a slight problem in an earlier command, the error gets passed on to the next command rather than the expected data.  For instance, if you mis-type your password, this command series will not notify you but rather produce an SHA1 string based on the input of “Invalid Password”.

In any case, as noted earlier in this tutorial, this is not a copy-and-paste command — you must adjust -alias and -keystore to your specific values. When running this command using the keystore created above, the result is:

tZRNBKXmYKOa22HvFl57za4gvU0=

Note the = sign at the end — this indicates the end of the string and it is important.

Generating a SHA1 Signature

GPGS, in contrast, needs a text representation of the SHA1 output. Fortunately, the keytool utility can output this without any additional commands:

keytool -exportcert -alias swapit -keystore swapit.keystore -list -v

After you enter the password, the output will look something like this:

In this output, the SHA1: line is the string of hex digits which you need to provide to GPGS when setting up your app, as well as the value you need to provide to Google when setting up your app there. Alternatively, if you need the SHA1 signature formatted as a string rather than a colon-separated hex string, use this command:

keytool -exportcert -alias swapit -keystore swapit.keystore | openssl sha1 -hex

Conclusion

Hopefully this tutorial has helped clarify and understand the Android signing process better. Remember these command lines and the familiarize yourself with the parameters, and Android signing will soon become a simple task.

Rob Miracle
[email protected]

Rob is the Developer Relations Manager for Corona Labs. Besides being passionate about helping other developers make great games using Corona, he is also enjoys making games in his spare time. Rob has been coding games since 1979 from personal computers to mainframes. He has over 16 years professional experience in the gaming industry.

23 Comments
  • Andreas
    Posted at 16:43h, 26 August

    Hi Rob,

    I haven’t done these steps for quite a while but I’ll have to do them in a few weeks again – so thanks a lot for this nice compilation of all the stuff that has to be done in a nutshell.

    Best,
    Andreas

  • undecode
    Posted at 20:10h, 26 August

    Rob, wonderful contribution.

    I remember back in the time having problems with this until i found a step-by-step guide to create a keystore to publish my app. This is really complete and will help new developers, also the additional information about keyhashes helps me in case google doesn’t recognize the one in the app automatically when using GPGS.

    Thanks

  • Mo
    Posted at 21:40h, 26 August

    PERFECT! Thanks Rob 🙂

    MO

  • Mo
    Posted at 21:44h, 26 August

    The reason I said perfect not only because it is a fantastic tutorial but also because I was always affraid to touch the GPGS part (for leaderboard) with this I think I can attempt to add leaderboards to my apps in Android! Still scary but this explain a lot about the SHA1 business (man who came up with this stuff 🙂

    Thanks again.

    Mo

  • Danial
    Posted at 04:38h, 27 August

    I’ve never had to provide the SHA1 to get GPGS leaderboards to work for my Android apps I haven’t been asked to provide it, so I am confused.

    • Rob Miracle
      Posted at 19:09h, 27 August

      If you upload your app to Google Play in Beta or Alpha mode before setting up the GPGS application, then it fetches the SHA1 signature from your uploaded APK (this is new, it didn’t use to be this way). But you can setup a GPGS application before you upload a .apk to Google Play. In which case you have to enter the SHA1 signature of the app’s release keystore.

      • Danial
        Posted at 09:11h, 28 August

        Ah, thanks for clearing that up, Rob! *phew*

  • Mo
    Posted at 22:27h, 27 August

    Hi Rob,

    Are you saying that IF we have apps already live on Google Play and wanted to add a leaderboard (GPGS) to them, we would not need to deal with all that SHA1 business?

    That would be cool! I was frankly scared to go thru those steps. Thanks God for your tutorial!

    Thanks,

    Mo

    • Rob Miracle
      Posted at 15:33h, 28 August

      You still have to go through all the setup steps, but if you have uploaded the .apk first and then “link to the app” then it will get the SHA1 signature for you, so that at least saves you the pain of generating it form the command line.

      Rob

  • Mo
    Posted at 23:57h, 29 August

    Thanks Rob!

    Mo

  • Kiffin Ayers
    Posted at 20:45h, 09 October

    The SHA1 is requested when setting up your Android app on GameThrive. This tutorial was/is a life saver! Thank you Rob!

  • Tarun
    Posted at 22:32h, 28 March

    Hi Rob,

    This has proved to be a very useful tutorial for me to at least start a process to create keystore. Bur I am stuck at a point. It says an error as:
    ‘-genkey’ is not recognized as an internal or external command,
    operable program or batch file.

    Please help

    • Rob Miracle
      Posted at 20:48h, 29 March

      That sounds like you’re running -genkey on a second line. That command has to be strung together on one line.

  • ssiri
    Posted at 14:01h, 02 April

    Superb Explanation.Thanks 🙂

  • Milind
    Posted at 21:35h, 08 September

    Thanks for a very clear and succinct explanation. One thing, I’d suggest is to increase the default strength of the keystore, if possible, before you put your first app in the PlayStore since you can’t change it after the fact.

    See https://commonsware.com/blog/2013/09/09/psa-think-about-stronger-app-signing-keys.html

    So adding a -keysize 4096 to the keytool command would be good.

  • Kritika Maheshwari
    Posted at 04:32h, 11 March

    Hii
    I have third party app and I dont have any SHA1 print. So while uploading it says print mismatch.Upload failed
    You uploaded an APK that is signed with a different certificate to your previous APKs. You must use the same certificate. Your existing APKs are signed with the certificate(s) with fingerprint(s).

    What should I do? I got large number of downloads.

    • Rob Miracle
      Posted at 19:44h, 11 March

      You must use the same keystore that you first submitted the app with when you update. If you’ve lost that keystore and create a new one, your only choice is to create a new app.

  • David
    Posted at 07:22h, 17 March

    How do I create the certificate in the keystore as a p12 or pfx file?

    • Rob Miracle
      Posted at 16:53h, 17 March

      You will probably have to go to Google and look that up. There isn’t anything special about our keystores. They are standard Android keystores. If it can be done there should be plenty of tutorials out there.

  • Ucef
    Posted at 16:27h, 31 March

    OMG, Why you Make it hard like it, with don’t use like eclipse or android studio signing

    • Rob Miracle
      Posted at 06:40h, 01 April

      I would argue that our signing is quite simple. You hit the build dialog. Make sure you’re pointing to the keystore and your app is signed with almost no effort. Getting the keystore is not GUI based, but nothing prevents you from using Eclipse or Android studio to create the keystore in the first place. Also consider that you have to install very large IDE’s with either Eclipse or Android Studio for the sole purpose of generating a keystore. Corona SDK doesn’t need either of those IDE’s to work. A simple command line command that is installed as part of the Android tools needed to build the apps from Corona SDK is already there, ready for you to use. Now if Corona SDK needed Eclipse or Android Studio as part of it development workflow, then this would be a different story.

  • mahender
    Posted at 07:02h, 14 July

    But after all these steps on the add a key time they are showing “your android signing key is locked”.
    How i can fix this problem

    • Rob Miracle
      Posted at 11:09h, 14 July

      I looked at that error and it seems to be a PhoneGap error. I’ve never seen a Corona Labs project produce that error. If you are using Corona SDK, I would suggest you ask in our community forums at https://forums.coronalabs.com. If you’re not using Corona SDK or one of our other products, I’m not sure of what benefit we would be to help you resolve this. If you don’t know what Corona SDK is all about I invite you to visit and check out our wonderful cross-platform development tools.