Skip to content

Instantly share code, notes, and snippets.

@erenkabakci
Forked from phatfly/Apple resigning an ipa
Created June 10, 2020 17:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save erenkabakci/958f2385b2cd1ff2cc3f38f51aadeb1b to your computer and use it in GitHub Desktop.
Save erenkabakci/958f2385b2cd1ff2cc3f38f51aadeb1b to your computer and use it in GitHub Desktop.
Resigning an iOS xcarchive for the app store (xcarchive to ipa)
Resigning an iOS ipa for the app store
Introduction
Friday, October 18, 2019
For the release of company iOS applications to the Apple app store we need to resign those apps with our appropriate distribution certificate. This is the process you need to follow, as-of-this-writing, to properly re-sign an foo.ipa to upload to Apple using the Application Loader.
This writing is making the assumption that the foo.ipa bundle that you has been created appropriately and that is only needs to be resigned.
Things you need to get started
1. A Mac with XCode installed.
2. A developer account with the appropriate access.
3. A company distribution certificate installed in your keychain.
4. The foo.mobileprovision file for the intended release.
5. The foo.ipa bundle.
Put the foo.ipa and the foo.mobileprovision files in a directory by themselves. This is purely a housekeeping suggestion.
Unzip the foo.ipa file
Start by using this command to unzip the foo.ipa bundle:
$ unzip -q foo.ipa -d ./newipa/
Create an Entitlements.plist file
Start by grabbing the entitlements from the existing foo.app buried in it. If you right click on the foo.ipa choose the “Show Package Contents” option (from now forward we will assume you know how to go into .app files using this option). The foo.app is in the Payload directory. Open a terminal at the Payload directory.
Use this command to copy the existing entitlements from the foo.app
$ codesign -d --entitlements :- *.app > ../../entitlements.plist
Run this command in terminal to read the foo.mobileprovision file:
$ security cms -D -i foo.mobileprovision
Look for the <key>Entitlements</key> and the dictionary of entitlements that follows in the printout of that command. There is a lot in that file, but only focus on the entitlements entry. These two sets of entitlements have options that the release needs and they may not match each other. If your entitlements.plist is different than the mobile provision file you will need to figure out why and which entries need to be corrected. The application-identifier and the team-identifier need to be changed to the ones that you are publishing for. All the other possible entitlements are ones the app is intending to support. If the development team has made a change in XCode, you will see that in the plist file.
Replace the embedded.mobileprovision file
Now you need to replace the embedded.mobileprovision file with the foo.Mobileprovision file.
Use this command to replace the embedded.mobileprovision file:
$ cp /pathToFile/foo.mobileprovision foo.app/embedded.mobileprovision
Update the info.plist
Now is a good time to update the info.plist file in the foo.app. Go into the foo.app and open the info.plist file and change the bundle id. You can also change the version numbers at this time, if you need. Also, you can add missing entries, but it is better to push this back at the development team of the app. Be careful to not make changes that are not coordinated with that development team. Just because we can make changes ... doesn’t mean we should.
Remove all _CodeSignature entries
Now you need to remove the code signatures. There are several places this needs to be done. All the frameworks, libraries, plugins, extensions and the main bundle need to be resigned. First, we remove the code signatures with these cmds:
(These are not ALL the commands you might need. If the app you are signing uses extensions, plugins, or other nested code, those need to be cleaned and signed, too.)
$ rm -rf /foo.app/Frameworks/*/_CodeSignature $ rm -rf /foo.app/_CodeSignature
$ rm -rf /foo.app/_CodeSignature
Resign the app
Now you need to resign the app and this happens in a certain order from nested components up to the main bundle. It must be done in this order.
First, you need to know your code signing identity account. Use security to find all the code signing accounts on your computer. If you don’t see the one you need, you need to install it before proceeding. Here is the security command to see all installed code signing identities:
$ security find-identity -vp codesigning
Use the appropriate code signing name in parenthesis in the next code signing commands.
These are the code signing commands in the needed order:
(These are not ALL the commands you might need. If the app you are signing uses extensions, plugins, or other nested code, those need to be cleaned and signed, too.)
$ codesign -f -s "codesiging identity" -v foo.app/Frameworks/*
$ codesign -f -s "codesiging identity " --entitlements /pathToEntitlements/entitlements.plist foo.app
You can check that the foo.app entitlements are now correct with this command:
$ codesign -d --entitlements - foo.app
Zip it back into an ipa
Make sure you are in the newipa/ directory and not in the Payload. You may have other directories there too. Most notably the Swift support and dsym directories. These are generally required, but not always. It depends on if this app is written in Swift and if the dev team wants to map crash logs back to readable errors. They may not be supporting crash analytics. If they are, the bitcode dsym and regular dsym directories need to be in the ipa before uploading to Apple. If they are not there, there is no way to map the crash logs.
Use this command to zip it back into an ipa:
$ zip -qr ../newSignedApp.ipa .
If everything went well, you have a resigned ipa file with the correct entitlements and dsym files to upload to Apple. If you got errors from the resign, you may not have resigned everything properly.
You could try using Fastlane to resign this latest ipa with this command:
$ fastlane sigh resign newSignedApp.ipa
I have found that many steps in this process are not well documented online. Read over the sources below and you will see what I mean. There are validation commands that can be used and found in the links below. I did not go over those, because they seem to be unreliable. Therearecodesigncommandsforvalidationthatpassedandspctlcommands that did not, but I was still able to successfully upload the ipa using Application Loader to Apple. Also, once processed by Apple, the dsym files were available in app store connect for downloading. To get the dsym files from app store connect, go to the activity tab and click into the version you uploaded. There is a lot of info there presented about the ipa, but what you hope to see is that the Includes Symbols is Yes, and you can download the dsym.
Sources
1. https://developer.apple.com/library/archive/documentation/Security/Conceptual/Code SigningGuide/Introduction/Introduction.html
2. https://developer.apple.com/library/archive/documentation/Security/Conceptual/Code SigningGuide/Procedures/Procedures.html#//apple_ref/doc/uid/TP40005929-CH4-SW2
3. https://developer.apple.com/library/archive/technotes/tn2318/_index.html
4. https://developer.apple.com/library/archive/technotes/tn2250/_index.html#//apple_re
f/doc/uid/DTS40009933-CH1-TNTAG13
5. https://www.practicallogix.com/how-to-re-sign-an-ios-build-without-xcode/
6. https://shashikantjagtap.net/ios-code-signing-5-signing-ios-app/
7. https://stackoverflow.com/questions/36888535/how-do-i-resign-app-with-entitlements
8. https://docs.fastlane.tools/codesigning/common-issues/
Resigning an iOS xcarchive for the app store
Thursday, October 17, 2019
Introduction
For the release of company iOS applications to the Apple app store we need to resign those apps with our appropriate distribution certificate. This is the process you need to follow, as-of-this-writing, to properly create an ipa to upload to Apple using the Application Loader.
Things you need to get started
1. A Mac with XCode installed.
2. A developer account with the appropriate access.
3. A company distribution certificate installed in your keychain.
4. The foo.mobileprovision file for the intended release.
5. The foo.xcarchive bundle.
Put the foo.xcarchive and the foo.mobileprovision files in a directory by themselves. This is purely a housekeeping suggestion.
Create an Entitlements.plist file
Start by grabbing the entitlements from the existing foo.app buried in the xcarchive. If you right click on the xcarchive choose the “Show Package Contents” option (from now forward we will assume you know how to go into the .xcarchive and .app files using this option). The foo.app is in the Products and then the Applications directories. Open a terminal at the Applications directory.
Use this command to copy the existing entitlements from the foo.app
$ codesign -d --entitlements :- *.app > ../../../entitlements.plist
Run this command in terminal to read the foo.mobileprovision file:
$ security cms -D -i foo.mobileprovision
Look for the <key>Entitlements</key> and the dictionary of entitlements that follows in the printout of that command. There is a lot in that file, but only focus on the entitlements entry. These two sets of entitlements have options that the release needs and they may not match each other. If your entitlements.plist is different than the mobile provision file you will need to figure out why and which entries need to be corrected. The application-identifier and the team-identifier need to be changed to the ones that you are publishing for. All the other possible entitlements are ones the app is intending to support. If the development team has made a change in XCode, you will see that in the plist file.
Once you have the entitlements.plist correct, change it to a plist file with this cmd:
Replace the embedded.mobileprovision file
Now you need to replace the embedded.mobileprovision file with the foo.Mobileprovision file.
Use this command to replace the embedded.mobileprovision file:
$ cp /pathToFile/foo.mobileprovision /pathToAppInXcarchive/foo.app/embedded.mobileprovision
Update the info.plist
Now is a good time to update the info.plist file in the foo.app. Go into the foo.app and open the info.plist file and change the bundle id. You can also change the version numbers at this time, if you need. Also, you can add missing entries, but it is better to push this back at the
development team of the app. Be careful to not make changes that are not coordinated with that development team. Just because we can make changes ... doesn’t mean we should.
Remove all _CodeSignature entries
Now you need to remove the code signatures. There are several places this needs to be done. All the frameworks, libraries, plugins, extensions and the main bundle need to be resigned. First, we remove the code signatures with these cmds:
(These are not ALL the commands you might need. If the app you are signing uses extensions, plugins, or other nested code, those need to be cleaned and signed, too.)
$ rm -rf /pathToAppInXcarchive/foo.app/Frameworks/*/_CodeSignature rm -rf /pathToAppInXcarchive/foo.app/_CodeSignature
Resign the app
Now you need to resign the app and this happens in a certain order from nested components up to the main bundle. It must be done in this order.
First, you need to know your code signing identity account. Use security to find all the code signing accounts on your computer. If you don’t see the one you need, you need to install it before proceeding.
Here is the security command to see all installed code signing identities:
security find-identity -vp codesigning
Use the appropriate code signing name in parenthesis in the next code signing commands.
These are the code signing commands in the needed order:
(These are not ALL the commands you might need. If the app you are signing uses extensions, plugins, or other nested code, those need to be cleaned and signed, too.)
$ codesign -f -s "codesiging identity" -v /foo.xcarchive/Products/Application/foo.app/Frameworks/*
$ codesign -f -s "codesiging identity " --entitlements /pathToEntitlements/entitlements.plist /foo.xcarchive/Products/Application/foo.app
You can check that the foo.app entitlements are now correct with this command:
$ codesign -d --entitlements - /foo.xcarchive/Products/Application/foo.app
Export the ipa from the xcarchive
Now you need to create an exportOptions.plist. You can create one similar to the example below. Notice that the provisioning profiles are bundle id specific. This one has the name of the provisioning profile, but you can also use the UUID that is in the profile itself, too. This is handy if you are not sure what the name is. Make sure that the correct signing certificate name is entered. Also, the correct teamID and that the other entries are the ones you desire. In this case we are uploading bitcode and symbols.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0">
<dict>
<key>generateAppStoreInformation</key> <false/>
<key>method</key> <string>app-store</string> <key>provisioningProfiles</key>
<dict>
<key>com.bundleid.for.app</key> <string>provisioning profile name or UUID</string>
</dict>
<key>signingCertificate</key>
<string>iPhone Distribution: identity name</string> <key>signingStyle</key>
<string>manual</string> <key>stripSwiftSymbols</key>
<true/>
<key>teamID</key>
<string>APPROPRIATE_ID</string> <key>uploadBitcode</key>
<true/>
<key>uploadSymbols</key>
<true/>
</dict> </plist>
Once you have the exportOptions.plist, you can export the ipa file for uploading to Apple. Use this cmd for exporting the ipa:
$ xcodebuild -exportArchive -archivePath '/foo.xcarchive' - exportPath '/pathToWhereYouWantIt/' -exportOptionsPlist '/pathToExportOptions/exportOptions.plist'
If everything went well, you have an exported ipa file with the correct entitlements and dsym files to upload to Apple. If you got errors from the export there is usually a good printout of what was the problem. In many cases you can backup a few steps to make changes as needed and then progress forward again through the process.
I have found that many steps in this process are not well documented online. Read over the sources below and you will see what I mean. There are validation commands that can be used and found in the links below. I did not go over those, because they seem to be unreliable. There are codesign commands for validation that passed and spctl commands that did not, but I was still able to successfully upload the ipa using Application Loader to Apple. Also, once processed by Apple, the dsym files were available in app store connect for downloading. To get the dsym files from app store connect, go to the activity tab and click into the version you uploaded. There is a lot of info there presented about the ipa, but what you hope to see is that the Includes Symbols is Yes, and you can download the dsym.
Sources
1. https://developer.apple.com/library/archive/documentation/Security/Conceptual/Code SigningGuide/Introduction/Introduction.html
2. https://developer.apple.com/library/archive/documentation/Security/Conceptual/Code SigningGuide/Procedures/Procedures.html#//apple_ref/doc/uid/TP40005929-CH4-SW2
3. https://developer.apple.com/library/archive/technotes/tn2318/_index.html
4. https://developer.apple.com/library/archive/technotes/tn2250/_index.html#//apple_re
f/doc/uid/DTS40009933-CH1-TNTAG13
5. https://www.practicallogix.com/how-to-re-sign-an-ios-build-without-xcode/
6. https://shashikantjagtap.net/ios-code-signing-5-signing-ios-app/
7. https://stackoverflow.com/questions/36888535/how-do-i-resign-app-with-entitlements
8. https://docs.fastlane.tools/codesigning/common-issues/
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>application-identifier</key>
<string>APPROPRIATE_ID.com.bundleid.for.app</string>
<key>com.apple.developer.default-data-protection</key>
<string>NSFileProtectionCompleteUntilFirstUserAuthentication</string>
<key>com.apple.developer.team-identifier</key>
<string>APPROPRIATE_ID</string>
<key>get-task-allow</key>
<false/>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0">
<dict>
<key>generateAppStoreInformation</key> <false/>
<key>method</key>
<string>app-store</string>
<key>provisioningProfiles</key>
<dict>
<key>com.bundleid.for.app</key>
<string>provisioning profile name or UUID</string>
</dict>
<key>signingCertificate</key>
<string>iPhone Distribution: identity name</string>
<key>signingStyle</key>
<string>manual</string>
<key>stripSwiftSymbols</key>
<true/>
<key>teamID</key>
<string>APPROPRIATE_ID</string>
<key>uploadBitcode</key>
<true/>
<key>uploadSymbols</key>
<true/>
</dict> </plist>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment