Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Installation and Deployment
  4. Build and codesign on MacOS Sierra 10.12, but "the identity of the developer cannot be confirmed."
Forum Updated to NodeBB v4.3 + New Features

Build and codesign on MacOS Sierra 10.12, but "the identity of the developer cannot be confirmed."

Scheduled Pinned Locked Moved Solved Installation and Deployment
10 Posts 4 Posters 4.1k Views 3 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Offline
    D Offline
    davidb
    wrote on last edited by davidb
    #1

    Codesigning my app appears to work correctly, but Sierra 10.12.3 doesn't like it on first run after download. My original question involving building and codesigning on Yosemite is here, but I'm posting this as a different question since in an effort to make Sierra happy, now I'm building on Sierra with Xcode 8.2.1.

    I have created a minimal example to illustrate the issue. Here is my minimal application:
    test_codesign.pro:

    QT       += core gui
    
    greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
    
    TARGET = TestCodesign
    TEMPLATE = app
    
    
    SOURCES += main.cpp
    

    main.cpp:

    #include <QApplication>
    #include <QtWidgets/QMessageBox>
    
    int main(int argc, char *argv[])
    {
      QApplication a(argc, argv);
      QMessageBox w(QMessageBox::Information, "Hello", "Hello world!");
      w.show();
    
      return a.exec();
    }
    

    Here is my minimal build script:

    #!/bin/sh
    
    # Minimal test:  this script goes in the same directory as the application code files (test_codesign.pro and main.cpp).
    # Before executing this script, set two variables:
    #   export QTDIR=/path/to/qtbase
    #   export MYID="[id to codesign with]"
    
    pushd `dirname "${0%}"`
    MYDIR=`pwd -P`
    popd
    
    # Establish our build tool environment
    QMAKE=$QTDIR/bin/qmake
    SDKBARE=MacOSX10.12
    QMAKEARGS="-r CONFIG+=release DEFINES+=QMAKE_MAC_SDK=$SDKBARE"
    
    # Build the app in the "release-build" subdir
    rm -rf "$MYDIR/release-build"
    mkdir -p "$MYDIR/release-build"
    pushd "$MYDIR/release-build"
    $QMAKE "$MYDIR/test_codesign.pro" -r CONFIG+=release DEFINES+=QMAKE_MAC_SDK=$SDKBARE
    make -j2 -w
    popd
    
    # Create the disk image folder.  "pkg-root" is our working folder to assemble everything.  The final product goes in "out".
    rm -rf "$MYDIR/pkg-root"
    rm -rf "$MYDIR/out"
    mkdir -p "$MYDIR/pkg-root/Applications"
    
    
    # Copy the application bundle
    cp -afv "$MYDIR/release-build/TestCodesign.app" "$MYDIR/pkg-root/Applications/"
    
    # Run the Qt Mac deploy tool, which resolves the linkage of the Qt frameworks
    "$QTDIR/bin/macdeployqt" "$MYDIR/pkg-root/Applications/TestCodesign.app"
    
    defaults write "$MYDIR/pkg-root/Applications/TestCodesign.app/Contents/Info" CFBundleName 'TestCodesign'
    defaults write "$MYDIR/pkg-root/Applications/TestCodesign.app/Contents/Info" CFBundleIdentifier 'com.fmosoft.TestCodesign'
    
    find ./pkg-root -name '*.DS_Store' -depth -type f -delete
    
    # Add a symbolic link to the Applications folder to the disk image.
    # Use a space as the destination name, because I haven't found a way to localize "Applications" in the dmg.
    # Apparently using a space is a common solution to this problem from what I found in a couple of google searches.
    ln -s /Applications "$MYDIR/pkg-root/Applications/ "
    
    # Create a clean backup of the .app
    cp -R "$MYDIR/pkg-root/Applications/TestCodesign.app" "$MYDIR/pkg-root/Applications/TestCodesignUnsigned.app"
    
    # repeat signing TestCodesign.app until the exit value is true (i.e. no crash)
    until codesign --deep --force --verify --verbose --sign "$MYID" "$MYDIR/pkg-root/Applications/TestCodesign.app"; do
      echo Failure. Trying again...
      rm -rf "$MYDIR/pkg-root/Applications/TestCodesign.app"
      cp -R "$MYDIR/pkg-root/Applications/TestCodesignUnsigned.app" "$MYDIR/pkg-root/Applications/TestCodesign.app"
    done
    
    # Delete the backup .app
    rm -rf "$MYDIR/pkg-root/Applications/TestCodesignUnsigned.app"
    
    # Verify the bundle's signature
    codesign --verify --verbose=4 --deep "$MYDIR/pkg-root/Applications/TestCodesign.app"
    
    # Create our disk image
    mkdir -p "$MYDIR/out"
    hdiutil create -srcfolder "$MYDIR/pkg-root/Applications" -fs HFS+ -fsargs "-c c=64,a=16,e=16" -format UDRW -volname TestCodesign -ov -attach "$MYDIR/out/TestCodesign.uncompressed.dmg"
    echo done first dmg
    
    echo '
      tell application "Finder"
        tell disk "TestCodesign"
          open
          set current view of container window to icon view
          set toolbar visible of container window to false
          set statusbar visible of container window to false
          set the bounds of container window to {100, 100, 600, 450}
          set theViewOptions to the icon view options of container window
          set arrangement of theViewOptions to not arranged
          set icon size of theViewOptions to 96
          set position of item "TestCodesign.app" of container window to {100, 90}
          set position of item "TestCodesign.app" of container window to {100, 90}
          close
          open
          set position of item " " of container window to {400, 160}
          set position of item " " of container window to {400, 160}
          close
          open
          update without registering applications
          delay 5
          eject
        end tell
      end tell
    ' | osascript
    
    #sleep 10
    
    hdiutil convert "$MYDIR/out/TestCodesign.uncompressed.dmg" -format UDZO -o "$MYDIR/out/test_codesign.dmg"
    
    # code sign the final .dmg, and verify the signature
    codesign --verify --verbose --sign "$MYID" "$MYDIR/out/test_codesign.dmg"
    spctl -a -t open --context context:primary-signature -v "$MYDIR/out/test_codesign.dmg"
    
    # remove the uncompressed .dmg
    rm "$MYDIR/out/TestCodesign.uncompressed.dmg"
    
    # We are done!  The file to distribute is $MYDIR/out/test_codesign.dmg
    

    EDIT: removed stray $X variable from script.

    The script runs fine, and the codesign tests in the script report that everything looks good.

    But, when I upload test_codesign.dmg to Dropbox and then download it (on the same Sierra 10.12.3 computer), double-click the downloaded .dmg, drag the app to /Applications, then double-click the app in /Applications: I get the message that the identity of the developer cannot be confirmed.

    Any idea what I need to do to my application/.dmg so Sierra's Gatekeeper will be happy?

    A 1 Reply Last reply
    0
    • D davidb

      Codesigning my app appears to work correctly, but Sierra 10.12.3 doesn't like it on first run after download. My original question involving building and codesigning on Yosemite is here, but I'm posting this as a different question since in an effort to make Sierra happy, now I'm building on Sierra with Xcode 8.2.1.

      I have created a minimal example to illustrate the issue. Here is my minimal application:
      test_codesign.pro:

      QT       += core gui
      
      greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
      
      TARGET = TestCodesign
      TEMPLATE = app
      
      
      SOURCES += main.cpp
      

      main.cpp:

      #include <QApplication>
      #include <QtWidgets/QMessageBox>
      
      int main(int argc, char *argv[])
      {
        QApplication a(argc, argv);
        QMessageBox w(QMessageBox::Information, "Hello", "Hello world!");
        w.show();
      
        return a.exec();
      }
      

      Here is my minimal build script:

      #!/bin/sh
      
      # Minimal test:  this script goes in the same directory as the application code files (test_codesign.pro and main.cpp).
      # Before executing this script, set two variables:
      #   export QTDIR=/path/to/qtbase
      #   export MYID="[id to codesign with]"
      
      pushd `dirname "${0%}"`
      MYDIR=`pwd -P`
      popd
      
      # Establish our build tool environment
      QMAKE=$QTDIR/bin/qmake
      SDKBARE=MacOSX10.12
      QMAKEARGS="-r CONFIG+=release DEFINES+=QMAKE_MAC_SDK=$SDKBARE"
      
      # Build the app in the "release-build" subdir
      rm -rf "$MYDIR/release-build"
      mkdir -p "$MYDIR/release-build"
      pushd "$MYDIR/release-build"
      $QMAKE "$MYDIR/test_codesign.pro" -r CONFIG+=release DEFINES+=QMAKE_MAC_SDK=$SDKBARE
      make -j2 -w
      popd
      
      # Create the disk image folder.  "pkg-root" is our working folder to assemble everything.  The final product goes in "out".
      rm -rf "$MYDIR/pkg-root"
      rm -rf "$MYDIR/out"
      mkdir -p "$MYDIR/pkg-root/Applications"
      
      
      # Copy the application bundle
      cp -afv "$MYDIR/release-build/TestCodesign.app" "$MYDIR/pkg-root/Applications/"
      
      # Run the Qt Mac deploy tool, which resolves the linkage of the Qt frameworks
      "$QTDIR/bin/macdeployqt" "$MYDIR/pkg-root/Applications/TestCodesign.app"
      
      defaults write "$MYDIR/pkg-root/Applications/TestCodesign.app/Contents/Info" CFBundleName 'TestCodesign'
      defaults write "$MYDIR/pkg-root/Applications/TestCodesign.app/Contents/Info" CFBundleIdentifier 'com.fmosoft.TestCodesign'
      
      find ./pkg-root -name '*.DS_Store' -depth -type f -delete
      
      # Add a symbolic link to the Applications folder to the disk image.
      # Use a space as the destination name, because I haven't found a way to localize "Applications" in the dmg.
      # Apparently using a space is a common solution to this problem from what I found in a couple of google searches.
      ln -s /Applications "$MYDIR/pkg-root/Applications/ "
      
      # Create a clean backup of the .app
      cp -R "$MYDIR/pkg-root/Applications/TestCodesign.app" "$MYDIR/pkg-root/Applications/TestCodesignUnsigned.app"
      
      # repeat signing TestCodesign.app until the exit value is true (i.e. no crash)
      until codesign --deep --force --verify --verbose --sign "$MYID" "$MYDIR/pkg-root/Applications/TestCodesign.app"; do
        echo Failure. Trying again...
        rm -rf "$MYDIR/pkg-root/Applications/TestCodesign.app"
        cp -R "$MYDIR/pkg-root/Applications/TestCodesignUnsigned.app" "$MYDIR/pkg-root/Applications/TestCodesign.app"
      done
      
      # Delete the backup .app
      rm -rf "$MYDIR/pkg-root/Applications/TestCodesignUnsigned.app"
      
      # Verify the bundle's signature
      codesign --verify --verbose=4 --deep "$MYDIR/pkg-root/Applications/TestCodesign.app"
      
      # Create our disk image
      mkdir -p "$MYDIR/out"
      hdiutil create -srcfolder "$MYDIR/pkg-root/Applications" -fs HFS+ -fsargs "-c c=64,a=16,e=16" -format UDRW -volname TestCodesign -ov -attach "$MYDIR/out/TestCodesign.uncompressed.dmg"
      echo done first dmg
      
      echo '
        tell application "Finder"
          tell disk "TestCodesign"
            open
            set current view of container window to icon view
            set toolbar visible of container window to false
            set statusbar visible of container window to false
            set the bounds of container window to {100, 100, 600, 450}
            set theViewOptions to the icon view options of container window
            set arrangement of theViewOptions to not arranged
            set icon size of theViewOptions to 96
            set position of item "TestCodesign.app" of container window to {100, 90}
            set position of item "TestCodesign.app" of container window to {100, 90}
            close
            open
            set position of item " " of container window to {400, 160}
            set position of item " " of container window to {400, 160}
            close
            open
            update without registering applications
            delay 5
            eject
          end tell
        end tell
      ' | osascript
      
      #sleep 10
      
      hdiutil convert "$MYDIR/out/TestCodesign.uncompressed.dmg" -format UDZO -o "$MYDIR/out/test_codesign.dmg"
      
      # code sign the final .dmg, and verify the signature
      codesign --verify --verbose --sign "$MYID" "$MYDIR/out/test_codesign.dmg"
      spctl -a -t open --context context:primary-signature -v "$MYDIR/out/test_codesign.dmg"
      
      # remove the uncompressed .dmg
      rm "$MYDIR/out/TestCodesign.uncompressed.dmg"
      
      # We are done!  The file to distribute is $MYDIR/out/test_codesign.dmg
      

      EDIT: removed stray $X variable from script.

      The script runs fine, and the codesign tests in the script report that everything looks good.

      But, when I upload test_codesign.dmg to Dropbox and then download it (on the same Sierra 10.12.3 computer), double-click the downloaded .dmg, drag the app to /Applications, then double-click the app in /Applications: I get the message that the identity of the developer cannot be confirmed.

      Any idea what I need to do to my application/.dmg so Sierra's Gatekeeper will be happy?

      A Offline
      A Offline
      ambershark
      wrote on last edited by
      #2

      @davidb Hi! Few questions ..

      1. Do you have a valid developer certificate from apple? Are you up to date on your payments to apple for it?

      2. Check out https://developer.apple.com/library/content/technotes/tn2206/_index.html it has a lot of info on signing applications.

      3. Why do you enter a code signing loop until "it doesn't crash"? If that is necessary you may have found your problem right there, lol.

      My L-GPL'd C++ Logger github.com/ambershark-mike/sharklog

      1 Reply Last reply
      0
      • D Offline
        D Offline
        davidb
        wrote on last edited by
        #3

        @ambershark : good questions, I probably should have mentioned the answers in the original post.

        1. Do you have a valid developer certificate from apple? Are you up to date on your payments to apple for it?

        Yes, as far as I can tell. The certificate doesn't expire until December 12, 2017, according to what Keychain Access shows me. We had let our Apple Developer Program membership lapse, but that was renewed a few days ago. It is my understanding that current membership in Apple's Developer Program is not required anyway, as long as the certificate is still valid. Building and signing on Yosemite (10.10.3) works fine, if I run on Yosemite - even before renewing our membership. But of course I can't insist my users run Yosemite, hence my question.

        1. Check out https://developer.apple.com/library/content/technotes/tn2206/_index.html it has a lot of info on signing applications.

        Thanks, I have been studying that document, as well as this one. Since nothing I tried met with success, I created the minimal example, hoping someone could point out a problem or perhaps test it and suggest what works for them.

        1. Why do you enter a code signing loop until "it doesn't crash"? If that is necessary you may have found your problem right there, lol.

        Perhaps that loop is no longer necessary, but it doesn't seem to me that leaving the loop in place should cause a problem. There used to be a concurrency issue in Apple's code somewhere that required this workaround. We found this workaround to be necessary when building/signing on 10.10.3. See this SO question and this Apple forum question. For the record, in all my tests I've NOT noticed this loop to be necessary on Sierra - the script has not executed the echo Failure. Trying again... command, so it seems likely that Apple fixed the issue sometime after 10.10.3.

        The only thing I'm doing that I see is not recommended is that I'm using --deep to sign the bundle. Here's the relevant quote from the Apple technote you mention:

        Important: While the --deep option can be applied to a signing operation, this is not recommended. We recommend that you sign code inside out in individual stages (as Xcode does automatically). Signing with --deep is for emergency repairs and temporary adjustments only.

        I'm not sure what "signing code inside out in individual stages" looks like for my minimal example. I understand it is something like starting at the most deeply nested files that require signing, and signing each one individually, and moving back toward the root of the bundle. But I don't understand exactly what order that means for Frameworks, main app, dylibs, etc. If that's really required, I'd think someone would have a bash script code sample that loops through and signs everything in the correct order, but I've not found anything like that.

        In any case, Apple's warning about signing with --deep implies that --deep should work, since you can use it for emergency repairs and temporary adjustments. And when I run Apple's recommended checks using codesign --verify and spctl, they pass. So I'm not sure --deep is the issue at all.

        I'm hoping someone who knows more than I do about this stuff can steer me in the right direction. If --deep is the issue, then what files should be signed in my minimal example, and in what order should they be signed?

        A 1 Reply Last reply
        0
        • D davidb

          @ambershark : good questions, I probably should have mentioned the answers in the original post.

          1. Do you have a valid developer certificate from apple? Are you up to date on your payments to apple for it?

          Yes, as far as I can tell. The certificate doesn't expire until December 12, 2017, according to what Keychain Access shows me. We had let our Apple Developer Program membership lapse, but that was renewed a few days ago. It is my understanding that current membership in Apple's Developer Program is not required anyway, as long as the certificate is still valid. Building and signing on Yosemite (10.10.3) works fine, if I run on Yosemite - even before renewing our membership. But of course I can't insist my users run Yosemite, hence my question.

          1. Check out https://developer.apple.com/library/content/technotes/tn2206/_index.html it has a lot of info on signing applications.

          Thanks, I have been studying that document, as well as this one. Since nothing I tried met with success, I created the minimal example, hoping someone could point out a problem or perhaps test it and suggest what works for them.

          1. Why do you enter a code signing loop until "it doesn't crash"? If that is necessary you may have found your problem right there, lol.

          Perhaps that loop is no longer necessary, but it doesn't seem to me that leaving the loop in place should cause a problem. There used to be a concurrency issue in Apple's code somewhere that required this workaround. We found this workaround to be necessary when building/signing on 10.10.3. See this SO question and this Apple forum question. For the record, in all my tests I've NOT noticed this loop to be necessary on Sierra - the script has not executed the echo Failure. Trying again... command, so it seems likely that Apple fixed the issue sometime after 10.10.3.

          The only thing I'm doing that I see is not recommended is that I'm using --deep to sign the bundle. Here's the relevant quote from the Apple technote you mention:

          Important: While the --deep option can be applied to a signing operation, this is not recommended. We recommend that you sign code inside out in individual stages (as Xcode does automatically). Signing with --deep is for emergency repairs and temporary adjustments only.

          I'm not sure what "signing code inside out in individual stages" looks like for my minimal example. I understand it is something like starting at the most deeply nested files that require signing, and signing each one individually, and moving back toward the root of the bundle. But I don't understand exactly what order that means for Frameworks, main app, dylibs, etc. If that's really required, I'd think someone would have a bash script code sample that loops through and signs everything in the correct order, but I've not found anything like that.

          In any case, Apple's warning about signing with --deep implies that --deep should work, since you can use it for emergency repairs and temporary adjustments. And when I run Apple's recommended checks using codesign --verify and spctl, they pass. So I'm not sure --deep is the issue at all.

          I'm hoping someone who knows more than I do about this stuff can steer me in the right direction. If --deep is the issue, then what files should be signed in my minimal example, and in what order should they be signed?

          A Offline
          A Offline
          ambershark
          wrote on last edited by
          #4

          @davidb Well it sounds like your covered all the stuff I would have thought was going wrong.

          The biggest thing is it works with yosemite but not with sierra. Maybe focus on the gatekeeper changes in sierra.

          I haven't done a signed application in sierra so I haven't experienced this problem before. I'll let someone else with more experience here come in the thread and help if they can. If not I can maybe do a quick signed app later on to test and see if it happens to me too.

          My L-GPL'd C++ Logger github.com/ambershark-mike/sharklog

          1 Reply Last reply
          0
          • D Offline
            D Offline
            davidb
            wrote on last edited by
            #5

            @ambershark thanks - at this point I'm wondering if it's even possible for a Qt-based app to make Sierra's Gatekeeper happy. If anyone has done it, I'd sure appreciate knowing that, and of course knowing how they did it would be really great, too!

            A 1 Reply Last reply
            0
            • D davidb

              @ambershark thanks - at this point I'm wondering if it's even possible for a Qt-based app to make Sierra's Gatekeeper happy. If anyone has done it, I'd sure appreciate knowing that, and of course knowing how they did it would be really great, too!

              A Offline
              A Offline
              ambershark
              wrote on last edited by
              #6

              @davidb AFAIK it's possible to sign any application, including Qt ones. If nobody else comes along with a solution I can run some tests and see if I can get one working with sierra.

              My L-GPL'd C++ Logger github.com/ambershark-mike/sharklog

              1 Reply Last reply
              0
              • D Offline
                D Offline
                davidb
                wrote on last edited by
                #7

                Not sure how I missed this, but here's what has solved the issue:

                After building the app, use otool -l on each Qt framework in the app and look for LC_RPATH to somewhere outside the bundle. For example:

                otool -l path/to/app/Contents/Frameworks/QtConcurrent.framework/Versions/5/QtConcurrent

                Then in the build script, for each framework with an LC_RPATH outside the bundle, add this command to remove it:

                install_name_tool -delete_rpath [the rpath] "path/to/app/Contents/Frameworks/QtConcurrent.framework/Versions/5/QtConcurrent"

                That worked for me. I also codesign the .dmg, not sure if that makes a difference for Gatekeeper.

                W 1 Reply Last reply
                1
                • SGaistS Offline
                  SGaistS Offline
                  SGaist
                  Lifetime Qt Champion
                  wrote on last edited by SGaist
                  #8

                  Glad you found out and thanks for sharing !

                  Can you post the original paths you had that were triggering the bug ?

                  Interested in AI ? www.idiap.ch
                  Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                  1 Reply Last reply
                  0
                  • D davidb

                    Not sure how I missed this, but here's what has solved the issue:

                    After building the app, use otool -l on each Qt framework in the app and look for LC_RPATH to somewhere outside the bundle. For example:

                    otool -l path/to/app/Contents/Frameworks/QtConcurrent.framework/Versions/5/QtConcurrent

                    Then in the build script, for each framework with an LC_RPATH outside the bundle, add this command to remove it:

                    install_name_tool -delete_rpath [the rpath] "path/to/app/Contents/Frameworks/QtConcurrent.framework/Versions/5/QtConcurrent"

                    That worked for me. I also codesign the .dmg, not sure if that makes a difference for Gatekeeper.

                    W Offline
                    W Offline
                    WJWJ
                    wrote on last edited by
                    #9

                    @davidb In our case we had to remove the rpath "@loader_path/../../../../lib" from the Assistant-executable, which pointed outside our app. We added the Qt-Assistant in our app, in the MacOs-map. (we also had to add the rpath "@loader_path/../Frameworks" in the Assistant-executable to get that work correctly.)

                    SGaistS 1 Reply Last reply
                    1
                    • W WJWJ

                      @davidb In our case we had to remove the rpath "@loader_path/../../../../lib" from the Assistant-executable, which pointed outside our app. We added the Qt-Assistant in our app, in the MacOs-map. (we also had to add the rpath "@loader_path/../Frameworks" in the Assistant-executable to get that work correctly.)

                      SGaistS Offline
                      SGaistS Offline
                      SGaist
                      Lifetime Qt Champion
                      wrote on last edited by
                      #10

                      @WJWJ thanks for the additional trick !

                      Interested in AI ? www.idiap.ch
                      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                      1 Reply Last reply
                      0

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved