Re-Signing an iOS App Without Xcode

Mobile Development, Tutorials Comments (41)

If you’re into any sort of iOS development, you’re likely spending a lot of time with .ipa files, code signing entitlements, provisioning profiles, and development certificates. If your experience has been anything like ours, some days the code signing process has been nothing but a big headache (judging by the grumbling we see on Twitter from time to time, we know this has to be true for others out there, too). Sometimes it seems like simply updating a provisioning profile takes way longer than it should as you wade through the cryptic error messages Xcode gives about code signatures and entitlements. When deadlines loom, anything that gets between you and your final deliverable is just unneeded stress. We want to share with you a snippet of a shortcut in our workflow that has helped us save time when updating a provisioning profile or diagnosing invalid entitlements errors and the like. Before we get to that, we thought it would be helpful to get us all on the same page about provisioning profiles and code signatures.

Jump to the good stuff

The Structure of an iOS App

If you aren’t very familiar with iOS development, Mac packages or that sort of file in general, you may not be aware that the .ipa file that gets generated from Xcode is actually just a zip file that contains your app and the iTunes information (e.g. iTunesArtwork) that iTunes uses to manage the app. You can unzip this file by changing the extension to .zip or opening Terminal and running

unzip app.ipa -d app/

This will unzip the contents of the ipa file to the “app” directory. Within this directory, you’ll find this structure:

ipa-diagram

The .app file within the Payload directory is actually a folder with a file extension. You can open this by alternate clicking and selecting “Show Package Contents.” Within this file are all the resources for your application (images, HTML, video, etc.) and the compiled binary of your app. Also within this file is a file named embedded.mobileprovision. This is the provisioning profile that was originally packaged with the application. iOS automatically installs this provisioning profile on the device when installing the application (if the provisioning profile doesn’t already exist on the device). The provisioning profile is a plist file that specifies a handful of permissions for your app–most notably, the devices that it is provisioned to run on (for development or ad-hoc releases). If you’re running into an issue where an app is not installing on a device, you can verify whether the UDID is included in the embedded provisioning profile by opening the file in a text editor and finding the ProvisionedDevices key.

The last component of the .app file is the code signature contained within the _CodeSignature folder. The purpose of the code signature is to verify that every byte within the .app file is exactly the same as when it was signed by it’s creator (specified by the signing identity). Even swapping out an image with another image (even if it has the same name) will invalidate the signature. Any changes made to the .app file requires that the whole package be re-signed.

The Entitlements File

The entitlements file is used during code signing to specify special permissions within your app (like access to a shared keychain). Most apps use it to disable the get-task-allow property with specifies whether other users may debug your application (e.g. using Instruments). The entitlements file doesn’t actually belong inside the .app file (it shouldn’t be part of your Copy Bundle Resources build phase in Xcode), it is only used during the code signing process. You don’t need the entitlements file for a development build using a development provisioning profile unless you want to use push notifications, iCloud storage, or keychain sharing–to enable these features you must specify an entitlements file during code signing. Don’t forget that your entitlements file must also contain the application-identifier key  (e.g. 123456789.com.floatlearning.app).

Re-signing an Application

You may ask why you would ever want to modify the .ipa outside of Xcode. There are a few reasons we’ve wanted to do it: first, to update a mobileprovision file. Occasionally we’ll want to add a UDID to the provisioning profile for the app. We can simply swap out the embedded.mobileprovision file instead of needing to go through Xcode and rebuild the app. Also, from time to time, we’ll run into an issue where a client may get an error “The executable was signed with invalid entitlements.” This is the result of a mistake made earlier in the development process (e.g. forgetting to update the application-identifier within the entitlements file after changing the bundle identifier), but it is easily fixable without needing to rebuild the entire app. You could even make updates to the Info.plist file (e.g. changing the bundle identifier) if you really wanted to.

