Morten Johan Sørvig

An update on OS X Code Signing

Published Wednesday October 29th, 2014
9 Comments on An update on OS X Code Signing
Posted in macOS

There has recently been updates to the OS X code signing process. These updates also affect Qt applications signed for distribution, both on and outside the App Store.

OS X 10.9 Mavericks introduced version 2 signatures. As of OS X 10.9.5 and 10.10 Yosemite, v2 signatures are now required. We’ve recently spent some time updating Qt to be v2 compliant and Qt 5.4 will be the first compliant release. This includes patches to qmake and the macdeployqt deployment utility. Manually correcting the signing errors is possible if you are using an older version of Qt.

The Apple documentation is quite comprehensive on this topic, in particular see Code Signing Guide and TN2206 OS X Code Signing In Depth. The Qt tracking bug for this issue is QTBUG-32896.

Required changes to Qt

The required changes falls in three categories: updating the framework and application bundle structure, updating Info.plist contents, and special Qt Quick imports handling.

Updating the framework and application bundle structure

  • The Info.plist file must be placed in Versions/5/Resources/Info.plist.
  • Updated symlink structure: “Current” symlink points to the actual version (“4” or “5”).
  • The framework must be “clean” at code signing time, with for example no QtCore.prl at the root. This is currently enforced by macdeployqt.

As an example, the QtCore.framework structure should look like this:

QtCore.framework/
    QtCore -> Versions/Current/QtCore
    Resources -> Versions/Current/Resources
    Versions/
        Current -> 5
        5/
            QtCore
            Resources/
                Info.plist

And a typical app bundle:

foo.app/
    Contents/
         Frameworks/
             QtCore.framework/
         Info.plist
         MacOS/
             foo
         PkgInfo/
         PlugIns/
         Resources/

Update Info.plist contents
The Info.plist files as generated by current qmake versions are missing some required keys:

  • CFBundleIdentifier (“org.qt-project.QtCore”)
  • CFBundleVersion (“5.4.0”)

Split Qt Quick imports into code and data in the application bundle

This is a v2 code signing requirement which affects applications with Qt Quick imports that contain both binary code (.dylib) and data (.qml) files.

Previous versions macdeployqt would deploy all files to Resources/, but as of v2 binary code in Resources/ is now prohibited. This is solved deploying .dylib files to PlugIns/ and then placing a symlink in Resources/ pointing to the .dylib.

Code signing flow and checkpoints

The following outlines a typical code signing process, with notes on where a current 4.8/5.3 Qt install may fail. The focus is on using the command line tools. Code signing using Xcode is possible but not covered here. The process is incremental: Some steps can be verified by any developer locally, while others require developer account admin access.

1) Signing and verifying the app bundle.

    sign: codesign --deep foo.app -s MyCertificate
      or: macdeployqt foo.app -codesign=MyCertificate
    verify: codesign —verify foo.app

The -deep option signs the app bundle recursively, including contained frameworks. While convenient to use, –deep is documented for “emergency repairs and temporary adjustments only“. As of Qt 5.4 macdeployqt has a -codesign option that recursively signs the app bundle without using –deep.

Common errors at this stage include “bundle format unrecognized, invalid, or unsuitable”, and/or “bar.dylib: code object is not signed at all”, which indicates that the framework structure is not correct or that some contained binary was not signed.

At this point which certificate you use does not matter. You can use a self-signed one created in Keychain Access for development and testing purposes.

2a) Distribution outside the App Store
Verify that GateKeeper will allow the app:

    spctl --assess --type execute foo.app

spctl outputs nothing on success. Common errors include “Rejected”. The bundle must be signed with the correct “Developer ID Application” production certificate for this check to work. The certificate is available for download to the Team Agent in the Mac Dev Center.

2b) App Store distribution
May trigger additional errors:

    ERROR ITMS-9000 The application bundle contains a tool or framework
    foo.app/Contents/Frameworks/QtCore.framework that is missing the
    bundle identifier.

This is currently a pending task for Qt 5.4. You can edit the plist files manually and add a bundle identifiers.

Availability

The updates are/will be available for three Qt versions:

  • 5.3 source code (not packaged)
  • 5.4 release. The updates will be be a part of the 5.4 source and binary release.
  • 4.8 patches: https://codereview.qt-project.org/#/c/95572, with the intention that this will be a part of a future 4.8.x release.

TODO list

The fixes for some issues are currently in progress:

  • Adding CFBundleIdentifier for the Qt frameworks
  • Changing the location of .prl files

Do you have corrections or additional info? Hit the comments section!

Do you like this? Share it
Share on LinkedInGoogle+Share on FacebookTweet about this on Twitter

Posted in macOS

9 comments

Thomas says:

Great summary! Can’t wait to see it in action – will save us a lot of time!!! Thanks!!!!

Andy Brice says:

I am glad this is being addressed. I have written some additional material on v2 signing for Mac here:
http://successfulsoftware.net/2014/10/17/signing-qt-applications-for-mac-os-x-10-9-5-and-10-10/

zeecrowddev says:

Great works but what about this problem when you try to deploy a Qt application with the QtFramework :

“Deprecated APi usage” – Apple no longer accepts submissions of apps that use QuickTime APIs …

Mac App Store rejected your bundle 🙁

Morten Johan Sørvig Morten Johan Sørvig says:

That’s interesting – which QuickTime APIs and which Qt module? (QtMultimedia being the obvious candidate.) If you have the info, paste it into a QTBUG and link back here.

zeecrowddev says:

Ok
Before that, i’m fighting against the entitlement sandbox apple system 🙂
The last step will be the QuickTime API …

Morten Johan Sørvig Morten Johan Sørvig says:

If this is QTBUG-41326 you can remove libqqt7engine.dylib from the app bundle before submitting the app. Or use Qt 5.4 where it is no longer included.

zeecrowddev says:

Thanks a lot
I’ll try it and make you a call back.
Qt 5.4 : of course the 2 december 🙂

zeecrowddev says:

“remove libqqt7engine.dylib”
It works fine, thanks a lot
My software is on verification step by the Mac App Store Team

zeecrowd says:

“remove libqqt7engine.dylib”
It works, thanks a lot

Commenting closed.

Get started today with Qt Download now