Marc Hughes


Home
Blog
Twitter
LinkedIn
GitHub
about
I am a developer from a bit west of Boston.

A lesson on AIR certificate signing

06 May 2010

Yesterday, I created a new version of one of my AIR apps. I tested it, it looked good, so I uploaded to my distribution site. One of the tests I always do after that is to use the auto-update feature to make sure the upgrade goes smoothly for my customers. It found the update, downloaded it as usual, began installing, and them BAMN

"Air cannot install this application because the installer is misconfigured."

Odd I thought. So I dusted off a couple virtual machine images with different versions of AIR and my application installed, and they all behaved the same.

Then I tried to upgrade by manually double-clicking the .air package and got this error: "The application could not be installed because an application with that name already exists at the selected installation location. "

It turns out that I hadn't made a release since last I renewed my code signing certificate. Now, last year, around this time I didn't have any problems. I just signed the new version with the new certificate and it all worked fine. But this year, something's different.

After some digging around, I found out I may have to migrate from my old certificate to the new one. It's a fairly trivial process. First you create your air package with your new certificate. Then you run adt and also sign it with your old certificate. A command like this works:

adt -migrate -storetype pkcs12 -keystore ../OLDAgileAgenda.p12 -storepass MYPASSWORD -keypass MYPASSWORD AgileAgendaBC0070.air AgileAgendaBC0070migrated.air

BUT. When I ran that I received an error about my old certificate being expired and I can't use it. Oh shit. You need to migrate certificates before they expire?

Some googling around and I found the answer. Apparently this was a common enough problem that AIR 1.5.3 changed this behavior slightly. Now, you can migrate from an expired certificate, but only for 180 days after the expiration. Luckily, I'm easily within that 180 day window, but I pitty large commercial applications that go out on CD and don't get updated that often. (About that time I got spooked since I worked on one of those.  But that's an enterprise-level problem to be solved in an enterprise-level way at an enterprise-later date and time.)

So to update my AIR sdk I downloaded from here and followed the instructions <a href="http://www.adobe.com/support/documentation/en/air/151/releasenotesdevelopers.html#sdk">here.

Now, my adt migrate command worked perfectly.

So I tried installing the migrated air package, and the upgrade went through perfectly.  A shot at the auto-update, and that worked as well.

But I noticed something when I ran the app.  It had forgotten all my settings.  Unfortunately, that included the registration info.  If I released like this, I know I'd have dozens of angry emails the next day with customers who can't find their license keys anymore.  So some more googling...

Turns out, the publisher ID changes when your certificate changes.  That publisher ID is the weird string in your local settings directory.  For instance, on OSX the local settings dir for my app was ~/Library/Preferences/com.agileagenda.AgileAgenda.F49A4D8DF78A1FEE7A3BE440DC11BAB18D922274.1

Now, there was an entirely new directory being created with a different publisher ID.

After some more searching, I found out that AIR 1.5.3 also solved this problem.  You can add a publisher id tag to your -app.xml file to specify one to use, such as:

<publisherID>F49A4D8DF78A1FEE7A3BE440DC11BAB18D922274.1</publisherID>

To use that, you'll also have to update the XML namespace at the top of the file

<application xmlns="http://ns.adobe.com/air/application/1.5.3" >

(NOTE: For brand new applications, don't specify a publisher id.  They're being phased out.  Blank is better since your config directory name will be cleaner)

After doing that, I rebuild my air package, re-signed it with the migration certificate, re-performed all my tests.  And all was good.

Hopefully, this blog post will save someone else in the same situation a lot of frustration.