{"id":1319,"date":"2015-02-19T00:00:00","date_gmt":"2015-02-19T00:00:00","guid":{"rendered":"https:\/\/www.fussylogic.co.uk\/blog\/?p=1319"},"modified":"2015-02-19T20:36:50","modified_gmt":"2015-02-19T20:36:50","slug":"signing-an-android-app","status":"publish","type":"post","link":"https:\/\/www.fussylogic.co.uk\/blog\/?p=1319","title":{"rendered":"Signing an Android App"},"content":{"rendered":"<p>Before you release you\u00e2\u20ac\u2122ll need to sign your <code>.apk<\/code> file. The <a href=\"http:\/\/developer.android.com\/tools\/publishing\/app-signing.html\">guide<\/a> from Google implies that you should make a single key for your identity, and sign all your apps with that key. I recommend against that. You should make a key per app. The reason I suggest that is because one day you might want to hand over responsibility for that app to another company or developer, or, the lottery win, a company wants to buy the whole thing from you. In that case, if you have a company-wide key, then you\u00e2\u20ac\u2122re handing over keys to all your apps, not just one.<\/p>\n<p>For all of this I\u00e2\u20ac\u2122ll assume you already have the Android SDK installed. You\u00e2\u20ac\u2122ll also need a JRE package for the <code>keytool<\/code> and <code>jarsigner<\/code> tools.<\/p>\n<p>Let\u00e2\u20ac\u2122s say then that you\u00e2\u20ac\u2122re signing <code>MegaApp.apk<\/code>. First you should generate an individual key store just for this app.<\/p>\n<pre><code>$ keystore -genkey -v \\\n    -keyalg RSA -keysize 2048 -validity 10000 \\\n    -keystore megaapp.jks \\\n    -alias megaapp\nEnter keystore password:  \nRe-enter new password: \nWhat is your first and last name?\n  [Unknown]:  MegaApp\nWhat is the name of your organizational unit?\n  [Unknown]:  Android Apps\nWhat is the name of your organization?\n  [Unknown]:  FussyLogic Ltd\nWhat is the name of your City or Locality?\n  [Unknown]:  Cheshire\nWhat is the name of your State or Province?\n  [Unknown]:  England\nWhat is the two-letter country code for this unit?\n  [Unknown]:  GB\nIs CN=MegaApp, OU=Android Apps, O=FussyLogic Ltd, L=Cheshire, ST=England, C=GB correct?\n  [no]:  yes\n\nGenerating 2,048 bit RSA key pair and self-signed certificate (SHA256withRSA) with a validity of 10,000 days\n        for: CN=MegaApp, OU=Android Apps, O=FussyLogic Ltd, L=Cheshire, ST=England, C=GB\nEnter key password for &lt;megaapp&gt;\n        (RETURN if same as keystore password):  \n[Storing megaapp.jks]<\/code><\/pre>\n<p>We\u00e2\u20ac\u2122re going to store one key per keystore, so we name the key and the keystore both megaapp (this makes it easier to remember what alias you used :-)). You can, of course, pick your keystore password as you wish to match the security of your organisation \u00e2\u20ac\u201c however, I suggest you treat the keystore file itself as the secure element, and make the password the same as the alias, \u00e2\u20ac\u0153megaapp\u00e2\u20ac\u009d (we\u00e2\u20ac\u2122ll see why below). You can pick the DN (distinguished name) as you please, my recommendation is not to put your own name when asked, but to put the name of the app again.<\/p>\n<p>We\u00e2\u20ac\u2122ve got a 2048 bit key, valid for 10,000 days (27 years), stored in a keystore file under an alias and password the same as the keystore name. Obviously this file has very poor internal security \u00e2\u20ac\u201c so you must be very circumspect in where you store and who you give access to this file.<\/p>\n<p>What I\u00e2\u20ac\u2122d like to describe is using a continuous integration system (I like Jenkins) to build and sign a release-ready version of your apk. For that reason we\u00e2\u20ac\u2122re going to do everything on the command line so that you can reproduce the process in your build server\u00e2\u20ac\u2122s scripts.<\/p>\n<p>Build your app. Here\u00e2\u20ac\u2122s how I do it:<\/p>\n<pre><code>cd your\/app\/directory\nrm -f build.xml\nrm -f local.properties\nandroid update project --name &quot;MegaApp&quot; --path .\nant clean\nant release<\/code><\/pre>\n<p>The <code>ant release<\/code> command builds you an <em>unsigned<\/em> <code>.apk<\/code> (unlike the <code>ant debug<\/code> command, which builds an <code>.apk<\/code> signed with the debug key, which is unsuitable for release to the Play store). If you have a more complicated app, perhaps with libraries, you may want to copy or symlink them in this sequence too.<\/p>\n<p>We\u00e2\u20ac\u2122re now in a position to produce a signed <code>.apk<\/code>. It\u00e2\u20ac\u2122s all boilerplate, so you will substitute your app name where appropriate.<\/p>\n<pre><code># input parameters\nAPKNAME=MegaApp\nKEYALIAS=megaapp\n\n# standard form of files and aliases\nKEYSTORE=${KEYALIAS}.jks\nSTOREPASS=${KEYALIAS}\nKEYPASS=${KEYALIAS}\nUNSIGNED=bin\/${APKNAME}-release-unsigned.apk\nSIGNED=bin\/${APKNAME}-release-signed.apk\nALIGNED=${APKNAME}.apk\n\n# generate signed-but-unaligned apk\njarsigner -verbose \\\n    -sigalg SHA1withRSA -digestalg SHA1 \\\n    -keystore ${KEYSTORE} \\\n    -storepass ${STOREPASS} \\\n    -keypass ${KEYPASS} \\\n    -signedjar &quot;${SIGNED}&quot; \\\n    &quot;${UNSIGNED}&quot; ${KEYALIAS}\n# check signing worked\njarsigner -verify -verbose -certs &quot;${SIGNED}&quot;\n# create aligned apk from signed apk\nzipalign -v 4 &quot;${SIGNED}&quot; &quot;${ALIGNED}&quot;<\/code><\/pre>\n<p>I\u00e2\u20ac\u2122m presenting this in a form that cuts-and-pastes into a script, with only a couple of name changes at the top to make it suit your app.<\/p>\n<p>Hopefully you see the logic in using such an insecure password \u00e2\u20ac\u201c if we <em>had<\/em> used a secure password, we would have had to write it, plain text, in this script anyway so that the signing could be automated \u00e2\u20ac\u201c so what security would we actually have gained? Someone with access to the key store would have access to this script, and hence would have the password anyway.<\/p>\n<p>Importantly: the keystore is now your signing security \u00e2\u20ac\u201c if you lose control of that then others can tell your users that any arbitrary <code>.apk<\/code> they produce is actually an upgrade to your app. <em>Keep this file safe<\/em>.<\/p>\n<p>Feel free to combine the build and sign snippets into a single file.<\/p>\n<p>As I said, I have, essentially, this script on my Jenkins build server for my Android apps \u00e2\u20ac\u201c that server is never exposed to the public internet. On completion the signed app is copied to a web server were my clients can download it at their leisure \u00e2\u20ac\u201c the advantage of a signed app is that your users can rely on upgrades being a trusted chain. Of course you can also upload the <code>.apk<\/code> to the Play store.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Before you release you\u00e2\u20ac\u2122ll need to sign your .apk file. The guide from Google implies that you should make a single key for your identity, and sign all your apps with that key. I recommend against that. You should make a key per app. The reason I suggest that is because one day you might\u2026 <span class=\"read-more\"><a href=\"https:\/\/www.fussylogic.co.uk\/blog\/?p=1319\">Read More &raquo;<\/a><\/span><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[9,146,6],"_links":{"self":[{"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1319"}],"collection":[{"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1319"}],"version-history":[{"count":1,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1319\/revisions"}],"predecessor-version":[{"id":1320,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1319\/revisions\/1320"}],"wp:attachment":[{"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1319"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1319"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1319"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}