I know how to sign an app with Appstore mobile provision, and how to re-sign an Adhoc-signed IPA with Appstore mobile provision. This is not my question.
My question is, can you submit Adhoc-signed IPA to Appstore / iTunesConnect, and have it pass Apple verification and eventually be distributed through Appstore. Why? So that I don't have to store a redundant Appstore-signed IPA along every Adhoc-signed release candidate IPA, and don't have to do the extra step of re-signing that requires a Mac machine.
When using Application Loader, it is able to find all the stupid little errors, like missing icons and launch images, but even when I upload Adhoc-signed IPA through Application Loader, it doesn't complain about non-appstore mobile provision (which is very easy to verify, just like icons).
I have also found out in my testing, that when you take an Appstore-signed IPA (which you are not supposed to be able to install on devices unless distributed through Appstore), it is possible to install it on testing devices, provided the device already has Adhoc provision profile on it (same AppID, same distribution cert).
So, this makes me think Apple just strips out mobile provision when distributing through Appstore.
There was a similar question (closed) from almost 3 years ago, but the OP never provided an answer if it had actually worked: Submitted app to appstore with adhoc profile.
I hope someone since then had actually tried with it confirmed results.
There are a few targeted inner questions within your main question, I'll call attention to each part as we go -- as always, I'll be happy to revise or clarify if I miss something. I suppose it is only a closely guarded secret because much of the reasoning for it working come back to cryptographic details as a function of the Public Key Infrastructure system that backs Apple's provisioning -- This stuff gets deep fast so it is considered by some to be [dark] magic. Hopefully this will shine some light on what is going on!
TL;DR Version
Yes you can, but it is technically an unsupported use case that may change at any time. This works because what information iTunes Connect chooses to validate does not include the single differentiating factor between an App Store and AdHoc distribution provisioning profile. Since this is technically not a permitted configuration, I'd advocate for at least having a backup plan since Apple may change iTunes Connect validation policy at any time breaking this submission edge case.
Now for the curious, the here is the rest of the story...
Can you submit Adhoc-signed IPA to Appstore / iTunesConnect, and have it pass Apple verification and eventually be distributed through Appstore[?]
As of this specific iteration of iTunesConnect and the Application Loader (4 Sept 2014 / Xcode 5.1.1), yes you can submit an AdHoc signed build and have it accepted through the pipeline. The eagle-eyed reader will note that my 'Yes' comes with a built-in escape hatch -- Because of the data encoded in AdHoc vs App Store provisioning profiles is nearly identical coupled with what parts of these files iTunesConnect is actually using for validation, an AdHoc provisioning profile presents to the delivery pipeline in the same manner as the AppStore version of the same app.
Should the provisioning format change between AdHoc and App Store files to explicitly differentiate the two types of Distribution provisioning profiles or should Apple iTunesConnect engineers change server-side validation rules, it is distinctly possible that this undocumented behavior will stop working. Of course we all know that we are supposed to use the App Store provisioning profile, as per Developer documentation in the App Distribution Guide > Submitting Your App > About Store Provisioning Profiles (https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/AppDistributionGuide/SubmittingYourApp/SubmittingYourApp.html#//apple_ref/doc/uid/TP40012582-CH9-SW32) [emphasis added]:
A store distribution provisioning profile contains a single App ID that matches one or more of your apps, and a distribution certificate. For iOS apps, you need a store provisioning profile to submit your app.
...but this other avenue works for now. If you do choose to use this avenue, you just need to be aware that it is not the documented behavior and thus would be subject to change at any point in time, likely without advanced notice. Since it is skirting the edges of submission requirements it would probably be good to at least have a backup plan setup for the case of Apple changing provisioning or iTC validation requirements -- Murphy's law would dictate that these validation changes would happen at the most inopportune time.
Stepping off the 'Best Practice' Soapbox and turning to the technical side of things...
Why [does this work]?
As you may or may not know, provisioning profiles are composed of exactly 1 appId, one or more signing certificates, and zero or more test devices.
Related Reading: I've got a longer answer to What are code signing identities? that speaks in more detail to the parts of the codesign process.
In this case the question is 'why do AdHoc profiles work when the documentation says you need to have an App Store profile?'
The guts of a provisioning profile contain a cryptographically signed .plist that includes the information identified above, plus some additional metadata. On an OS X machine you can open Terminal and run:
security cms -D -i path/to/AdHoc.mobileprovision
...and in a separate Terminal window run the App Store profile equivalent:
security cms -D -i path/to/AppStore.mobileprovison
These commands will dump out the plist portion of the provisioning profile to their respective Terminal windows. When you scroll through the contents of both windows you will note that the following sections are identical:
AppIDName
AppliationIdentifierPrefix
DeveloperCertificates
Entitlements
TeamIdentifier
Version
The profile's metadata are different, but those are entirely expected differences that only matter for validating profile validity, or for humans interrogating the profile:
CreationDate
ExpirationDate
Name
TimeToLive
UUID
The salient points to take away are:
The DeveloperCertificates blocks are identical between both profiles.
The AdHoc profile only adds information (ProvisionedDevices) to the structure and format of the App Store profile.
The contents of the DeveloperCertificates array is the DER encoded X.509 iPhone Distribution Certificate -- The exact same as the one in your keychain. Is is important to note that this DER data is only the public portion of your Distribution certificate public-private keypair, and it can only be used by others to authenticate the application's signature came from you -- It can not be used to resign a binary as you.
If you paste the contents of DeveloperCertificates:Array:Data element into an ASN.1 decoder (http://lapo.it/asn1js/) and compare the elements of the output to the information encoded in the Distribution certificate included in the Keychain, you'll find that it is an exact copy of the public Distribution certificate you downloaded from Apple after submitting your Certificate Signing Request though the Certificates, Identifiers, and Profiles tool.
Because both the AdHoc and App Store provisioning profiles use the same public key certificate as their signing identity, they are inherently using the same private key when generating the application's signature. This means that the signature generated when signing with an AdHoc profile is functionally identical to one generated when signing with the App Store profile
When Apple performs a signature validation on iTunes Connect during the submission process, both and AdHoc signed cryptographic signature and an App Store signed cryptographic signature will successfully validate against the Distribution Certificate Apple has on file as both provisioning profiles are backed by the same Distribution Certificate.
So the signatures match, but why doesn't the extra information in AdHoc profiles trip up the submission?
Your original question suggests that you have familiarity with iOS' app install policies. For the benefit of someone stumbling across this answer in the future I'll briefly summarize:
iOS operates on a 'deny-all unless specifically permitted' policy. That is, iOS assumes you are not allowed to install an app unless a specific 'grant' has been allowed. For devices coming from the App Store, the app's signature includes Apple's App Store identity for which iOS has a specific 'grant' privilege. AdHoc installs by default fall under the 'deny' policy and the ProvisionedDevices section of a Development or AdHoc profile are the specific 'grant' privileges. The app will install outside of the App Store if all of the following hold true:
The application's cryptographic signature is valid
The application's embedded provisioning profile's cryptographic signature is still valid (the profile hasn't been tampered with)
The application's embedded provisioning profile's ExpirationDate hasn't passed and the current time isn't before the CreationDate
The embedded profile or a profile installed to the device match the AppId being proposed for installation.
The embedded profile or a profile installed to the device contain an entry in ProvisionedDevices that exactly match the device's UDID.
As we saw above, the app identity and signing information is identical between an App Store profile and and Ad Hoc profile -- the addition of ProvisionedDevices serves only to add these 'grant' privileges for an external (outside of App Store) distribution mechanism. It turns out that iTunes Connect / Application Loader validation is currently only validating that a Distribution profile was used for the app's signature, not that the profile that was used was an App Store profile instead of an AdHoc profile.
This boils down to the fact that the as of Version 1 (ala Version block in the plist) the only differentiating factor between AdHoc and App Store distribution profiles is the presence or absence of the ProvisionedDevices block. It turns out that as of today, this is not a detail that Apple looks for when interrogating the profile that was used, thus the binary passes the automated portions of app verification. They definitely do check that the AppId in the profile matches what the App claims, that the signing identity matches what was used to sign the binary, expiration dates, and any entitlements used match what is found in the automated scan of the app, in addition to the items you highlighted in your original question (version checks between iTunes Connect and the info.plist, iconography presence, iconography sizes, etc.)
Hypothetically, in a subsequent iTunes Connect / Application Loader update, they could start checking for the absence of this key in the embedded.mobileprovision profile that exists within the submitted binary and auto-reject the submission on the grounds that an App Store profile was not used. Similarly, if the provisioning profile format was updated (ex. Version=2) they could add a new element that explicitly calls out the type of profile and auto-reject if it isn't an App Store type. It could perhaps look like this:
<key>ProfileType</key>
<integer>1</integer>
Where the integer value could be 1, 2 or, 3 depending on the type of profile in use, consistent with the formats used in things like Info.plist for identifying supported device families (iPhone-only, iPad-only, or Universal). This would clarify other questions that have been asked about identifying the type of build.
Related Reading:
How to detect that a provisioning profile is for development or distribution, programmatically
Check if app is ad-hoc|dev|app-store build at run time
So, this makes me think Apple just strips out mobile provision when distributing through Appstore.
Yes they do! If you look at archived versions of the apps you submitted you'll find that the contents of the app contain embedded.mobileprovision -- if you then go download the same version from the App Store, you'll find that file missing. Apple only uses embedded.mobileprovision to verify the contents of your app during the submission and review process. When the app is 'Processing for App Store' the final package is assembled and the embedded profile is removed.
Related
I am trying to understand signing identities and provisioning profiles in iOS development. (Let us focus on development for now and not distribution via app-store. One issue at a time)
Note: I'm not looking for a how-to, but rather a general conceptual overview. In fact, Xcode seems to have taken care of all of it for me in some mysterious fashion, and things seem to work, but I want to understand what it actually did, and how it all fits together.
Signing Identities
I think I understand signing identities. Here is how I think it works (let me know if I'm mistaken):
Apple has decided that users should not be able to run any random application on iOS and part of the technology it has used to implement this selectiveness is code signing.
Code signing is process of encrypting a hash of the binary with a private key and including the encrypted hash along with the binary. This is now a signed binary. Also included along with the binary is a certificate signed by Apple with includes the public key part of the key pair and effectively says that a binary signed with the private key that corresponds to the public key in the certificate is approved by Apple to run.
When iOS is asked to launch an app, it looks to see if the certificate is valid and that the app is indeed signed by the private key corresponding to the public key in the certificate. If everything is good, it launches the app.
Provisioning Profiles
This is where my understanding of things start to break down. Here is what (I think) I know:
Code signing as described above can't be the whole story in the implementation of selectiveness. As a developer I can get a key pair and a certificate from Apple and I can sign my code with it. But that actually won't run as-is on an iOS device, as indeed it should not. If it did, then all one needs to build an app that runs on every iOS device is a developer account, and anyone can get that (well, anyone that can afford $100 a year).
What explains this is that the certificate I get from Apple is a developer certificate and that doesn't actually tell iOS that the app signed with the (private key corresponding to the) certificate is approved to run. It simply says that it is built by a valid developer. In order for iOS to decide that it is OK to run, it needs some additional information. I believe that information is what is stored in development provisioning profile.
The profile seems to associate developers, applications ids, and devices, saying in effect that applications with the id specified in the profile, built by the developers specified in the profile, are ok to run in the devices specified by the profile.
The Actual Questions
What I don't understand is that the provisioning profile must:
Be available on the device. iOS on the device is the entity that is in the end making the decision whether to run the app or not, so it must look through the provisioning profiles to decide. How do the profiles get to the device?
Be certified by Apple. If the profile is not certified by Apple, then I can associate any app I want to my developer certificate and get it to run. How does that certification happen? Or is there some other mechanism at work?
We are trying to supply one of our clients with an ipa to deploy on their AirWatch. There is a lot of conflicting information on what is the best way to do that, but they all seem to agree on the fact that it needs to be signed with the certificate and private keys of some account. However, the client seems to be managing their apple enterprise account through AirWatch. Does this mean that we could supply them with an unsigned ipa file and let AirWatch do its thing?
I have been scouring the internet for a while for this information and the closest ones are similar to Renew iOS Development and APNs Production for Corporate Apps [AirWatch] which is not what i was looking for
No - AirWatch does not re-sign anything IPA-wise. It can interrogate your IPA to make sure you're not trying to accidentally update App A's IPA with the IPA for App B but that's about it.
The link you provided has nothing to do with re-signing applications within AirWatch as much as it is the general practice for renewing your Enterprise Apple Developer Cert and Provisioning Profiles.
If you try to deploy an unsigned IPA to a device not in your Developer Portal you will likely run into an issue where the app will begin installation then throw an error that it cannot be installed.
Regarding what your client is doing there may be some confusion as AirWatch does not directly tie back to the Apple Developer Portal except for the MDM APNs cert which is unrelated to IPAs.
It depends on how sophisticated AirWatch's re-signing is. A good re-signer, should be able to take anything, re-sign it AND add the correct entitlements.
That said, in Xcode unsigned feels like an unsupported path - so my conservative approach is to sign a production build of the app (Ad Hoc, Enterprise or even AppStore if that makes sense) with its entitlements being as similar as possible to those of the final app's. If the app entitlements are simple (e.g. push notifications only), then this is the way to go.
But there's a problem: matching client entitlements has recently become harder, in part due to the proliferation of App Groups (which require an explicit, globally unique App ID - thanks, Apple Watch!), so your unsigned suggestion is starting to look more attractive.
Airwatch only resigns IPAs if you wrap it with their App Wrapper, because it will alter the original IPA and invalidate the Signature.
You have to provide both the Certificate and the Provisioning Profile to allow that.
If the IPA has to be signed with the Enterprise Certificate of your customer, you either require access to their Member Center or let them do it.
Apps like AppSign or iReSign can do that for you or your customer, if you provide them with the IPA.
I am a bit lost in all the certificates/provisioning profiles.
When I am doing ad-hoc distribution by first doing "archive" and then "distribute" in XCode and chose then my ad-hoc distribution profile, does it matter at all what I have set up in the Project->Target->Build Settings->Code Signing?
On one hand I read in different places that when you archive a build, you can (and really should) use that same archive both for beta testing with ad-hoc and then when ready just sign/distribute the same archive with an appstore profile and upload to app store. That kind of makes sense. It also tells me that I can really leave blank the provisioning profile in the project settings, the one that is chosen during "distribute" action is actually used, and the signing identity is actually the private key associated with the distribution certificate listed in that provisioning profile. Right?
On the other hand, testflight instructions (http://help.testflightapp.com/customer/portal/articles/1333914) clearly state that project settings should be set to use Ad-hoc profile as well, and the same profile must be used in the project settings and in "distribute". That means that I can not use the same archive both for ad-hoc and app-store distribution, can I? Do I need to change project settings every time I want to release for this or that distribution?
Also, if project settings are making any differences in archive/distribute scenario, it is not clear what Code Signing Identity should be used there. Testflight screenshots show iOS Developer is set both for debug and release, yet neither ad-hoc nor app store distribution have the individual iOS developer certificate associated with them, distribution profiles usually are associated with one and one only distribution certificate.
Can someone please shed some light and explain how is it actually supposed to be working?
Thanks
Yes, your build settings matter. Xcode picks up various entitlements from your initial code signing/provisioning profile configuration and it only makes minimal changes to them in the Distribute... phase.
So if Xcode chooses the incorrect profile during the Archive step you can end up with incorrect bundle seed ID, keychain groups, APN environment and iCloud entitlements.
The Distribute... button calls the PackageApplication script, which makes sure that get-task-allow is false (debuggers can't connect), embeds a provisioning profile, then re-signs and zips your app (although I may have the order wrong).
PackageApplication is worth reading. One could fault it for not being very smart, but I think it should be stricter and refuse to package an app whose entitlements differ from the provisioning profile it is using.
You can find it here Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/PackageApplication
I think one stable workflow for distributing Ad Hoc builds is
remove all wildcard provisioning profiles from your system
select your App Store profile in Release Configuration (used in Archive phase)
in Distribute select your Ad Hoc profile
The reason for 1. is that wildcard profiles (profiles that match multiple BundleIDs, created either manually by you or automatically by Xcode) are not worth the trouble. Yes, they get you running code on a device quicker, but you soon have to abandon them if you want to use push notifications or any other interesting service and then they hang around on your system and sooner or later Xcode will silently pick one of them and sabotage your App Store submission.
As for point 2. (selecting the App Store provisioning profile), I'm a little hesitant of specifying profile in the project, but the App Store one only needs to change once a year when your certificate expires (unless you edit the App Identifier in the Certificates, Identifiers & Profiles portal, then you'll need to regenerate your profile & re-select it in your project settings).
Since the Ad Hoc and App Store profiles are based on the same App Identifier, their entitlements will always be in sync.
Point 2. should make point 1. unnecessary, but wildcard profiles will also happily screw up your dev builds too, so why give them the chance to stab you in the back?
Point 3. - you can change your Ad Hoc profile as much as you like - just remember to select the right one in Distribute; the entitlements are taken from the App Store profile which should change rarely. There's nothing stopping you distributing to the App Store from here. That's perfectly natural.
p.s. I don't know why TestFlight recommend selecting Ad Hoc in release instead of App Store.
When you build a project in xcode, you specify the provisioning profile/certificate pair in the build settings, and when exporting an archive, you specify an additional provisioning profile to use. What is the reason for asking for this information twice?
Edit for clarification: I've gone through the contents of a bunch of my generated .ipa files, and there seem to be two locations that pertain to signing/provisioning. The document in the _CodeSign folder (which seems to contain encrypted hashes of the file contents, to verify contents/source), and the .mobileprovision file, which seems like it would be added when the build is exported. At this point in time, I don't see anything that would indicate the purpose of the provisioning profile selected in build settings.
You specify a provision profile in the build settings that Xcode uses to sign the app. This makes it possible for you to run your app on a device during development, for example. If I remember correct, in the past the project build settings was the only place where you could specify the profile to use, so you'd typically set the Debug build to use your development profile, and your Release build to use the distribution profile.
At some point (Xcode 4, I think), application archives were introduced to make things easier for developers. You create a single archive and then distribute the app it contains in different ways. You can do an ad hoc distribution to send out to your testers, and then you can use the very same archive to submit to the app store, or create a version for enterprise distribution, depending on the type of program you've joined. But since different distribution methods require different profiles, Xcode asks you for the profile you want to use when you distribute.
Xcode's Archive function is a huge convenience -- it takes a lot of the complexity out of submitting your app, and also takes care of saving the symbols file for each version you distribute so that you can make sense of any crash logs you might receive. It's a recognition of developers' need to use the very same build of an app in different ways. If it seems a little odd that you specify the provision profile to use in two different places, so be it -- that's a rough edge that might get cleaned up in a future Xcode version.
I don't know of any authoritative information on exactly how app signing works, but I think it goes like this:
the provision profile contains your certificate (which includes your public key), and is signed with Apple's private key
you sign your app with the private key that is the counterpart to the public key in your certificate
the device uses Apple's public key to authenticate the profile, and then uses your public key from the profile to authenticate the app signature
if everything matches up, the device will run the app; if not, the app will fail to install
Forget about the "app binary" and "ipa" being signed separately -- I think that's a red herring, and it's unlikely that iOS has to validate two different signatures.
Not sure, but think - First time xCode sign just binary app, and second time whole .ipa archive.
This might have been asked lots of times, but still I couldn't find info on why are they needed. I use DEVELOPER prov profiles to test apps on my device, that makes sense.
The Provisioning Portal explains prov profiles like this:
A Provisioning Profile is a collection of digital assets that uniquely ties
developers and devices to an authorized iOS Development Team and enables
a device to be used for testing.
By this logic they are only needed for testing, eg not for distribution. Do we need one to deploy the app on the AppStore?
Absolutely yes. The distribution profile is used for submission to the App Store. It does not have the 100 device limit that the development profiles have.
From the Tools Workflow Guide:
When you’re ready to share your app for user testing or for general distribution through the
App Store, you need to create an archive of the app using a distribution provisioning
profile and send it to app testers or submit it to iTunes Connect. This chapter shows
how to perform these tasks.
The distribution profile prevents the attackers from submitting a modified version of your app to the store - only you, who hold the private key of the distribution certificate, can submit and update your app.
Once your app is submitted, your embedded.mobileprovision and your binary will be checked and compared to make sure that you are the legitimate author. embedded.mobileprovision file is then discard and the app is signed again by Apple using their own certificate (which is by default accepted by all iDevices), so that all iDevices can run it.
When an iDevice downloads the app, the executable binary is then encrypted with an encryption key associated that device. At run time, only that device can decrypt the executable binary and run it.
There are two types of distibution profiles, the first one is to submit your app to the appstore and the other one (Ad-Hoc) is necessary if you can´t connect a device to your mac(developer profile). Then you can share your app wit the Ad-Hoc profile to someone else e.g. via mail.
Distribution Provisioning Profile
Distribution Provisioning Profile is used by Apple to publish an application to App Store. When Apple approve the application it is signed by Apple and became public.
Distribution Provisioning Profile contains:
Application ID - application which are going to run
Distribution certificate - who can debug the app
[Development Provisioning Profile]
[Certificate]