When you installed the Xcode developer tools, it included with it an application called codesign (/usr/bin/codesign). This is the application used by Xcode and the Xcode Organizer to sign your app after it has been built. We can use this application to replace an existing code signature after changing bundle resources or wanting to modify the entitlements that were used during code signing. You can use man codesign to get a description of all the possible arguments available to you, but we’ll call out the two we care about:

-f This flag allows us to “force” a code signature replacing the existing one. If we don’t specify -f, the code signing process will exit if a code signature already exists.
–entitlements=path This flag specifies the entitlements file to use for the code signature.

Our Signing Shortcut Script

When updating a provisioning profile or the entitlements of an already compiled app, we found ourselves repeating the same steps over and over again: unzipping the file, replacing the embedded.mobileprovision file, resigning the .app file, and packaging back up the .ipa. It wasn’t saving any time over simply going through Xcode–so we wrote a small bash script that does all the nitty-gritty work for us and we’d like to share it with you:

http://git.io/floatsign

This script will take a signed or unsigned app (either .ipa or .app), sign it, and package it up into a new .ipa file.

./floatsign source identity -p "path/to/profile" -e "path/to/entitlements" target
source The .ipa or .app file that needs signing.
identity The name of the code signing identity to use (e.g. iPhone Developer: Daniel Pfeiffer (ABC1234567)).
This is your development/distribution certificate provided by Apple. You can find out the common name of this certificate by looking in Keychain Access (we find it helpful to filter the list by clicking on “My Certificates” in the left column).
target The target for the newly-signed .ipa file.

This likely won’t cover every possible requirement in signing an iOS application, but it has been very helpful in our development process and we hope you find it to be helpful too. If you make any improvements to the script, please let us know in the comments or by making a Pull request on Github!

