Andrey
Andrey

Reputation: 377

How to sign Mac OS X application?

I created a Mac OS X application but I don't know which steps I have to do for signing my Mac OS X application correctly. Thank you.

Upvotes: 20

Views: 27589

Answers (5)

Stephane Paquet
Stephane Paquet

Reputation: 2344

At first you need an fully functional (and thus paid) Apple developer account. Then you can follow this information: https://developer.apple.com/library/archive/documentation/Security/Conceptual/CodeSigningGuide/Introduction/Introduction.html

The above link is the global procedure, but there is a specific topic with clean illustrated how to at the following URL: https://developer.apple.com/library/archive/documentation/Security/Conceptual/CodeSigningGuide/Procedures/Procedures.html#//apple_ref/doc/uid/TP40005929-CH4-SW2

Upvotes: 8

Cao Shouguang
Cao Shouguang

Reputation: 148

When you sign an app, all executables inside that app need to be signed, otherwise, the notarization will fail.

I wrote this node code that will recursively find all executables within an app and sign them.

#!/usr/bin/env node
// 5.14

const APP = "./yourAppName.app";
const IDENTITY = "your_signature_";

/****************************************************************************/
const items = [];
console.log("### finding things to sign");

const fs = require('fs');
const child_process = require('child_process');
const recursive = require("recursive-readdir");
const listdirs = require('listdirs');


const folder = `./nwjs.app`;

const main = async()=>{

    const allFiles = await recursive(folder);
    const exeFiles = allFiles.filter((x)=>{
        try {
            fs.accessSync(x, fs.constants.X_OK)
            return true;    
        } catch (error) {
            return false
        }
        
    })
    console.log("all files", exeFiles); 
    items.push(...exeFiles)

    const myListDir = (folder)=>{
        return new Promise((resolve, reject) => {
            listdirs(folder, function callback(err, list){
                if(err){
                  return reject(err)
                }
                else {
                  return resolve(list)
                }
            });         
        });
    }

    const allFolders = await myListDir(folder);
    const appFolders = allFolders.filter((x)=>{
        return x.endsWith(".app")
    })

   console.log("all Folders", appFolders); 
   items.push(...appFolders)


    /****************************************************************************/

    console.log("");
    console.log("### signing");

    function exec(cmd) {
        console.log(cmd);
        const result = child_process.spawnSync(cmd, {shell: true, stdio: 'inherit'});
        if (result.status !== 0) {
            console.log(`Command failed with status ${result.status}`);
            if (result.error) console.log(result.error);
            //process.exit(1);
        }
    }

    items.push(`${APP}/Contents/MacOS/nwjs`)
    
    
    for (const item of items) {
        try {
            exec(`codesign --verbose --force --deep --strict --options runtime --timestamp --sign "${IDENTITY}" --entitlements neededToRun.entitlements "${item}"`);    
        } catch (error) {
            console.log(error);
        }
        
    }

    exec(`codesign --verbose --force --deep --strict --options runtime --timestamp --sign "${IDENTITY}" --entitlements neededToRun.entitlements "${APP}"`);

    /****************************************************************************/

    console.log("");
    console.log("### verifying signature");

    exec(`codesign --verify -vvvv "${APP}"`);
}

main();

Upvotes: -1

Daniel Georgiev
Daniel Georgiev

Reputation: 1340

With Qt

macdeployqt APP_NAME.app -codesign="Developer ID Application: YOUR NAME (ID_NUMBERS)"

Otherwise

codesign --force --verify --verbose --sign "Developer ID Application: YOUR NAME (ID_NUMBERS)" APP_NAME.app

You also need to sign every framework and dylib file into the package with something like this

codesign --force --verify --verbose --sign "Developer ID Application: YOUR NAME (ID_NUMBERS)" APP_NAME.app/Contents/Frameworks/QtCore.framework/Versions/5/QtCore
codesign --force --verify --verbose --sign "Developer ID Application: YOUR NAME (ID_NUMBERS)" APP_NAME.app/Contents/Plugins/bearer/libqcorewlanbearer.dylib

Upvotes: 8

Andy Brice
Andy Brice

Reputation: 2317

I found the Apple documentation far too verbose. I have written up some detailed notes on how I signed my own software for Mac. There is too much to put it all here. See: http://successfulsoftware.net/2012/08/30/how-to-sign-your-mac-os-x-app-for-gatekeeper/

Upvotes: 30

gnuchu
gnuchu

Reputation: 1496

There is good Apple documentation on this. Go to the developer provisioning section and there is a good primer there that can get you running quickly.

Upvotes: 1

Related Questions