If you’re not the Terminal type, Brian Gorby (http://www.gorbster.net/) has created a droplet app for Mac, AppResigner, that does the same thing (but just with .app files; you’ll have to do the unzipping and zipping yourself if you only have a .ipa file).

Wish you could find some books about mobile development? Wondering how much a mobile app costs?

Interested in learning more about mobile development? Wish you could find some books about mobile development. Wondering how much a mobile app costs? Maybe your organization is looking to create its first mobile learning application. Contact us to learn more!

Follow Float
The following two tabs change content below.

» Mobile Development, Tutorials » Re-Signing an iOS App Without...
On November 15, 2011
By
, ,

41 Responses to Re-Signing an iOS App Without Xcode

  1. Rameesh says:

    I’m having this error running the script:

    codesign_allocate: object: /Users/Rameesh/Desktop/signme/temp/Payload/ITraters Group Wi-Fi.app/ITraters Group Wi-fi malformed object (unknown load command 9)
    temp/Payload/ITraters Gropu Wi-Fi.app: object file format invalid or unsuitable

    • Daniel Pfeiffer says:

      There are a few reasons (that I know of) that could cause an error like this. Most of the issues relate to an application package that doesn’t match the standard.

      I would first check the Info.plist file and make sure that the executable name matches the product name. It could also be that your product name is invalid–it looks like it has a space in it (ITraters Gropu Wi-Fi.app)? Try renaming it to not have a space or a hyphen.

      If those fail, you may also try reinstalling the developer tools.

      Hope that helps!

  2. Rameesh says:

    Hi again,

    Sorry for asking one more time, but I managed to get the sign process completed using your script..


    export CODESIGN_ALLOCATE=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/codesign_allocate

    ./floatsign.sh notsigned-final.ipa "iPhone Distribution: ITRaters Enterprise Ltd" -p ITRaters_Wifi_Profile.mobileprovision try1.ipa
    Specified provisioning profile: ITRaters_Wifi_Profile.mobileprovision
    APP_NAME=ITRaters Wi-Fi.app
    Adding the new provision: ITRaters_Wifi_Profile.mobileprovision
    Resigning application using certificate: iPhone Distribution: ITRaters Enterprise Ltd
    temp/Payload/ITRaters Wi-Fi.app: replacing existing signature
    Repackaging as try1.ipa

    The issue now is that when I try to upload the ipa file using the Application Loader I get the errors:


    The CodeResources file must be a symbolic link to _CodeSignature/CodeResources...


    Application failed codesign verification. The signature was invalid, or it was no signed with an IPhone Distribution Certificate.


    Unable to extract entitlements from application...

    And I’m sure the certificate used is valid, we use it in other development projects that we have the source code for, and the application submission works fine.

    Any suggestion would be more than appreciated.

    • Daniel Pfeiffer says:

      It looks like the signature that the script generated was invalid after it was wrapped up into an ipa. I think this is due to a small error in the script. On line 106, where it zips back up the ipa, try adding the -y argument. This keeps symbolic links in tack.

      Hope that helps!
      –Dan

  3. RS says:

    I really enjoyed this article and the script, but I just could not get it to work. I used the follwoing

    export CODESIGN_ALLOCATE=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/codesign_allocate

    And called the script as designed, but I received the following error:

    codesign_allocate: for architecture armv7 object: /Users/user/work2/temp/Payload/iDetail.app/iDetail malformed object (unknown load command 9)
    temp/Payload/iDetail.app: object file format invalid or unsuitable

    • Daniel Pfeiffer says:

      Hi RS,

      The first reason I can think of why you’d be receiving that error is that your executable name does not match the product name–in your case, make sure that the executable name in Info.plist is iDetail. Also make sure there are no special characters (like apostrophes).

      Hope that helps!
      –Dan

  4. [SIO-1796] PREHISTORIC MIGRATIONS: As a Shazamer I don’t want bad things to happen if I upgrade to 5.0 from a very old version (pre-3.0) so that I do not switch to a competing product…

    @Tim – one other thing. If at all possible, please can you try and get hold of *binary* snapshots of previous releases and re-sign them to run with an up to date provisioning profile, rather compiling from source? The logic here is that we need to tr…..

  5. […] Re-Signing an iOS App Without Xcode: Float Mobile Learning. […]

  6. Dave says:

    Thanks for the script!

    I also ran into the “object file format invalid or unsuitable” problem. This was the fix for me on Mountain Lion:
    http://stackoverflow.com/a/11723891/890558

  7. Lonny G says:

    Great post! I built a GUI implementation of an iOS app re-signer called ReSignMe which is targeted at those who shudder at the sight of a shell prompt. This post has brought up use cases that I didn’t even consider (such as handling entitlements).

    The latest build for ReSignMe can be found on GitHub. Any suggestions and/or contributions would be greatly welcome!

  8. amit says:

    Can we do this resignning an iOS app on windows too, or do we really need a Mac for this?
    Asking because I’m going to get .ipa file from my vendor and I want to resign this against my companies Enterprise license.

    • Daniel Pfeiffer says:

      Apple has only made the signing tools available for the Mac. It’s possible someone has made a Windows version, but the official tools are only available for Mac.

  9. amit says:

    @Daniel Pfeiffer: Thanks Daniel for the quick reply.
    Actually in solution posted above they have mentioned about some script: http://git.io/floatsign
    Which can be run from terminal like this
    ./floatsign source identity -p “path/to/profile” -e “path/to/entitlements” target

    So here its just source, cert path and target path, so I thought if I just want to resign the app with my own enterprise certificate do I really need Mac for this.
    It would be really helpful, if you can throw some light on this.
    My prob statement is: I’m getting an app from some developer say X and I want to resign this again, against my enterprise license, so this script will do the job for me, right?
    And do i need Mac for this script to resign the app?

    Thanks in advance.
    Amit.

    • Daniel Pfeiffer says:

      Unfortunately, you still need a Mac to run the script. The tools that it uses are part of the Xcode command line toolset which is only available for Mac.

  10. Olexandr Ponomarenko says:

    Please consider to adjust the script to let it work with files having multiple dots in name. Now the error Error: Only can resign .app files and .ipa files. produced for such kind of files.

    I fix it by changing the code in lines:
    64: if [ "${ORIGINAL_FILE##*.}" = "ipa" ]
    68: elif [ "${ORIGINAL_FILE##*.}" = "app" ]

    Note: use of longest matching pattern in parameter expansion (##).

  11. Sudheendra says:

    HI Daniel,

    Thanks for the article and insights.

    I am entirely new to this IOS stuff, i had to resign one of my apps for testing. But i could not figure what should i pass as input at argument 3 (IDENTITY), is this the name of developer or certificate name.
    Also if i have a provision certificate with me can i get the IDENTITY.

    Thanks for any inputs,
    Sudheendra

    • Daniel Pfeiffer says:

      “Identity” should be the name of the certificate to use for signing (e.g. “iPhone Developer: John Doe”). A provisioning profile can be tied to multiple certificates. The Apple Developer Portal website allows you to see which certificates are valid to use with which provisioning profile.

  12. MrDungLe says:

    Hey Daniel, i’ve resigned app and it’s installed on iPhone, but when i tap on icon app, it step out. Cannot access this application. Please explain me, many thanks!

    • Daniel Pfeiffer says:

      If the application installs on the phone, then the signature was prepared correctly. If the app is immediately closing then it is likely one of two problems: 1. The application is crashing (due to a programming problem) or 2. the certificate used to sign the application is expired. If you check the device console (through Xcode), it should help determine the problem.

      • MrDungLe says:

        This is console when crash app:

        Jun 23 14:30:06 CStoreIP7 crash_mover[3170] : MS:Notice: Injecting: (null) [crash_mover] (847.21)
        Jun 23 14:30:17 CStoreIP7 crash_mover[3172] : MS:Notice: Injecting: (null) [crash_mover] (847.21)
        Jun 23 14:30:22 CStoreIP7 backboardd[32] : __hid_dispatch_pthread_root_queue_create_block_invoke: specific=0x17d92750 pthread_self=0x3d35000
        Jun 23 14:30:24 CStoreIP7 kernel[0] : AppleFairplayTextCrypterSession::fairplayOpen() failed, error -42022
        Jun 23 14:30:24 CStoreIP7 backboardd[32] : Unable to obtain a task name port right for pid 3174: (os/kern) failure (5)
        Jun 23 14:30:24 CStoreIP7 com.apple.launchd[1] (UIKitApplication:com.sss.angicungduoc[0x1d4c][3174]) : (UIKitApplication:com.sss.angicungduoc[0x1d4c]) Exited: Killed: 9
        Jun 23 14:30:24 CStoreIP7 com.apple.launchd[1] (UIKitApplication:com.sss.angicungduoc[0x1d4c]) : (UIKitApplication:com.sss.angicungduoc[0x1d4c]) assertion failed: 11B554a: launchd + 74747 [C04CBC4A-F11B-3F42-8619-D512726C6533]: 0x16
        Jun 23 14:30:24 CStoreIP7 com.apple.launchd[1] (UIKitApplication:com.sss.angicungduoc[0x1d4c]) : (UIKitApplication:com.sss.angicungduoc[0x1d4c]) assertion failed: 11B554a: launchd + 74747 [C04CBC4A-F11B-3F42-8619-D512726C6533]: 0x16
        Jun 23 14:30:24 CStoreIP7 backboardd[32] : Could not set priority of [3174] to 1, priority: No such process
        Jun 23 14:30:24 CStoreIP7 backboardd[32] : Could not set priority of [3174] to 0, priority: No such process
        Jun 23 14:30:24 CStoreIP7 com.apple.launchd[1] (UIKitApplication:com.sss.angicungduoc[0x1d4c]) : (UIKitApplication:com.sss.angicungduoc[0x1d4c]) Throttling respawn: Will start in 2147483647 seconds
        Jun 23 14:30:24 CStoreIP7 backboardd[32] : Application ‘UIKitApplication:com.sss.angicungduoc[0x1d4c]’ exited abnormally with signal 9: Killed: 9
        Jun 23 14:30:30 CStoreIP7 crash_mover[3175] : MS:Notice: Injecting: (null) [crash_mover] (847.21)

        • Daniel Pfeiffer says:

          The console log indicates the application was terminated due to FairPlay. Applications on the App Store are protected; you should only re-sign applications that you’ve created.

  13. Jet Fire says:

    Hi i’d like to Know something very important: this script resign apps SO it resign ap for one registred device or for each person which try to install the ipa on their phones ?
    Thanks in advance

    • Daniel Pfeiffer says:

      This script is for updating the code signature using a different/updated provisioning profile than that which was used to create the original signature.
      Thanks,
      –Daniel

      • Kevin says:

        Would it be possible to run this script on a VPS? I want to sign IPA’s online where people upload a .IPA and a certificate. Is this possible?

        • Daniel Pfeiffer says:

          Yes, this is very possible–but the VPS would need to have Xcode installed meaning it would have to be running the Mac OS. The script uses dependencies that are only (officially) available with Xcode on a Mac.

  14. John Son says:

    Hi,
    I wonder whether the script can resign multi ipa file by once execution time? It means the script can browser all ipa file in a folder and resign them. Many thanks.

  15. JohnnyK says:

    I’m trying to set get-task-allow to true. Is that a possible and simple thing to do with this script?

    • Daniel Pfeiffer says:

      You may specify your own entitlements with the -e option. Keep in mind that enabling get-task-allow requires a development provisioning profile, not a distribution provisioning profile.

  16. John Quier says:

    Hi if i read correctly it’s possible to sign an unsigned ipa isn’t it ?

  17. Ron Aaron says:

    I have successfully used your script in the past (thank you!), but now I’m getting told by XCode (when I try to install the app) that it “cannot be verified”.

    I removed my certificates and created new ones and installed them, and new provisioning profiles.

    I did the ‘codesign verify’ which tells me that everything is fine. But I can’t get the ipa to deploy via XCode or any other mechanism!

    I am not using XCode to build the application, but that hasn’t been a problem in the past; I just have no idea what to try next. Any clues you can throw my way will be most appreciated. Thanks!

    • Daniel Pfeiffer says:

      Hi Ron,

      Try editing the script and removing the resource rules around lines 96 and 98. These are no longer needed. I’ve also updated the script on GitHub.

      Thanks!
      –Dan

      • Ron Aaron says:

        Hi, Dan –
        I refreshed the script from GitHub just to make sure I had the latest and greatest.
        Getting the ‘The application does not have a valid signature’ from XCode.

        The thing that’s making me crazy is that I know it’s possible on this machine; XCode can create and install an application (I tried that to make sure it wasn’t something more serious). So my credentials are OK (or should be).

        I’m using my ‘iPhone Developer’ certificate, and a provisioning profile which has the devices I’ve got listed in them.

        Could it be something wonky in the layout of my .app or maybe my plist?

        Thanks for your help!

        • Daniel Pfeiffer says:

          Do you get any errors or warnings while re-signing the application? Do you need to specify entitlements during the signing process?
          Thanks,
          –Dan

  18. Philip says:

    Thanks for writing and sharing the script. It was very helpful to encounter.

    For others coming here:
    It does look like its gotten forked extensively without quite converging and a lot of good fixes getting done during that. From reviewing a lot of them, it looks like the most evolved version of this is:
    https://github.com/nanonation/floatsign

    I’m just now giving it a try, but it does visibly have fixes for several issues that the current script has.

  19. Abhishek says:

    Thanks for writing and sharing this script. Can we resign any developer or distribution (app store , enterprising , testing ) app with our developer certificates and provisioning profile to debug them??

Leave a Reply

Your email address will not be published. Required fields are marked *

« »